Home | History | Annotate | Download | only in cert
      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 * @author Alexander Y. Kleymenov
     19 */
     20 
     21 package org.apache.harmony.security.tests.provider.cert;
     22 
     23 import java.io.ByteArrayInputStream;
     24 import java.io.IOException;
     25 import java.math.BigInteger;
     26 import java.security.KeyPair;
     27 import java.security.KeyPairGenerator;
     28 import java.security.PrivateKey;
     29 import java.security.PublicKey;
     30 import java.security.Signature;
     31 import java.security.cert.CRLException;
     32 import java.security.cert.CertificateFactory;
     33 import java.util.Arrays;
     34 import java.util.Date;
     35 import java.util.List;
     36 import java.util.Set;
     37 
     38 import javax.security.auth.x500.X500Principal;
     39 
     40 import junit.framework.Test;
     41 import junit.framework.TestCase;
     42 import junit.framework.TestSuite;
     43 
     44 import org.apache.harmony.security.provider.cert.X509CRLImpl;
     45 import org.apache.harmony.security.provider.cert.X509CertImpl;
     46 import org.apache.harmony.security.x501.Name;
     47 import org.apache.harmony.security.x509.AlgorithmIdentifier;
     48 import org.apache.harmony.security.x509.AuthorityKeyIdentifier;
     49 import org.apache.harmony.security.x509.CRLNumber;
     50 import org.apache.harmony.security.x509.Certificate;
     51 import org.apache.harmony.security.x509.CertificateIssuer;
     52 import org.apache.harmony.security.x509.CertificateList;
     53 import org.apache.harmony.security.x509.DistributionPointName;
     54 import org.apache.harmony.security.x509.Extension;
     55 import org.apache.harmony.security.x509.Extensions;
     56 import org.apache.harmony.security.x509.GeneralName;
     57 import org.apache.harmony.security.x509.GeneralNames;
     58 import org.apache.harmony.security.x509.InvalidityDate;
     59 import org.apache.harmony.security.x509.IssuingDistributionPoint;
     60 import org.apache.harmony.security.x509.ReasonCode;
     61 import org.apache.harmony.security.x509.ReasonFlags;
     62 import org.apache.harmony.security.x509.SubjectPublicKeyInfo;
     63 import org.apache.harmony.security.x509.TBSCertList;
     64 import org.apache.harmony.security.x509.TBSCertificate;
     65 import org.apache.harmony.security.x509.Validity;
     66 
     67 /**
     68  * X509CRLImplTest
     69  */
     70 public class X509CRLImplTest extends TestCase {
     71 
     72     // Algorithm name and its OID (http://oid.elibel.tm.fr)
     73     private static String algOID          = "1.2.840.10040.4.3";
     74     private static String algName         = "SHA1withDSA";
     75     // DER boolean false encoding (http://asn1.elibel.tm.fr)
     76     // Makes no sense. For testing purposes we need just provide
     77     // some ASN.1 structure:
     78     private static byte[] algParams       = {1, 1, 0};
     79     private static AlgorithmIdentifier signature;
     80     private static byte[] signatureValue;
     81     static {
     82         signature = new AlgorithmIdentifier(algOID, algParams);
     83     }
     84     private static String issuerName      = "O=CRL Issuer";
     85     private static String certIssuerName      = "O=Certificate Issuer";
     86 
     87     private static BigInteger certSerialNumber1 = BigInteger.valueOf(555);
     88     private static BigInteger certSerialNumber2 = BigInteger.valueOf(567);
     89     private static BigInteger certSerialNumber3 = BigInteger.valueOf(777);
     90 
     91     private static Date thisUpdate = new Date();
     92     private static Date nextUpdate;
     93     static {
     94         nextUpdate = new Date(thisUpdate.getTime()+100000);
     95     }
     96     private static Extensions crlEntryExtensions = new Extensions();
     97     static {
     98         // Reason Code
     99         crlEntryExtensions.addExtension(
    100                 new Extension("2.5.29.21", Extension.NON_CRITICAL,
    101                     new ReasonCode(ReasonCode.KEY_COMPROMISE)));
    102         // Invalidity Date Extension
    103         crlEntryExtensions.addExtension(
    104                 new Extension("2.5.29.24", Extension.NON_CRITICAL,
    105                     new InvalidityDate(new Date())));
    106         // add the Certificate Issuer Extension to check if implementation
    107         // support indirect CRLs. As says rfc 3280 (p.62):
    108         // "If used by conforming CRL issuers, this extension MUST always be
    109         // critical. If an implementation ignored this extension it could not
    110         // correctly attribute CRL entries to certificates. This specification
    111         // RECOMMENDS that implementations recognize this extension."
    112         try {
    113             crlEntryExtensions.addExtension(
    114                     new Extension("2.5.29.29", true,
    115                         new CertificateIssuer(
    116                             new GeneralName(new Name(certIssuerName))
    117                             ))
    118             );
    119         } catch (Exception e) {
    120             e.printStackTrace();
    121         }
    122     }
    123     private static Date revocationDate = new Date();
    124     private static List revokedCertificates = Arrays.asList(
    125             new TBSCertList.RevokedCertificate[] {
    126                 new TBSCertList.RevokedCertificate(certSerialNumber1,
    127                     revocationDate, null),
    128                 // the item for certificate issued by other authority
    129                 new TBSCertList.RevokedCertificate(certSerialNumber2,
    130                     revocationDate, crlEntryExtensions),
    131                 new TBSCertList.RevokedCertificate(certSerialNumber3,
    132                     revocationDate, null),
    133             });
    134     private static Extensions crlExtensions;
    135     static {
    136         try {
    137             crlExtensions = new Extensions(
    138                 Arrays.asList(new Extension[] {
    139                     // CRL Number Extension
    140                     new Extension("2.5.29.20", Extension.NON_CRITICAL,
    141                         new CRLNumber(BigInteger.valueOf(4444))),
    142                     // Authority Key Identifier
    143                     new Extension("2.5.29.35", false,
    144                         new AuthorityKeyIdentifier(
    145                             // keyIdentifier (random value)
    146                             new byte[] {1, 2, 3, 4, 5},
    147                             // authorityCertIssuer
    148                             new GeneralNames(
    149                                 Arrays.asList(new GeneralName[] {
    150                                     new GeneralName(new Name(certIssuerName))
    151                             })),
    152                             // authorityCertSerialNumber
    153                             certSerialNumber2)),
    154                     // Issuing Distribution Point
    155                     new Extension("2.5.29.28", Extension.CRITICAL,
    156                         new IssuingDistributionPoint(
    157                             new DistributionPointName(new GeneralNames(
    158                                 Arrays.asList(new GeneralName[] {
    159                                     new GeneralName(1, "rfc (at) 822.Name"),
    160                                     new GeneralName(2, "dNSName"),
    161                                     new GeneralName(4, "O=Organization"),
    162                                     new GeneralName(6, "http://uniform.Resource.Id"),
    163                                     new GeneralName(7, "255.255.255.0"),
    164                                     new GeneralName(8, "1.2.3.4444.55555")
    165                                 }))),
    166                             new ReasonFlags(new boolean[] {true, true, false, false, true, true})
    167                             )),
    168                 }));
    169         } catch (Exception e) {
    170             e.printStackTrace();
    171         }
    172     }
    173 
    174     // keys are using to make signature and to verify it
    175     private static PublicKey   publicKey;
    176     private static PrivateKey  privateKey;
    177     private static byte[] signatureValueBytes;
    178     static {
    179         try {
    180             KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
    181             keyGen.initialize(1024);
    182             KeyPair keyPair = keyGen.genKeyPair();
    183             publicKey = keyPair.getPublic();
    184             privateKey = keyPair.getPrivate();
    185         } catch (Exception e) {
    186             e.printStackTrace();
    187         }
    188     }
    189 
    190     private static X509CRLImpl crl;
    191     private static CertificateList certificateList;
    192     private static TBSCertList tbscertlist;
    193     private static byte[] encoding;
    194     private static byte[] tbsEncoding;
    195     static CertificateFactory factory;
    196 
    197     static {
    198         try {
    199             Name issuer = new Name(issuerName);
    200 
    201             tbscertlist =
    202                 new TBSCertList(2, signature, issuer, thisUpdate,
    203                     nextUpdate, revokedCertificates, crlExtensions);
    204 
    205             tbsEncoding = tbscertlist.getEncoded();
    206 
    207             try {
    208                 Signature sig= Signature.getInstance("DSA");
    209                 sig.initSign(privateKey);
    210                 sig.update(tbsEncoding, 0, tbsEncoding.length);
    211                 signatureValueBytes = sig.sign();
    212             } catch (Exception e) {
    213                 e.printStackTrace();
    214                 fail("Unexpected exception was thrown: "+e.getMessage());
    215             }
    216             factory = CertificateFactory.getInstance("X.509");
    217         } catch (Exception e) {
    218             e.printStackTrace();
    219             fail("Unexpected Exception was thrown: "+e.getMessage());
    220         }
    221     }
    222 
    223     ByteArrayInputStream stream;
    224 
    225     protected void setUp() throws java.lang.Exception {
    226         if ("testVerify3".equals(getName())) {
    227             signatureValue = new byte[signatureValueBytes.length];
    228             // make incorrect signature value:
    229             System.arraycopy(signatureValueBytes, 0,
    230                     signatureValue, 0, signatureValueBytes.length);
    231             signatureValue[20]++;
    232         } else {
    233             signatureValue = signatureValueBytes;
    234         }
    235         certificateList =
    236             new CertificateList(tbscertlist, signature, signatureValue);
    237 
    238         encoding = CertificateList.ASN1.encode(certificateList);
    239         stream = new ByteArrayInputStream(encoding);
    240 
    241         crl = new X509CRLImpl(certificateList);
    242     }
    243 
    244     private static int XXX = 0, counter = 0;
    245 
    246     public void testCreationCRL() throws Exception {
    247         byte[] stamp = new byte[10];
    248         if ((++counter)%10 != 0) {
    249             XXX++;
    250         }
    251         byte tmp[] = BigInteger.valueOf(XXX).toByteArray();
    252         System.arraycopy(tmp, 0, stamp, 0, tmp.length);
    253         System.arraycopy(stamp, 0, encoding,
    254                 encoding.length-stamp.length, stamp.length);
    255 
    256         stream.reset();
    257         java.security.cert.X509CRL c = (java.security.cert.X509CRL)
    258             factory.generateCRL(stream);
    259 
    260         if (counter == 1) {
    261             System.out.println("\nUSING: "+ c.getClass());
    262         }
    263 
    264         byte[] enc = c.getEncoded();
    265         byte[] stamp_chek = new byte[stamp.length];
    266 
    267         System.arraycopy(enc, enc.length - stamp.length,
    268                 stamp_chek, 0, stamp.length);
    269 
    270         if (!Arrays.equals(stamp, stamp_chek)) {
    271             fail("Wrong encoding received.");
    272         }
    273     }
    274 
    275     /**
    276      * X509CRLImpl(CertificateList crl) method testing.
    277      * Tested during setup.
    278      */
    279     public void testX509CRLImpl() {
    280         try {
    281             new X509CRLImpl((CertificateList)
    282                     CertificateList.ASN1.decode(encoding));
    283         } catch (IOException e) {
    284             fail("Unexpected exception was thrown");
    285         }
    286     }
    287 
    288     /**
    289      * getEncoded() method testing.
    290      */
    291     public void testGetEncoded() {
    292         try {
    293             if (!Arrays.equals(encoding, crl.getEncoded())) {
    294                 fail("Incorrect encoding of CRL.");
    295             }
    296         } catch (CRLException e) {
    297             fail("Unexpected CRLException was thrown.");
    298         }
    299     }
    300 
    301     /**
    302      * getVersion() method testing.
    303      */
    304     public void testGetVersion() {
    305         assertEquals("Incorrect version value", 2, crl.getVersion());
    306     }
    307 
    308     /**
    309      * getIssuerDN() method testing.
    310      */
    311     public void testGetIssuerDN() {
    312         assertEquals("Incorrect issuer value",
    313                 new X500Principal(issuerName), crl.getIssuerDN());
    314     }
    315 
    316     /**
    317      * getIssuerX500Principal() method testing.
    318      */
    319     public void testGetIssuerX500Principal() {
    320         assertEquals("Incorrect issuer value",
    321                 new X500Principal(issuerName), crl.getIssuerDN());
    322     }
    323 
    324     /**
    325      * getThisUpdate() method testing.
    326      */
    327     public void testGetThisUpdate() {
    328         assertTrue("Incorrect thisUpdate value",
    329                 thisUpdate.getTime()/1000 == crl.getThisUpdate().getTime()/1000);
    330     }
    331 
    332     /**
    333      * getNextUpdate() method testing.
    334      */
    335     public void testGetNextUpdate() {
    336         assertTrue("Incorrect nextUpdate value",
    337                 nextUpdate.getTime()/1000 == crl.getNextUpdate().getTime()/1000);
    338     }
    339 
    340     /**
    341      * getRevokedCertificate(X509Certificate certificate) method testing.
    342      */
    343     public void testGetRevokedCertificate1() {
    344         try {
    345             X509CertImpl cert1 = new X509CertImpl(
    346                 new Certificate(
    347                     new TBSCertificate(2, certSerialNumber1, signature,
    348                         new Name(certIssuerName),
    349                         new Validity(new Date(), new Date()),
    350                     new Name(certIssuerName),
    351                     new SubjectPublicKeyInfo(signature, new byte[10]),
    352                     null, null, null),
    353                 signature, new byte[10]));
    354             X509CertImpl cert2 = new X509CertImpl(
    355                 new Certificate(
    356                     new TBSCertificate(2, certSerialNumber2, signature,
    357                         new Name(certIssuerName),
    358                         new Validity(new Date(), new Date()),
    359                     new Name(certIssuerName),
    360                     new SubjectPublicKeyInfo(signature, new byte[10]),
    361                     null, null, null),
    362                 signature, new byte[10]));
    363             X509CertImpl cert3 = new X509CertImpl(
    364                 new Certificate(
    365                     new TBSCertificate(2, certSerialNumber3, signature,
    366                         new Name("O=Another Cert Issuer"),
    367                         new Validity(new Date(), new Date()),
    368                     new Name(certIssuerName),
    369                     new SubjectPublicKeyInfo(signature, new byte[10]),
    370                     null, null, null),
    371                 signature, new byte[10]));
    372             assertNull("Certificate should not be presented in CRL "
    373                     + "because issuer is not the same as CRL issuer",
    374                     crl.getRevokedCertificate(cert1));
    375             assertNotNull("Certificate should be presented in CRL",
    376                     crl.getRevokedCertificate(cert2));
    377             assertNull("Certificate should not be presented in CRL "
    378                     + "because issuer is not the same as CRL issuer",
    379                     crl.getRevokedCertificate(cert3));
    380         } catch (IOException e) {
    381             // should never happen;
    382             e.printStackTrace();
    383             fail("Unexpected IOException was thrown:"+e.getMessage());
    384         }
    385     }
    386 
    387     /**
    388      * getRevokedCertificate(BigInteger serialNumber) method testing.
    389      */
    390     public void testGetRevokedCertificate2() {
    391         assertNotNull("The revoked certificate with the serial number '"
    392                 + certSerialNumber1 + "' should be presented in CRL.",
    393                 crl.getRevokedCertificate(certSerialNumber1));
    394         assertNull("The revoked certificate with the serial number '"
    395                 + certSerialNumber2 + "' should not be presented in CRL.",
    396                 crl.getRevokedCertificate(certSerialNumber2));
    397         assertNull("The revoked certificate with the serial number '"
    398                 + certSerialNumber3 + "' should not be presented in CRL.",
    399                 crl.getRevokedCertificate(certSerialNumber3));
    400     }
    401 
    402     /**
    403      * getRevokedCertificates() method testing.
    404      */
    405     public void testGetRevokedCertificates() {
    406         Set rcerts = crl.getRevokedCertificates();
    407         assertNotNull("The set should not be null", rcerts);
    408         assertTrue("The size of returned set is incorrect",
    409                 rcerts.size() == revokedCertificates.size());
    410     }
    411 
    412     /**
    413      * getTBSCertList() method testing.
    414      */
    415     public void testGetTBSCertList() {
    416         try {
    417             assertTrue(
    418                 "Retrieved tbsCertList encoding does not equal to expected",
    419                 Arrays.equals(tbscertlist.getEncoded(),
    420                 crl.getTBSCertList()));
    421         } catch(CRLException e) {
    422             e.printStackTrace();
    423             fail("Unexpected CRLException was thrown: "+e.getMessage());
    424         }
    425     }
    426 
    427     /**
    428      * getSignature() method testing.
    429      */
    430     public void testGetSignature() {
    431         if (!Arrays.equals(signatureValueBytes, crl.getSignature())) {
    432             fail("Incorrect Signature value.");
    433         }
    434     }
    435 
    436     /**
    437      * getSigAlgName() method testing.
    438      */
    439     public void testGetSigAlgName() {
    440         assertEquals("Incorrect value of signature algorithm name",
    441                 algName, crl.getSigAlgName());
    442     }
    443 
    444     /**
    445      * getSigAlgOID() method testing.
    446      */
    447     public void testGetSigAlgOID() {
    448         assertEquals("Incorrect value of signature algorithm OID",
    449                 algOID, crl.getSigAlgOID());
    450     }
    451 
    452     /**
    453      * getSigAlgParams() method testing.
    454      */
    455     public void testGetSigAlgParams() {
    456         if (!Arrays.equals(algParams, crl.getSigAlgParams())) {
    457             fail("Incorrect SigAlgParams value.");
    458         }
    459     }
    460 
    461     /**
    462      * verify(PublicKey key) method testing.
    463      */
    464     public void testVerify1() throws Exception {
    465         crl.verify(publicKey);
    466     }
    467 
    468     /**
    469      * verify(PublicKey key, String sigProvider) method testing.
    470      */
    471     public void testVerify2() throws Exception {
    472         crl.verify(publicKey, Signature.getInstance("SHA1withDSA")
    473                 .getProvider().getName());
    474     }
    475 
    476     /**
    477      * verify(PublicKey key) method testing.
    478      */
    479     public void testVerify3() throws Exception {
    480         try {
    481             crl.verify(publicKey);
    482             fail("Incorrect signature successfully verified.");
    483         } catch (Exception e) {
    484         }
    485     }
    486 
    487     /**
    488      * isRevoked(Certificate cert) method testing.
    489      */
    490     public void testIsRevoked() {
    491         try {
    492             X509CertImpl cert1 = new X509CertImpl(
    493                 new Certificate(
    494                     new TBSCertificate(2, certSerialNumber1, signature,
    495                         new Name(certIssuerName),
    496                         new Validity(new Date(), new Date()),
    497                     new Name(certIssuerName),
    498                     new SubjectPublicKeyInfo(signature, new byte[10]),
    499                     null, null, null),
    500                 signature, new byte[10]));
    501             X509CertImpl cert2 = new X509CertImpl(
    502                 new Certificate(
    503                     new TBSCertificate(2, certSerialNumber2, signature,
    504                         new Name(certIssuerName),
    505                         new Validity(new Date(), new Date()),
    506                     new Name(certIssuerName),
    507                     new SubjectPublicKeyInfo(signature, new byte[10]),
    508                     null, null, null),
    509                 signature, new byte[10]));
    510             X509CertImpl cert3 = new X509CertImpl(
    511                 new Certificate(
    512                     new TBSCertificate(2, certSerialNumber3, signature,
    513                         new Name("O=Another Cert Issuer"),
    514                         new Validity(new Date(), new Date()),
    515                     new Name(certIssuerName),
    516                     new SubjectPublicKeyInfo(signature, new byte[10]),
    517                     null, null, null),
    518                 signature, new byte[10]));
    519             assertFalse("Certificate should not be presented in CRL "
    520                     + "because issuer is not the same as CRL issuer",
    521                     crl.isRevoked(cert1));
    522             assertTrue("Certificate should be presented in CRL",
    523                     crl.isRevoked(cert2));
    524             assertFalse("Certificate should not be presented in CRL "
    525                     + "because issuer is not the same as CRL issuer",
    526                     crl.isRevoked(cert3));
    527         } catch (IOException e) {
    528             // should never happen;
    529             e.printStackTrace();
    530             fail("Unexpected IOException was thrown:"+e.getMessage());
    531         }
    532     }
    533 
    534     /**
    535      * toString() method testing.
    536      */
    537     public void testToString() {
    538         assertNotNull("The string representation should not be null",
    539                 crl.toString());
    540     }
    541 
    542     // the following implementations are tested in X509CertImplTest:
    543 
    544     /**
    545      * getNonCriticalExtensionOIDs() method testing.
    546      */
    547     public void testGetNonCriticalExtensionOIDs() {
    548         System.out.println("getNonCriticalExtensionOIDs: "
    549                 + crl.getNonCriticalExtensionOIDs());
    550     }
    551 
    552     /**
    553      * getCriticalExtensionOIDs() method testing.
    554      */
    555     public void testGetCriticalExtensionOIDs() {
    556         System.out.println("getCriticalExtensionOIDs: "
    557                 + crl.getCriticalExtensionOIDs());
    558     }
    559 
    560     /**
    561      * getExtensionValue(String oid) method testing.
    562      */
    563     public void testGetExtensionValue() throws Exception {
    564         assertNotNull(crl.getExtensionValue("2.5.29.20"));
    565         assertNull("Null value should be returned in the case of "
    566                 + "nonexisting extension", crl.getExtensionValue("1.1.1.1"));
    567     }
    568 
    569     /**
    570      * hasUnsupportedCriticalExtension() method testing.
    571      */
    572     public void testHasUnsupportedCriticalExtension() {
    573         System.out.println("hasUnsupportedCriticalExtension: "
    574                 + crl.hasUnsupportedCriticalExtension());
    575     }
    576 
    577     public static Test suite() {
    578         return new TestSuite(X509CRLImplTest.class);
    579     }
    580 
    581 }
    582