Home | History | Annotate | Download | only in pkcs7
      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