• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.conscrypt;
18 
19 import java.io.ByteArrayOutputStream;
20 import java.math.BigInteger;
21 import java.security.cert.CRLException;
22 import java.security.cert.X509CRLEntry;
23 import java.util.Arrays;
24 import java.util.Date;
25 import java.util.HashSet;
26 import java.util.Set;
27 import org.conscrypt.OpenSSLX509CertificateFactory.ParsingException;
28 
29 /**
30  * An implementation of {@link X509CRLEntry} based on BoringSSL.
31  */
32 final class OpenSSLX509CRLEntry extends X509CRLEntry {
33     private final long mContext;
34     private final Date revocationDate;
35 
OpenSSLX509CRLEntry(long ctx)36     OpenSSLX509CRLEntry(long ctx) throws ParsingException {
37         mContext = ctx;
38         // The legacy X509 OpenSSL APIs don't validate ASN1_TIME structures until access, so
39         // parse them here because this is the only time we're allowed to throw ParsingException
40         revocationDate = OpenSSLX509CRL.toDate(NativeCrypto.get_X509_REVOKED_revocationDate(mContext));
41     }
42 
43     @Override
getCriticalExtensionOIDs()44     public Set<String> getCriticalExtensionOIDs() {
45         String[] critOids =
46                 NativeCrypto.get_X509_REVOKED_ext_oids(mContext,
47                         NativeCrypto.EXTENSION_TYPE_CRITICAL);
48 
49         /*
50          * This API has a special case that if there are no extensions, we
51          * should return null. So if we have no critical extensions, we'll check
52          * non-critical extensions.
53          */
54         if ((critOids.length == 0)
55                 && (NativeCrypto.get_X509_REVOKED_ext_oids(mContext,
56                         NativeCrypto.EXTENSION_TYPE_NON_CRITICAL).length == 0)) {
57             return null;
58         }
59 
60         return new HashSet<String>(Arrays.asList(critOids));
61     }
62 
63     @Override
getExtensionValue(String oid)64     public byte[] getExtensionValue(String oid) {
65         return NativeCrypto.X509_REVOKED_get_ext_oid(mContext, oid);
66     }
67 
68     @Override
getNonCriticalExtensionOIDs()69     public Set<String> getNonCriticalExtensionOIDs() {
70         String[] critOids =
71                 NativeCrypto.get_X509_REVOKED_ext_oids(mContext,
72                         NativeCrypto.EXTENSION_TYPE_NON_CRITICAL);
73 
74         /*
75          * This API has a special case that if there are no extensions, we
76          * should return null. So if we have no non-critical extensions, we'll
77          * check critical extensions.
78          */
79         if ((critOids.length == 0)
80                 && (NativeCrypto.get_X509_REVOKED_ext_oids(mContext,
81                         NativeCrypto.EXTENSION_TYPE_CRITICAL).length == 0)) {
82             return null;
83         }
84 
85         return new HashSet<String>(Arrays.asList(critOids));
86     }
87 
88     @Override
hasUnsupportedCriticalExtension()89     public boolean hasUnsupportedCriticalExtension() {
90         final String[] criticalOids =
91                 NativeCrypto.get_X509_REVOKED_ext_oids(mContext,
92                         NativeCrypto.EXTENSION_TYPE_CRITICAL);
93         for (String oid : criticalOids) {
94             final long extensionRef = NativeCrypto.X509_REVOKED_get_ext(mContext, oid);
95             if (NativeCrypto.X509_supported_extension(extensionRef) != 1) {
96                 return true;
97             }
98         }
99 
100         return false;
101     }
102 
103     @Override
getEncoded()104     public byte[] getEncoded() throws CRLException {
105         return NativeCrypto.i2d_X509_REVOKED(mContext);
106     }
107 
108     @Override
getSerialNumber()109     public BigInteger getSerialNumber() {
110         return new BigInteger(NativeCrypto.X509_REVOKED_get_serialNumber(mContext));
111     }
112 
113     @Override
getRevocationDate()114     public Date getRevocationDate() {
115         return (Date) revocationDate.clone();
116     }
117 
118     @Override
hasExtensions()119     public boolean hasExtensions() {
120         return (NativeCrypto.get_X509_REVOKED_ext_oids(mContext,
121                 NativeCrypto.EXTENSION_TYPE_NON_CRITICAL).length != 0)
122                 || (NativeCrypto.get_X509_REVOKED_ext_oids(mContext,
123                         NativeCrypto.EXTENSION_TYPE_CRITICAL).length != 0);
124     }
125 
126     @Override
toString()127     public String toString() {
128         ByteArrayOutputStream os = new ByteArrayOutputStream();
129         long bioCtx = NativeCrypto.create_BIO_OutputStream(os);
130         try {
131             NativeCrypto.X509_REVOKED_print(bioCtx, mContext);
132             return os.toString();
133         } finally {
134             NativeCrypto.BIO_free_all(bioCtx);
135         }
136     }
137 }
138