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 */ 91 OCSPRequest(CertId certId) { 92 this(Collections.singletonList(certId)); 93 } 94 95 OCSPRequest(List<CertId> certIds) { 96 this.certIds = certIds; 97 this.extensions = Collections.<Extension>emptyList(); 98 } 99 100 OCSPRequest(List<CertId> certIds, List<Extension> extensions) { 101 this.certIds = certIds; 102 this.extensions = extensions; 103 } 104 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 149 List<CertId> getCertIds() { 150 return certIds; 151 } 152 153 byte[] getNonce() { 154 return nonce; 155 } 156 } 157