1 package org.bouncycastle.jcajce.provider.symmetric; 2 3 import java.io.IOException; 4 import java.security.spec.AlgorithmParameterSpec; 5 import java.security.spec.InvalidKeySpecException; 6 import java.security.spec.InvalidParameterSpecException; 7 import java.security.spec.KeySpec; 8 9 import javax.crypto.SecretKey; 10 import javax.crypto.spec.PBEKeySpec; 11 import javax.crypto.spec.PBEParameterSpec; 12 13 import org.bouncycastle.asn1.ASN1Encoding; 14 import org.bouncycastle.asn1.ASN1ObjectIdentifier; 15 import org.bouncycastle.asn1.ASN1Primitive; 16 // Android-removed: Unsupported algorithms 17 // import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; 18 import org.bouncycastle.asn1.pkcs.PBKDF2Params; 19 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 20 import org.bouncycastle.crypto.CipherParameters; 21 import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; 22 import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey; 23 import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameters; 24 import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory; 25 import org.bouncycastle.jcajce.provider.symmetric.util.PBE; 26 import org.bouncycastle.jcajce.provider.util.AlgorithmProvider; 27 import org.bouncycastle.jcajce.spec.PBKDF2KeySpec; 28 29 public class PBEPBKDF2 30 { 31 private PBEPBKDF2() 32 { 33 34 } 35 36 // BEGIN Android-removed: Unsupported algorithms 37 /* 38 public static class AlgParams 39 extends BaseAlgorithmParameters 40 { 41 PBKDF2Params params; 42 43 protected byte[] engineGetEncoded() 44 { 45 try 46 { 47 return params.getEncoded(ASN1Encoding.DER); 48 } 49 catch (IOException e) 50 { 51 throw new RuntimeException("Oooops! " + e.toString()); 52 } 53 } 54 55 protected byte[] engineGetEncoded( 56 String format) 57 { 58 if (this.isASN1FormatString(format)) 59 { 60 return engineGetEncoded(); 61 } 62 63 return null; 64 } 65 66 protected AlgorithmParameterSpec localEngineGetParameterSpec( 67 Class paramSpec) 68 throws InvalidParameterSpecException 69 { 70 if (paramSpec == PBEParameterSpec.class) 71 { 72 return new PBEParameterSpec(params.getSalt(), 73 params.getIterationCount().intValue()); 74 } 75 76 throw new InvalidParameterSpecException("unknown parameter spec passed to PBKDF2 PBE parameters object."); 77 } 78 79 protected void engineInit( 80 AlgorithmParameterSpec paramSpec) 81 throws InvalidParameterSpecException 82 { 83 if (!(paramSpec instanceof PBEParameterSpec)) 84 { 85 throw new InvalidParameterSpecException("PBEParameterSpec required to initialise a PBKDF2 PBE parameters algorithm parameters object"); 86 } 87 88 PBEParameterSpec pbeSpec = (PBEParameterSpec)paramSpec; 89 90 this.params = new PBKDF2Params(pbeSpec.getSalt(), 91 pbeSpec.getIterationCount()); 92 } 93 94 protected void engineInit( 95 byte[] params) 96 throws IOException 97 { 98 this.params = PBKDF2Params.getInstance(ASN1Primitive.fromByteArray(params)); 99 } 100 101 protected void engineInit( 102 byte[] params, 103 String format) 104 throws IOException 105 { 106 if (this.isASN1FormatString(format)) 107 { 108 engineInit(params); 109 return; 110 } 111 112 throw new IOException("Unknown parameters format in PBKDF2 parameters object"); 113 } 114 115 protected String engineToString() 116 { 117 return "PBKDF2 Parameters"; 118 } 119 } 120 */ 121 // END Android-removed: Unsupported algorithms 122 123 public static class BasePBKDF2 124 extends BaseSecretKeyFactory 125 { 126 private int scheme; 127 // BEGIN Android-added: Allow to specify a key using only the password. 128 private int keySizeInBits; 129 private int ivSizeInBits; 130 // END Android-added: Allow to specify a key using only the password. 131 private int defaultDigest; 132 133 public BasePBKDF2(String name, int scheme) 134 { 135 this(name, scheme, SHA1); 136 } 137 138 // BEGIN Android-changed: Allow to specify a key using only the password. 139 // public BasePBKDF2(String name, int scheme, int defaultDigest) 140 private BasePBKDF2( 141 String name, int scheme, int digest, int keySizeInBits, int ivSizeInBits) 142 // END Android-changed: Allow to specify a key using only the password. 143 { 144 super(name, PKCSObjectIdentifiers.id_PBKDF2); 145 146 this.scheme = scheme; 147 // BEGIN Android-added: Support key-restricted versions. 148 this.keySizeInBits = keySizeInBits; 149 this.ivSizeInBits = ivSizeInBits; 150 // END Android-added: Support key-restricted versions. 151 this.defaultDigest = digest; 152 } 153 154 // BEGIN Android-added: Allow to specify a key using only the password. 155 private BasePBKDF2(String name, int scheme, int digest) { 156 this(name, scheme, digest, 0, 0); 157 } 158 // END Android-added: Allow to specify a key using only the password. 159 160 protected SecretKey engineGenerateSecret( 161 KeySpec keySpec) 162 throws InvalidKeySpecException 163 { 164 if (keySpec instanceof PBEKeySpec) 165 { 166 PBEKeySpec pbeSpec = (PBEKeySpec)keySpec; 167 168 // BEGIN Android-added: Allow to specify a key using only the password. 169 // The key will be generated later when other parameters are known. 170 if (pbeSpec.getSalt() == null 171 && pbeSpec.getIterationCount() == 0 172 && pbeSpec.getKeyLength() == 0 173 && pbeSpec.getPassword().length > 0 174 && keySizeInBits != 0) { 175 return new BCPBEKey( 176 this.algName, this.algOid, scheme, defaultDigest, keySizeInBits, 177 ivSizeInBits, pbeSpec, 178 // cipherParameters, to be generated when the PBE parameters are known. 179 null); 180 } 181 // END Android-added: Allow to specify a key using only the password. 182 183 if (pbeSpec.getSalt() == null) 184 { 185 throw new InvalidKeySpecException("missing required salt"); 186 } 187 188 if (pbeSpec.getIterationCount() <= 0) 189 { 190 throw new InvalidKeySpecException("positive iteration count required: " 191 + pbeSpec.getIterationCount()); 192 } 193 194 if (pbeSpec.getKeyLength() <= 0) 195 { 196 throw new InvalidKeySpecException("positive key length required: " 197 + pbeSpec.getKeyLength()); 198 } 199 200 if (pbeSpec.getPassword().length == 0) 201 { 202 throw new IllegalArgumentException("password empty"); 203 } 204 205 if (pbeSpec instanceof PBKDF2KeySpec) 206 { 207 PBKDF2KeySpec spec = (PBKDF2KeySpec)pbeSpec; 208 209 int digest = getDigestCode(spec.getPrf().getAlgorithm()); 210 int keySize = pbeSpec.getKeyLength(); 211 int ivSize = -1; // JDK 1,2 and earlier does not understand simplified version. 212 CipherParameters param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize); 213 214 return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param); 215 } 216 else 217 { 218 int digest = defaultDigest; 219 int keySize = pbeSpec.getKeyLength(); 220 int ivSize = -1; // JDK 1,2 and earlier does not understand simplified version. 221 CipherParameters param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize); 222 223 return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param); 224 } 225 } 226 227 throw new InvalidKeySpecException("Invalid KeySpec"); 228 } 229 230 231 private int getDigestCode(ASN1ObjectIdentifier algorithm) 232 throws InvalidKeySpecException 233 { 234 // BEGIN Android-removed: Unsupported algorithms 235 /* 236 if (algorithm.equals(CryptoProObjectIdentifiers.gostR3411Hmac)) 237 { 238 return GOST3411; 239 } 240 else 241 */ 242 // END Android-removed: Unsupported algorithms 243 if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA1)) 244 { 245 return SHA1; 246 } 247 else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA256)) 248 { 249 return SHA256; 250 } 251 else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA224)) 252 { 253 return SHA224; 254 } 255 else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA384)) 256 { 257 return SHA384; 258 } 259 else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA512)) 260 { 261 return SHA512; 262 } 263 264 throw new InvalidKeySpecException("Invalid KeySpec: unknown PRF algorithm " + algorithm); 265 } 266 } 267 268 // BEGIN Android-removed: Unsupported algorithms 269 /* 270 public static class PBKDF2withUTF8 271 extends BasePBKDF2 272 { 273 public PBKDF2withUTF8() 274 { 275 super("PBKDF2", PKCS5S2_UTF8); 276 } 277 } 278 279 public static class PBKDF2withSHA224 280 extends BasePBKDF2 281 { 282 public PBKDF2withSHA224() 283 { 284 super("PBKDF2", PKCS5S2_UTF8, SHA224); 285 } 286 } 287 288 public static class PBKDF2withSHA256 289 extends BasePBKDF2 290 { 291 public PBKDF2withSHA256() 292 { 293 super("PBKDF2", PKCS5S2_UTF8, SHA256); 294 } 295 } 296 297 public static class PBKDF2withSHA384 298 extends BasePBKDF2 299 { 300 public PBKDF2withSHA384() 301 { 302 super("PBKDF2", PKCS5S2_UTF8, SHA384); 303 } 304 } 305 public static class PBKDF2withSHA512 306 extends BasePBKDF2 307 { 308 public PBKDF2withSHA512() 309 { 310 super("PBKDF2", PKCS5S2_UTF8, SHA512); 311 } 312 } 313 314 public static class PBKDF2with8BIT 315 extends BasePBKDF2 316 { 317 public PBKDF2with8BIT() 318 { 319 super("PBKDF2", PKCS5S2); 320 } 321 } 322 */ 323 // END Android-removed: Unsupported algorithms 324 325 // BEGIN Android-added: Android implementations of PBKDF2 algorithms. 326 // See note in Mappings below. 327 public static class BasePBKDF2WithHmacSHA1 extends BasePBKDF2 { 328 public BasePBKDF2WithHmacSHA1(String name, int scheme) 329 { 330 super(name, scheme, SHA1); 331 } 332 } 333 334 public static class PBKDF2WithHmacSHA1UTF8 335 extends BasePBKDF2WithHmacSHA1 336 { 337 public PBKDF2WithHmacSHA1UTF8() 338 { 339 super("PBKDF2WithHmacSHA1", PKCS5S2_UTF8); 340 } 341 } 342 343 public static class PBKDF2WithHmacSHA18BIT 344 extends BasePBKDF2WithHmacSHA1 345 { 346 public PBKDF2WithHmacSHA18BIT() 347 { 348 super("PBKDF2WithHmacSHA1And8bit", PKCS5S2); 349 } 350 } 351 352 public static class BasePBKDF2WithHmacSHA224 extends BasePBKDF2 { 353 public BasePBKDF2WithHmacSHA224(String name, int scheme) 354 { 355 super(name, scheme, SHA224); 356 } 357 } 358 359 public static class PBKDF2WithHmacSHA224UTF8 360 extends BasePBKDF2WithHmacSHA224 361 { 362 public PBKDF2WithHmacSHA224UTF8() 363 { 364 super("PBKDF2WithHmacSHA224", PKCS5S2_UTF8); 365 } 366 } 367 368 public static class BasePBKDF2WithHmacSHA256 extends BasePBKDF2 { 369 public BasePBKDF2WithHmacSHA256(String name, int scheme) 370 { 371 super(name, scheme, SHA256); 372 } 373 } 374 375 public static class PBKDF2WithHmacSHA256UTF8 376 extends BasePBKDF2WithHmacSHA256 377 { 378 public PBKDF2WithHmacSHA256UTF8() 379 { 380 super("PBKDF2WithHmacSHA256", PKCS5S2_UTF8); 381 } 382 } 383 384 385 public static class BasePBKDF2WithHmacSHA384 extends BasePBKDF2 { 386 public BasePBKDF2WithHmacSHA384(String name, int scheme) 387 { 388 super(name, scheme, SHA384); 389 } 390 } 391 392 public static class PBKDF2WithHmacSHA384UTF8 393 extends BasePBKDF2WithHmacSHA384 394 { 395 public PBKDF2WithHmacSHA384UTF8() 396 { 397 super("PBKDF2WithHmacSHA384", PKCS5S2_UTF8); 398 } 399 } 400 401 public static class BasePBKDF2WithHmacSHA512 extends BasePBKDF2 { 402 public BasePBKDF2WithHmacSHA512(String name, int scheme) 403 { 404 super(name, scheme, SHA512); 405 } 406 } 407 408 public static class PBKDF2WithHmacSHA512UTF8 409 extends BasePBKDF2WithHmacSHA512 410 { 411 public PBKDF2WithHmacSHA512UTF8() 412 { 413 super("PBKDF2WithHmacSHA512", PKCS5S2_UTF8); 414 } 415 } 416 417 public static class PBEWithHmacSHA1AndAES_128 418 extends BasePBKDF2 { 419 public PBEWithHmacSHA1AndAES_128() { 420 super("PBEWithHmacSHA1AndAES_128", PKCS5S2_UTF8, SHA1, 128, 128); 421 } 422 } 423 424 public static class PBEWithHmacSHA224AndAES_128 425 extends BasePBKDF2 { 426 public PBEWithHmacSHA224AndAES_128() { 427 super("PBEWithHmacSHA224AndAES_128", PKCS5S2_UTF8, SHA224, 128, 128); 428 } 429 } 430 431 public static class PBEWithHmacSHA256AndAES_128 432 extends BasePBKDF2 { 433 public PBEWithHmacSHA256AndAES_128() { 434 super("PBEWithHmacSHA256AndAES_128", PKCS5S2_UTF8, SHA256, 128, 128); 435 } 436 } 437 438 public static class PBEWithHmacSHA384AndAES_128 439 extends BasePBKDF2 { 440 public PBEWithHmacSHA384AndAES_128() { 441 super("PBEWithHmacSHA384AndAES_128", PKCS5S2_UTF8, SHA384, 128, 128); 442 } 443 } 444 445 public static class PBEWithHmacSHA512AndAES_128 446 extends BasePBKDF2 { 447 public PBEWithHmacSHA512AndAES_128() { 448 super("PBEWithHmacSHA512AndAES_128", PKCS5S2_UTF8, SHA512, 128, 128); 449 } 450 } 451 452 453 public static class PBEWithHmacSHA1AndAES_256 454 extends BasePBKDF2 { 455 public PBEWithHmacSHA1AndAES_256() { 456 super("PBEWithHmacSHA1AndAES_256", PKCS5S2_UTF8, SHA1, 256, 128); 457 } 458 } 459 460 public static class PBEWithHmacSHA224AndAES_256 461 extends BasePBKDF2 { 462 public PBEWithHmacSHA224AndAES_256() { 463 super("PBEWithHmacSHA224AndAES_256", PKCS5S2_UTF8, SHA224, 256, 128); 464 } 465 } 466 467 public static class PBEWithHmacSHA256AndAES_256 468 extends BasePBKDF2 { 469 public PBEWithHmacSHA256AndAES_256() { 470 super("PBEWithHmacSHA256AndAES_256", PKCS5S2_UTF8, SHA256, 256, 128); 471 } 472 } 473 474 public static class PBEWithHmacSHA384AndAES_256 475 extends BasePBKDF2 { 476 public PBEWithHmacSHA384AndAES_256() { 477 super("PBEWithHmacSHA384AndAES_256", PKCS5S2_UTF8, SHA384, 256, 128); 478 } 479 } 480 481 public static class PBEWithHmacSHA512AndAES_256 482 extends BasePBKDF2 { 483 public PBEWithHmacSHA512AndAES_256() { 484 super("PBEWithHmacSHA512AndAES_256", PKCS5S2_UTF8, SHA512, 256, 128); 485 } 486 } 487 // END Android-added: Android implementations of PBKDF2 algorithms. 488 489 public static class Mappings 490 extends AlgorithmProvider 491 { 492 private static final String PREFIX = PBEPBKDF2.class.getName(); 493 494 public Mappings() 495 { 496 } 497 498 public void configure(ConfigurableProvider provider) 499 { 500 // Android-note: Provided classes differ significantly from upstream. 501 // Before BC 1.56, this class was omitted in Android and the algorithms we desired 502 // were provided in org.bouncycastle.jcajce.provider.digest.SHA1. During that 503 // time, Android added some additional versions of these algorithms for fixed key sizes. 504 // BC eventually consolidated the algorithms into this class. As a result, when 505 // upgrading to BC 1.56, we added this class but replaced its contents with 506 // our versions. 507 // BEGIN Android-removed: Bouncy Castle versions of algorithms. 508 /* 509 provider.addAlgorithm("AlgorithmParameters.PBKDF2", PREFIX + "$AlgParams"); 510 provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2"); 511 provider.addAlgorithm("SecretKeyFactory.PBKDF2", PREFIX + "$PBKDF2withUTF8"); 512 provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WITHHMACSHA1", "PBKDF2"); 513 provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WITHHMACSHA1ANDUTF8", "PBKDF2"); 514 provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2"); 515 provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHASCII", PREFIX + "$PBKDF2with8BIT"); 516 provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WITH8BIT", "PBKDF2WITHASCII"); 517 provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WITHHMACSHA1AND8BIT", "PBKDF2WITHASCII"); 518 provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA224", PREFIX + "$PBKDF2withSHA224"); 519 provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA256", PREFIX + "$PBKDF2withSHA256"); 520 provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA384", PREFIX + "$PBKDF2withSHA384"); 521 provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA512", PREFIX + "$PBKDF2withSHA512"); 522 */ 523 // END Android-removed: Bouncy Castle versions of algorithms. 524 // BEGIN Android-added: Android versions of algorithms. 525 provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WithHmacSHA1AndUTF8", "PBKDF2WithHmacSHA1"); 526 provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2with8BIT", "PBKDF2WithHmacSHA1And8BIT"); 527 provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2withASCII", "PBKDF2WithHmacSHA1And8BIT"); 528 provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1", PREFIX + "$PBKDF2WithHmacSHA1UTF8"); 529 provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA224", PREFIX + "$PBKDF2WithHmacSHA224UTF8"); 530 provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA256", PREFIX + "$PBKDF2WithHmacSHA256UTF8"); 531 provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA384", PREFIX + "$PBKDF2WithHmacSHA384UTF8"); 532 provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA512", PREFIX + "$PBKDF2WithHmacSHA512UTF8"); 533 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA1AndAES_128", PREFIX + "$PBEWithHmacSHA1AndAES_128"); 534 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA224AndAES_128", PREFIX + "$PBEWithHmacSHA224AndAES_128"); 535 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA256AndAES_128", PREFIX + "$PBEWithHmacSHA256AndAES_128"); 536 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA384AndAES_128", PREFIX + "$PBEWithHmacSHA384AndAES_128"); 537 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA512AndAES_128", PREFIX + "$PBEWithHmacSHA512AndAES_128"); 538 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA1AndAES_256", PREFIX + "$PBEWithHmacSHA1AndAES_256"); 539 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA224AndAES_256", PREFIX + "$PBEWithHmacSHA224AndAES_256"); 540 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA256AndAES_256", PREFIX + "$PBEWithHmacSHA256AndAES_256"); 541 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA384AndAES_256", PREFIX + "$PBEWithHmacSHA384AndAES_256"); 542 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA512AndAES_256", PREFIX + "$PBEWithHmacSHA512AndAES_256"); 543 provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1And8BIT", PREFIX + "$PBKDF2WithHmacSHA18BIT"); 544 // END Android-added: Android versions of algorithms. 545 } 546 } 547 } 548