Home | History | Annotate | Download | only in pkcs
      1 /*
      2  * Copyright (c) 1996, 2011, 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.*;
     29 
     30 import sun.security.util.*;
     31 
     32 /**
     33  * A ContentInfo type, as defined in PKCS#7.
     34  *
     35  * @author Benjamin Renaud
     36  */
     37 
     38 public class ContentInfo {
     39 
     40     // pkcs7 pre-defined content types
     41     private static int[]  pkcs7 = {1, 2, 840, 113549, 1, 7};
     42     private static int[]   data = {1, 2, 840, 113549, 1, 7, 1};
     43     private static int[]  sdata = {1, 2, 840, 113549, 1, 7, 2};
     44     private static int[]  edata = {1, 2, 840, 113549, 1, 7, 3};
     45     private static int[] sedata = {1, 2, 840, 113549, 1, 7, 4};
     46     private static int[]  ddata = {1, 2, 840, 113549, 1, 7, 5};
     47     private static int[] crdata = {1, 2, 840, 113549, 1, 7, 6};
     48     private static int[] nsdata = {2, 16, 840, 1, 113730, 2, 5};
     49     // timestamp token (id-ct-TSTInfo) from RFC 3161
     50     private static int[] tstInfo = {1, 2, 840, 113549, 1, 9, 16, 1, 4};
     51     // this is for backwards-compatibility with JDK 1.1.x
     52     private static final int[] OLD_SDATA = {1, 2, 840, 1113549, 1, 7, 2};
     53     private static final int[] OLD_DATA = {1, 2, 840, 1113549, 1, 7, 1};
     54     public static ObjectIdentifier PKCS7_OID;
     55     public static ObjectIdentifier DATA_OID;
     56     public static ObjectIdentifier SIGNED_DATA_OID;
     57     public static ObjectIdentifier ENVELOPED_DATA_OID;
     58     public static ObjectIdentifier SIGNED_AND_ENVELOPED_DATA_OID;
     59     public static ObjectIdentifier DIGESTED_DATA_OID;
     60     public static ObjectIdentifier ENCRYPTED_DATA_OID;
     61     public static ObjectIdentifier OLD_SIGNED_DATA_OID;
     62     public static ObjectIdentifier OLD_DATA_OID;
     63     public static ObjectIdentifier NETSCAPE_CERT_SEQUENCE_OID;
     64     public static ObjectIdentifier TIMESTAMP_TOKEN_INFO_OID;
     65 
     66     static {
     67         PKCS7_OID =  ObjectIdentifier.newInternal(pkcs7);
     68         DATA_OID = ObjectIdentifier.newInternal(data);
     69         SIGNED_DATA_OID = ObjectIdentifier.newInternal(sdata);
     70         ENVELOPED_DATA_OID = ObjectIdentifier.newInternal(edata);
     71         SIGNED_AND_ENVELOPED_DATA_OID = ObjectIdentifier.newInternal(sedata);
     72         DIGESTED_DATA_OID = ObjectIdentifier.newInternal(ddata);
     73         ENCRYPTED_DATA_OID = ObjectIdentifier.newInternal(crdata);
     74         OLD_SIGNED_DATA_OID = ObjectIdentifier.newInternal(OLD_SDATA);
     75         OLD_DATA_OID = ObjectIdentifier.newInternal(OLD_DATA);
     76         /**
     77          * The ASN.1 systax for the Netscape Certificate Sequence
     78          * data type is defined
     79          * <a href=http://wp.netscape.com/eng/security/comm4-cert-download.html>
     80          * here.</a>
     81          */
     82         NETSCAPE_CERT_SEQUENCE_OID = ObjectIdentifier.newInternal(nsdata);
     83         TIMESTAMP_TOKEN_INFO_OID = ObjectIdentifier.newInternal(tstInfo);
     84     }
     85 
     86     ObjectIdentifier contentType;
     87     DerValue content; // OPTIONAL
     88 
     89     public ContentInfo(ObjectIdentifier contentType, DerValue content) {
     90         this.contentType = contentType;
     91         this.content = content;
     92     }
     93 
     94     /**
     95      * Make a contentInfo of type data.
     96      */
     97     public ContentInfo(byte[] bytes) {
     98         DerValue octetString = new DerValue(DerValue.tag_OctetString, bytes);
     99         this.contentType = DATA_OID;
    100         this.content = octetString;
    101     }
    102 
    103     /**
    104      * Parses a PKCS#7 content info.
    105      */
    106     public ContentInfo(DerInputStream derin)
    107         throws IOException, ParsingException
    108     {
    109         this(derin, false);
    110     }
    111 
    112     /**
    113      * Parses a PKCS#7 content info.
    114      *
    115      * <p>This constructor is used only for backwards compatibility with
    116      * PKCS#7 blocks that were generated using JDK1.1.x.
    117      *
    118      * @param derin the ASN.1 encoding of the content info.
    119      * @param oldStyle flag indicating whether or not the given content info
    120      * is encoded according to JDK1.1.x.
    121      */
    122     public ContentInfo(DerInputStream derin, boolean oldStyle)
    123         throws IOException, ParsingException
    124     {
    125         DerInputStream disType;
    126         DerInputStream disTaggedContent;
    127         DerValue type;
    128         DerValue taggedContent;
    129         DerValue[] typeAndContent;
    130         DerValue[] contents;
    131 
    132         typeAndContent = derin.getSequence(2);
    133 
    134         // Parse the content type
    135         type = typeAndContent[0];
    136         disType = new DerInputStream(type.toByteArray());
    137         contentType = disType.getOID();
    138 
    139         if (oldStyle) {
    140             // JDK1.1.x-style encoding
    141             content = typeAndContent[1];
    142         } else {
    143             // This is the correct, standards-compliant encoding.
    144             // Parse the content (OPTIONAL field).
    145             // Skip the [0] EXPLICIT tag by pretending that the content is the
    146             // one and only element in an implicitly tagged set
    147             if (typeAndContent.length > 1) { // content is OPTIONAL
    148                 taggedContent = typeAndContent[1];
    149                 disTaggedContent
    150                     = new DerInputStream(taggedContent.toByteArray());
    151                 contents = disTaggedContent.getSet(1, true);
    152                 content = contents[0];
    153             }
    154         }
    155     }
    156 
    157     public DerValue getContent() {
    158         return content;
    159     }
    160 
    161     public ObjectIdentifier getContentType() {
    162         return contentType;
    163     }
    164 
    165     public byte[] getData() throws IOException {
    166         if (contentType.equals((Object)DATA_OID) ||
    167             contentType.equals((Object)OLD_DATA_OID) ||
    168             contentType.equals((Object)TIMESTAMP_TOKEN_INFO_OID)) {
    169             if (content == null)
    170                 return null;
    171             else
    172                 return content.getOctetString();
    173         }
    174         throw new IOException("content type is not DATA: " + contentType);
    175     }
    176 
    177     public void encode(DerOutputStream out) throws IOException {
    178         DerOutputStream contentDerCode;
    179         DerOutputStream seq;
    180 
    181         seq = new DerOutputStream();
    182         seq.putOID(contentType);
    183 
    184         // content is optional, it could be external
    185         if (content != null) {
    186             DerValue taggedContent = null;
    187             contentDerCode = new DerOutputStream();
    188             content.encode(contentDerCode);
    189 
    190             // Add the [0] EXPLICIT tag in front of the content encoding
    191             taggedContent = new DerValue((byte)0xA0,
    192                                          contentDerCode.toByteArray());
    193             seq.putDerValue(taggedContent);
    194         }
    195 
    196         out.write(DerValue.tag_Sequence, seq);
    197     }
    198 
    199     /**
    200      * Returns a byte array representation of the data held in
    201      * the content field.
    202      */
    203     public byte[] getContentBytes() throws IOException {
    204         if (content == null)
    205             return null;
    206 
    207         DerInputStream dis = new DerInputStream(content.toByteArray());
    208         return dis.getOctetString();
    209     }
    210 
    211     public String toString() {
    212         String out = "";
    213 
    214         out += "Content Info Sequence\n\tContent type: " + contentType + "\n";
    215         out += "\tContent: " + content;
    216         return out;
    217     }
    218 }
    219