1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19 * @author Vladimir N. Molotkov
20 */
21
22package org.apache.harmony.security.tests.support.cert;
23
24import java.io.BufferedInputStream;
25import java.io.ByteArrayInputStream;
26import java.io.FileNotFoundException;
27import java.io.IOException;
28import java.io.UnsupportedEncodingException;
29import java.security.InvalidAlgorithmParameterException;
30import java.security.KeyStore;
31import java.security.NoSuchAlgorithmException;
32import java.security.cert.CertPathValidatorException;
33import java.security.cert.CertStore;
34import java.security.cert.Certificate;
35import java.security.cert.CertificateException;
36import java.security.cert.CertificateFactory;
37import java.security.cert.CollectionCertStoreParameters;
38import java.security.cert.PKIXCertPathChecker;
39import java.security.cert.PolicyNode;
40import java.security.cert.TrustAnchor;
41import java.security.cert.X509Certificate;
42import java.util.ArrayList;
43import java.util.Collection;
44import java.util.HashSet;
45import java.util.Iterator;
46import java.util.List;
47import java.util.Set;
48
49import tests.support.resource.Support_Resources;
50
51/**
52 * java.security.cert test utilities
53 */
54public class TestUtils {
55    // Certificate type used during testing
56    private static final String certType = "X.509";
57    // Key store type used during testing
58    private static final String keyStoreType = "BKS";
59    // The file name prefix to load keystore from
60    private static final String keyStoreFileName = "test." + keyStoreType
61            + ".ks";
62    //
63    // The file name suffixes to load keystore from
64    //  *.ks1 - keystore containing untrusted certificates only
65    //  *.ks2 - keystore containing trusted certificates only
66    //  *.ks3 - keystore containing both trusted and untrusted certificates
67    //
68    public static final int UNTRUSTED = 1;
69    public static final int TRUSTED = 2;
70    public static final int TRUSTED_AND_UNTRUSTED = 3;
71    //
72    // Common passwords for all test keystores
73    //
74    private final static char[] storepass =
75            new char[] { 's', 't', 'o', 'r', 'e', 'p', 'w', 'd' };
76
77    /**
78     * Creates <code>TrustAnchor</code> instance
79     * constructed using self signed test certificate
80     *
81     * @return <code>TrustAnchor</code> instance
82     * @throws CertificateException
83     * @throws FileNotFoundException
84     */
85    public static TrustAnchor getTrustAnchor() {
86        CertificateFactory cf = null;
87        try {
88            cf = CertificateFactory.getInstance(certType);
89        } catch (CertificateException e) {
90            // requested cert type is not available in the
91            // default provider package or any of the other provider packages
92            // that were searched
93            throw new RuntimeException(e);
94        }
95        BufferedInputStream bis = null;
96        try {
97            bis = new BufferedInputStream(new ByteArrayInputStream(
98                    getEncodedX509Certificate()));
99            X509Certificate c1 = (X509Certificate) cf.generateCertificate(bis);
100
101            return new TrustAnchor(c1, null);
102        } catch (Exception e) {
103            // all failures are fatal
104            throw new RuntimeException(e);
105        } finally {
106            if (bis != null) {
107                try {
108                    bis.close();
109                } catch (IOException ign) {
110                }
111            }
112        }
113    }
114
115    /**
116     * Creates <code>Set</code> of <code>TrustAnchor</code>s
117     * containing single element (self signed test certificate).
118     *
119     * @return Returns <code>Set</code> of <code>TrustAnchor</code>s
120     */
121    public static Set getTrustAnchorSet() {
122        TrustAnchor ta = getTrustAnchor();
123        if (ta == null) {
124            return null;
125        }
126        HashSet set = new HashSet();
127        if (!set.add(ta)) {
128            throw new RuntimeException("Could not create trust anchor set");
129        }
130        return set;
131    }
132
133    /**
134     * Creates test <code>KeyStore</code> instance
135     *
136     * @param initialize       Do not initialize returned <code>KeyStore</code> if false
137     * @param testKeyStoreType this parameter ignored if <code>initialize</code> is false;
138     *                         The following types supported:<br>
139     *                         1 - <code>KeyStore</code> with untrusted certificates only<br>
140     *                         2 - <code>KeyStore</code> with trusted certificates only<br>
141     *                         3 - <code>KeyStore</code> with both trusted and untrusted certificates
142     * @return Returns test <code>KeyStore</code> instance
143     */
144    public static KeyStore getKeyStore(boolean initialize,
145            int testKeyStoreType) {
146        BufferedInputStream bis = null;
147        try {
148            KeyStore ks = KeyStore.getInstance(keyStoreType);
149            if (initialize) {
150                String fileName = keyStoreFileName + testKeyStoreType;
151                ks.load(Support_Resources.getResourceStream(fileName),
152                        storepass);
153            }
154            return ks;
155        } catch (Exception e) {
156            throw new RuntimeException(e);
157        } finally {
158            if (initialize && bis != null) {
159                try {
160                    bis.close();
161                } catch (IOException ign) {
162                }
163            }
164        }
165    }
166
167    /**
168     * Creates <code>List</code> of <code>CollectionCertStores</code>
169     *
170     * @return The list created
171     * @throws InvalidAlgorithmParameterException
172     *
173     * @throws NoSuchAlgorithmException
174     */
175    public static List getCollectionCertStoresList()
176            throws InvalidAlgorithmParameterException,
177            NoSuchAlgorithmException {
178        CertStore cs = CertStore.getInstance("Collection",
179                new CollectionCertStoreParameters());
180        ArrayList l = new ArrayList();
181        if (!l.add(cs)) {
182            throw new RuntimeException("Could not create cert stores list");
183        }
184        return l;
185    }
186
187    /**
188     * Creates stub implementation of the <code>PKIXCertPathChecker</code>
189     *
190     * @return Stub implementation of the <code>PKIXCertPathChecker</code>
191     */
192    public static PKIXCertPathChecker getTestCertPathChecker() {
193        // stub implementation for testing purposes only
194        return new PKIXCertPathChecker() {
195            private boolean forward = false;
196
197            public void check(Certificate arg0, Collection arg1)
198                    throws CertPathValidatorException {
199            }
200
201            public Set getSupportedExtensions() {
202                return null;
203            }
204
205            public void init(boolean arg0) throws CertPathValidatorException {
206                forward = arg0;
207            }
208
209            public boolean isForwardCheckingSupported() {
210                // just to check this checker state
211                return forward;
212            }
213        };
214    }
215
216    /**
217     * Creates policy tree stub containing two <code>PolicyNode</code>s
218     * for testing purposes
219     *
220     * @return root <code>PolicyNode</code> of the policy tree
221     */
222    public static PolicyNode getPolicyTree() {
223        return new PolicyNode() {
224            final PolicyNode parent = this;
225
226            public int getDepth() {
227                // parent
228                return 0;
229            }
230
231            public boolean isCritical() {
232                return false;
233            }
234
235            public String getValidPolicy() {
236                return null;
237            }
238
239            public PolicyNode getParent() {
240                return null;
241            }
242
243            public Iterator getChildren() {
244                PolicyNode child = new PolicyNode() {
245                    public int getDepth() {
246                        // child
247                        return 1;
248                    }
249
250                    public boolean isCritical() {
251                        return false;
252                    }
253
254                    public String getValidPolicy() {
255                        return null;
256                    }
257
258                    public PolicyNode getParent() {
259                        return parent;
260                    }
261
262                    public Iterator getChildren() {
263                        return null;
264                    }
265
266                    public Set getExpectedPolicies() {
267                        return null;
268                    }
269
270                    public Set getPolicyQualifiers() {
271                        return null;
272                    }
273                };
274                HashSet s = new HashSet();
275                s.add(child);
276                return s.iterator();
277            }
278
279            public Set getExpectedPolicies() {
280                return null;
281            }
282
283            public Set getPolicyQualifiers() {
284                return null;
285            }
286        };
287    }
288
289    // X.509 encoded certificate
290    private static final String ENCODED_X509_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"
291            + "MIIDHTCCAtsCBEFT72swCwYHKoZIzjgEAwUAMHQxCzAJBgNVBAYTAlJVMQwwCgYDVQQIEwNOU08x\n"
292            + "FDASBgNVBAcTC05vdm9zaWJpcnNrMQ4wDAYDVQQKEwVJbnRlbDEVMBMGA1UECxMMRFJMIFNlY3Vy\n"
293            + "aXR5MRowGAYDVQQDExFWbGFkaW1pciBNb2xvdGtvdjAeFw0wNDA5MjQwOTU2NTlaFw0wNjA1MTcw\n"
294            + "OTU2NTlaMHQxCzAJBgNVBAYTAlJVMQwwCgYDVQQIEwNOU08xFDASBgNVBAcTC05vdm9zaWJpcnNr\n"
295            + "MQ4wDAYDVQQKEwVJbnRlbDEVMBMGA1UECxMMRFJMIFNlY3VyaXR5MRowGAYDVQQDExFWbGFkaW1p\n"
296            + "ciBNb2xvdGtvdjCCAbgwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3Ujzv\n"
297            + "RADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7\n"
298            + "qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8V\n"
299            + "IwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrU\n"
300            + "WU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEk\n"
301            + "O8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GFAAKBgQDiNmj9jgWu1ILYqYWcUhNN\n"
302            + "8CjjRitf80yWP/s/565wZz3anb2w72jum63mdShDko9eOOOd1hiVuiBnNhSL7D6JfIYBJvNXr1av\n"
303            + "Gw583BBv12OBgg0eAW/GRWBn2Ak2JjsoBc5x2c1HAEufakep7T6RoC+n3lqbKPKyHWVdfqQ9KTAL\n"
304            + "BgcqhkjOOAQDBQADLwAwLAIUaRS3C9dXcMbrOAhmidFBr7oMvH0CFEC3LUwfLJX5gY8P6uxpkPx3\n"
305            + "JDSM\n" + "-----END CERTIFICATE-----\n";
306
307    public static byte[] getEncodedX509Certificate() {
308        byte cert[];
309        try {
310            cert = ENCODED_X509_CERTIFICATE.getBytes("UTF-8");
311        } catch (UnsupportedEncodingException e) {
312            throw new RuntimeException(e.getMessage());
313        }
314        return cert;
315    }
316
317    /**
318     * Returns X.509 certificate encoding corresponding to version v1.
319     * <p/>
320     * Certificate encoding was created by hands according to X.509 Certificate
321     * ASN.1 notation. The certificate encoding has the following encoded
322     * field values:<br>
323     * - version: 1<br>
324     * - serialNumber: 5<br>
325     * - issuer: CN=Z<br>
326     * - notBefore: 13 Dec 1999 14:15:16<br>
327     * - notAfter: 01 Jan 2000 00:00:00<br>
328     * - subject: CN=Y<br>
329     *
330     * @return X.509 certificate encoding corresponding to version v1.
331     */
332    public static byte[] getX509Certificate_v1() {
333        return new byte[] {
334                // Certificate: SEQUENCE
335                0x30, 0x6B,
336
337                //
338                // TBSCertificate: SEQUENCE {
339                //
340                0x30, 0x5C,
341
342                // version: [0] EXPLICIT Version DEFAULT v1
343                (byte) 0xA0, 0x03, 0x02, 0x01, 0x00,
344
345                // serialNumber: CertificateSerialNumber
346                0x02, 0x01, 0x05,
347
348                // signature: AlgorithmIdentifier
349                0x30, 0x07, // SEQUENCE
350                0x06, 0x02, 0x03, 0x05,//OID
351                0x01, 0x01, 0x07, //ANY
352
353                //issuer: Name
354                0x30, 0x0C, 0x31, 0x0A, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04, 0x03,
355                0x13, 0x01, 0x5A, // CN=Z
356
357                //validity: Validity
358                0x30, 0x1E, // SEQUENCE
359                // notBefore: UTCTime
360                0x17, 0x0D, 0x39, 0x39, 0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x31,
361                0x35, 0x31, 0x36, 0x5A, // 13 Dec 1999 14:15:16
362                // notAfter:  UTCTime
363                0x17, 0x0D, 0x30, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
364                0x30, 0x30, 0x30, 0x5A, // 01 Jan 2000 00:00:00
365
366                //subject: Name
367                0x30, 0x0C, 0x31, 0x0A, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04, 0x03,
368                0x13, 0x01, 0x59, // CN=Y
369                //SubjectPublicKeyInfo  ::=  SEQUENCE  {
370                //    algorithm            AlgorithmIdentifier,
371                //    subjectPublicKey     BIT STRING  }
372                0x30, 0x0D, // SEQUENCE
373                0x30, 0x07, // SEQUENCE
374                0x06, 0x02, 0x03, 0x05,//OID
375                0x01, 0x01, 0x07, //ANY
376                0x03, 0x02, 0x00, 0x01, // subjectPublicKey
377
378                // issuerUniqueID - missed
379                // subjectUniqueID - missed
380                // extensions - missed
381
382                // } end TBSCertificate
383
384                //
385                // signatureAlgorithm: AlgorithmIdentifier
386                //
387                0x30, 0x07, // SEQUENCE
388                0x06, 0x02, 0x03, 0x05,//OID
389                0x01, 0x01, 0x07, //ANY
390
391                //
392                // signature: BIT STRING
393                //
394                0x03, 0x02, 0x00, 0x01 };
395    }
396
397    /**
398     * Returns X.509 certificate encoding corresponding to version v3.
399     * <p/>
400     * Certificate encoding was created by hands according to X.509 Certificate
401     * ASN.1 notation. The certificate encoding has the following encoded
402     * field values:<br>
403     * - version: 3<br>
404     * - serialNumber: 5<br>
405     * - issuer: CN=Z<br>
406     * - notBefore: 13 Dec 1999 14:15:16<br>
407     * - notAfter: 01 Jan 2000 00:00:00<br>
408     * - subject: CN=Y<br>
409     * - extensions:
410     * 1) AuthorityKeyIdentifier(OID=2.5.29.35): no values in it(empty sequence)
411     *
412     * @return X.509 certificate encoding corresponding to version v3.
413     */
414    public static byte[] getX509Certificate_v3() {
415        return new byte[] {
416                // Certificate: SEQUENCE
417                0x30, 0x7D,
418
419                //
420                // TBSCertificate: SEQUENCE {
421                //
422                0x30, 0x6E,
423
424                // version: [0] EXPLICIT Version DEFAULT v1
425                (byte) 0xA0, 0x03, 0x02, 0x01, 0x02,
426
427                // serialNumber: CertificateSerialNumber
428                0x02, 0x01, 0x05,
429
430                // signature: AlgorithmIdentifier
431                0x30, 0x07, // SEQUENCE
432                0x06, 0x02, 0x03, 0x05,//OID
433                0x01, 0x01, 0x07, //ANY
434
435                //issuer: Name
436                0x30, 0x0C, 0x31, 0x0A, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04, 0x03,
437                0x13, 0x01, 0x5A, // CN=Z
438
439                //validity: Validity
440                0x30, 0x1E, // SEQUENCE
441                // notBefore: UTCTime
442                0x17, 0x0D, 0x39, 0x39, 0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x31,
443                0x35, 0x31, 0x36, 0x5A, // 13 Dec 1999 14:15:16
444                // notAfter:  UTCTime
445                0x17, 0x0D, 0x30, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
446                0x30, 0x30, 0x30, 0x5A, // 01 Jan 2000 00:00:00
447
448                //subject: Name
449                0x30, 0x0C, 0x31, 0x0A, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04, 0x03,
450                0x13, 0x01, 0x59, // CN=Y
451                //SubjectPublicKeyInfo  ::=  SEQUENCE  {
452                //    algorithm            AlgorithmIdentifier,
453                //    subjectPublicKey     BIT STRING  }
454                0x30, 0x0D, // SEQUENCE
455                0x30, 0x07, // SEQUENCE
456                0x06, 0x02, 0x03, 0x05,//OID
457                0x01, 0x01, 0x07, //ANY
458                0x03, 0x02, 0x00, 0x01, // subjectPublicKey
459
460                // issuerUniqueID - missed
461                // subjectUniqueID - missed
462                // extensions : [3]  EXPLICIT Extensions OPTIONAL
463                (byte) 0xA3, 0x10,
464                // Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
465                0x30, 0x0E,
466                // Extension  ::=  SEQUENCE  {
467                // extnID      OBJECT IDENTIFIER,
468                // critical    BOOLEAN DEFAULT FALSE,
469                // extnValue   OCTET STRING  }
470
471                // 1) AuthorityKeyIdentifier extension (see HARMONY-3384)
472                0x30, 0x0C,
473                0x06, 0x03, 0x55, 0x1D, 0x23, // OID = 2.5.29.35
474                0x01, 0x01, 0x00, // critical = FALSE
475                0x04, 0x02, 0x30, 0x00, // extnValue: MUST be empty sequence
476                // missed: keyIdentifier
477                // missed: authorityCertIssuer
478                // missed" authorityCertSerialNumber
479
480                // } end TBSCertificate
481
482                //
483                // signatureAlgorithm: AlgorithmIdentifier
484                //
485                0x30, 0x07, // SEQUENCE
486                0x06, 0x02, 0x03, 0x05,//OID
487                0x01, 0x01, 0x07, //ANY
488
489                //
490                // signature: BIT STRING
491                //
492                0x03, 0x02, 0x00, 0x01 };
493    }
494
495    /**
496     * Returns X.509 CRL encoding corresponding to version v1.
497     * <p/>
498     * CRL encoding was created by hands according to X.509 CRL ASN.1
499     * notation. The CRL encoding has the following encoded field values:<br>
500     * - version: 1<br>
501     * - issuer: CN=Z<br>
502     * - thisUpdate: 01 Jan 2001 01:02:03<br>
503     *
504     * @return X.509 CRL encoding corresponding to version v1.
505     */
506    public static byte[] getX509CRL_v1() {
507        return new byte[] {
508                //CertificateList: SEQUENCE
509                0x30, 0x35,
510
511                // TBSCertList: SEQUENCE
512                0x30, 0x27,
513                // Version: INTEGER OPTIONAL
514                // 0x02, 0x01, 0x01, - missed here cause it is v1
515                // signature: AlgorithmIdentifier
516                0x30, 0x06, // SEQUENCE
517                0x06, 0x01, 0x01, // OID
518                0x01, 0x01, 0x11, // ANY
519                // issuer: Name
520                0x30, 0x0C, 0x31, 0x0A, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04,
521                0x03, 0x13, 0x01, 0x5A, // CN=Z
522                // thisUpdate: ChoiceOfTime
523                // GeneralizedTime: 01 Jan 2001 01:02:03
524                0x18, 0x0F, 0x32, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
525                0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x5A,
526
527                // nextUpdate - missed
528                // revokedCertificates - missed
529                // crlExtensions - missed
530
531                // signatureAlgorithm: AlgorithmIdentifier
532                0x30, 0x06, // SEQUENCE
533                0x06, 0x01, 0x01, //OID
534                0x01, 0x01, 0x11, //ANY
535                // signature: BIT STRING
536                0x03, 0x02, 0x00, 0x01 };
537    }
538}
539