107 * constraints specified in security property |
110 * constraints specified in security property |
108 * "jdk.certpath.disabledAlgorithms". |
111 * "jdk.certpath.disabledAlgorithms". |
109 * |
112 * |
110 * @param anchor the trust anchor selected to validate the target |
113 * @param anchor the trust anchor selected to validate the target |
111 * certificate |
114 * certificate |
112 */ |
115 * @param variant is the Validator variants of the operation. A null value |
113 public AlgorithmChecker(TrustAnchor anchor) { |
116 * passed will set it to Validator.GENERIC. |
114 this(anchor, certPathDefaultConstraints, null); |
117 */ |
115 } |
118 public AlgorithmChecker(TrustAnchor anchor, String variant) { |
116 |
119 this(anchor, certPathDefaultConstraints, null, variant); |
117 /** |
120 } |
118 * Create a new {@code AlgorithmChecker} with the |
121 |
119 * given {@code TrustAnchor} and {@code AlgorithmConstraints}. |
122 /** |
120 * |
123 * Create a new {@code AlgorithmChecker} with the given |
121 * @param anchor the trust anchor selected to validate the target |
124 * {@code AlgorithmConstraints}, {@code Timestamp}, and/or {@code Variant}. |
122 * certificate |
125 * <p> |
|
126 * Note that this constructor can initialize a variation of situations where |
|
127 * the AlgorithmConstraints, Timestamp, or Variant maybe known. |
|
128 * |
123 * @param constraints the algorithm constraints (or null) |
129 * @param constraints the algorithm constraints (or null) |
124 * |
130 * @param jarTimestamp Timestamp passed for JAR timestamp constraint |
125 * @throws IllegalArgumentException if the {@code anchor} is null |
131 * checking. Set to null if not applicable. |
126 */ |
132 * @param variant is the Validator variants of the operation. A null value |
127 public AlgorithmChecker(TrustAnchor anchor, |
133 * passed will set it to Validator.GENERIC. |
128 AlgorithmConstraints constraints) { |
134 */ |
129 this(anchor, constraints, null); |
135 public AlgorithmChecker(AlgorithmConstraints constraints, |
130 } |
136 Timestamp jarTimestamp, String variant) { |
131 |
|
132 /** |
|
133 * Create a new {@code AlgorithmChecker} with the |
|
134 * given {@code AlgorithmConstraints}. |
|
135 * <p> |
|
136 * Note that this constructor will be used to check a certification |
|
137 * path where the trust anchor is unknown, or a certificate list which may |
|
138 * contain the trust anchor. This constructor is used by SunJSSE. |
|
139 * |
|
140 * @param constraints the algorithm constraints (or null) |
|
141 */ |
|
142 public AlgorithmChecker(AlgorithmConstraints constraints) { |
|
143 this.prevPubKey = null; |
137 this.prevPubKey = null; |
144 this.trustedPubKey = null; |
138 this.trustedPubKey = null; |
145 this.constraints = constraints; |
139 this.constraints = (constraints == null ? certPathDefaultConstraints : |
146 this.pkixdate = null; |
140 constraints); |
147 this.jarTimestamp = null; |
141 this.pkixdate = (jarTimestamp != null ? jarTimestamp.getTimestamp() : |
148 } |
142 null); |
149 |
|
150 /** |
|
151 * Create a new {@code AlgorithmChecker} with the given |
|
152 * {@code Timestamp}. |
|
153 * <p> |
|
154 * Note that this constructor will be used to check a certification |
|
155 * path for signed JAR files that are timestamped. |
|
156 * |
|
157 * @param jarTimestamp Timestamp passed for JAR timestamp constraint |
|
158 * checking. Set to null if not applicable. |
|
159 */ |
|
160 public AlgorithmChecker(Timestamp jarTimestamp) { |
|
161 this.prevPubKey = null; |
|
162 this.trustedPubKey = null; |
|
163 this.constraints = certPathDefaultConstraints; |
|
164 if (jarTimestamp == null) { |
|
165 throw new IllegalArgumentException( |
|
166 "Timestamp cannot be null"); |
|
167 } |
|
168 this.pkixdate = jarTimestamp.getTimestamp(); |
|
169 this.jarTimestamp = jarTimestamp; |
143 this.jarTimestamp = jarTimestamp; |
|
144 this.variant = (variant == null ? Validator.VAR_GENERIC : variant); |
170 } |
145 } |
171 |
146 |
172 /** |
147 /** |
173 * Create a new {@code AlgorithmChecker} with the |
148 * Create a new {@code AlgorithmChecker} with the |
174 * given {@code TrustAnchor} and {@code AlgorithmConstraints}. |
149 * given {@code TrustAnchor} and {@code AlgorithmConstraints}. |
284 throw new CertPathValidatorException( |
263 throw new CertPathValidatorException( |
285 "incorrect KeyUsage extension", |
264 "incorrect KeyUsage extension", |
286 null, null, -1, PKIXReason.INVALID_KEY_USAGE); |
265 null, null, -1, PKIXReason.INVALID_KEY_USAGE); |
287 } |
266 } |
288 |
267 |
289 // Assume all key usage bits are set if key usage is not present |
|
290 Set<CryptoPrimitive> primitives = KU_PRIMITIVE_SET; |
|
291 |
|
292 if (keyUsage != null) { |
|
293 primitives = EnumSet.noneOf(CryptoPrimitive.class); |
|
294 |
|
295 if (keyUsage[0] || keyUsage[1] || keyUsage[5] || keyUsage[6]) { |
|
296 // keyUsage[0]: KeyUsage.digitalSignature |
|
297 // keyUsage[1]: KeyUsage.nonRepudiation |
|
298 // keyUsage[5]: KeyUsage.keyCertSign |
|
299 // keyUsage[6]: KeyUsage.cRLSign |
|
300 primitives.add(CryptoPrimitive.SIGNATURE); |
|
301 } |
|
302 |
|
303 if (keyUsage[2]) { // KeyUsage.keyEncipherment |
|
304 primitives.add(CryptoPrimitive.KEY_ENCAPSULATION); |
|
305 } |
|
306 |
|
307 if (keyUsage[3]) { // KeyUsage.dataEncipherment |
|
308 primitives.add(CryptoPrimitive.PUBLIC_KEY_ENCRYPTION); |
|
309 } |
|
310 |
|
311 if (keyUsage[4]) { // KeyUsage.keyAgreement |
|
312 primitives.add(CryptoPrimitive.KEY_AGREEMENT); |
|
313 } |
|
314 |
|
315 // KeyUsage.encipherOnly and KeyUsage.decipherOnly are |
|
316 // undefined in the absence of the keyAgreement bit. |
|
317 |
|
318 if (primitives.isEmpty()) { |
|
319 throw new CertPathValidatorException( |
|
320 "incorrect KeyUsage extension bits", |
|
321 null, null, -1, PKIXReason.INVALID_KEY_USAGE); |
|
322 } |
|
323 } |
|
324 |
|
325 PublicKey currPubKey = cert.getPublicKey(); |
|
326 |
|
327 if (constraints instanceof DisabledAlgorithmConstraints) { |
|
328 // Check against DisabledAlgorithmConstraints certpath constraints. |
|
329 // permits() will throw exception on failure. |
|
330 ((DisabledAlgorithmConstraints)constraints).permits(primitives, |
|
331 new CertConstraintParameters((X509Certificate)cert, |
|
332 trustedMatch, pkixdate, jarTimestamp)); |
|
333 // If there is no previous key, set one and exit |
|
334 if (prevPubKey == null) { |
|
335 prevPubKey = currPubKey; |
|
336 return; |
|
337 } |
|
338 } |
|
339 |
|
340 X509CertImpl x509Cert; |
268 X509CertImpl x509Cert; |
341 AlgorithmId algorithmId; |
269 AlgorithmId algorithmId; |
342 try { |
270 try { |
343 x509Cert = X509CertImpl.toImpl((X509Certificate)cert); |
271 x509Cert = X509CertImpl.toImpl((X509Certificate)cert); |
344 algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG); |
272 algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG); |
345 } catch (CertificateException ce) { |
273 } catch (CertificateException ce) { |
346 throw new CertPathValidatorException(ce); |
274 throw new CertPathValidatorException(ce); |
347 } |
275 } |
348 |
276 |
349 AlgorithmParameters currSigAlgParams = algorithmId.getParameters(); |
277 AlgorithmParameters currSigAlgParams = algorithmId.getParameters(); |
|
278 PublicKey currPubKey = cert.getPublicKey(); |
350 String currSigAlg = x509Cert.getSigAlgName(); |
279 String currSigAlg = x509Cert.getSigAlgName(); |
351 |
280 |
352 // If 'constraints' is not of DisabledAlgorithmConstraints, check all |
281 // Check the signature algorithm and parameters against constraints. |
353 // everything individually |
282 if (!constraints.permits(SIGNATURE_PRIMITIVE_SET, currSigAlg, |
354 if (!(constraints instanceof DisabledAlgorithmConstraints)) { |
283 currSigAlgParams)) { |
355 // Check the current signature algorithm |
284 throw new CertPathValidatorException( |
356 if (!constraints.permits( |
285 "Algorithm constraints check failed on signature " + |
357 SIGNATURE_PRIMITIVE_SET, |
286 "algorithm: " + currSigAlg, null, null, -1, |
358 currSigAlg, currSigAlgParams)) { |
287 BasicReason.ALGORITHM_CONSTRAINED); |
|
288 } |
|
289 |
|
290 // Assume all key usage bits are set if key usage is not present |
|
291 Set<CryptoPrimitive> primitives = KU_PRIMITIVE_SET; |
|
292 |
|
293 if (keyUsage != null) { |
|
294 primitives = EnumSet.noneOf(CryptoPrimitive.class); |
|
295 |
|
296 if (keyUsage[0] || keyUsage[1] || keyUsage[5] || keyUsage[6]) { |
|
297 // keyUsage[0]: KeyUsage.digitalSignature |
|
298 // keyUsage[1]: KeyUsage.nonRepudiation |
|
299 // keyUsage[5]: KeyUsage.keyCertSign |
|
300 // keyUsage[6]: KeyUsage.cRLSign |
|
301 primitives.add(CryptoPrimitive.SIGNATURE); |
|
302 } |
|
303 |
|
304 if (keyUsage[2]) { // KeyUsage.keyEncipherment |
|
305 primitives.add(CryptoPrimitive.KEY_ENCAPSULATION); |
|
306 } |
|
307 |
|
308 if (keyUsage[3]) { // KeyUsage.dataEncipherment |
|
309 primitives.add(CryptoPrimitive.PUBLIC_KEY_ENCRYPTION); |
|
310 } |
|
311 |
|
312 if (keyUsage[4]) { // KeyUsage.keyAgreement |
|
313 primitives.add(CryptoPrimitive.KEY_AGREEMENT); |
|
314 } |
|
315 |
|
316 // KeyUsage.encipherOnly and KeyUsage.decipherOnly are |
|
317 // undefined in the absence of the keyAgreement bit. |
|
318 |
|
319 if (primitives.isEmpty()) { |
359 throw new CertPathValidatorException( |
320 throw new CertPathValidatorException( |
360 "Algorithm constraints check failed on signature " + |
321 "incorrect KeyUsage extension bits", |
361 "algorithm: " + currSigAlg, null, null, -1, |
322 null, null, -1, PKIXReason.INVALID_KEY_USAGE); |
362 BasicReason.ALGORITHM_CONSTRAINED); |
323 } |
363 } |
324 } |
364 |
325 |
|
326 ConstraintsParameters cp = |
|
327 new ConstraintsParameters((X509Certificate)cert, |
|
328 trustedMatch, pkixdate, jarTimestamp, variant); |
|
329 |
|
330 // Check against local constraints if it is DisabledAlgorithmConstraints |
|
331 if (constraints instanceof DisabledAlgorithmConstraints) { |
|
332 ((DisabledAlgorithmConstraints)constraints).permits(currSigAlg, cp); |
|
333 // DisabledAlgorithmsConstraints does not check primitives, so key |
|
334 // additional key check. |
|
335 |
|
336 } else { |
|
337 // Perform the default constraints checking anyway. |
|
338 certPathDefaultConstraints.permits(currSigAlg, cp); |
|
339 // Call locally set constraints to check key with primitives. |
365 if (!constraints.permits(primitives, currPubKey)) { |
340 if (!constraints.permits(primitives, currPubKey)) { |
366 throw new CertPathValidatorException( |
341 throw new CertPathValidatorException( |
367 "Algorithm constraints check failed on keysize: " + |
342 "Algorithm constraints check failed on key " + |
368 sun.security.util.KeyUtil.getKeySize(currPubKey), |
343 currPubKey.getAlgorithm() + " with size of " + |
|
344 sun.security.util.KeyUtil.getKeySize(currPubKey) + |
|
345 "bits", |
369 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
346 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
370 } |
347 } |
371 } |
348 } |
372 |
349 |
|
350 // If there is no previous key, set one and exit |
|
351 if (prevPubKey == null) { |
|
352 prevPubKey = currPubKey; |
|
353 return; |
|
354 } |
|
355 |
373 // Check with previous cert for signature algorithm and public key |
356 // Check with previous cert for signature algorithm and public key |
374 if (prevPubKey != null) { |
357 if (!constraints.permits( |
375 if (!constraints.permits( |
358 SIGNATURE_PRIMITIVE_SET, |
376 SIGNATURE_PRIMITIVE_SET, |
359 currSigAlg, prevPubKey, currSigAlgParams)) { |
377 currSigAlg, prevPubKey, currSigAlgParams)) { |
360 throw new CertPathValidatorException( |
378 throw new CertPathValidatorException( |
|
379 "Algorithm constraints check failed on " + |
361 "Algorithm constraints check failed on " + |
380 "signature algorithm: " + currSigAlg, |
362 "signature algorithm: " + currSigAlg, |
381 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
363 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
382 } |
364 } |
383 |
365 |
384 // Inherit key parameters from previous key |
366 // Inherit key parameters from previous key |
385 if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) { |
367 if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) { |
386 // Inherit DSA parameters from previous key |
368 // Inherit DSA parameters from previous key |
387 if (!(prevPubKey instanceof DSAPublicKey)) { |
369 if (!(prevPubKey instanceof DSAPublicKey)) { |
388 throw new CertPathValidatorException("Input key is not " + |
370 throw new CertPathValidatorException("Input key is not " + |
389 "of a appropriate type for inheriting parameters"); |
371 "of a appropriate type for inheriting parameters"); |
390 } |
372 } |
391 |
373 |
392 DSAParams params = ((DSAPublicKey)prevPubKey).getParams(); |
374 DSAParams params = ((DSAPublicKey)prevPubKey).getParams(); |
393 if (params == null) { |
375 if (params == null) { |
394 throw new CertPathValidatorException( |
376 throw new CertPathValidatorException( |
395 "Key parameters missing from public key."); |
377 "Key parameters missing from public key."); |
396 } |
378 } |
397 |
379 |
398 try { |
380 try { |
399 BigInteger y = ((DSAPublicKey)currPubKey).getY(); |
381 BigInteger y = ((DSAPublicKey)currPubKey).getY(); |
400 KeyFactory kf = KeyFactory.getInstance("DSA"); |
382 KeyFactory kf = KeyFactory.getInstance("DSA"); |
401 DSAPublicKeySpec ks = new DSAPublicKeySpec(y, |
383 DSAPublicKeySpec ks = new DSAPublicKeySpec(y, params.getP(), |
402 params.getP(), |
384 params.getQ(), params.getG()); |
403 params.getQ(), |
385 currPubKey = kf.generatePublic(ks); |
404 params.getG()); |
386 } catch (GeneralSecurityException e) { |
405 currPubKey = kf.generatePublic(ks); |
387 throw new CertPathValidatorException("Unable to generate " + |
406 } catch (GeneralSecurityException e) { |
|
407 throw new CertPathValidatorException("Unable to generate " + |
|
408 "key with inherited parameters: " + e.getMessage(), e); |
388 "key with inherited parameters: " + e.getMessage(), e); |
409 } |
|
410 } |
389 } |
411 } |
390 } |
412 |
391 |
413 // reset the previous public key |
392 // reset the previous public key |
414 prevPubKey = currPubKey; |
393 prevPubKey = currPubKey; |
415 |
|
416 // check the extended key usage, ignore the check now |
|
417 // List<String> extendedKeyUsages = x509Cert.getExtendedKeyUsage(); |
|
418 |
|
419 // DO NOT remove any unresolved critical extensions |
|
420 } |
394 } |
421 |
395 |
422 /** |
396 /** |
423 * Try to set the trust anchor of the checker. |
397 * Try to set the trust anchor of the checker. |
424 * <p> |
398 * <p> |
454 /** |
428 /** |
455 * Check the signature algorithm with the specified public key. |
429 * Check the signature algorithm with the specified public key. |
456 * |
430 * |
457 * @param key the public key to verify the CRL signature |
431 * @param key the public key to verify the CRL signature |
458 * @param crl the target CRL |
432 * @param crl the target CRL |
459 */ |
433 * @param variant is the Validator variants of the operation. A null value |
460 static void check(PublicKey key, X509CRL crl) |
434 * passed will set it to Validator.GENERIC. |
|
435 */ |
|
436 static void check(PublicKey key, X509CRL crl, String variant) |
461 throws CertPathValidatorException { |
437 throws CertPathValidatorException { |
462 |
438 |
463 X509CRLImpl x509CRLImpl = null; |
439 X509CRLImpl x509CRLImpl = null; |
464 try { |
440 try { |
465 x509CRLImpl = X509CRLImpl.toImpl(crl); |
441 x509CRLImpl = X509CRLImpl.toImpl(crl); |
466 } catch (CRLException ce) { |
442 } catch (CRLException ce) { |
467 throw new CertPathValidatorException(ce); |
443 throw new CertPathValidatorException(ce); |
468 } |
444 } |
469 |
445 |
470 AlgorithmId algorithmId = x509CRLImpl.getSigAlgId(); |
446 AlgorithmId algorithmId = x509CRLImpl.getSigAlgId(); |
471 check(key, algorithmId); |
447 check(key, algorithmId, variant); |
472 } |
448 } |
473 |
449 |
474 /** |
450 /** |
475 * Check the signature algorithm with the specified public key. |
451 * Check the signature algorithm with the specified public key. |
476 * |
452 * |
477 * @param key the public key to verify the CRL signature |
453 * @param key the public key to verify the CRL signature |
478 * @param algorithmId signature algorithm Algorithm ID |
454 * @param algorithmId signature algorithm Algorithm ID |
479 */ |
455 * @param variant is the Validator variants of the operation. A null value |
480 static void check(PublicKey key, AlgorithmId algorithmId) |
456 * passed will set it to Validator.GENERIC. |
|
457 */ |
|
458 static void check(PublicKey key, AlgorithmId algorithmId, String variant) |
481 throws CertPathValidatorException { |
459 throws CertPathValidatorException { |
482 String sigAlgName = algorithmId.getName(); |
460 String sigAlgName = algorithmId.getName(); |
483 AlgorithmParameters sigAlgParams = algorithmId.getParameters(); |
461 AlgorithmParameters sigAlgParams = algorithmId.getParameters(); |
484 |
462 |
485 if (!certPathDefaultConstraints.permits( |
463 certPathDefaultConstraints.permits(new ConstraintsParameters( |
486 SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) { |
464 sigAlgName, sigAlgParams, key, variant)); |
487 throw new CertPathValidatorException( |
465 } |
488 "Algorithm constraints check failed on signature algorithm: " + |
|
489 sigAlgName + " is disabled", |
|
490 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
|
491 } |
|
492 } |
|
493 |
|
494 } |
466 } |
495 |
467 |