|
1 | 1 | /* |
2 | | - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | 4 | * |
5 | 5 | * This code is free software; you can redistribute it and/or modify it |
|
32 | 32 | import java.security.spec.InvalidParameterSpecException; |
33 | 33 | import javax.crypto.spec.IvParameterSpec; |
34 | 34 | import javax.crypto.spec.PBEParameterSpec; |
| 35 | +import sun.security.util.PBKDF2Parameters; |
35 | 36 | import sun.security.util.*; |
36 | 37 |
|
37 | 38 | /** |
|
93 | 94 | abstract class PBES2Parameters extends AlgorithmParametersSpi { |
94 | 95 |
|
95 | 96 | private static final ObjectIdentifier pkcs5PBKDF2_OID = |
96 | | - ObjectIdentifier.of(KnownOIDs.PBKDF2WithHmacSHA1); |
| 97 | + ObjectIdentifier.of(KnownOIDs.PBKDF2); |
97 | 98 | private static final ObjectIdentifier pkcs5PBES2_OID = |
98 | 99 | ObjectIdentifier.of(KnownOIDs.PBES2); |
99 | 100 | private static final ObjectIdentifier aes128CBC_OID = |
@@ -224,77 +225,32 @@ protected void engineInit(byte[] encoded) |
224 | 225 | // next DerValue as the real PBES2-params. |
225 | 226 | if (kdf.getTag() == DerValue.tag_ObjectId) { |
226 | 227 | pBES2_params = pBES2_params.data.getDerValue(); |
| 228 | + if (pBES2_params.tag != DerValue.tag_Sequence) { |
| 229 | + throw new IOException("PBE parameter parsing error: " |
| 230 | + + "not an ASN.1 SEQUENCE tag"); |
| 231 | + } |
227 | 232 | kdf = pBES2_params.data.getDerValue(); |
228 | 233 | } |
229 | 234 |
|
230 | | - String kdfAlgo = parseKDF(kdf); |
231 | | - |
232 | | - if (pBES2_params.tag != DerValue.tag_Sequence) { |
233 | | - throw new IOException("PBE parameter parsing error: " |
234 | | - + "not an ASN.1 SEQUENCE tag"); |
235 | | - } |
236 | | - String cipherAlgo = parseES(pBES2_params.data.getDerValue()); |
237 | | - |
238 | | - this.pbes2AlgorithmName = "PBEWith" + kdfAlgo + "And" + cipherAlgo; |
239 | | - } |
240 | | - |
241 | | - private String parseKDF(DerValue keyDerivationFunc) throws IOException { |
242 | | - |
243 | | - if (!pkcs5PBKDF2_OID.equals(keyDerivationFunc.data.getOID())) { |
| 235 | + if (!pkcs5PBKDF2_OID.equals(kdf.data.getOID())) { |
244 | 236 | throw new IOException("PBE parameter parsing error: " |
245 | 237 | + "expecting the object identifier for PBKDF2"); |
246 | 238 | } |
247 | | - if (keyDerivationFunc.tag != DerValue.tag_Sequence) { |
| 239 | + if (kdf.tag != DerValue.tag_Sequence) { |
248 | 240 | throw new IOException("PBE parameter parsing error: " |
249 | 241 | + "not an ASN.1 SEQUENCE tag"); |
250 | 242 | } |
251 | | - DerValue pBKDF2_params = keyDerivationFunc.data.getDerValue(); |
252 | | - if (pBKDF2_params.tag != DerValue.tag_Sequence) { |
253 | | - throw new IOException("PBE parameter parsing error: " |
254 | | - + "not an ASN.1 SEQUENCE tag"); |
255 | | - } |
256 | | - DerValue specified = pBKDF2_params.data.getDerValue(); |
257 | | - // the 'specified' ASN.1 CHOICE for 'salt' is supported |
258 | | - if (specified.tag == DerValue.tag_OctetString) { |
259 | | - salt = specified.getOctetString(); |
260 | | - } else { |
261 | | - // the 'otherSource' ASN.1 CHOICE for 'salt' is not supported |
262 | | - throw new IOException("PBE parameter parsing error: " |
263 | | - + "not an ASN.1 OCTET STRING tag"); |
264 | | - } |
265 | | - iCount = pBKDF2_params.data.getInteger(); |
| 243 | + DerValue pBKDF2_params = kdf.data.getDerValue(); |
266 | 244 |
|
267 | | - // keyLength INTEGER (1..MAX) OPTIONAL, |
268 | | - var ksDer = pBKDF2_params.data.getOptional(DerValue.tag_Integer); |
269 | | - if (ksDer.isPresent()) { |
270 | | - keysize = ksDer.get().getInteger() * 8; // keysize (in bits) |
271 | | - } |
| 245 | + var kdfParams = new PBKDF2Parameters(pBKDF2_params); |
| 246 | + String kdfAlgo = kdfParams.getPrfAlgo(); |
| 247 | + salt = kdfParams.getSalt(); |
| 248 | + iCount = kdfParams.getIterationCount(); |
| 249 | + keysize = kdfParams.getKeyLength(); |
272 | 250 |
|
273 | | - // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 |
274 | | - String kdfAlgo; |
275 | | - var prfDer = pBKDF2_params.data.getOptional(DerValue.tag_Sequence); |
276 | | - if (prfDer.isPresent()) { |
277 | | - DerValue prf = prfDer.get(); |
278 | | - kdfAlgo_OID = prf.data.getOID(); |
279 | | - KnownOIDs o = KnownOIDs.findMatch(kdfAlgo_OID.toString()); |
280 | | - if (o == null || (!o.stdName().equals("HmacSHA1") && |
281 | | - !o.stdName().equals("HmacSHA224") && |
282 | | - !o.stdName().equals("HmacSHA256") && |
283 | | - !o.stdName().equals("HmacSHA384") && |
284 | | - !o.stdName().equals("HmacSHA512") && |
285 | | - !o.stdName().equals("HmacSHA512/224") && |
286 | | - !o.stdName().equals("HmacSHA512/256"))) { |
287 | | - throw new IOException("PBE parameter parsing error: " |
288 | | - + "expecting the object identifier for a HmacSHA key " |
289 | | - + "derivation function"); |
290 | | - } |
291 | | - kdfAlgo = o.stdName(); |
292 | | - prf.data.getOptional(DerValue.tag_Null); |
293 | | - prf.data.atEnd(); |
294 | | - } else { |
295 | | - kdfAlgo = "HmacSHA1"; |
296 | | - } |
297 | | - return kdfAlgo; |
| 251 | + String cipherAlgo = parseES(pBES2_params.data.getDerValue()); |
| 252 | + |
| 253 | + this.pbes2AlgorithmName = "PBEWith" + kdfAlgo + "And" + cipherAlgo; |
298 | 254 | } |
299 | 255 |
|
300 | 256 | private String parseES(DerValue encryptionScheme) throws IOException { |
@@ -345,26 +301,9 @@ protected byte[] engineGetEncoded() throws IOException { |
345 | 301 |
|
346 | 302 | DerOutputStream pBES2_params = new DerOutputStream(); |
347 | 303 |
|
348 | | - DerOutputStream keyDerivationFunc = new DerOutputStream(); |
349 | | - keyDerivationFunc.putOID(pkcs5PBKDF2_OID); |
350 | | - |
351 | | - DerOutputStream pBKDF2_params = new DerOutputStream(); |
352 | | - pBKDF2_params.putOctetString(salt); // choice: 'specified OCTET STRING' |
353 | | - pBKDF2_params.putInteger(iCount); |
354 | | - |
355 | | - if (keysize > 0) { |
356 | | - pBKDF2_params.putInteger(keysize / 8); // derived key length (in octets) |
357 | | - } |
358 | | - |
359 | | - DerOutputStream prf = new DerOutputStream(); |
360 | | - // algorithm is id-hmacWith<MD> |
361 | | - prf.putOID(kdfAlgo_OID); |
362 | | - // parameters is 'NULL' |
363 | | - prf.putNull(); |
364 | | - pBKDF2_params.write(DerValue.tag_Sequence, prf); |
365 | | - |
366 | | - keyDerivationFunc.write(DerValue.tag_Sequence, pBKDF2_params); |
367 | | - pBES2_params.write(DerValue.tag_Sequence, keyDerivationFunc); |
| 304 | + // keysize encoded as octets |
| 305 | + pBES2_params.writeBytes(PBKDF2Parameters.encode(salt, iCount, |
| 306 | + keysize/8, kdfAlgo_OID)); |
368 | 307 |
|
369 | 308 | DerOutputStream encryptionScheme = new DerOutputStream(); |
370 | 309 | // algorithm is id-aes128-CBC or id-aes256-CBC |
|
0 commit comments