1/*
2 * Copyright (c) 2003, 2004, 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
26package sun.security.pkcs;
27
28import java.io.IOException;
29import java.util.ArrayList;
30
31import sun.security.util.HexDumpEncoder;
32import sun.security.util.DerInputStream;
33import sun.security.util.DerValue;
34import sun.security.x509.GeneralNames;
35import sun.security.x509.SerialNumber;
36
37/**
38 * This class represents a signing certificate attribute.
39 * Its attribute value is defined by the following ASN.1 definition.
40 * <pre>
41 *
42 *   id-aa-signingCertificate OBJECT IDENTIFIER ::= { iso(1)
43 *     member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
44 *     smime(16) id-aa(2) 12 }
45 *
46 *   SigningCertificate ::=  SEQUENCE {
47 *       certs       SEQUENCE OF ESSCertID,
48 *       policies    SEQUENCE OF PolicyInformation OPTIONAL
49 *   }
50 *
51 *   ESSCertID ::=  SEQUENCE {
52 *       certHash        Hash,
53 *       issuerSerial    IssuerSerial OPTIONAL
54 *   }
55 *
56 *   Hash ::= OCTET STRING -- SHA1 hash of entire certificate
57 *
58 *   IssuerSerial ::= SEQUENCE {
59 *       issuer         GeneralNames,
60 *       serialNumber   CertificateSerialNumber
61 *   }
62 *
63 *   PolicyInformation ::= SEQUENCE {
64 *       policyIdentifier   CertPolicyId,
65 *       policyQualifiers   SEQUENCE SIZE (1..MAX) OF
66 *               PolicyQualifierInfo OPTIONAL }
67 *
68 *   CertPolicyId ::= OBJECT IDENTIFIER
69 *
70 *   PolicyQualifierInfo ::= SEQUENCE {
71 *       policyQualifierId  PolicyQualifierId,
72 *       qualifier        ANY DEFINED BY policyQualifierId }
73 *
74 *   -- Implementations that recognize additional policy qualifiers MUST
75 *   -- augment the following definition for PolicyQualifierId
76 *
77 *   PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
78 *
79 * </pre>
80 *
81 * @since 1.5
82 * @author Vincent Ryan
83 */
84public class SigningCertificateInfo {
85
86    private byte[] ber = null;
87
88    private ESSCertId[] certId = null;
89
90    public SigningCertificateInfo(byte[] ber) throws IOException {
91        parse(ber);
92    }
93
94    public String toString() {
95        StringBuilder sb = new StringBuilder();
96        sb.append("[\n");
97        for (int i = 0; i < certId.length; i++) {
98            sb.append(certId[i].toString());
99        }
100        // format policies as a string
101        sb.append("\n]");
102
103        return sb.toString();
104    }
105
106    public void parse(byte[] bytes) throws IOException {
107
108        // Parse signingCertificate
109        DerValue derValue = new DerValue(bytes);
110        if (derValue.tag != DerValue.tag_Sequence) {
111            throw new IOException("Bad encoding for signingCertificate");
112        }
113
114        // Parse certs
115        DerValue[] certs = derValue.data.getSequence(1);
116        certId = new ESSCertId[certs.length];
117        for (int i = 0; i < certs.length; i++) {
118            certId[i] = new ESSCertId(certs[i]);
119        }
120
121        // Parse policies, if present
122        if (derValue.data.available() > 0) {
123            DerValue[] policies = derValue.data.getSequence(1);
124            for (int i = 0; i < policies.length; i++) {
125                // parse PolicyInformation
126            }
127        }
128    }
129}
130
131class ESSCertId {
132
133    private static volatile HexDumpEncoder hexDumper;
134
135    private byte[] certHash;
136    private GeneralNames issuer;
137    private SerialNumber serialNumber;
138
139    ESSCertId(DerValue certId) throws IOException {
140        // Parse certHash
141        certHash = certId.data.getDerValue().toByteArray();
142
143        // Parse issuerSerial, if present
144        if (certId.data.available() > 0) {
145            DerValue issuerSerial = certId.data.getDerValue();
146            // Parse issuer
147            issuer = new GeneralNames(issuerSerial.data.getDerValue());
148            // Parse serialNumber
149            serialNumber = new SerialNumber(issuerSerial.data.getDerValue());
150        }
151    }
152
153    public String toString() {
154        StringBuilder sb = new StringBuilder();
155        sb.append("[\n\tCertificate hash (SHA-1):\n");
156        if (hexDumper == null) {
157            hexDumper = new HexDumpEncoder();
158        }
159        sb.append(hexDumper.encode(certHash));
160        if (issuer != null && serialNumber != null) {
161            sb.append("\n\tIssuer: " + issuer + "\n");
162            sb.append("\t" + serialNumber);
163        }
164        sb.append("\n]");
165        return sb.toString();
166    }
167}
168