summaryrefslogtreecommitdiff
path: root/repackaged_platform/bcprov/src/main/java/com/android/internal/org/bouncycastle/asn1/ASN1OctetString.java
blob: f7b9617aaabc5f541b1b1b0c2ec9fb1b5d8d3e9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
/* GENERATED SOURCE. DO NOT MODIFY. */
package com.android.internal.org.bouncycastle.asn1;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import com.android.internal.org.bouncycastle.util.Arrays;
import com.android.internal.org.bouncycastle.util.Strings;
import com.android.internal.org.bouncycastle.util.encoders.Hex;

/**
 * Abstract base for the ASN.1 OCTET STRING data type
 * <p>
 * This supports BER, and DER forms of the data.
 * </p><p>
 * DER form is always primitive single OCTET STRING, while
 * BER support includes the constructed forms.
 * </p>
 * <p><b>X.690</b></p>
 * <p><b>8: Basic encoding rules</b></p>
 * <p><b>8.7 Encoding of an octetstring value</b></p>
 * <p>
 * <b>8.7.1</b> The encoding of an octetstring value shall be
 * either primitive or constructed at the option of the sender.
 * <blockquote>
 * NOTE &mdash; Where it is necessary to transfer part of an octet string
 * before the entire OCTET STRING is available, the constructed encoding
 * is used.
 * </blockquote>
 * <p>
 * <b>8.7.2</b> The primitive encoding contains zero,
 * one or more contents octets equal in value to the octets
 * in the data value, in the order they appear in the data value,
 * and with the most significant bit of an octet of the data value
 * aligned with the most significant bit of an octet of the contents octets.
 * </p>
 * <p>
 * <b>8.7.3</b> The contents octets for the constructed encoding shall consist
 * of zero, one, or more encodings.
 * </p>
 * <blockquote>
 * NOTE &mdash; Each such encoding includes identifier, length, and contents octets,
 * and may include end-of-contents octets if it is constructed.
 * </blockquote>
 * <p>
 * <b>8.7.3.1</b> To encode an octetstring value in this way,
 * it is segmented. Each segment shall consist of a series of
 * consecutive octets of the value. There shall be no significance
 * placed on the segment boundaries.</p>
 * <blockquote>
 * NOTE &mdash; A segment may be of size zero, i.e. contain no octets.
 * </blockquote>
 * <p>
 * <b>8.7.3.2</b> Each encoding in the contents octets shall represent
 * a segment of the overall octetstring, the encoding arising from
 * a recursive application of this subclause.
 * In this recursive application, each segment is treated as if it were
 * a octetstring value. The encodings of the segments shall appear in the contents
 * octets in the order in which their octets appear in the overall value.
 * </p>
 * <blockquote>
 * NOTE 1 &mdash; As a consequence of this recursion,
 * each encoding in the contents octets may itself
 * be primitive or constructed.
 * However, such encodings will usually be primitive.
 * </blockquote>
 * <blockquote>
 * NOTE 2 &mdash; In particular, the tags in the contents octets are always universal class, number 4.
 * </blockquote>
 * <p><b>9: Canonical encoding rules</b></p>
 * <p><b>9.1 Length forms</b></p>
 * <p>
 * If the encoding is constructed, it shall employ the indefinite-length form.
 * If the encoding is primitive, it shall include the fewest length octets necessary.
 * [Contrast with 8.1.3.2 b).]
 * </p>
 * <p><b>9.2 String encoding forms</b></p>
 * <p>
 * BIT STRING, OCTET STRING,and restricted character string
 * values shall be encoded with a primitive encoding if they would
 * require no more than 1000 contents octets, and as a constructed
 * encoding otherwise. The string fragments contained in
 * the constructed encoding shall be encoded with a primitive encoding.
 * The encoding of each fragment, except possibly
 * the last, shall have 1000 contents octets. (Contrast with 8.21.6.)
 * </p><p>
 * <b>10: Distinguished encoding rules</b>
 * </p><p>
 * <b>10.1 Length forms</b>
 * The definite form of length encoding shall be used,
 * encoded in the minimum number of octets.
 * [Contrast with 8.1.3.2 b).] 
 * </p><p>
 * <b>10.2 String encoding forms</b>
 * For BIT STRING, OCTET STRING and restricted character string types,
 * the constructed form of encoding shall not be used.
 * (Contrast with 8.21.6.)
 * @hide This class is not part of the Android public SDK API
 */
public abstract class ASN1OctetString
    extends ASN1Primitive
    implements ASN1OctetStringParser
{
    byte[]  string;

    /**
     * return an Octet String from a tagged object.
     *
     * @param taggedObject the tagged object holding the object we want.
     * @param explicit true if the object is meant to be explicitly
     *              tagged false otherwise.
     * @exception IllegalArgumentException if the tagged object cannot
     *              be converted.
     */
    public static ASN1OctetString getInstance(
        ASN1TaggedObject    taggedObject,
        boolean             explicit)
    {
        if (explicit)
        {
            if (!taggedObject.isExplicit())
            {
                throw new IllegalArgumentException("object implicit - explicit expected.");
            }

            return getInstance(taggedObject.getObject());
        }

        ASN1Primitive o = taggedObject.getObject();

        /*
         * constructed object which appears to be explicitly tagged and it's really implicit means
         * we have to add the surrounding octet string.
         */
        if (taggedObject.isExplicit())
        {
            ASN1OctetString singleSegment = getInstance(o);

            if (taggedObject instanceof BERTaggedObject)
            {
                return new BEROctetString(new ASN1OctetString[]{ singleSegment });
            }

            // TODO Should really be similar to the BERTaggedObject case above:
//            return new DLOctetString(new ASN1OctetString[]{ singleSegment });
            return (ASN1OctetString)new BEROctetString(new ASN1OctetString[]{ singleSegment }).toDLObject();
        }

        if (o instanceof ASN1OctetString)
        {
            ASN1OctetString s = (ASN1OctetString)o;

            if (taggedObject instanceof BERTaggedObject)
            {
                return s;
            }

            return (ASN1OctetString)s.toDLObject();
        }

        /*
         * in this case the parser returns a sequence, convert it into an octet string.
         */
        if (o instanceof ASN1Sequence)
        {
            ASN1Sequence s = (ASN1Sequence)o;

            if (taggedObject instanceof BERTaggedObject)
            {
                return BEROctetString.fromSequence(s);
            }

            // TODO Should really be similar to the BERTaggedObject case above:
//            return DLOctetString.fromSequence(s);
            return (ASN1OctetString)BEROctetString.fromSequence(s).toDLObject();
        }

        throw new IllegalArgumentException("unknown object in getInstance: " + taggedObject.getClass().getName());
    }

    /**
     * return an Octet String from the given object.
     *
     * @param obj the object we want converted.
     * @exception IllegalArgumentException if the object cannot be converted.
     */
    public static ASN1OctetString getInstance(
        Object  obj)
    {
        if (obj == null || obj instanceof ASN1OctetString)
        {
            return (ASN1OctetString)obj;
        }
        else if (obj instanceof byte[])
        {
            try
            {
                return getInstance(fromByteArray((byte[])obj));
            }
            catch (IOException e)
            {
                throw new IllegalArgumentException("failed to construct OCTET STRING from byte[]: " + e.getMessage());
            }
        }
        else if (obj instanceof ASN1Encodable)
        {
            ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();

            if (primitive instanceof ASN1OctetString)
            {
                return (ASN1OctetString)primitive;
            }
        }

        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
    }

    /**
     * Base constructor.
     *
     * @param string the octets making up the octet string.
     */
    public ASN1OctetString(
        byte[]  string)
    {
        if (string == null)
        {
            throw new NullPointerException("'string' cannot be null");
        }
        this.string = string;
    }

    /**
     * Return the content of the OCTET STRING as an InputStream.
     *
     * @return an InputStream representing the OCTET STRING's content.
     */
    public InputStream getOctetStream()
    {
        return new ByteArrayInputStream(string);
    }

    /**
     * Return the parser associated with this object.
     *
     * @return a parser based on this OCTET STRING
     */
    public ASN1OctetStringParser parser()
    {
        return this;
    }

    /**
     * Return the content of the OCTET STRING as a byte array.
     *
     * @return the byte[] representing the OCTET STRING's content.
     */
    public byte[] getOctets()
    {
        return string;
    }

    public int hashCode()
    {
        return Arrays.hashCode(this.getOctets());
    }

    boolean asn1Equals(
        ASN1Primitive o)
    {
        if (!(o instanceof ASN1OctetString))
        {
            return false;
        }

        ASN1OctetString  other = (ASN1OctetString)o;

        return Arrays.areEqual(string, other.string);
    }

    public ASN1Primitive getLoadedObject()
    {
        return this.toASN1Primitive();
    }

    ASN1Primitive toDERObject()
    {
        return new DEROctetString(string);
    }

    ASN1Primitive toDLObject()
    {
        return new DEROctetString(string);
    }

    abstract void encode(ASN1OutputStream out, boolean withTag) throws IOException;

    public String toString()
    {
      return "#" + Strings.fromByteArray(Hex.encode(string));
    }
}