From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../java/org/mozilla/gecko/EnterpriseRoots.java | 96 ++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 mobile/android/geckoview/src/main/java/org/mozilla/gecko/EnterpriseRoots.java (limited to 'mobile/android/geckoview/src/main/java/org/mozilla/gecko/EnterpriseRoots.java') diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EnterpriseRoots.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EnterpriseRoots.java new file mode 100644 index 0000000000..0aacef39a4 --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EnterpriseRoots.java @@ -0,0 +1,96 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko; + +import android.util.Log; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.Enumeration; +import org.mozilla.gecko.annotation.WrapForJNI; + +// This class implements the functionality needed to find third-party root +// certificates that have been added to the android CA store. +public class EnterpriseRoots { + private static final String LOGTAG = "EnterpriseRoots"; + + // Gecko calls this function from C++ to find third-party root certificates + // it can use as trust anchors for TLS connections. + @WrapForJNI + private static byte[][] gatherEnterpriseRoots() { + + // The KeyStore "AndroidCAStore" contains the certificates we're + // interested in. + final KeyStore ks; + try { + ks = KeyStore.getInstance("AndroidCAStore"); + } catch (final KeyStoreException kse) { + Log.e(LOGTAG, "getInstance() failed", kse); + return new byte[0][0]; + } + try { + ks.load(null); + } catch (final CertificateException ce) { + Log.e(LOGTAG, "load() failed", ce); + return new byte[0][0]; + } catch (final IOException ioe) { + Log.e(LOGTAG, "load() failed", ioe); + return new byte[0][0]; + } catch (final NoSuchAlgorithmException nsae) { + Log.e(LOGTAG, "load() failed", nsae); + return new byte[0][0]; + } + // Given the KeyStore, we get an identifier for each object in it. For + // each one that is a Certificate, we try to distinguish between + // entries that shipped with the OS and entries that were added by the + // user or an administrator. The former we ignore and the latter we + // collect in an array of byte arrays and return. + final Enumeration aliases; + try { + aliases = ks.aliases(); + } catch (final KeyStoreException kse) { + Log.e(LOGTAG, "aliases() failed", kse); + return new byte[0][0]; + } + final ArrayList roots = new ArrayList(); + while (aliases.hasMoreElements()) { + final String alias = aliases.nextElement(); + final boolean isCertificate; + try { + isCertificate = ks.isCertificateEntry(alias); + } catch (final KeyStoreException kse) { + Log.e(LOGTAG, "isCertificateEntry() failed", kse); + continue; + } + // Built-in certificate aliases start with "system:", whereas + // 3rd-party certificate aliases start with "user:". It's + // unfortunate to be relying on this implementation detail, but + // there appears to be no other way to differentiate between the + // two. + if (isCertificate && alias.startsWith("user:")) { + final Certificate certificate; + try { + certificate = ks.getCertificate(alias); + } catch (final KeyStoreException kse) { + Log.e(LOGTAG, "getCertificate() failed", kse); + continue; + } + try { + roots.add(certificate.getEncoded()); + } catch (final CertificateEncodingException cee) { + Log.e(LOGTAG, "getEncoded() failed", cee); + } + } + } + Log.d(LOGTAG, "found " + roots.size() + " enterprise roots"); + return roots.toArray(new byte[0][0]); + } +} -- cgit v1.2.3