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