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 
26 package sun.security.pkcs;
27 
28 import java.io.IOException;
29 import java.util.ArrayList;
30 
31 import sun.misc.HexDumpEncoder;
32 import sun.security.util.DerInputStream;
33 import sun.security.util.DerValue;
34 import sun.security.x509.GeneralNames;
35 import 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  */
84 public class SigningCertificateInfo {
85 
86     private byte[] ber = null;
87 
88     private ESSCertId[] certId = null;
89 
SigningCertificateInfo(byte[] ber)90     public SigningCertificateInfo(byte[] ber) throws IOException {
91         parse(ber);
92     }
93 
toString()94     public String toString() {
95         StringBuffer buffer = new StringBuffer();
96         buffer.append("[\n");
97         for (int i = 0; i < certId.length; i++) {
98             buffer.append(certId[i].toString());
99         }
100         // format policies as a string
101         buffer.append("\n]");
102 
103         return buffer.toString();
104     }
105 
parse(byte[] bytes)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 
131 class ESSCertId {
132 
133     private static volatile HexDumpEncoder hexDumper;
134 
135     private byte[] certHash;
136     private GeneralNames issuer;
137     private SerialNumber serialNumber;
138 
ESSCertId(DerValue certId)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 
toString()153     public String toString() {
154         StringBuffer buffer = new StringBuffer();
155         buffer.append("[\n\tCertificate hash (SHA-1):\n");
156         if (hexDumper == null) {
157             hexDumper = new HexDumpEncoder();
158         }
159         buffer.append(hexDumper.encode(certHash));
160         if (issuer != null && serialNumber != null) {
161             buffer.append("\n\tIssuer: " + issuer + "\n");
162             buffer.append("\t" + serialNumber);
163         }
164         buffer.append("\n]");
165         return buffer.toString();
166     }
167 }
168