J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 1996-2005 Sun Microsystems, Inc. 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. Sun designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 23 | * have any 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(DATA_OID) || |
| 167 | contentType.equals(OLD_DATA_OID) || |
| 168 | contentType.equals(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 | } |