diff options
author | Kenny Root <kroot@google.com> | 2013-05-06 20:21:51 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2013-05-06 20:21:51 +0000 |
commit | 3e7a5a2188accd38f4bee36449ced7d36b717aa9 (patch) | |
tree | f5e345f3191db3f23b1d98a7c0feb599f527d47d /crypto | |
parent | f7e1ba4804f7365e6ab47a34e019532b428b1546 (diff) | |
parent | 6a71da569514b7b3dc8041ea06daf21313826b80 (diff) | |
download | libcore-3e7a5a2188accd38f4bee36449ced7d36b717aa9.zip libcore-3e7a5a2188accd38f4bee36449ced7d36b717aa9.tar.gz libcore-3e7a5a2188accd38f4bee36449ced7d36b717aa9.tar.bz2 |
Merge "NativeCrypto: replace Harmony routines with OpenSSL"
Diffstat (limited to 'crypto')
3 files changed, 40 insertions, 82 deletions
diff --git a/crypto/src/main/java/org/conscrypt/NativeCrypto.java b/crypto/src/main/java/org/conscrypt/NativeCrypto.java index 208f89e..c6d1b2d 100644 --- a/crypto/src/main/java/org/conscrypt/NativeCrypto.java +++ b/crypto/src/main/java/org/conscrypt/NativeCrypto.java @@ -445,6 +445,8 @@ public final class NativeCrypto { public static native int get_X509_ex_flags(long x509ctx); + public static native int X509_check_issued(long ctx, long ctx2); + // --- X509 EXFLAG --------------------------------------------------------- public static final int EXFLAG_CA = 0x10; diff --git a/crypto/src/main/java/org/conscrypt/TrustedCertificateStore.java b/crypto/src/main/java/org/conscrypt/TrustedCertificateStore.java index 4c4f6ce..1356776 100644 --- a/crypto/src/main/java/org/conscrypt/TrustedCertificateStore.java +++ b/crypto/src/main/java/org/conscrypt/TrustedCertificateStore.java @@ -23,25 +23,17 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.math.BigInteger; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.security.auth.x500.X500Principal; import libcore.io.IoUtils; -import libcore.util.Objects; -import org.apache.harmony.security.x501.Name; -import org.apache.harmony.security.x509.AuthorityKeyIdentifier; -import org.apache.harmony.security.x509.GeneralName; -import org.apache.harmony.security.x509.GeneralNames; -import org.apache.harmony.security.x509.SubjectKeyIdentifier; /** * A source for trusted root certificate authority (CA) certificates @@ -380,81 +372,30 @@ public final class TrustedCertificateStore { return null; } - private static AuthorityKeyIdentifier getAuthorityKeyIdentifier(X509Certificate cert) { - final byte[] akidBytes = cert.getExtensionValue("2.5.29.35"); - if (akidBytes == null) { - return null; - } - - try { - return AuthorityKeyIdentifier.decode(akidBytes); - } catch (IOException e) { - return null; - } + private static boolean isSelfIssuedCertificate(OpenSSLX509Certificate cert) { + final long ctx = cert.getContext(); + return NativeCrypto.X509_check_issued(ctx, ctx) == 0; } - private static SubjectKeyIdentifier getSubjectKeyIdentifier(X509Certificate cert) { - final byte[] skidBytes = cert.getExtensionValue("2.5.29.14"); - if (skidBytes == null) { + /** + * Converts the {@code cert} to the internal OpenSSL X.509 format so we can + * run {@link NativeCrypto} methods on it. + */ + private static OpenSSLX509Certificate convertToOpenSSLIfNeeded(X509Certificate cert) + throws CertificateException { + if (cert == null) { return null; } - try { - return SubjectKeyIdentifier.decode(skidBytes); - } catch (IOException e) { - return null; + if (cert instanceof OpenSSLX509Certificate) { + return (OpenSSLX509Certificate) cert; } - } - private static boolean isSelfSignedCertificate(X509Certificate cert) { - if (!Objects.equal(cert.getSubjectX500Principal(), cert.getIssuerX500Principal())) { - return false; - } - - final AuthorityKeyIdentifier akid = getAuthorityKeyIdentifier(cert); - if (akid != null) { - final byte[] akidKeyId = akid.getKeyIdentifier(); - if (akidKeyId != null) { - final SubjectKeyIdentifier skid = getSubjectKeyIdentifier(cert); - if (!Arrays.equals(akidKeyId, skid.getKeyIdentifier())) { - return false; - } - } - - final BigInteger akidSerial = akid.getAuthorityCertSerialNumber(); - if (akidSerial != null && !akidSerial.equals(cert.getSerialNumber())) { - return false; - } - - final GeneralNames possibleIssuerNames = akid.getAuthorityCertIssuer(); - if (possibleIssuerNames != null) { - GeneralName issuerName = null; - - /* Get the first Directory Name (DN) to match how OpenSSL works. */ - for (GeneralName possibleName : possibleIssuerNames.getNames()) { - if (possibleName.getTag() == GeneralName.DIR_NAME) { - issuerName = possibleName; - break; - } - } - - if (issuerName != null) { - final String issuerCanonical = ((Name) issuerName.getName()) - .getName(X500Principal.CANONICAL); - - try { - final String subjectCanonical = new Name(cert.getSubjectX500Principal() - .getEncoded()).getName(X500Principal.CANONICAL); - if (!issuerCanonical.equals(subjectCanonical)) { - return false; - } - } catch (IOException ignored) { - } - } - } + try { + return OpenSSLX509Certificate.fromX509Der(cert.getEncoded()); + } catch (Exception e) { + throw new CertificateException(e); } - - return true; } /** @@ -463,24 +404,28 @@ public final class TrustedCertificateStore { * can't be completed, the most complete chain available will be returned. * This means that a list with only the {@code leaf} certificate is returned * if no issuer certificates could be found. + * + * @throws CertificateException if there was a problem parsing the + * certificates */ - public List<X509Certificate> getCertificateChain(X509Certificate leaf) { - final List<X509Certificate> chain = new ArrayList<X509Certificate>(); - chain.add(leaf); + public List<X509Certificate> getCertificateChain(X509Certificate leaf) + throws CertificateException { + final List<OpenSSLX509Certificate> chain = new ArrayList<OpenSSLX509Certificate>(); + chain.add(convertToOpenSSLIfNeeded(leaf)); for (int i = 0; true; i++) { - X509Certificate cert = chain.get(i); - if (isSelfSignedCertificate(cert)) { + OpenSSLX509Certificate cert = chain.get(i); + if (isSelfIssuedCertificate(cert)) { break; } - X509Certificate issuer = findIssuer(cert); + OpenSSLX509Certificate issuer = convertToOpenSSLIfNeeded(findIssuer(cert)); if (issuer == null) { break; } chain.add(issuer); } - return chain; + return new ArrayList<X509Certificate>(chain); } // like java.security.cert.CertSelector but with X509Certificate and without cloning diff --git a/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp b/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp index 562a614..9ee9c8e 100644 --- a/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp +++ b/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp @@ -4165,6 +4165,16 @@ static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref) { return x509->ex_flags; } +static jboolean NativeCrypto_X509_check_issued(JNIEnv* env, jclass, jlong x509Ref1, jlong x509Ref2) { + X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1)); + X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2)); + JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2); + + int ret = X509_check_issued(x509_1, x509_2); + JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret); + return ret; +} + static void get_X509_signature(X509 *x509, ASN1_BIT_STRING** signature) { *signature = x509->signature; } @@ -7876,6 +7886,7 @@ static JNINativeMethod sNativeCryptoMethods[] = { NATIVE_METHOD(NativeCrypto, get_X509_signature, "(J)[B"), NATIVE_METHOD(NativeCrypto, get_X509_CRL_signature, "(J)[B"), NATIVE_METHOD(NativeCrypto, get_X509_ex_flags, "(J)I"), + NATIVE_METHOD(NativeCrypto, X509_check_issued, "(JJ)I"), NATIVE_METHOD(NativeCrypto, d2i_X509_CRL_bio, "(J)J"), NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509_CRL, "(J)J"), NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_cert, "(JJ)J"), |