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 public 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