175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root/* 275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * Copyright (C) 2012 The Android Open Source Project 375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * 475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * you may not use this file except in compliance with the License. 675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * You may obtain a copy of the License at 775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * 875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * http://www.apache.org/licenses/LICENSE-2.0 975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * 1075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * Unless required by applicable law or agreed to in writing, software 1175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * distributed under the License is distributed on an "AS IS" BASIS, 1275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * See the License for the specific language governing permissions and 1475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * limitations under the License. 1575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root */ 1675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 1738375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Rootpackage org.conscrypt; 1875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 1975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.io.ByteArrayOutputStream; 2075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.io.InputStream; 2175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.math.BigInteger; 2275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.InvalidKeyException; 2375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.KeyFactory; 2475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.NoSuchAlgorithmException; 2575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.NoSuchProviderException; 2675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.Principal; 2775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.PublicKey; 2875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.Signature; 2975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.SignatureException; 3075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.cert.CertificateEncodingException; 3175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.cert.CertificateException; 3275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.cert.CertificateExpiredException; 3375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.cert.CertificateNotYetValidException; 3475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.cert.CertificateParsingException; 3575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.cert.X509Certificate; 3675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.spec.InvalidKeySpecException; 3775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.security.spec.X509EncodedKeySpec; 3875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.util.ArrayList; 3975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.util.Arrays; 4075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.util.Calendar; 4175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.util.Collection; 4275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.util.Collections; 4375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.util.Date; 4475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.util.HashSet; 4575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.util.List; 4675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.util.Set; 4775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport java.util.TimeZone; 4875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootimport javax.security.auth.x500.X500Principal; 4938375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Rootimport org.apache.harmony.security.utils.AlgNameMapper; 5038375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Rootimport org.conscrypt.OpenSSLX509CertificateFactory.ParsingException; 5175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 5275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Rootpublic class OpenSSLX509Certificate extends X509Certificate { 5375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root private final long mContext; 5475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 5552055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root OpenSSLX509Certificate(long ctx) { 5675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root mContext = ctx; 5775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 5875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 5975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public static OpenSSLX509Certificate fromX509DerInputStream(InputStream is) 6075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throws ParsingException { 618a7427fa40d7fec1eb0298e20688c5751111091fKenny Root @SuppressWarnings("resource") 6275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is); 6375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 6475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root try { 6575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final long certCtx = NativeCrypto.d2i_X509_bio(bis.getBioContext()); 6675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (certCtx == 0) { 6775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return null; 6875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 6975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return new OpenSSLX509Certificate(certCtx); 7075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } catch (Exception e) { 7175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throw new ParsingException(e); 7275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } finally { 7375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.BIO_free(bis.getBioContext()); 7475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 7575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 7675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 7752055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root public static OpenSSLX509Certificate fromX509Der(byte[] encoded) { 7852055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root final long certCtx = NativeCrypto.d2i_X509(encoded); 7952055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root if (certCtx == 0) { 8052055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root return null; 8152055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root } 8252055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root return new OpenSSLX509Certificate(certCtx); 8352055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root } 8452055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root 8575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public static List<OpenSSLX509Certificate> fromPkcs7DerInputStream(InputStream is) 8675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throws ParsingException { 878a7427fa40d7fec1eb0298e20688c5751111091fKenny Root @SuppressWarnings("resource") 8875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is); 8975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 9075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final long[] certRefs; 9175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root try { 9275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root certRefs = NativeCrypto.d2i_PKCS7_bio(bis.getBioContext(), NativeCrypto.PKCS7_CERTS); 9375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } catch (Exception e) { 9475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throw new ParsingException(e); 9575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } finally { 9675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.BIO_free(bis.getBioContext()); 9775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 9875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 9952055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root if (certRefs == null) { 10052055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root return Collections.emptyList(); 10152055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root } 10252055836ff1f8c235a558b3754b3f3dd25f5d38cKenny Root 10375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final List<OpenSSLX509Certificate> certs = new ArrayList<OpenSSLX509Certificate>( 10475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root certRefs.length); 10575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root for (int i = 0; i < certRefs.length; i++) { 10675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (certRefs[i] == 0) { 10775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root continue; 10875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 10975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root certs.add(new OpenSSLX509Certificate(certRefs[i])); 11075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 11175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return certs; 11275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 11375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 11475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public static OpenSSLX509Certificate fromX509PemInputStream(InputStream is) 11575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throws ParsingException { 1168a7427fa40d7fec1eb0298e20688c5751111091fKenny Root @SuppressWarnings("resource") 11775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is); 11875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 11975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root try { 12075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final long certCtx = NativeCrypto.PEM_read_bio_X509(bis.getBioContext()); 12175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (certCtx == 0L) { 12275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return null; 12375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 12475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return new OpenSSLX509Certificate(certCtx); 12575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } catch (Exception e) { 12675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throw new ParsingException(e); 12775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } finally { 12875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.BIO_free(bis.getBioContext()); 12975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 13075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 13175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 13275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public static List<OpenSSLX509Certificate> fromPkcs7PemInputStream(InputStream is) 13375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throws ParsingException { 1348a7427fa40d7fec1eb0298e20688c5751111091fKenny Root @SuppressWarnings("resource") 13575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is); 13675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 13775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final long[] certRefs; 13875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root try { 13975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root certRefs = NativeCrypto.PEM_read_bio_PKCS7(bis.getBioContext(), 14075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.PKCS7_CERTS); 14175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } catch (Exception e) { 14275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throw new ParsingException(e); 14375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } finally { 14475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.BIO_free(bis.getBioContext()); 14575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 14675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 14775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final List<OpenSSLX509Certificate> certs = new ArrayList<OpenSSLX509Certificate>( 14875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root certRefs.length); 14975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root for (int i = 0; i < certRefs.length; i++) { 15075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (certRefs[i] == 0) { 15175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root continue; 15275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 15375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root certs.add(new OpenSSLX509Certificate(certRefs[i])); 15475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 15575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return certs; 15675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 15775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 15875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 15975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public Set<String> getCriticalExtensionOIDs() { 16075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root String[] critOids = 16175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.get_X509_ext_oids(mContext, NativeCrypto.EXTENSION_TYPE_CRITICAL); 16275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 16375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root /* 16475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * This API has a special case that if there are no extensions, we 16575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * should return null. So if we have no critical extensions, we'll check 16675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * non-critical extensions. 16775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root */ 16875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if ((critOids.length == 0) 16975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root && (NativeCrypto.get_X509_ext_oids(mContext, 17075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.EXTENSION_TYPE_NON_CRITICAL).length == 0)) { 17175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return null; 17275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 17375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 17475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return new HashSet<String>(Arrays.asList(critOids)); 17575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 17675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 17775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 17875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public byte[] getExtensionValue(String oid) { 17975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return NativeCrypto.X509_get_ext_oid(mContext, oid); 18075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 18175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 18275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 18375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public Set<String> getNonCriticalExtensionOIDs() { 18475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root String[] nonCritOids = 18575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.get_X509_ext_oids(mContext, NativeCrypto.EXTENSION_TYPE_NON_CRITICAL); 18675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 18775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root /* 18875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * This API has a special case that if there are no extensions, we 18975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * should return null. So if we have no non-critical extensions, we'll 19075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * check critical extensions. 19175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root */ 19275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if ((nonCritOids.length == 0) 19375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root && (NativeCrypto.get_X509_ext_oids(mContext, 19475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.EXTENSION_TYPE_CRITICAL).length == 0)) { 19575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return null; 19675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 19775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 19875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return new HashSet<String>(Arrays.asList(nonCritOids)); 19975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 20075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 20175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 20275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public boolean hasUnsupportedCriticalExtension() { 20375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return (NativeCrypto.get_X509_ex_flags(mContext) & NativeCrypto.EXFLAG_CRITICAL) != 0; 20475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 20575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 20675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 20775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public void checkValidity() throws CertificateExpiredException, 20875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root CertificateNotYetValidException { 20975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root checkValidity(new Date()); 21075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 21175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 21275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 21375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public void checkValidity(Date date) throws CertificateExpiredException, 21475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root CertificateNotYetValidException { 21575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (getNotBefore().compareTo(date) > 0) { 21675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throw new CertificateNotYetValidException(); 21775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 21875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 21975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (getNotAfter().compareTo(date) < 0) { 22075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throw new CertificateExpiredException(); 22175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 22275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 22375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 22475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 22575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public int getVersion() { 22675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return (int) NativeCrypto.X509_get_version(mContext) + 1; 22775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 22875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 22975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 23075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public BigInteger getSerialNumber() { 23175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return new BigInteger(NativeCrypto.X509_get_serialNumber(mContext)); 23275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 23375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 23475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 23575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public Principal getIssuerDN() { 23675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return getIssuerX500Principal(); 23775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 23875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 23975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 24075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public Principal getSubjectDN() { 24175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return getSubjectX500Principal(); 24275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 24375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 24475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 24575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public Date getNotBefore() { 246674979bffe6f45df0beaf79128b86770d7f7cec9Kenny Root Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 247674979bffe6f45df0beaf79128b86770d7f7cec9Kenny Root calendar.set(Calendar.MILLISECOND, 0); 24875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.ASN1_TIME_to_Calendar(NativeCrypto.X509_get_notBefore(mContext), calendar); 24975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return calendar.getTime(); 25075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 25175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 25275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 25375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public Date getNotAfter() { 254674979bffe6f45df0beaf79128b86770d7f7cec9Kenny Root Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 255674979bffe6f45df0beaf79128b86770d7f7cec9Kenny Root calendar.set(Calendar.MILLISECOND, 0); 25675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.ASN1_TIME_to_Calendar(NativeCrypto.X509_get_notAfter(mContext), calendar); 25775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return calendar.getTime(); 25875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 25975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 26075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 26175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public byte[] getTBSCertificate() throws CertificateEncodingException { 26275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return NativeCrypto.get_X509_cert_info_enc(mContext); 26375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 26475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 26575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 26675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public byte[] getSignature() { 26775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return NativeCrypto.get_X509_signature(mContext); 26875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 26975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 27075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 27175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public String getSigAlgName() { 27275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return AlgNameMapper.map2AlgName(getSigAlgOID()); 27375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 27475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 27575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 27675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public String getSigAlgOID() { 27775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return NativeCrypto.get_X509_sig_alg_oid(mContext); 27875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 27975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 28075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 28175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public byte[] getSigAlgParams() { 28275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return NativeCrypto.get_X509_sig_alg_parameter(mContext); 28375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 28475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 28575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 28675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public boolean[] getIssuerUniqueID() { 28775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return NativeCrypto.get_X509_issuerUID(mContext); 28875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 28975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 29075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 29175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public boolean[] getSubjectUniqueID() { 29275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return NativeCrypto.get_X509_subjectUID(mContext); 29375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 29475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 29575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 29675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public boolean[] getKeyUsage() { 29775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final boolean[] kusage = NativeCrypto.get_X509_ex_kusage(mContext); 298e6de385bae91943cae91d88ad8e1bfdd951930f4Kenny Root if (kusage == null) { 299e6de385bae91943cae91d88ad8e1bfdd951930f4Kenny Root return null; 300e6de385bae91943cae91d88ad8e1bfdd951930f4Kenny Root } 301e6de385bae91943cae91d88ad8e1bfdd951930f4Kenny Root 30275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (kusage.length >= 9) { 30375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return kusage; 30475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 30575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 30675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final boolean resized[] = new boolean[9]; 30775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root System.arraycopy(kusage, 0, resized, 0, kusage.length); 30875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return resized; 30975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 31075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 31175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 31275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public int getBasicConstraints() { 313cd59afd3e34cb6b3645babdace22c03882e0ec19Kenny Root if ((NativeCrypto.get_X509_ex_flags(mContext) & NativeCrypto.EXFLAG_CA) == 0) { 31475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return -1; 31575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 31675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 31775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final int pathLen = NativeCrypto.get_X509_ex_pathlen(mContext); 31875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (pathLen == -1) { 31975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return Integer.MAX_VALUE; 32075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 32175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 32275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return pathLen; 32375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 32475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 32575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 32675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public byte[] getEncoded() throws CertificateEncodingException { 32775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return NativeCrypto.i2d_X509(mContext); 32875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 32975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 33075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root private void verifyOpenSSL(OpenSSLKey pkey) throws CertificateException, 33175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, 33275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root SignatureException { 333f04fc33c88d2ad1f06d58d50a0734c0ef511c5b9Kenny Root try { 334f04fc33c88d2ad1f06d58d50a0734c0ef511c5b9Kenny Root NativeCrypto.X509_verify(mContext, pkey.getPkeyContext()); 335f04fc33c88d2ad1f06d58d50a0734c0ef511c5b9Kenny Root } catch (RuntimeException e) { 336f04fc33c88d2ad1f06d58d50a0734c0ef511c5b9Kenny Root throw new CertificateException(e); 337f04fc33c88d2ad1f06d58d50a0734c0ef511c5b9Kenny Root } 33875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 33975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 34075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root private void verifyInternal(PublicKey key, String sigProvider) throws CertificateException, 34175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, 34275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root SignatureException { 34375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root String sigAlg = getSigAlgName(); 34475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (sigAlg == null) { 34575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root sigAlg = getSigAlgOID(); 34675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 34775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 34875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final Signature sig; 34975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (sigProvider == null) { 35075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root sig = Signature.getInstance(sigAlg); 35175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } else { 35275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root sig = Signature.getInstance(sigAlg, sigProvider); 35375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 35475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 35575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root sig.initVerify(key); 35675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root sig.update(getTBSCertificate()); 35775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (!sig.verify(getSignature())) { 35875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root throw new SignatureException("signature did not verify"); 35975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 36075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 36175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 36275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 36375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, 36475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root InvalidKeyException, NoSuchProviderException, SignatureException { 36575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (key instanceof OpenSSLKeyHolder) { 36675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root OpenSSLKey pkey = ((OpenSSLKeyHolder) key).getOpenSSLKey(); 36775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root verifyOpenSSL(pkey); 36875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return; 36975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 37075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 37175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root verifyInternal(key, null); 37275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 37375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 37475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 37575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public void verify(PublicKey key, String sigProvider) throws CertificateException, 37675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, 37775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root SignatureException { 37875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root verifyInternal(key, sigProvider); 37975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 38075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 38175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 38275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public String toString() { 38375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root ByteArrayOutputStream os = new ByteArrayOutputStream(); 38475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root long bioCtx = NativeCrypto.create_BIO_OutputStream(os); 38575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root try { 38675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.X509_print_ex(bioCtx, mContext, 0, 0); 38775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return os.toString(); 38875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } finally { 38975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.BIO_free(bioCtx); 39075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 39175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 39275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 39375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 39475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public PublicKey getPublicKey() { 39575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root /* First try to generate the key from supported OpenSSL key types. */ 39675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root try { 39775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root OpenSSLKey pkey = new OpenSSLKey(NativeCrypto.X509_get_pubkey(mContext)); 39875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return pkey.getPublicKey(); 39975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } catch (NoSuchAlgorithmException ignored) { 40075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 40175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 40275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root /* Try generating the key using other Java providers. */ 40375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root String oid = NativeCrypto.get_X509_pubkey_oid(mContext); 40475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root byte[] encoded = NativeCrypto.i2d_X509_PUBKEY(mContext); 40575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root try { 40675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root KeyFactory kf = KeyFactory.getInstance(oid); 40775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return kf.generatePublic(new X509EncodedKeySpec(encoded)); 40875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } catch (NoSuchAlgorithmException ignored) { 40975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } catch (InvalidKeySpecException ignored) { 41075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 41175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 41275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root /* 41375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * We couldn't find anything else, so just return a nearly-unusable 41475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root * X.509-encoded key. 41575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root */ 416bd788522b36f03dc12750c69fd8b3733ef3801bdKenny Root return new X509PublicKey(oid, encoded); 41775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 41875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 41975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 42075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public X500Principal getIssuerX500Principal() { 42175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final byte[] issuer = NativeCrypto.X509_get_issuer_name(mContext); 42275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return new X500Principal(issuer); 42375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 42475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 42575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 42675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public X500Principal getSubjectX500Principal() { 42775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root final byte[] subject = NativeCrypto.X509_get_subject_name(mContext); 42875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return new X500Principal(subject); 42975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 43075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 43175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 43275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public List<String> getExtendedKeyUsage() throws CertificateParsingException { 43375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root String[] extUsage = NativeCrypto.get_X509_ex_xkusage(mContext); 43475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (extUsage == null) { 43575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return null; 43675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 43775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 43875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return Arrays.asList(extUsage); 43975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 44075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 44175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root private static Collection<List<?>> alternativeNameArrayToList(Object[][] altNameArray) { 44275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (altNameArray == null) { 44375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return null; 44475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 44575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 44675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root Collection<List<?>> coll = new ArrayList<List<?>>(altNameArray.length); 44775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root for (int i = 0; i < altNameArray.length; i++) { 44875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root coll.add(Collections.unmodifiableList(Arrays.asList(altNameArray[i]))); 44975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 45075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 45175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return Collections.unmodifiableCollection(coll); 45275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 45375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 45475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 45575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException { 45675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return alternativeNameArrayToList(NativeCrypto.get_X509_GENERAL_NAME_stack(mContext, 45775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.GN_STACK_SUBJECT_ALT_NAME)); 45875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 45975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 46075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 46175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public Collection<List<?>> getIssuerAlternativeNames() throws CertificateParsingException { 46275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return alternativeNameArrayToList(NativeCrypto.get_X509_GENERAL_NAME_stack(mContext, 46375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.GN_STACK_ISSUER_ALT_NAME)); 46475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 46575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 46675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 46775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public boolean equals(Object other) { 46875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (other instanceof OpenSSLX509Certificate) { 46975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root OpenSSLX509Certificate o = (OpenSSLX509Certificate) other; 47075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 47175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return NativeCrypto.X509_cmp(mContext, o.mContext) == 0; 47275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 47375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 47475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return super.equals(other); 47575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 47675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 47775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 47875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root public int hashCode() { 47975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root /* Make this faster since we might be in hash-based structures. */ 48075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return NativeCrypto.get_X509_hashCode(mContext); 48175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 48275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 48375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root long getContext() { 48475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root return mContext; 48575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 48675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root 48775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root @Override 48875dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root protected void finalize() throws Throwable { 48975dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root try { 49075dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root if (mContext != 0) { 49175dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root NativeCrypto.X509_free(mContext); 49275dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 49375dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } finally { 49475dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root super.finalize(); 49575dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 49675dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root } 49775dc9601af8ab3c65114e3c8c57d29ce5ac64125Kenny Root} 498