132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root/* 232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * Copyright (C) 2012 The Android Open Source Project 332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * 432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * you may not use this file except in compliance with the License. 632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * You may obtain a copy of the License at 732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * 832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * http://www.apache.org/licenses/LICENSE-2.0 932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * 1032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * Unless required by applicable law or agreed to in writing, software 1132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 1232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * See the License for the specific language governing permissions and 1432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * limitations under the License. 1532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root */ 1632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt; 1832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 1932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.io.ByteArrayOutputStream; 2032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.io.InputStream; 2132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.math.BigInteger; 2232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.InvalidKeyException; 2332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.KeyFactory; 2432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.NoSuchAlgorithmException; 2532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.NoSuchProviderException; 2632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.Principal; 2732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.PublicKey; 2832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.Signature; 2932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.SignatureException; 300e9746b7b132058651155b33f219c7789997985bKenny Rootimport java.security.cert.Certificate; 3132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.CertificateEncodingException; 3232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.CertificateException; 3332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.CertificateExpiredException; 3432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.CertificateNotYetValidException; 3532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.CertificateParsingException; 3632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.X509Certificate; 3732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.spec.InvalidKeySpecException; 3832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.spec.X509EncodedKeySpec; 3932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.ArrayList; 4032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.Arrays; 4132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.Calendar; 4232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.Collection; 4332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.Collections; 4432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.Date; 4532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.HashSet; 4632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.List; 4732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.Set; 4832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.TimeZone; 497c3263f16bae0f1b2125de2c3c1c683303e768ceKenny Rootimport javax.crypto.BadPaddingException; 5032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport javax.security.auth.x500.X500Principal; 51860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport org.apache.harmony.security.utils.AlgNameMapper; 52860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport org.conscrypt.OpenSSLX509CertificateFactory.ParsingException; 5332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 5432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootpublic class OpenSSLX509Certificate extends X509Certificate { 5532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root private final long mContext; 5632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 57e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root OpenSSLX509Certificate(long ctx) { 5832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root mContext = ctx; 5932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 6032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 6132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public static OpenSSLX509Certificate fromX509DerInputStream(InputStream is) 6232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root throws ParsingException { 63209c986cfe42dbaa5497c6e68d1b5db96b28db78Kenny Root @SuppressWarnings("resource") 6432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is); 6532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 6632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root try { 6732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final long certCtx = NativeCrypto.d2i_X509_bio(bis.getBioContext()); 6832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (certCtx == 0) { 6932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return null; 7032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 7132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return new OpenSSLX509Certificate(certCtx); 7232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } catch (Exception e) { 7332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root throw new ParsingException(e); 7432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } finally { 7519fdf1af6bada9ebf4820839780d8713ac3824faKenny Root bis.release(); 7632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 7732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 7832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 79e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root public static OpenSSLX509Certificate fromX509Der(byte[] encoded) { 80e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root final long certCtx = NativeCrypto.d2i_X509(encoded); 81e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root if (certCtx == 0) { 82e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root return null; 83e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root } 84e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root return new OpenSSLX509Certificate(certCtx); 85e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root } 86e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root 8732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public static List<OpenSSLX509Certificate> fromPkcs7DerInputStream(InputStream is) 8832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root throws ParsingException { 89209c986cfe42dbaa5497c6e68d1b5db96b28db78Kenny Root @SuppressWarnings("resource") 9032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is); 9132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 9232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final long[] certRefs; 9332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root try { 9432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root certRefs = NativeCrypto.d2i_PKCS7_bio(bis.getBioContext(), NativeCrypto.PKCS7_CERTS); 9532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } catch (Exception e) { 9632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root throw new ParsingException(e); 9732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } finally { 9819fdf1af6bada9ebf4820839780d8713ac3824faKenny Root bis.release(); 9932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 10032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 101e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root if (certRefs == null) { 102e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root return Collections.emptyList(); 103e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root } 104e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root 10532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final List<OpenSSLX509Certificate> certs = new ArrayList<OpenSSLX509Certificate>( 10632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root certRefs.length); 10732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root for (int i = 0; i < certRefs.length; i++) { 10832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (certRefs[i] == 0) { 10932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root continue; 11032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 11132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root certs.add(new OpenSSLX509Certificate(certRefs[i])); 11232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 11332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return certs; 11432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 11532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 11632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public static OpenSSLX509Certificate fromX509PemInputStream(InputStream is) 11732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root throws ParsingException { 118209c986cfe42dbaa5497c6e68d1b5db96b28db78Kenny Root @SuppressWarnings("resource") 11932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is); 12032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 12132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root try { 12232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final long certCtx = NativeCrypto.PEM_read_bio_X509(bis.getBioContext()); 12332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (certCtx == 0L) { 12432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return null; 12532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 12632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return new OpenSSLX509Certificate(certCtx); 12732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } catch (Exception e) { 12832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root throw new ParsingException(e); 12932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } finally { 13019fdf1af6bada9ebf4820839780d8713ac3824faKenny Root bis.release(); 13132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 13232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 13332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 13432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public static List<OpenSSLX509Certificate> fromPkcs7PemInputStream(InputStream is) 13532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root throws ParsingException { 136209c986cfe42dbaa5497c6e68d1b5db96b28db78Kenny Root @SuppressWarnings("resource") 13732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is); 13832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 13932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final long[] certRefs; 14032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root try { 14132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root certRefs = NativeCrypto.PEM_read_bio_PKCS7(bis.getBioContext(), 14232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.PKCS7_CERTS); 14332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } catch (Exception e) { 14432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root throw new ParsingException(e); 14532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } finally { 14619fdf1af6bada9ebf4820839780d8713ac3824faKenny Root bis.release(); 14732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 14832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 14932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final List<OpenSSLX509Certificate> certs = new ArrayList<OpenSSLX509Certificate>( 15032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root certRefs.length); 15132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root for (int i = 0; i < certRefs.length; i++) { 15232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (certRefs[i] == 0) { 15332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root continue; 15432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 15532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root certs.add(new OpenSSLX509Certificate(certRefs[i])); 15632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 15732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return certs; 15832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 15932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 1600e9746b7b132058651155b33f219c7789997985bKenny Root public static OpenSSLX509Certificate fromCertificate(Certificate cert) 1610e9746b7b132058651155b33f219c7789997985bKenny Root throws CertificateEncodingException { 1620e9746b7b132058651155b33f219c7789997985bKenny Root if (cert instanceof OpenSSLX509Certificate) { 1630e9746b7b132058651155b33f219c7789997985bKenny Root return (OpenSSLX509Certificate) cert; 1640e9746b7b132058651155b33f219c7789997985bKenny Root } else if (cert instanceof X509Certificate) { 1650e9746b7b132058651155b33f219c7789997985bKenny Root return fromX509Der(cert.getEncoded()); 1660e9746b7b132058651155b33f219c7789997985bKenny Root } else { 1670e9746b7b132058651155b33f219c7789997985bKenny Root throw new CertificateEncodingException("Only X.509 certificates are supported"); 1680e9746b7b132058651155b33f219c7789997985bKenny Root } 1690e9746b7b132058651155b33f219c7789997985bKenny Root } 1700e9746b7b132058651155b33f219c7789997985bKenny Root 17132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 17232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public Set<String> getCriticalExtensionOIDs() { 17332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root String[] critOids = 17432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.get_X509_ext_oids(mContext, NativeCrypto.EXTENSION_TYPE_CRITICAL); 17532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 17632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root /* 17732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * This API has a special case that if there are no extensions, we 17832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * should return null. So if we have no critical extensions, we'll check 17932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * non-critical extensions. 18032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root */ 18132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if ((critOids.length == 0) 18232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root && (NativeCrypto.get_X509_ext_oids(mContext, 18332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.EXTENSION_TYPE_NON_CRITICAL).length == 0)) { 18432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return null; 18532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 18632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 18732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return new HashSet<String>(Arrays.asList(critOids)); 18832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 18932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 19032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 19132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public byte[] getExtensionValue(String oid) { 19232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return NativeCrypto.X509_get_ext_oid(mContext, oid); 19332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 19432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 19532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 19632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public Set<String> getNonCriticalExtensionOIDs() { 19732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root String[] nonCritOids = 19832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.get_X509_ext_oids(mContext, NativeCrypto.EXTENSION_TYPE_NON_CRITICAL); 19932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 20032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root /* 20132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * This API has a special case that if there are no extensions, we 20232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * should return null. So if we have no non-critical extensions, we'll 20332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * check critical extensions. 20432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root */ 20532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if ((nonCritOids.length == 0) 20632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root && (NativeCrypto.get_X509_ext_oids(mContext, 20732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.EXTENSION_TYPE_CRITICAL).length == 0)) { 20832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return null; 20932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 21032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 21132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return new HashSet<String>(Arrays.asList(nonCritOids)); 21232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 21332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 21432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 21532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public boolean hasUnsupportedCriticalExtension() { 21632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return (NativeCrypto.get_X509_ex_flags(mContext) & NativeCrypto.EXFLAG_CRITICAL) != 0; 21732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 21832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 21932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 22032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public void checkValidity() throws CertificateExpiredException, 22132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root CertificateNotYetValidException { 22232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root checkValidity(new Date()); 22332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 22432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 22532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 22632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public void checkValidity(Date date) throws CertificateExpiredException, 22732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root CertificateNotYetValidException { 22832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (getNotBefore().compareTo(date) > 0) { 229cb713c076de9b3d458727ecb2ae2658859a893e2Kenny Root throw new CertificateNotYetValidException("Certificate not valid until " 230cb713c076de9b3d458727ecb2ae2658859a893e2Kenny Root + getNotBefore().toString() + " (compared to " + date.toString() + ")"); 23132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 23232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 23332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (getNotAfter().compareTo(date) < 0) { 234cb713c076de9b3d458727ecb2ae2658859a893e2Kenny Root throw new CertificateExpiredException("Certificate expired at " 235cb713c076de9b3d458727ecb2ae2658859a893e2Kenny Root + getNotAfter().toString() + " (compared to " + date.toString() + ")"); 23632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 23732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 23832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 23932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 24032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public int getVersion() { 24132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return (int) NativeCrypto.X509_get_version(mContext) + 1; 24232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 24332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 24432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 24532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public BigInteger getSerialNumber() { 2461744cf2b54cc7183ff83a3a2eab3a92a8d95ff55Kenny Root return new BigInteger(NativeCrypto.X509_get_serialNumber(mContext)); 24732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 24832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 24932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 25032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public Principal getIssuerDN() { 25132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return getIssuerX500Principal(); 25232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 25332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 25432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 25532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public Principal getSubjectDN() { 25632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return getSubjectX500Principal(); 25732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 25832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 25932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 26032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public Date getNotBefore() { 2614c87dc62be38bf5b5378c494a225316cb3101f2cKenny Root Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 2624c87dc62be38bf5b5378c494a225316cb3101f2cKenny Root calendar.set(Calendar.MILLISECOND, 0); 26332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.ASN1_TIME_to_Calendar(NativeCrypto.X509_get_notBefore(mContext), calendar); 26432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return calendar.getTime(); 26532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 26632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 26732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 26832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public Date getNotAfter() { 2694c87dc62be38bf5b5378c494a225316cb3101f2cKenny Root Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 2704c87dc62be38bf5b5378c494a225316cb3101f2cKenny Root calendar.set(Calendar.MILLISECOND, 0); 27132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.ASN1_TIME_to_Calendar(NativeCrypto.X509_get_notAfter(mContext), calendar); 27232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return calendar.getTime(); 27332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 27432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 27532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 27632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public byte[] getTBSCertificate() throws CertificateEncodingException { 27732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return NativeCrypto.get_X509_cert_info_enc(mContext); 27832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 27932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 28032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 28132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public byte[] getSignature() { 28232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return NativeCrypto.get_X509_signature(mContext); 28332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 28432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 28532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 28632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public String getSigAlgName() { 28732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return AlgNameMapper.map2AlgName(getSigAlgOID()); 28832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 28932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 29032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 29132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public String getSigAlgOID() { 29232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return NativeCrypto.get_X509_sig_alg_oid(mContext); 29332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 29432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 29532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 29632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public byte[] getSigAlgParams() { 29732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return NativeCrypto.get_X509_sig_alg_parameter(mContext); 29832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 29932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 30032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 30132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public boolean[] getIssuerUniqueID() { 30232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return NativeCrypto.get_X509_issuerUID(mContext); 30332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 30432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 30532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 30632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public boolean[] getSubjectUniqueID() { 30732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return NativeCrypto.get_X509_subjectUID(mContext); 30832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 30932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 31032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 31132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public boolean[] getKeyUsage() { 31232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final boolean[] kusage = NativeCrypto.get_X509_ex_kusage(mContext); 31315c727fbf84cea10d0f64065a4f8f541acd6f647Kenny Root if (kusage == null) { 31415c727fbf84cea10d0f64065a4f8f541acd6f647Kenny Root return null; 31515c727fbf84cea10d0f64065a4f8f541acd6f647Kenny Root } 31615c727fbf84cea10d0f64065a4f8f541acd6f647Kenny Root 31732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (kusage.length >= 9) { 31832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return kusage; 31932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 32032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 32132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final boolean resized[] = new boolean[9]; 32232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root System.arraycopy(kusage, 0, resized, 0, kusage.length); 32332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return resized; 32432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 32532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 32632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 32732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public int getBasicConstraints() { 3289ec4f876b0b8e2b659728d0468492cde3763ad5dKenny Root if ((NativeCrypto.get_X509_ex_flags(mContext) & NativeCrypto.EXFLAG_CA) == 0) { 32932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return -1; 33032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 33132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 33232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final int pathLen = NativeCrypto.get_X509_ex_pathlen(mContext); 33332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (pathLen == -1) { 33432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return Integer.MAX_VALUE; 33532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 33632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 33732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return pathLen; 33832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 33932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 34032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 34132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public byte[] getEncoded() throws CertificateEncodingException { 34232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return NativeCrypto.i2d_X509(mContext); 34332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 34432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 34532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root private void verifyOpenSSL(OpenSSLKey pkey) throws CertificateException, 34632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, 34732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root SignatureException { 348d12d4d481246a06df6b4cbc9f49106bdf615610fKenny Root try { 349d12d4d481246a06df6b4cbc9f49106bdf615610fKenny Root NativeCrypto.X509_verify(mContext, pkey.getPkeyContext()); 350d12d4d481246a06df6b4cbc9f49106bdf615610fKenny Root } catch (RuntimeException e) { 351d12d4d481246a06df6b4cbc9f49106bdf615610fKenny Root throw new CertificateException(e); 3527c3263f16bae0f1b2125de2c3c1c683303e768ceKenny Root } catch (BadPaddingException e) { 353cea9ec153ef5bf27e3eee74d7c503bce02084bc2Kenny Root throw new SignatureException(); 354d12d4d481246a06df6b4cbc9f49106bdf615610fKenny Root } 35532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 35632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 35732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root private void verifyInternal(PublicKey key, String sigProvider) throws CertificateException, 35832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, 35932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root SignatureException { 36032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root String sigAlg = getSigAlgName(); 36132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (sigAlg == null) { 36232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root sigAlg = getSigAlgOID(); 36332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 36432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 36532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final Signature sig; 36632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (sigProvider == null) { 36732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root sig = Signature.getInstance(sigAlg); 36832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } else { 36932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root sig = Signature.getInstance(sigAlg, sigProvider); 37032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 37132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 37232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root sig.initVerify(key); 37332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root sig.update(getTBSCertificate()); 37432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (!sig.verify(getSignature())) { 37532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root throw new SignatureException("signature did not verify"); 37632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 37732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 37832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 37932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 38032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, 38132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root InvalidKeyException, NoSuchProviderException, SignatureException { 38232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (key instanceof OpenSSLKeyHolder) { 38332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root OpenSSLKey pkey = ((OpenSSLKeyHolder) key).getOpenSSLKey(); 38432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root verifyOpenSSL(pkey); 38532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return; 38632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 38732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 38832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root verifyInternal(key, null); 38932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 39032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 39132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 39232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public void verify(PublicKey key, String sigProvider) throws CertificateException, 39332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, 39432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root SignatureException { 39532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root verifyInternal(key, sigProvider); 39632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 39732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 39832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 39932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public String toString() { 40032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root ByteArrayOutputStream os = new ByteArrayOutputStream(); 40132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root long bioCtx = NativeCrypto.create_BIO_OutputStream(os); 40232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root try { 40332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.X509_print_ex(bioCtx, mContext, 0, 0); 40432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return os.toString(); 40532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } finally { 40619fdf1af6bada9ebf4820839780d8713ac3824faKenny Root NativeCrypto.BIO_free_all(bioCtx); 40732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 40832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 40932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 41032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 41132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public PublicKey getPublicKey() { 41232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root /* First try to generate the key from supported OpenSSL key types. */ 41332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root try { 41432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root OpenSSLKey pkey = new OpenSSLKey(NativeCrypto.X509_get_pubkey(mContext)); 41532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return pkey.getPublicKey(); 41632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } catch (NoSuchAlgorithmException ignored) { 41732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 41832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 41932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root /* Try generating the key using other Java providers. */ 42032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root String oid = NativeCrypto.get_X509_pubkey_oid(mContext); 42132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root byte[] encoded = NativeCrypto.i2d_X509_PUBKEY(mContext); 42232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root try { 42332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root KeyFactory kf = KeyFactory.getInstance(oid); 42432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return kf.generatePublic(new X509EncodedKeySpec(encoded)); 42532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } catch (NoSuchAlgorithmException ignored) { 42632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } catch (InvalidKeySpecException ignored) { 42732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 42832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 42932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root /* 43032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * We couldn't find anything else, so just return a nearly-unusable 43132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * X.509-encoded key. 43232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root */ 4337d97b2cee4acabea6c8cb795d25fb1fb564f016cKenny Root return new X509PublicKey(oid, encoded); 43432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 43532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 43632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 43732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public X500Principal getIssuerX500Principal() { 43832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final byte[] issuer = NativeCrypto.X509_get_issuer_name(mContext); 43932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return new X500Principal(issuer); 44032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 44132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 44232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 44332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public X500Principal getSubjectX500Principal() { 44432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root final byte[] subject = NativeCrypto.X509_get_subject_name(mContext); 44532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return new X500Principal(subject); 44632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 44732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 44832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 44932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public List<String> getExtendedKeyUsage() throws CertificateParsingException { 45032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root String[] extUsage = NativeCrypto.get_X509_ex_xkusage(mContext); 45132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (extUsage == null) { 45232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return null; 45332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 45432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 45532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return Arrays.asList(extUsage); 45632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 45732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 45832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root private static Collection<List<?>> alternativeNameArrayToList(Object[][] altNameArray) { 45932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (altNameArray == null) { 46032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return null; 46132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 46232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 46332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root Collection<List<?>> coll = new ArrayList<List<?>>(altNameArray.length); 46432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root for (int i = 0; i < altNameArray.length; i++) { 46532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root coll.add(Collections.unmodifiableList(Arrays.asList(altNameArray[i]))); 46632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 46732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 46832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return Collections.unmodifiableCollection(coll); 46932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 47032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 47132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 47232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException { 47332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return alternativeNameArrayToList(NativeCrypto.get_X509_GENERAL_NAME_stack(mContext, 47432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.GN_STACK_SUBJECT_ALT_NAME)); 47532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 47632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 47732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 47832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public Collection<List<?>> getIssuerAlternativeNames() throws CertificateParsingException { 47932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return alternativeNameArrayToList(NativeCrypto.get_X509_GENERAL_NAME_stack(mContext, 48032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.GN_STACK_ISSUER_ALT_NAME)); 48132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 48232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 48332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 48432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public boolean equals(Object other) { 48532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (other instanceof OpenSSLX509Certificate) { 48632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root OpenSSLX509Certificate o = (OpenSSLX509Certificate) other; 48732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 48832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return NativeCrypto.X509_cmp(mContext, o.mContext) == 0; 48932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 49032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 49132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return super.equals(other); 49232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 49332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 49432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 49532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root public int hashCode() { 49632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root /* Make this faster since we might be in hash-based structures. */ 49732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return NativeCrypto.get_X509_hashCode(mContext); 49832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 49932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 50016c041fa20ef70221f487631f07eaf53d39ae51cKenny Root /** 50116c041fa20ef70221f487631f07eaf53d39ae51cKenny Root * Returns the raw pointer to the X509 context for use in JNI calls. The 50216c041fa20ef70221f487631f07eaf53d39ae51cKenny Root * life cycle of this native pointer is managed by the 50316c041fa20ef70221f487631f07eaf53d39ae51cKenny Root * {@code OpenSSLX509Certificate} instance and must not be destroyed or 50416c041fa20ef70221f487631f07eaf53d39ae51cKenny Root * freed by users of this API. 50516c041fa20ef70221f487631f07eaf53d39ae51cKenny Root */ 50616c041fa20ef70221f487631f07eaf53d39ae51cKenny Root public long getContext() { 50732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root return mContext; 50832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 50932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root 51032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root @Override 51132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root protected void finalize() throws Throwable { 51232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root try { 51332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root if (mContext != 0) { 51432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root NativeCrypto.X509_free(mContext); 51532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 51632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } finally { 51732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root super.finalize(); 51832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 51932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root } 52032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root} 521