001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Boris Kuznetsov
020: * @version $Revision$
021: */package org.apache.harmony.security.pkcs7;
022:
023: import java.io.IOException;
024: import java.util.Arrays;
025:
026: import org.apache.harmony.security.asn1.ASN1Any;
027: import org.apache.harmony.security.asn1.ASN1Explicit;
028: import org.apache.harmony.security.asn1.ASN1OctetString;
029: import org.apache.harmony.security.asn1.ASN1Oid;
030: import org.apache.harmony.security.asn1.ASN1Sequence;
031: import org.apache.harmony.security.asn1.ASN1Type;
032: import org.apache.harmony.security.asn1.BerInputStream;
033:
034: /**
035: * As defined in PKCS #7: Cryptographic Message Syntax Standard
036: * (http://www.ietf.org/rfc/rfc2315.txt)
037: *
038: * ContentInfo ::= SEQUENCE {
039: * contentType ContentType,
040: * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
041: * }
042: */
043:
044: public class ContentInfo {
045:
046: // OIDs
047: public static final int[] DATA = new int[] { 1, 2, 840, 113549, 1,
048: 7, 1 };
049: public static final int[] SIGNED_DATA = new int[] { 1, 2, 840,
050: 113549, 1, 7, 2 };
051: public static final int[] ENVELOPED_DATA = new int[] { 1, 2, 840,
052: 113549, 1, 7, 3 };
053: public static final int[] SIGNED_AND_ENVELOPED_DATA = new int[] {
054: 1, 2, 840, 113549, 1, 7, 4 };
055: public static final int[] DIGESTED_DATA = new int[] { 1, 2, 840,
056: 113549, 1, 7, 5 };
057: public static final int[] ENCRYPTED_DATA = new int[] { 1, 2, 840,
058: 113549, 1, 7, 6 };
059:
060: private int[] oid;
061: private Object content;
062: private byte[] encoding;
063:
064: public ContentInfo(int[] oid, Object content) {
065: this .oid = oid;
066: this .content = content;
067: }
068:
069: private ContentInfo(int[] oid, Object content, byte[] encoding) {
070: this .oid = oid;
071: this .content = content;
072: this .encoding = encoding;
073: }
074:
075: public SignedData getSignedData() {
076: if (Arrays.equals(oid, SIGNED_DATA)) {
077: return (SignedData) content;
078: }
079: return null;
080: }
081:
082: public Object getContent() {
083: return content;
084: }
085:
086: public int[] getContentType() {
087: return oid;
088: }
089:
090: public byte[] getEncoded() {
091: if (encoding == null) {
092: encoding = ASN1.encode(this );
093: }
094: // Note: this is internal object and can not be accessible from
095: // public API, so encoding is not copied. The classes which use
096: // this class should copy encoding before passing it out.
097: return encoding;
098: }
099:
100: public String toString() {
101: StringBuffer res = new StringBuffer();
102: res.append("==== ContentInfo:"); //$NON-NLS-1$
103: res.append("\n== ContentType (OID): "); //$NON-NLS-1$
104: for (int i = 0; i < oid.length; i++) {
105: res.append(oid[i]);
106: res.append(' ');
107: }
108: res.append("\n== Content: "); //$NON-NLS-1$
109: if (content != null) {
110: res.append("\n"); //$NON-NLS-1$
111: res.append(content.toString());
112: }
113: res.append("\n== Content End"); //$NON-NLS-1$
114: res.append("\n==== ContentInfo End\n"); //$NON-NLS-1$
115: return res.toString();
116: }
117:
118: public static final ASN1Sequence ASN1 = new ASN1Sequence(
119: new ASN1Type[] { ASN1Oid.getInstance(),
120: new ASN1Explicit(0, ASN1Any.getInstance()) }) {
121: {
122: setOptional(1); // content is optional
123: }
124:
125: protected void getValues(Object object, Object[] values) {
126: ContentInfo ci = (ContentInfo) object;
127: values[0] = ci.oid;
128: if (ci.content != null) {
129: if (Arrays.equals(ci.oid, DATA)) {
130: if (ci.content != null) {
131: values[1] = ASN1OctetString.getInstance()
132: .encode(ci.content);
133: }
134: } else if (ci.content instanceof SignedData) {
135: values[1] = SignedData.ASN1.encode(ci.content);
136: } else {
137: values[1] = ci.content;
138: }
139: }
140: }
141:
142: protected Object getDecodedObject(BerInputStream in)
143: throws IOException {
144: Object[] values = (Object[]) in.content;
145: int[] oid = (int[]) values[0];
146: if (Arrays.equals(oid, DATA)) {
147: if (values[1] != null) {
148: return new ContentInfo(oid, ASN1OctetString
149: .getInstance().decode((byte[]) values[1]),
150: in.getEncoded());
151: } else {
152: return new ContentInfo((int[]) values[0], null, in
153: .getEncoded());
154: }
155: }
156: if (Arrays.equals(oid, SIGNED_DATA)) {
157: return new ContentInfo((int[]) values[0],
158: SignedData.ASN1.decode((byte[]) values[1]), in
159: .getEncoded());
160: }
161: return new ContentInfo((int[]) values[0],
162: (byte[]) values[1], in.getEncoded());
163: }
164: };
165: }
|