1 package org.bouncycastle.jcajce;
2 
3 import java.io.InputStream;
4 import java.io.OutputStream;
5 import java.security.Key;
6 import java.security.KeyStore;
7 import java.security.PrivateKey;
8 import java.security.PublicKey;
9 import java.security.cert.X509Certificate;
10 
11 import org.bouncycastle.crypto.util.PBKDF2Config;
12 import org.bouncycastle.crypto.util.PBKDFConfig;
13 
14 /**
15  * LoadStoreParameter to allow configuring of the PBKDF used to generate encryption keys for
16  * use in the keystore.
17  */
18 public class BCFKSLoadStoreParameter
19     extends BCLoadStoreParameter
20 {
21     public enum EncryptionAlgorithm
22     {
23         AES256_CCM,
24         AES256_KWP
25     }
26 
27     public enum MacAlgorithm
28     {
29         HmacSHA512,
30         HmacSHA3_512
31     }
32 
33     public enum SignatureAlgorithm
34     {
35         SHA512withDSA,
36         SHA3_512withDSA,
37         SHA512withECDSA,
38         SHA3_512withECDSA,
39         SHA512withRSA,
40         SHA3_512withRSA
41     }
42 
43     public interface CertChainValidator
44     {
45         /**
46          * Return true if the passed in chain is valid, false otherwise.
47          *
48          * @param chain the certChain we know about, the end-entity is at position 0.
49          * @return true if valid, false otherwise.
50          */
isValid(X509Certificate[] chain)51          boolean isValid(X509Certificate[] chain);
52     }
53 
54     public static class Builder
55     {
56         private final OutputStream out;
57         private final InputStream in;
58         private final KeyStore.ProtectionParameter protectionParameter;
59         private final Key sigKey;
60 
61         private PBKDFConfig storeConfig = new PBKDF2Config.Builder()
62                                                 .withIterationCount(16384)
63                                                 .withSaltLength(64).withPRF(PBKDF2Config.PRF_SHA512).build();
64         private EncryptionAlgorithm encAlg = EncryptionAlgorithm.AES256_CCM;
65         private MacAlgorithm macAlg = MacAlgorithm.HmacSHA512;
66         private SignatureAlgorithm sigAlg = SignatureAlgorithm.SHA512withECDSA;
67         private X509Certificate[] certs = null;
68         private CertChainValidator validator;
69 
70 
71         /**
72          * Base constructor for creating a LoadStoreParameter for initializing a key store.
73          */
Builder()74         public Builder()
75         {
76             this((OutputStream)null, (KeyStore.ProtectionParameter)null);
77         }
78 
79         /**
80          * Base constructor for storing to an OutputStream using a password.
81          *
82          * @param out OutputStream to write KeyStore to.
83          * @param password the password to use to protect the KeyStore.
84          */
Builder(OutputStream out, char[] password)85         public Builder(OutputStream out, char[] password)
86         {
87             this(out, new KeyStore.PasswordProtection(password));
88         }
89 
90         /**
91          * Base constructor for storing to an OutputStream using a protection parameter.
92          *
93          * @param out OutputStream to write KeyStore to.
94          * @param protectionParameter the protection parameter to use to protect the KeyStore.
95          */
Builder(OutputStream out, KeyStore.ProtectionParameter protectionParameter)96         public Builder(OutputStream out, KeyStore.ProtectionParameter protectionParameter)
97         {
98             this.in = null;
99             this.out = out;
100             this.protectionParameter = protectionParameter;
101             this.sigKey = null;
102         }
103 
104         /**
105          * Base constructor for storing to an OutputStream using a protection parameter.
106          *
107          * @param out OutputStream to write KeyStore to.
108          * @param sigKey the key used to protect the integrity of the key store.
109          */
Builder(OutputStream out, PrivateKey sigKey)110         public Builder(OutputStream out, PrivateKey sigKey)
111         {
112             this.in = null;
113             this.out = out;
114             this.protectionParameter = null;
115             this.sigKey = sigKey;
116         }
117 
118         /**
119          * Base constructor for reading a KeyStore from an InputStream using a public key for validation.
120          *
121          * @param in InputStream to load KeyStore to.
122          * @param sigKey the public key parameter to used to verify the KeyStore.
123          */
Builder(InputStream in, PublicKey sigKey)124         public Builder(InputStream in, PublicKey sigKey)
125         {
126             this.in = in;
127             this.out = null;
128             this.protectionParameter = null;
129             this.sigKey = sigKey;
130         }
131 
132         /**
133          * Base constructor for reading a KeyStore from an InputStream using validation based on
134          * encapsulated certificates in the KeyStore data.
135          *
136          * @param in InputStream to load KeyStore to.
137          * @param validator the certificate chain validator to check the signing certificates.
138          */
Builder(InputStream in, CertChainValidator validator)139         public Builder(InputStream in, CertChainValidator validator)
140         {
141             this.in = in;
142             this.out = null;
143             this.protectionParameter = null;
144             this.validator = validator;
145             this.sigKey = null;
146         }
147 
148         /**
149          * Base constructor for reading a KeyStore from an InputStream using a password.
150          *
151          * @param in InputStream to read the KeyStore from.
152          * @param password the password used to protect the KeyStore.
153          */
Builder(InputStream in, char[] password)154         public Builder(InputStream in, char[] password)
155         {
156             this(in, new KeyStore.PasswordProtection(password));
157         }
158 
159         /**
160          * Base constructor for reading a KeyStore from an InputStream using a password.
161          *
162          * @param in InputStream to read the KeyStore from.
163          * @param protectionParameter  the protection parameter used to protect the KeyStore.
164          */
Builder(InputStream in, KeyStore.ProtectionParameter protectionParameter)165         public Builder(InputStream in, KeyStore.ProtectionParameter protectionParameter)
166         {
167             this.in = in;
168             this.out = null;
169             this.protectionParameter = protectionParameter;
170             this.sigKey = null;
171         }
172 
173         /**
174          * Configure the PBKDF to use for protecting the KeyStore.
175          *
176          * @param storeConfig the PBKDF config to use for protecting the KeyStore.
177          * @return the current Builder instance.
178          */
withStorePBKDFConfig(PBKDFConfig storeConfig)179         public Builder withStorePBKDFConfig(PBKDFConfig storeConfig)
180         {
181             this.storeConfig = storeConfig;
182             return this;
183         }
184 
185         /**
186          * Configure the encryption algorithm to use for protecting the KeyStore and its keys.
187          *
188          * @param encAlg the PBKDF config to use for protecting the KeyStore and its keys.
189          * @return the current Builder instance.
190          */
withStoreEncryptionAlgorithm(EncryptionAlgorithm encAlg)191         public Builder withStoreEncryptionAlgorithm(EncryptionAlgorithm encAlg)
192         {
193             this.encAlg = encAlg;
194             return this;
195         }
196 
197         /**
198          * Configure the MAC algorithm to use for protecting the KeyStore.
199          *
200          * @param macAlg the PBKDF config to use for protecting the KeyStore.
201          * @return the current Builder instance.
202          */
withStoreMacAlgorithm(MacAlgorithm macAlg)203         public Builder withStoreMacAlgorithm(MacAlgorithm macAlg)
204         {
205             this.macAlg = macAlg;
206             return this;
207         }
208 
209 
210         /**
211          * Add a valid certificate chain where certs[0] is the end-entity matching the
212          * private key we are using to sign the key store.
213          *
214          * @param certs an array of X509 certificates.
215          * @return the current Builder instance.
216          */
withCertificates(X509Certificate[] certs)217         public Builder withCertificates(X509Certificate[] certs)
218         {
219             X509Certificate[] tmp = new X509Certificate[certs.length];
220             System.arraycopy(certs, 0, tmp, 0, tmp.length);
221             this.certs = tmp;
222 
223             return this;
224         }
225 
226         /**
227          * Configure the signature algorithm to use for protecting the KeyStore.
228          *
229          * @param sigAlg the signature config to use for protecting the KeyStore.
230          * @return the current Builder instance.
231          */
withStoreSignatureAlgorithm(SignatureAlgorithm sigAlg)232         public Builder withStoreSignatureAlgorithm(SignatureAlgorithm sigAlg)
233         {
234             this.sigAlg = sigAlg;
235 
236             return this;
237         }
238 
239         /**
240          * Build and return a BCFKSLoadStoreParameter.
241          *
242          * @return a new BCFKSLoadStoreParameter.
243          */
build()244         public BCFKSLoadStoreParameter build()
245         {
246             return new BCFKSLoadStoreParameter(this);
247         }
248     }
249 
250     private final PBKDFConfig storeConfig;
251     private final EncryptionAlgorithm encAlg;
252     private final MacAlgorithm macAlg;
253     private final SignatureAlgorithm sigAlg;
254     private final Key sigKey;
255     private final X509Certificate[] certificates;
256     private final CertChainValidator validator;
257 
BCFKSLoadStoreParameter(Builder bldr)258     private BCFKSLoadStoreParameter(Builder bldr)
259     {
260         super(bldr.in, bldr.out, bldr.protectionParameter);
261 
262         this.storeConfig = bldr.storeConfig;
263         this.encAlg = bldr.encAlg;
264         this.macAlg = bldr.macAlg;
265         this.sigAlg = bldr.sigAlg;
266         this.sigKey = bldr.sigKey;
267         this.certificates = bldr.certs;
268         this.validator = bldr.validator;
269     }
270 
271     /**
272      * Return the PBKDF used for generating the HMAC and store encryption keys.
273      *
274      * @return the PBKDF to use for deriving HMAC and store encryption keys.
275      */
getStorePBKDFConfig()276     public PBKDFConfig getStorePBKDFConfig()
277     {
278         return storeConfig;
279     }
280 
281     /**
282      * Return encryption algorithm used to secure the store and its entries.
283      *
284      * @return the encryption algorithm to use.
285      */
getStoreEncryptionAlgorithm()286     public EncryptionAlgorithm getStoreEncryptionAlgorithm()
287     {
288         return encAlg;
289     }
290 
291     /**
292      * Return mac algorithm used to protect the integrity of the store and its contents.
293      *
294      * @return the mac algorithm to use.
295      */
getStoreMacAlgorithm()296     public MacAlgorithm getStoreMacAlgorithm()
297     {
298         return macAlg;
299     }
300 
301     /**
302      * Return signature algorithm used to protect the integrity of the store and its contents.
303      *
304      * @return the signature algorithm to use.
305      */
getStoreSignatureAlgorithm()306     public SignatureAlgorithm getStoreSignatureAlgorithm()
307     {
308         return sigAlg;
309     }
310 
getStoreSignatureKey()311     public Key getStoreSignatureKey()
312     {
313         return sigKey;
314     }
315 
getStoreCertificates()316     public X509Certificate[] getStoreCertificates()
317     {
318         return certificates;
319     }
320 
getCertChainValidator()321     public CertChainValidator getCertChainValidator()
322     {
323         return validator;
324     }
325 }
326