1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /** 19 * @author Boris Kuznetsov 20 * @version $Revision$ 21 */ 22 package org.apache.harmony.security.pkcs7; 23 24 import java.io.IOException; 25 import java.util.Arrays; 26 import org.apache.harmony.security.asn1.ASN1Any; 27 import org.apache.harmony.security.asn1.ASN1Explicit; 28 import org.apache.harmony.security.asn1.ASN1OctetString; 29 import org.apache.harmony.security.asn1.ASN1Oid; 30 import org.apache.harmony.security.asn1.ASN1Sequence; 31 import org.apache.harmony.security.asn1.ASN1Type; 32 import org.apache.harmony.security.asn1.BerInputStream; 33 34 /** 35 * As defined in PKCS #7: Cryptographic Message Syntax Standard 36 * (http://www.ietf.org/rfc/rfc2315.txt) 37 * 38 * ContentInfo ::= SEQUENCE { 39 * contentType ContentType, 40 * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL 41 * } 42 */ 43 44 public class ContentInfo { 45 46 // OIDs 47 public static final int[] DATA = new int[] {1, 2, 840, 113549, 1, 7, 1}; 48 public static final int[] SIGNED_DATA = new int[] {1, 2, 840, 113549, 1, 7, 2}; 49 public static final int[] ENVELOPED_DATA = new int[] {1, 2, 840, 113549, 1, 7, 3}; 50 public static final int[] SIGNED_AND_ENVELOPED_DATA = new int[] {1, 2, 840, 113549, 1, 7, 4}; 51 public static final int[] DIGESTED_DATA = new int[] {1, 2, 840, 113549, 1, 7, 5}; 52 public static final int[] ENCRYPTED_DATA = new int[] {1, 2, 840, 113549, 1, 7, 6}; 53 54 private int[] oid; 55 private Object content; 56 private byte[] encoding; 57 58 public ContentInfo(int[] oid, Object content) { 59 this.oid = oid; 60 this.content = content; 61 } 62 63 private ContentInfo(int[] oid, Object content, byte[] encoding) { 64 this.oid = oid; 65 this.content = content; 66 this.encoding = encoding; 67 } 68 69 public SignedData getSignedData() { 70 if (Arrays.equals(oid, SIGNED_DATA)) { 71 return (SignedData)content; 72 } 73 return null; 74 } 75 76 public Object getContent() { 77 return content; 78 } 79 80 public int[] getContentType() { 81 return oid; 82 } 83 84 public byte[] getEncoded() { 85 if (encoding == null) { 86 encoding = ASN1.encode(this); 87 } 88 // Note: this is internal object and can not be accessible from 89 // public API, so encoding is not copied. The classes which use 90 // this class should copy encoding before passing it out. 91 return encoding; 92 } 93 94 public String toString() { 95 StringBuilder res = new StringBuilder(); 96 res.append("==== ContentInfo:"); 97 res.append("\n== ContentType (OID): "); 98 for (int i = 0; i< oid.length; i++) { 99 res.append(oid[i]); 100 res.append(' '); 101 } 102 res.append("\n== Content: "); 103 if (content != null) { 104 res.append("\n"); 105 res.append(content.toString()); 106 } 107 res.append("\n== Content End"); 108 res.append("\n==== ContentInfo End\n"); 109 return res.toString(); 110 } 111 112 public static final ASN1Sequence ASN1 = 113 new ASN1Sequence(new ASN1Type[] { 114 ASN1Oid.getInstance(), 115 new ASN1Explicit(0, ASN1Any.getInstance()) 116 }) { 117 { 118 setOptional(1); // content is optional 119 } 120 121 protected void getValues(Object object, Object[] values) { 122 ContentInfo ci = (ContentInfo) object; 123 values[0] = ci.oid; 124 if (ci.content != null) { 125 if (Arrays.equals(ci.oid, DATA)) { 126 if (ci.content != null) { 127 values[1] = 128 ASN1OctetString.getInstance().encode(ci.content); 129 } 130 } else if (ci.content instanceof SignedData) { 131 values[1] = SignedData.ASN1.encode(ci.content); 132 } else { 133 values[1] = ci.content; 134 } 135 } 136 } 137 138 protected Object getDecodedObject(BerInputStream in) throws IOException { 139 Object[] values = (Object[]) in.content; 140 int[] oid = (int[]) values[0]; 141 if (Arrays.equals(oid, DATA)) { 142 if (values[1] != null) { 143 return new ContentInfo(oid, 144 ASN1OctetString.getInstance().decode((byte[])values[1]), 145 in.getEncoded()); 146 } else { 147 return new ContentInfo((int[])values[0], null, 148 in.getEncoded()); 149 } 150 } 151 if (Arrays.equals(oid, SIGNED_DATA)) { 152 return new ContentInfo((int[])values[0], 153 SignedData.ASN1.decode((byte[])values[1]), 154 in.getEncoded()); 155 } 156 return new ContentInfo((int[])values[0], (byte[])values[1], 157 in.getEncoded()); 158 } 159 }; 160 } 161