1 package org.bouncycastle.cert;
2 
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.text.ParseException;
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.Collections;
9 import java.util.Date;
10 import java.util.HashSet;
11 import java.util.List;
12 import java.util.Set;
13 
14 import org.bouncycastle.asn1.ASN1Encodable;
15 import org.bouncycastle.asn1.ASN1EncodableVector;
16 import org.bouncycastle.asn1.ASN1GeneralizedTime;
17 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
18 import org.bouncycastle.asn1.DERBitString;
19 import org.bouncycastle.asn1.DERNull;
20 import org.bouncycastle.asn1.DEROutputStream;
21 import org.bouncycastle.asn1.DERSequence;
22 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
23 import org.bouncycastle.asn1.x509.AttributeCertificate;
24 import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
25 import org.bouncycastle.asn1.x509.Certificate;
26 import org.bouncycastle.asn1.x509.CertificateList;
27 import org.bouncycastle.asn1.x509.Extensions;
28 import org.bouncycastle.asn1.x509.ExtensionsGenerator;
29 import org.bouncycastle.asn1.x509.TBSCertList;
30 import org.bouncycastle.asn1.x509.TBSCertificate;
31 import org.bouncycastle.operator.ContentSigner;
32 
33 class CertUtils
34 {
35     private static Set EMPTY_SET = Collections.unmodifiableSet(new HashSet());
36     private static List EMPTY_LIST = Collections.unmodifiableList(new ArrayList());
37 
generateFullCert(ContentSigner signer, TBSCertificate tbsCert)38     static X509CertificateHolder generateFullCert(ContentSigner signer, TBSCertificate tbsCert)
39     {
40         try
41         {
42             return new X509CertificateHolder(generateStructure(tbsCert, signer.getAlgorithmIdentifier(), generateSig(signer, tbsCert)));
43         }
44         catch (IOException e)
45         {
46             throw new IllegalStateException("cannot produce certificate signature");
47         }
48     }
49 
generateFullAttrCert(ContentSigner signer, AttributeCertificateInfo attrInfo)50     static X509AttributeCertificateHolder generateFullAttrCert(ContentSigner signer, AttributeCertificateInfo attrInfo)
51     {
52         try
53         {
54             return new X509AttributeCertificateHolder(generateAttrStructure(attrInfo, signer.getAlgorithmIdentifier(), generateSig(signer, attrInfo)));
55         }
56         catch (IOException e)
57         {
58             throw new IllegalStateException("cannot produce attribute certificate signature");
59         }
60     }
61 
generateFullCRL(ContentSigner signer, TBSCertList tbsCertList)62     static X509CRLHolder generateFullCRL(ContentSigner signer, TBSCertList tbsCertList)
63     {
64         try
65         {
66             return new X509CRLHolder(generateCRLStructure(tbsCertList, signer.getAlgorithmIdentifier(), generateSig(signer, tbsCertList)));
67         }
68         catch (IOException e)
69         {
70             throw new IllegalStateException("cannot produce certificate signature");
71         }
72     }
73 
generateSig(ContentSigner signer, ASN1Encodable tbsObj)74     private static byte[] generateSig(ContentSigner signer, ASN1Encodable tbsObj)
75         throws IOException
76     {
77         OutputStream sOut = signer.getOutputStream();
78         DEROutputStream dOut = new DEROutputStream(sOut);
79 
80         dOut.writeObject(tbsObj);
81 
82         sOut.close();
83 
84         return signer.getSignature();
85     }
86 
generateStructure(TBSCertificate tbsCert, AlgorithmIdentifier sigAlgId, byte[] signature)87     private static Certificate generateStructure(TBSCertificate tbsCert, AlgorithmIdentifier sigAlgId, byte[] signature)
88     {
89         ASN1EncodableVector v = new ASN1EncodableVector();
90 
91         v.add(tbsCert);
92         v.add(sigAlgId);
93         v.add(new DERBitString(signature));
94 
95         return Certificate.getInstance(new DERSequence(v));
96     }
97 
generateAttrStructure(AttributeCertificateInfo attrInfo, AlgorithmIdentifier sigAlgId, byte[] signature)98     private static AttributeCertificate generateAttrStructure(AttributeCertificateInfo attrInfo, AlgorithmIdentifier sigAlgId, byte[] signature)
99     {
100         ASN1EncodableVector v = new ASN1EncodableVector();
101 
102         v.add(attrInfo);
103         v.add(sigAlgId);
104         v.add(new DERBitString(signature));
105 
106         return AttributeCertificate.getInstance(new DERSequence(v));
107     }
108 
generateCRLStructure(TBSCertList tbsCertList, AlgorithmIdentifier sigAlgId, byte[] signature)109     private static CertificateList generateCRLStructure(TBSCertList tbsCertList, AlgorithmIdentifier sigAlgId, byte[] signature)
110     {
111         ASN1EncodableVector v = new ASN1EncodableVector();
112 
113         v.add(tbsCertList);
114         v.add(sigAlgId);
115         v.add(new DERBitString(signature));
116 
117         return CertificateList.getInstance(new DERSequence(v));
118     }
119 
getCriticalExtensionOIDs(Extensions extensions)120     static Set getCriticalExtensionOIDs(Extensions extensions)
121     {
122         if (extensions == null)
123         {
124             return EMPTY_SET;
125         }
126 
127         return Collections.unmodifiableSet(new HashSet(Arrays.asList(extensions.getCriticalExtensionOIDs())));
128     }
129 
getNonCriticalExtensionOIDs(Extensions extensions)130     static Set getNonCriticalExtensionOIDs(Extensions extensions)
131     {
132         if (extensions == null)
133         {
134             return EMPTY_SET;
135         }
136 
137         // TODO: should probably produce a set that imposes correct ordering
138         return Collections.unmodifiableSet(new HashSet(Arrays.asList(extensions.getNonCriticalExtensionOIDs())));
139     }
140 
getExtensionOIDs(Extensions extensions)141     static List getExtensionOIDs(Extensions extensions)
142     {
143         if (extensions == null)
144         {
145             return EMPTY_LIST;
146         }
147 
148         return Collections.unmodifiableList(Arrays.asList(extensions.getExtensionOIDs()));
149     }
150 
addExtension(ExtensionsGenerator extGenerator, ASN1ObjectIdentifier oid, boolean isCritical, ASN1Encodable value)151     static void addExtension(ExtensionsGenerator extGenerator, ASN1ObjectIdentifier oid, boolean isCritical, ASN1Encodable value)
152         throws CertIOException
153     {
154         try
155         {
156             extGenerator.addExtension(oid, isCritical, value);
157         }
158         catch (IOException e)
159         {
160             throw new CertIOException("cannot encode extension: " + e.getMessage(), e);
161         }
162     }
163 
booleanToBitString(boolean[] id)164     static DERBitString booleanToBitString(boolean[] id)
165     {
166         byte[] bytes = new byte[(id.length + 7) / 8];
167 
168         for (int i = 0; i != id.length; i++)
169         {
170             bytes[i / 8] |= (id[i]) ? (1 << ((7 - (i % 8)))) : 0;
171         }
172 
173         int pad = id.length % 8;
174 
175         if (pad == 0)
176         {
177             return new DERBitString(bytes);
178         }
179         else
180         {
181             return new DERBitString(bytes, 8 - pad);
182         }
183     }
184 
bitStringToBoolean(DERBitString bitString)185     static boolean[] bitStringToBoolean(DERBitString bitString)
186     {
187         if (bitString != null)
188         {
189             byte[]          bytes = bitString.getBytes();
190             boolean[]       boolId = new boolean[bytes.length * 8 - bitString.getPadBits()];
191 
192             for (int i = 0; i != boolId.length; i++)
193             {
194                 boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
195             }
196 
197             return boolId;
198         }
199 
200         return null;
201     }
202 
recoverDate(ASN1GeneralizedTime time)203     static Date recoverDate(ASN1GeneralizedTime time)
204     {
205         try
206         {
207             return time.getDate();
208         }
209         catch (ParseException e)
210         {
211             throw new IllegalStateException("unable to recover date: " + e.getMessage());
212         }
213     }
214 
isAlgIdEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2)215     static boolean isAlgIdEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2)
216     {
217         if (!id1.getAlgorithm().equals(id2.getAlgorithm()))
218         {
219             return false;
220         }
221 
222         if (id1.getParameters() == null)
223         {
224             if (id2.getParameters() != null && !id2.getParameters().equals(DERNull.INSTANCE))
225             {
226                 return false;
227             }
228 
229             return true;
230         }
231 
232         if (id2.getParameters() == null)
233         {
234             if (id1.getParameters() != null && !id1.getParameters().equals(DERNull.INSTANCE))
235             {
236                 return false;
237             }
238 
239             return true;
240         }
241 
242         return id1.getParameters().equals(id2.getParameters());
243     }
244 }
245