Home | History | Annotate | Download | only in asn1
      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 Vladimir N. Molotkov, Stepan M. Mishura
     20 * @version $Revision$
     21 */
     22 
     23 package org.apache.harmony.security.asn1;
     24 
     25 import java.io.IOException;
     26 
     27 /**
     28  * This class represents ASN.1 Bitstring type.
     29  *
     30  * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a>
     31  */
     32 
     33 public class ASN1BitString extends ASN1StringType {
     34 
     35     // default implementation
     36     private static final ASN1BitString ASN1 = new ASN1BitString();
     37 
     38     /**
     39      * Constructs ASN.1 Bitstring type
     40      *
     41      * The constructor is provided for inheritance purposes
     42      * when there is a need to create a custom ASN.1 Bitstring type.
     43      * To get a default implementation it is recommended to use
     44      * getInstance() method.
     45      */
     46     public ASN1BitString() {
     47         super(TAG_BITSTRING);
     48     }
     49 
     50     /**
     51      * Returns ASN.1 Bitstring type default implementation
     52      *
     53      * The default implementation works with encoding
     54      * that is represented as BitString object.
     55      *
     56      * @return ASN.1 Bitstring type default implementation
     57      * @see org.apache.harmony.security.asn1.BitString
     58      */
     59     public static ASN1BitString getInstance() {
     60         return ASN1;
     61     }
     62 
     63     //
     64     //
     65     // Decode
     66     //
     67     //
     68 
     69     public Object decode(BerInputStream in) throws IOException {
     70 
     71         in.readBitString();
     72 
     73         if (in.isVerify) {
     74             return null;
     75         }
     76         return getDecodedObject(in);
     77     }
     78 
     79     /**
     80      * Extracts BitString object from BER input stream.
     81      *
     82      * @param in - BER input stream
     83      * @return BitString object
     84      */
     85     public Object getDecodedObject(BerInputStream in) throws IOException {
     86         byte[] bytes = new byte[in.length - 1];
     87         System.arraycopy(in.buffer, in.contentOffset + 1, bytes, 0,
     88                 in.length - 1);
     89         return new BitString(bytes, in.buffer[in.contentOffset]);
     90     }
     91 
     92     //
     93     // Encode
     94     //
     95 
     96     public void encodeContent(BerOutputStream out) {
     97         out.encodeBitString();
     98     }
     99 
    100     public void setEncodingContent(BerOutputStream out) {
    101         out.length = ((BitString) out.content).bytes.length + 1;
    102     }
    103 
    104     //
    105     //
    106     // Named Bit List
    107     //
    108     //
    109 
    110     /**
    111      * Default implementation for ASN.1 Named Bitstring type
    112      *
    113      * The default implementation works with encoding
    114      * that is mapped to array of boolean.
    115      */
    116     public static class ASN1NamedBitList extends ASN1BitString {
    117 
    118         private static final byte[] SET_MASK = { (byte) 128, 64, 32, 16, 8, 4,
    119                 2, 1 };
    120 
    121         private static final BitString emptyString = new BitString(
    122                 new byte[] {}, 0);
    123 
    124         private static final int INDEFINITE_SIZE = -1;
    125 
    126         private final int minBits;
    127 
    128         private final int maxBits;
    129 
    130         public ASN1NamedBitList() {
    131             this.minBits = INDEFINITE_SIZE;
    132             this.maxBits = INDEFINITE_SIZE;
    133         }
    134 
    135         public ASN1NamedBitList(int minBits) {
    136             this.minBits = minBits;
    137             this.maxBits = INDEFINITE_SIZE;
    138         }
    139 
    140         public ASN1NamedBitList(int minBits, int maxBits) {
    141             this.minBits = minBits;
    142             this.maxBits = maxBits;
    143         }
    144 
    145         public Object getDecodedObject(BerInputStream in) throws IOException {
    146 
    147             boolean[] value = null;
    148 
    149             int unusedBits = in.buffer[in.contentOffset];
    150             int bitsNumber = (in.length - 1) * 8 - unusedBits;
    151 
    152             if (maxBits == INDEFINITE_SIZE) {
    153                 if (minBits == INDEFINITE_SIZE) {
    154                     value = new boolean[bitsNumber];
    155                 } else {
    156                     if (bitsNumber > minBits) {
    157                         value = new boolean[bitsNumber];
    158                     } else {
    159                         value = new boolean[minBits];
    160                     }
    161                 }
    162             } else {
    163                 if (bitsNumber > maxBits) {
    164                     throw new ASN1Exception("ASN.1 Named Bitstring: size constraints");
    165                 }
    166                 value = new boolean[maxBits];
    167             }
    168 
    169             if (bitsNumber == 0) {
    170                 // empty bit string
    171                 return value;
    172             }
    173 
    174             int i = 1;
    175             int j = 0;
    176             byte octet = in.buffer[in.contentOffset + i];
    177             for (int size = in.length - 1; i < size; i++) {
    178 
    179                 for (int k = 0; k < 8; k++, j++) {
    180                     value[j] = (SET_MASK[k] & octet) != 0;
    181                 }
    182                 i++;
    183                 octet = in.buffer[in.contentOffset + i];
    184             }
    185 
    186             // final octet
    187             for (int k = 0; k < (8 - unusedBits); k++, j++) {
    188                 value[j] = (SET_MASK[k] & octet) != 0;
    189             }
    190 
    191             return value;
    192         }
    193 
    194         public void setEncodingContent(BerOutputStream out) {
    195 
    196             boolean[] toEncode = (boolean[]) out.content;
    197 
    198             int index = toEncode.length - 1;
    199             while (index > -1 && !toEncode[index]) {
    200                 index--;
    201             }
    202 
    203             if (index == -1) {
    204                 out.content = emptyString;
    205                 out.length = 1;
    206             } else {
    207                 int unusedBits = 7 - index % 8;
    208                 byte[] bytes = new byte[index / 8 + 1];
    209 
    210                 int j = 0;
    211                 index = bytes.length - 1;
    212                 for (int i = 0; i < index; i++) {
    213                     for (int k = 0; k < 8; k++, j++) {
    214                         if (toEncode[j]) {
    215                             bytes[i] = (byte) (bytes[i] | SET_MASK[k]);
    216                         }
    217                     }
    218                 }
    219 
    220                 //final octet
    221                 for (int k = 0; k < (8 - unusedBits); k++, j++) {
    222                     if (toEncode[j]) {
    223                         bytes[index] = (byte) (bytes[index] | SET_MASK[k]);
    224                     }
    225                 }
    226 
    227                 out.content = new BitString(bytes, unusedBits);
    228                 out.length = bytes.length + 1;
    229             }
    230         }
    231     }
    232 }
    233