History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/provider/certpath/AlgorithmChecker.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/provider/certpath/AlgorithmChecker.java+367−0
@@ -0,0 +1,367 @@
1+/*
2+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.security.provider.certpath;
27+
28+import java.security.AlgorithmConstraints;
29+import java.security.CryptoPrimitive;
30+import java.util.Collection;
31+import java.util.Collections;
32+import java.util.Set;
33+import java.util.EnumSet;
34+import java.util.HashSet;
35+import java.math.BigInteger;
36+import java.security.PublicKey;
37+import java.security.KeyFactory;
38+import java.security.AlgorithmParameters;
39+import java.security.NoSuchAlgorithmException;
40+import java.security.GeneralSecurityException;
41+import java.security.cert.Certificate;
42+import java.security.cert.X509CRL;
43+import java.security.cert.X509Certificate;
44+import java.security.cert.PKIXCertPathChecker;
45+import java.security.cert.TrustAnchor;
46+import java.security.cert.CRLException;
47+import java.security.cert.CertificateException;
48+import java.security.cert.CertPathValidatorException;
49+import java.security.cert.CertPathValidatorException.BasicReason;
50+import java.security.cert.PKIXReason;
51+import java.io.IOException;
52+import java.security.interfaces.*;
53+import java.security.spec.*;
54+
55+import sun.security.util.DisabledAlgorithmConstraints;
56+import sun.security.x509.X509CertImpl;
57+import sun.security.x509.X509CRLImpl;
58+import sun.security.x509.AlgorithmId;
59+
60+/**
61+ * A <code>PKIXCertPathChecker</code> implementation to check whether a
62+ * specified certificate contains the required algorithm constraints.
63+ * <p>
64+ * Certificate fields such as the subject public key, the signature
65+ * algorithm, key usage, extended key usage, etc. need to conform to
66+ * the specified algorithm constraints.
67+ *
68+ * @see PKIXCertPathChecker
69+ * @see PKIXParameters
70+ */
71+final public class AlgorithmChecker extends PKIXCertPathChecker {
72+
73+ private final AlgorithmConstraints constraints;
74+ private final PublicKey trustedPubKey;
75+ private PublicKey prevPubKey;
76+
77+ private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
78+ EnumSet.of(CryptoPrimitive.SIGNATURE);
79+
80+ private final static DisabledAlgorithmConstraints
81+ certPathDefaultConstraints = new DisabledAlgorithmConstraints(
82+ DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
83+
84+ /**
85+ * Create a new <code>AlgorithmChecker</code> with the algorithm
86+ * constraints specified in security property
87+ * "jdk.certpath.disabledAlgorithms".
88+ *
89+ * @param anchor the trust anchor selected to validate the target
90+ * certificate
91+ */
92+ public AlgorithmChecker(TrustAnchor anchor) {
93+ this(anchor, certPathDefaultConstraints);
94+ }
95+
96+ /**
97+ * Create a new <code>AlgorithmChecker</code> with the
98+ * given {@code AlgorithmConstraints}.
99+ * <p>
100+ * Note that this constructor will be used to check a certification
101+ * path where the trust anchor is unknown, or a certificate list which may
102+ * contain the trust anchor. This constructor is used by SunJSSE.
103+ *
104+ * @param constraints the algorithm constraints (or null)
105+ */
106+ public AlgorithmChecker(AlgorithmConstraints constraints) {
107+ this.prevPubKey = null;
108+ this.trustedPubKey = null;
109+ this.constraints = constraints;
110+ }
111+
112+ /**
113+ * Create a new <code>AlgorithmChecker</code> with the
114+ * given <code>TrustAnchor</code> and <code>AlgorithmConstraints</code>.
115+ *
116+ * @param anchor the trust anchor selected to validate the target
117+ * certificate
118+ * @param constraints the algorithm constraints (or null)
119+ *
120+ * @throws IllegalArgumentException if the <code>anchor</code> is null
121+ */
122+ public AlgorithmChecker(TrustAnchor anchor,
123+ AlgorithmConstraints constraints) {
124+
125+ if (anchor == null) {
126+ throw new IllegalArgumentException(
127+ "The trust anchor cannot be null");
128+ }
129+
130+ if (anchor.getTrustedCert() != null) {
131+ this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
132+ } else {
133+ this.trustedPubKey = anchor.getCAPublicKey();
134+ }
135+
136+ this.prevPubKey = trustedPubKey;
137+ this.constraints = constraints;
138+ }
139+
140+ @Override
141+ public void init(boolean forward) throws CertPathValidatorException {
142+ // Note that this class does not support forward mode.
143+ if (!forward) {
144+ if (trustedPubKey != null) {
145+ prevPubKey = trustedPubKey;
146+ } else {
147+ prevPubKey = null;
148+ }
149+ } else {
150+ throw new
151+ CertPathValidatorException("forward checking not supported");
152+ }
153+ }
154+
155+ @Override
156+ public boolean isForwardCheckingSupported() {
157+ // Note that as this class does not support forward mode, the method
158+ // will always returns false.
159+ return false;
160+ }
161+
162+ @Override
163+ public Set<String> getSupportedExtensions() {
164+ return null;
165+ }
166+
167+ @Override
168+ public void check(Certificate cert,
169+ Collection<String> unresolvedCritExts)
170+ throws CertPathValidatorException {
171+
172+ if (!(cert instanceof X509Certificate) || constraints == null) {
173+ // ignore the check for non-x.509 certificate or null constraints
174+ return;
175+ }
176+
177+ X509CertImpl x509Cert = null;
178+ try {
179+ x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
180+ } catch (CertificateException ce) {
181+ throw new CertPathValidatorException(ce);
182+ }
183+
184+ PublicKey currPubKey = x509Cert.getPublicKey();
185+ String currSigAlg = x509Cert.getSigAlgName();
186+
187+ AlgorithmId algorithmId = null;
188+ try {
189+ algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
190+ } catch (CertificateException ce) {
191+ throw new CertPathValidatorException(ce);
192+ }
193+
194+ AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
195+
196+ // Check the current signature algorithm
197+ if (!constraints.permits(
198+ SIGNATURE_PRIMITIVE_SET,
199+ currSigAlg, currSigAlgParams)) {
200+ throw new CertPathValidatorException(
201+ "Algorithm constraints check failed: " + currSigAlg,
202+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
203+ }
204+
205+ // check the key usage and key size
206+ boolean[] keyUsage = x509Cert.getKeyUsage();
207+ if (keyUsage != null && keyUsage.length < 9) {
208+ throw new CertPathValidatorException(
209+ "incorrect KeyUsage extension",
210+ null, null, -1, PKIXReason.INVALID_KEY_USAGE);
211+ }
212+
213+ if (keyUsage != null) {
214+ Set<CryptoPrimitive> primitives =
215+ EnumSet.noneOf(CryptoPrimitive.class);
216+
217+ if (keyUsage[0] || keyUsage[1] || keyUsage[5] || keyUsage[6]) {
218+ // keyUsage[0]: KeyUsage.digitalSignature
219+ // keyUsage[1]: KeyUsage.nonRepudiation
220+ // keyUsage[5]: KeyUsage.keyCertSign
221+ // keyUsage[6]: KeyUsage.cRLSign
222+ primitives.add(CryptoPrimitive.SIGNATURE);
223+ }
224+
225+ if (keyUsage[2]) { // KeyUsage.keyEncipherment
226+ primitives.add(CryptoPrimitive.KEY_ENCAPSULATION);
227+ }
228+
229+ if (keyUsage[3]) { // KeyUsage.dataEncipherment
230+ primitives.add(CryptoPrimitive.PUBLIC_KEY_ENCRYPTION);
231+ }
232+
233+ if (keyUsage[4]) { // KeyUsage.keyAgreement
234+ primitives.add(CryptoPrimitive.KEY_AGREEMENT);
235+ }
236+
237+ // KeyUsage.encipherOnly and KeyUsage.decipherOnly are
238+ // undefined in the absence of the keyAgreement bit.
239+
240+ if (!primitives.isEmpty()) {
241+ if (!constraints.permits(primitives, currPubKey)) {
242+ throw new CertPathValidatorException(
243+ "algorithm constraints check failed",
244+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
245+ }
246+ }
247+ }
248+
249+ // Check with previous cert for signature algorithm and public key
250+ if (prevPubKey != null) {
251+ if (currSigAlg != null) {
252+ if (!constraints.permits(
253+ SIGNATURE_PRIMITIVE_SET,
254+ currSigAlg, prevPubKey, currSigAlgParams)) {
255+ throw new CertPathValidatorException(
256+ "Algorithm constraints check failed: " + currSigAlg,
257+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
258+ }
259+ }
260+
261+ // Inherit key parameters from previous key
262+ if (currPubKey instanceof DSAPublicKey &&
263+ ((DSAPublicKey)currPubKey).getParams() == null) {
264+ // Inherit DSA parameters from previous key
265+ if (!(prevPubKey instanceof DSAPublicKey)) {
266+ throw new CertPathValidatorException("Input key is not " +
267+ "of a appropriate type for inheriting parameters");
268+ }
269+
270+ DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
271+ if (params == null) {
272+ throw new CertPathValidatorException(
273+ "Key parameters missing");
274+ }
275+
276+ try {
277+ BigInteger y = ((DSAPublicKey)currPubKey).getY();
278+ KeyFactory kf = KeyFactory.getInstance("DSA");
279+ DSAPublicKeySpec ks = new DSAPublicKeySpec(y,
280+ params.getP(),
281+ params.getQ(),
282+ params.getG());
283+ currPubKey = kf.generatePublic(ks);
284+ } catch (GeneralSecurityException e) {
285+ throw new CertPathValidatorException("Unable to generate " +
286+ "key with inherited parameters: " + e.getMessage(), e);
287+ }
288+ }
289+ }
290+
291+ // reset the previous public key
292+ prevPubKey = currPubKey;
293+
294+ // check the extended key usage, ignore the check now
295+ // List<String> extendedKeyUsages = x509Cert.getExtendedKeyUsage();
296+
297+ // DO NOT remove any unresolved critical extensions
298+ }
299+
300+ /**
301+ * Try to set the trust anchor of the checker.
302+ * <p>
303+ * If there is no trust anchor specified and the checker has not started,
304+ * set the trust anchor.
305+ *
306+ * @param anchor the trust anchor selected to validate the target
307+ * certificate
308+ */
309+ void trySetTrustAnchor(TrustAnchor anchor) {
310+ // Don't bother if the check has started or trust anchor has already
311+ // specified.
312+ if (prevPubKey == null) {
313+ if (anchor == null) {
314+ throw new IllegalArgumentException(
315+ "The trust anchor cannot be null");
316+ }
317+
318+ // Don't bother to change the trustedPubKey.
319+ if (anchor.getTrustedCert() != null) {
320+ prevPubKey = anchor.getTrustedCert().getPublicKey();
321+ } else {
322+ prevPubKey = anchor.getCAPublicKey();
323+ }
324+ }
325+ }
326+
327+ /**
328+ * Check the signature algorithm with the specified public key.
329+ *
330+ * @param key the public key to verify the CRL signature
331+ * @param crl the target CRL
332+ */
333+ static void check(PublicKey key, X509CRL crl)
334+ throws CertPathValidatorException {
335+
336+ X509CRLImpl x509CRLImpl = null;
337+ try {
338+ x509CRLImpl = X509CRLImpl.toImpl(crl);
339+ } catch (CRLException ce) {
340+ throw new CertPathValidatorException(ce);
341+ }
342+
343+ AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
344+ check(key, algorithmId);
345+ }
346+
347+ /**
348+ * Check the signature algorithm with the specified public key.
349+ *
350+ * @param key the public key to verify the CRL signature
351+ * @param crl the target CRL
352+ */
353+ static void check(PublicKey key, AlgorithmId algorithmId)
354+ throws CertPathValidatorException {
355+ String sigAlgName = algorithmId.getName();
356+ AlgorithmParameters sigAlgParams = algorithmId.getParameters();
357+
358+ if (!certPathDefaultConstraints.permits(
359+ SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
360+ throw new CertPathValidatorException(
361+ "algorithm check failed: " + sigAlgName + " is disabled",
362+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
363+ }
364+ }
365+
366+}
367+