Home | History | Annotate | Download | only in certpath
      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