1 /*
2  * Copyright (c) 2003, 2013, 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.provider.certpath;
27 
28 import java.io.IOException;
29 import java.security.cert.Extension;
30 import java.util.Collections;
31 import java.util.List;
32 
33 import sun.misc.HexDumpEncoder;
34 import sun.security.util.*;
35 
36 /**
37  * This class can be used to generate an OCSP request and send it over
38  * an outputstream. Currently we do not support signing requests
39  * The OCSP Request is specified in RFC 2560 and
40  * the ASN.1 definition is as follows:
41  * <pre>
42  *
43  * OCSPRequest     ::=     SEQUENCE {
44  *      tbsRequest                  TBSRequest,
45  *      optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
46  *
47  *   TBSRequest      ::=     SEQUENCE {
48  *      version             [0]     EXPLICIT Version DEFAULT v1,
49  *      requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
50  *      requestList                 SEQUENCE OF Request,
51  *      requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
52  *
53  *  Signature       ::=     SEQUENCE {
54  *      signatureAlgorithm      AlgorithmIdentifier,
55  *      signature               BIT STRING,
56  *      certs               [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
57  *   }
58  *
59  *  Version         ::=             INTEGER  {  v1(0) }
60  *
61  *  Request         ::=     SEQUENCE {
62  *      reqCert                     CertID,
63  *      singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
64  *
65  *  CertID          ::= SEQUENCE {
66  *       hashAlgorithm  AlgorithmIdentifier,
67  *       issuerNameHash OCTET STRING, -- Hash of Issuer's DN
68  *       issuerKeyHash  OCTET STRING, -- Hash of Issuers public key
69  *       serialNumber   CertificateSerialNumber
70  * }
71  *
72  * </pre>
73  *
74  * @author      Ram Marti
75  */
76 
77 class OCSPRequest {
78 
79     private static final Debug debug = Debug.getInstance("certpath");
80     private static final boolean dump = debug != null && Debug.isOn("ocsp");
81 
82     // List of request CertIds
83     private final List<CertId> certIds;
84     private final List<Extension> extensions;
85     private byte[] nonce;
86 
87     /*
88      * Constructs an OCSPRequest. This constructor is used
89      * to construct an unsigned OCSP Request for a single user cert.
90      */
OCSPRequest(CertId certId)91     OCSPRequest(CertId certId) {
92         this(Collections.singletonList(certId));
93     }
94 
OCSPRequest(List<CertId> certIds)95     OCSPRequest(List<CertId> certIds) {
96         this.certIds = certIds;
97         this.extensions = Collections.<Extension>emptyList();
98     }
99 
OCSPRequest(List<CertId> certIds, List<Extension> extensions)100     OCSPRequest(List<CertId> certIds, List<Extension> extensions) {
101         this.certIds = certIds;
102         this.extensions = extensions;
103     }
104 
encodeBytes()105     byte[] encodeBytes() throws IOException {
106 
107         // encode tbsRequest
108         DerOutputStream tmp = new DerOutputStream();
109         DerOutputStream requestsOut = new DerOutputStream();
110         for (CertId certId : certIds) {
111             DerOutputStream certIdOut = new DerOutputStream();
112             certId.encode(certIdOut);
113             requestsOut.write(DerValue.tag_Sequence, certIdOut);
114         }
115 
116         tmp.write(DerValue.tag_Sequence, requestsOut);
117         if (!extensions.isEmpty()) {
118             DerOutputStream extOut = new DerOutputStream();
119             for (Extension ext : extensions) {
120                 ext.encode(extOut);
121                 if (ext.getId().equals(OCSP.NONCE_EXTENSION_OID.toString())) {
122                     nonce = ext.getValue();
123                 }
124             }
125             DerOutputStream extsOut = new DerOutputStream();
126             extsOut.write(DerValue.tag_Sequence, extOut);
127             tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT,
128                                          true, (byte)2), extsOut);
129         }
130 
131         DerOutputStream tbsRequest = new DerOutputStream();
132         tbsRequest.write(DerValue.tag_Sequence, tmp);
133 
134         // OCSPRequest without the signature
135         DerOutputStream ocspRequest = new DerOutputStream();
136         ocspRequest.write(DerValue.tag_Sequence, tbsRequest);
137 
138         byte[] bytes = ocspRequest.toByteArray();
139 
140         if (dump) {
141             HexDumpEncoder hexEnc = new HexDumpEncoder();
142             debug.println("OCSPRequest bytes...\n\n" +
143                 hexEnc.encode(bytes) + "\n");
144         }
145 
146         return bytes;
147     }
148 
getCertIds()149     List<CertId> getCertIds() {
150         return certIds;
151     }
152 
getNonce()153     byte[] getNonce() {
154         return nonce;
155     }
156 }
157