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*/ 22package org.apache.harmony.security.pkcs7; 23 24import java.io.IOException; 25import java.util.Arrays; 26import org.apache.harmony.security.asn1.ASN1Any; 27import org.apache.harmony.security.asn1.ASN1Explicit; 28import org.apache.harmony.security.asn1.ASN1OctetString; 29import org.apache.harmony.security.asn1.ASN1Oid; 30import org.apache.harmony.security.asn1.ASN1Sequence; 31import org.apache.harmony.security.asn1.ASN1Type; 32import 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 */ 43public final class ContentInfo { 44 45 // OIDs 46 public static final int[] DATA = new int[] {1, 2, 840, 113549, 1, 7, 1}; 47 public static final int[] SIGNED_DATA = new int[] {1, 2, 840, 113549, 1, 7, 2}; 48 public static final int[] ENVELOPED_DATA = new int[] {1, 2, 840, 113549, 1, 7, 3}; 49 public static final int[] SIGNED_AND_ENVELOPED_DATA = new int[] {1, 2, 840, 113549, 1, 7, 4}; 50 public static final int[] DIGESTED_DATA = new int[] {1, 2, 840, 113549, 1, 7, 5}; 51 public static final int[] ENCRYPTED_DATA = new int[] {1, 2, 840, 113549, 1, 7, 6}; 52 53 private final int[] oid; 54 private final Object content; 55 private byte[] encoding; 56 57 private ContentInfo(int[] oid, Object content, byte[] encoding) { 58 this.oid = oid; 59 this.content = content; 60 this.encoding = encoding; 61 } 62 63 public SignedData getSignedData() { 64 if (Arrays.equals(oid, SIGNED_DATA)) { 65 return (SignedData)content; 66 } 67 return null; 68 } 69 70 public Object getContent() { 71 return content; 72 } 73 74 public int[] getContentType() { 75 return oid; 76 } 77 78 public byte[] getEncoded() { 79 if (encoding == null) { 80 encoding = ASN1.encode(this); 81 } 82 // Note: this is internal object and can not be accessible from 83 // public API, so encoding is not copied. The classes which use 84 // this class should copy encoding before passing it out. 85 return encoding; 86 } 87 88 @Override public String toString() { 89 StringBuilder res = new StringBuilder(); 90 res.append("==== ContentInfo:"); 91 res.append("\n== ContentType (OID): "); 92 for (int i : oid) { 93 res.append(i); 94 res.append(' '); 95 } 96 res.append("\n== Content: "); 97 if (content != null) { 98 res.append("\n"); 99 res.append(content.toString()); 100 } 101 res.append("\n== Content End"); 102 res.append("\n==== ContentInfo End\n"); 103 return res.toString(); 104 } 105 106 public static final ASN1Sequence ASN1 = 107 new ASN1Sequence(new ASN1Type[] { 108 ASN1Oid.getInstance(), 109 new ASN1Explicit(0, ASN1Any.getInstance()) 110 }) { 111 { 112 setOptional(1); // content is optional 113 } 114 115 @Override protected void getValues(Object object, Object[] values) { 116 ContentInfo ci = (ContentInfo) object; 117 values[0] = ci.oid; 118 if (ci.content != null) { 119 if (Arrays.equals(ci.oid, DATA)) { 120 if (ci.content != null) { 121 values[1] = 122 ASN1OctetString.getInstance().encode(ci.content); 123 } 124 } else if (ci.content instanceof SignedData) { 125 values[1] = SignedData.ASN1.encode(ci.content); 126 } else { 127 values[1] = ci.content; 128 } 129 } 130 } 131 132 @Override protected Object getDecodedObject(BerInputStream in) throws IOException { 133 Object[] values = (Object[]) in.content; 134 int[] oid = (int[]) values[0]; 135 if (Arrays.equals(oid, DATA)) { 136 if (values[1] != null) { 137 return new ContentInfo(oid, 138 ASN1OctetString.getInstance().decode((byte[])values[1]), 139 in.getEncoded()); 140 } else { 141 return new ContentInfo((int[])values[0], null, 142 in.getEncoded()); 143 } 144 } 145 if (Arrays.equals(oid, SIGNED_DATA)) { 146 return new ContentInfo((int[])values[0], 147 SignedData.ASN1.decode((byte[])values[1]), 148 in.getEncoded()); 149 } 150 return new ContentInfo((int[]) values[0], values[1], in.getEncoded()); 151 } 152 }; 153} 154