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 Alexander Y. Kleymenov
20 */
21
22package org.apache.harmony.security.tests.x509;
23
24
25import java.io.ByteArrayInputStream;
26import java.io.IOException;
27import java.math.BigInteger;
28import java.security.cert.CertificateFactory;
29import java.security.cert.X509CRL;
30import java.security.cert.X509CRLEntry;
31import java.util.Arrays;
32import java.util.Date;
33import java.util.List;
34import java.util.Set;
35
36import junit.framework.Test;
37import junit.framework.TestCase;
38import junit.framework.TestSuite;
39
40import org.apache.harmony.security.asn1.ASN1GeneralizedTime;
41import org.apache.harmony.security.asn1.ASN1Integer;
42import org.apache.harmony.security.x501.Name;
43import org.apache.harmony.security.x509.AlgorithmIdentifier;
44import org.apache.harmony.security.x509.CertificateList;
45import org.apache.harmony.security.x509.Extension;
46import org.apache.harmony.security.x509.Extensions;
47import org.apache.harmony.security.x509.GeneralName;
48import org.apache.harmony.security.x509.GeneralNames;
49import org.apache.harmony.security.x509.TBSCertList;
50
51/**
52 * CertificateListTest
53 */
54public class CertificateListTest extends TestCase {
55
56    // OID was taken from http://oid.elibel.tm.fr
57    private static String algOID = "1.2.840.10040.4.3";
58    //private static String algName         = "SHA1withDSA";
59    private static byte[] algParams = { 1, 1, 0 }; // DER boolean false encoding
60    private static AlgorithmIdentifier signature;
61    private static byte[] signatureValue = new byte[10];
62
63    static {
64        signature = new AlgorithmIdentifier(algOID, algParams);
65    }
66
67    private static String issuerName = "O=Certificate Issuer";
68    private static Date thisUpdate = new Date();
69    private static Date nextUpdate;
70
71    static {
72        nextUpdate = new Date(thisUpdate.getTime() + 100000);
73    }
74
75    private static Extension crlEntryExtension;
76
77    static {
78        // Invalidity Date Extension (rfc 3280)
79        crlEntryExtension = new Extension("2.5.29.24",
80                ASN1GeneralizedTime.getInstance().encode(new Date()));
81    }
82
83    private static Extensions crlEntryExtensions = new Extensions();
84
85    static {
86        //*
87        crlEntryExtensions.addExtension(crlEntryExtension);
88        // add the Certificate Issuer Extension to check if implementation
89        // support indirect CRLs. As says rfc 3280 (p.62):
90        // "If used by conforming CRL issuers, this extension MUST always be
91        // critical. If an implementation ignored this extension it could not
92        // correctly attribute CRL entries to certificates. This specification
93        // RECOMMENDS that implementations recognize this extension."
94        try {
95            crlEntryExtensions.addExtension(
96                    new Extension("2.5.29.29", true,
97                            //*
98                            //ASN1OctetString.getInstance().encode(
99                            GeneralNames.ASN1.encode(
100                                    new GeneralNames(Arrays.asList(
101                                            new GeneralName[] {
102                                                    new GeneralName(new Name("O=Cert Organization"))//new GeneralName(4, "O=Organization")
103                                            })
104                                    )
105                            )
106                            //)
107                            //*/
108                    )
109            );
110        } catch (Exception e) {
111            e.printStackTrace();
112        }
113        //*/
114    }
115
116    private static Date revocationDate = new Date();
117    private static List revokedCertificates = Arrays.asList(
118            new TBSCertList.RevokedCertificate[] {
119                    new TBSCertList.RevokedCertificate(BigInteger.valueOf(555),
120                            revocationDate, null),//crlEntryExtensions),
121                    new TBSCertList.RevokedCertificate(BigInteger.valueOf(666),
122                            revocationDate, crlEntryExtensions),
123                    new TBSCertList.RevokedCertificate(BigInteger.valueOf(777),
124                            revocationDate, null),//crlEntryExtensions)
125            });
126    private static Extensions crlExtensions = new Extensions(
127            Arrays.asList(new Extension[] {
128                    new Extension("2.5.29.20", // CRL Number Extension (rfc 3280)
129                            ASN1Integer.getInstance().encode(
130                                    BigInteger.valueOf(4444).toByteArray())),
131            }));
132
133    private CertificateList certificateList;
134    private TBSCertList tbscertlist;
135    private byte[] encoding;
136
137    protected void setUp() throws java.lang.Exception {
138        try {
139            Name issuer = new Name(issuerName);
140
141            tbscertlist =
142                    new TBSCertList(2, signature, issuer, thisUpdate,
143                            nextUpdate, revokedCertificates, crlExtensions);
144
145            certificateList =
146                    new CertificateList(tbscertlist, signature, signatureValue);
147
148            encoding = CertificateList.ASN1.encode(certificateList);
149
150            certificateList = (CertificateList)
151                    CertificateList.ASN1.decode(encoding);
152
153        } catch (IOException e) {
154            e.printStackTrace();
155            fail("Unexpected IOException was thrown: " + e.getMessage());
156        }
157    }
158
159
160    /**
161     * CertificateList(TBSCertList tbsCertList, AlgorithmIdentifier
162     * signatureAlgorithm, byte[] signatureValue) method testing.
163     */
164    public void testCertificateList() {
165        try {
166            AlgorithmIdentifier signature =
167                    new AlgorithmIdentifier(algOID, algParams);
168            Name issuer = new Name(issuerName);
169            TBSCertList tbscl =
170                    new TBSCertList(signature, issuer, thisUpdate);
171            CertificateList cl =
172                    new CertificateList(tbscl, signature, new byte[] { 0 });
173
174            byte[] encoding = CertificateList.ASN1.encode(cl);
175            CertificateList.ASN1.decode(encoding);
176
177            tbscl = new TBSCertList(2, signature, issuer, thisUpdate,
178                    nextUpdate, revokedCertificates, crlExtensions);
179
180            cl = new CertificateList(tbscl, signature, new byte[] { 0 });
181
182            encoding = CertificateList.ASN1.encode(cl);
183            CertificateList.ASN1.decode(encoding);
184
185        } catch (IOException e) {
186            e.printStackTrace();
187            fail("Unexpected IOException was thrown: " + e.getMessage());
188        }
189    }
190
191    /**
192     * getTbsCertList() method testing.
193     */
194    public void testGetTbsCertList() {
195        assertTrue("Returned tbsCertList value is incorrect",
196                tbscertlist.equals(certificateList.getTbsCertList()));
197    }
198
199    /**
200     * getSignatureAlgorithm() method testing.
201     */
202    public void testGetSignatureAlgorithm() {
203        assertTrue("Returned signatureAlgorithm value is incorrect",
204                signature.equals(certificateList.getSignatureAlgorithm()));
205    }
206
207    /**
208     * getSignatureValue() method testing.
209     */
210    public void testGetSignatureValue() {
211        assertTrue("Returned signatureAlgorithm value is incorrect",
212                Arrays.equals(signatureValue, certificateList.getSignatureValue()));
213    }
214
215    public void testSupportIndirectCRLs() throws Exception {
216        X509CRL crl = (X509CRL)
217                CertificateFactory.getInstance("X.509").generateCRL(
218                        new ByteArrayInputStream(encoding));
219        Set rcerts = crl.getRevokedCertificates();
220        System.out.println(">> rcerts:" + rcerts);
221
222        System.out.println("}>> " + rcerts.toArray()[0]);
223        System.out.println("}>> " + ((X509CRLEntry) rcerts.toArray()[0]).getCertificateIssuer());
224        System.out.println("}>> " + ((X509CRLEntry) rcerts.toArray()[1]).getCertificateIssuer());
225        System.out.println("}>> " + ((X509CRLEntry) rcerts.toArray()[2]).getCertificateIssuer());
226        System.out.println(">> " + crl.getRevokedCertificate(
227                BigInteger.valueOf(555)).getCertificateIssuer());
228    }
229
230    public static Test suite() {
231        return new TestSuite(CertificateListTest.class);
232    }
233
234}
235