29 import java.security.CryptoPrimitive; |
29 import java.security.CryptoPrimitive; |
30 import java.util.Collection; |
30 import java.util.Collection; |
31 import java.util.Collections; |
31 import java.util.Collections; |
32 import java.util.Set; |
32 import java.util.Set; |
33 import java.util.EnumSet; |
33 import java.util.EnumSet; |
34 import java.util.HashSet; |
|
35 import java.math.BigInteger; |
34 import java.math.BigInteger; |
36 import java.security.PublicKey; |
35 import java.security.PublicKey; |
37 import java.security.KeyFactory; |
36 import java.security.KeyFactory; |
38 import java.security.AlgorithmParameters; |
37 import java.security.AlgorithmParameters; |
39 import java.security.NoSuchAlgorithmException; |
|
40 import java.security.GeneralSecurityException; |
38 import java.security.GeneralSecurityException; |
41 import java.security.cert.Certificate; |
39 import java.security.cert.Certificate; |
42 import java.security.cert.X509CRL; |
40 import java.security.cert.X509CRL; |
43 import java.security.cert.X509Certificate; |
41 import java.security.cert.X509Certificate; |
44 import java.security.cert.PKIXCertPathChecker; |
42 import java.security.cert.PKIXCertPathChecker; |
46 import java.security.cert.CRLException; |
44 import java.security.cert.CRLException; |
47 import java.security.cert.CertificateException; |
45 import java.security.cert.CertificateException; |
48 import java.security.cert.CertPathValidatorException; |
46 import java.security.cert.CertPathValidatorException; |
49 import java.security.cert.CertPathValidatorException.BasicReason; |
47 import java.security.cert.CertPathValidatorException.BasicReason; |
50 import java.security.cert.PKIXReason; |
48 import java.security.cert.PKIXReason; |
51 import java.io.IOException; |
49 import java.security.interfaces.DSAParams; |
52 import java.security.interfaces.*; |
50 import java.security.interfaces.DSAPublicKey; |
53 import java.security.spec.*; |
51 import java.security.spec.DSAPublicKeySpec; |
54 |
52 |
|
53 import sun.security.util.AnchorCertificates; |
|
54 import sun.security.util.CertConstraintParameters; |
|
55 import sun.security.util.Debug; |
55 import sun.security.util.DisabledAlgorithmConstraints; |
56 import sun.security.util.DisabledAlgorithmConstraints; |
56 import sun.security.x509.X509CertImpl; |
57 import sun.security.x509.X509CertImpl; |
57 import sun.security.x509.X509CRLImpl; |
58 import sun.security.x509.X509CRLImpl; |
58 import sun.security.x509.AlgorithmId; |
59 import sun.security.x509.AlgorithmId; |
59 |
60 |
86 |
88 |
87 private static final DisabledAlgorithmConstraints |
89 private static final DisabledAlgorithmConstraints |
88 certPathDefaultConstraints = new DisabledAlgorithmConstraints( |
90 certPathDefaultConstraints = new DisabledAlgorithmConstraints( |
89 DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); |
91 DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); |
90 |
92 |
|
93 // If there is no "cacerts" keyword, then disable anchor checking |
|
94 private static final boolean publicCALimits = |
|
95 certPathDefaultConstraints.checkProperty("jdkCA"); |
|
96 |
|
97 // If anchor checking enabled, this will be true if the trust anchor |
|
98 // has a match in the cacerts file |
|
99 private boolean trustedMatch = false; |
|
100 |
91 /** |
101 /** |
92 * Create a new <code>AlgorithmChecker</code> with the algorithm |
102 * Create a new <code>AlgorithmChecker</code> with the algorithm |
93 * constraints specified in security property |
103 * constraints specified in security property |
94 * "jdk.certpath.disabledAlgorithms". |
104 * "jdk.certpath.disabledAlgorithms". |
95 * |
105 * |
134 "The trust anchor cannot be null"); |
144 "The trust anchor cannot be null"); |
135 } |
145 } |
136 |
146 |
137 if (anchor.getTrustedCert() != null) { |
147 if (anchor.getTrustedCert() != null) { |
138 this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); |
148 this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); |
|
149 // Check for anchor certificate restrictions |
|
150 trustedMatch = checkFingerprint(anchor.getTrustedCert()); |
|
151 if (trustedMatch && debug != null) { |
|
152 debug.println("trustedMatch = true"); |
|
153 } |
139 } else { |
154 } else { |
140 this.trustedPubKey = anchor.getCAPublicKey(); |
155 this.trustedPubKey = anchor.getCAPublicKey(); |
141 } |
156 } |
142 |
157 |
143 this.prevPubKey = trustedPubKey; |
158 this.prevPubKey = trustedPubKey; |
144 this.constraints = constraints; |
159 this.constraints = constraints; |
|
160 } |
|
161 |
|
162 // Check this 'cert' for restrictions in the AnchorCertificates |
|
163 // trusted certificates list |
|
164 private static boolean checkFingerprint(X509Certificate cert) { |
|
165 if (!publicCALimits) { |
|
166 return false; |
|
167 } |
|
168 |
|
169 if (debug != null) { |
|
170 debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName()); |
|
171 } |
|
172 return AnchorCertificates.contains(cert); |
145 } |
173 } |
146 |
174 |
147 @Override |
175 @Override |
148 public void init(boolean forward) throws CertPathValidatorException { |
176 public void init(boolean forward) throws CertPathValidatorException { |
149 // Note that this class does not support forward mode. |
177 // Note that this class does not support forward mode. |
179 if (!(cert instanceof X509Certificate) || constraints == null) { |
207 if (!(cert instanceof X509Certificate) || constraints == null) { |
180 // ignore the check for non-x.509 certificate or null constraints |
208 // ignore the check for non-x.509 certificate or null constraints |
181 return; |
209 return; |
182 } |
210 } |
183 |
211 |
184 X509CertImpl x509Cert = null; |
|
185 try { |
|
186 x509Cert = X509CertImpl.toImpl((X509Certificate)cert); |
|
187 } catch (CertificateException ce) { |
|
188 throw new CertPathValidatorException(ce); |
|
189 } |
|
190 |
|
191 PublicKey currPubKey = x509Cert.getPublicKey(); |
|
192 String currSigAlg = x509Cert.getSigAlgName(); |
|
193 |
|
194 AlgorithmId algorithmId = null; |
|
195 try { |
|
196 algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG); |
|
197 } catch (CertificateException ce) { |
|
198 throw new CertPathValidatorException(ce); |
|
199 } |
|
200 |
|
201 AlgorithmParameters currSigAlgParams = algorithmId.getParameters(); |
|
202 |
|
203 // Check the current signature algorithm |
|
204 if (!constraints.permits( |
|
205 SIGNATURE_PRIMITIVE_SET, |
|
206 currSigAlg, currSigAlgParams)) { |
|
207 throw new CertPathValidatorException( |
|
208 "Algorithm constraints check failed: " + currSigAlg, |
|
209 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
|
210 } |
|
211 |
|
212 // check the key usage and key size |
212 // check the key usage and key size |
213 boolean[] keyUsage = x509Cert.getKeyUsage(); |
213 boolean[] keyUsage = ((X509Certificate) cert).getKeyUsage(); |
214 if (keyUsage != null && keyUsage.length < 9) { |
214 if (keyUsage != null && keyUsage.length < 9) { |
215 throw new CertPathValidatorException( |
215 throw new CertPathValidatorException( |
216 "incorrect KeyUsage extension", |
216 "incorrect KeyUsage extension", |
217 null, null, -1, PKIXReason.INVALID_KEY_USAGE); |
217 null, null, -1, PKIXReason.INVALID_KEY_USAGE); |
218 } |
218 } |
246 // KeyUsage.encipherOnly and KeyUsage.decipherOnly are |
246 // KeyUsage.encipherOnly and KeyUsage.decipherOnly are |
247 // undefined in the absence of the keyAgreement bit. |
247 // undefined in the absence of the keyAgreement bit. |
248 |
248 |
249 if (primitives.isEmpty()) { |
249 if (primitives.isEmpty()) { |
250 throw new CertPathValidatorException( |
250 throw new CertPathValidatorException( |
251 "incorrect KeyUsage extension", |
251 "incorrect KeyUsage extension bits", |
252 null, null, -1, PKIXReason.INVALID_KEY_USAGE); |
252 null, null, -1, PKIXReason.INVALID_KEY_USAGE); |
253 } |
253 } |
254 } |
254 } |
255 |
255 |
256 if (!constraints.permits(primitives, currPubKey)) { |
256 PublicKey currPubKey = cert.getPublicKey(); |
257 throw new CertPathValidatorException( |
257 |
258 "algorithm constraints check failed", |
258 // Check against DisabledAlgorithmConstraints certpath constraints. |
259 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
259 // permits() will throw exception on failure. |
|
260 certPathDefaultConstraints.permits(primitives, |
|
261 new CertConstraintParameters((X509Certificate)cert, |
|
262 trustedMatch)); |
|
263 // new CertConstraintParameters(x509Cert, trustedMatch)); |
|
264 // If there is no previous key, set one and exit |
|
265 if (prevPubKey == null) { |
|
266 prevPubKey = currPubKey; |
|
267 return; |
|
268 } |
|
269 |
|
270 X509CertImpl x509Cert; |
|
271 AlgorithmId algorithmId; |
|
272 try { |
|
273 x509Cert = X509CertImpl.toImpl((X509Certificate)cert); |
|
274 algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG); |
|
275 } catch (CertificateException ce) { |
|
276 throw new CertPathValidatorException(ce); |
|
277 } |
|
278 |
|
279 AlgorithmParameters currSigAlgParams = algorithmId.getParameters(); |
|
280 String currSigAlg = x509Cert.getSigAlgName(); |
|
281 |
|
282 // If 'constraints' is not of DisabledAlgorithmConstraints, check all |
|
283 // everything individually |
|
284 if (!(constraints instanceof DisabledAlgorithmConstraints)) { |
|
285 // Check the current signature algorithm |
|
286 if (!constraints.permits( |
|
287 SIGNATURE_PRIMITIVE_SET, |
|
288 currSigAlg, currSigAlgParams)) { |
|
289 throw new CertPathValidatorException( |
|
290 "Algorithm constraints check failed on signature " + |
|
291 "algorithm: " + currSigAlg, null, null, -1, |
|
292 BasicReason.ALGORITHM_CONSTRAINED); |
|
293 } |
|
294 |
|
295 if (!constraints.permits(primitives, currPubKey)) { |
|
296 throw new CertPathValidatorException( |
|
297 "Algorithm constraints check failed on keysize: " + |
|
298 sun.security.util.KeyUtil.getKeySize(currPubKey), |
|
299 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
|
300 } |
260 } |
301 } |
261 |
302 |
262 // Check with previous cert for signature algorithm and public key |
303 // Check with previous cert for signature algorithm and public key |
263 if (prevPubKey != null) { |
304 if (prevPubKey != null) { |
264 if (currSigAlg != null) { |
305 if (!constraints.permits( |
265 if (!constraints.permits( |
306 SIGNATURE_PRIMITIVE_SET, |
266 SIGNATURE_PRIMITIVE_SET, |
307 currSigAlg, prevPubKey, currSigAlgParams)) { |
267 currSigAlg, prevPubKey, currSigAlgParams)) { |
308 throw new CertPathValidatorException( |
268 throw new CertPathValidatorException( |
309 "Algorithm constraints check failed on " + |
269 "Algorithm constraints check failed: " + currSigAlg, |
310 "signature algorithm: " + currSigAlg, |
270 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
311 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
271 } |
|
272 } |
312 } |
273 |
313 |
274 // Inherit key parameters from previous key |
314 // Inherit key parameters from previous key |
275 if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) { |
315 if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) { |
276 // Inherit DSA parameters from previous key |
316 // Inherit DSA parameters from previous key |
368 AlgorithmParameters sigAlgParams = algorithmId.getParameters(); |
413 AlgorithmParameters sigAlgParams = algorithmId.getParameters(); |
369 |
414 |
370 if (!certPathDefaultConstraints.permits( |
415 if (!certPathDefaultConstraints.permits( |
371 SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) { |
416 SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) { |
372 throw new CertPathValidatorException( |
417 throw new CertPathValidatorException( |
373 "algorithm check failed: " + sigAlgName + " is disabled", |
418 "Algorithm constraints check failed on signature algorithm: " + |
|
419 sigAlgName + " is disabled", |
374 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
420 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); |
375 } |
421 } |
376 } |
422 } |
377 |
423 |
378 } |
424 } |