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* @author Vladimir N. Molotkov
19* @version $Revision$
20*/
21
22package tests.security.cert;
23
24import dalvik.annotation.TestTargets;
25import dalvik.annotation.TestLevel;
26import dalvik.annotation.TestTargetNew;
27import dalvik.annotation.TestTargetClass;
28
29import junit.framework.TestCase;
30
31import java.io.IOException;
32import java.security.cert.PolicyQualifierInfo;
33import java.util.Arrays;
34
35/**
36 * PolicyQualifierInfo test
37 *
38 */
39@TestTargetClass(PolicyQualifierInfo.class)
40public class PolicyQualifierInfoTest extends TestCase {
41
42
43    /**
44     * Test #1 for <code>PolicyQualifierInfo</code> constructor<br>
45     * Assertion: throws <code>IOException</code> if byte array
46     * parameter does not represent a valid and parsable policy
47     * qualifier info
48     */
49    @TestTargetNew(
50        level = TestLevel.PARTIAL_COMPLETE,
51        notes = "Verifies NullPointerException and IOException.",
52        method = "PolicyQualifierInfo",
53        args = {byte[].class}
54    )
55    public final void test_Ctor() throws IOException {
56        try {
57            // pass null
58            new PolicyQualifierInfo(null);
59            fail("No expected NullPointerException");
60        } catch (NullPointerException e) {
61        }
62
63        try {
64            // pass empty array
65            new PolicyQualifierInfo(new byte[0]);
66            fail("IOE expected");
67        } catch (IOException e) {
68        }
69
70
71        try {
72            // pass invalid array
73            new PolicyQualifierInfo(
74                    new byte[] {(byte)0x06, (byte)0x03,
75                            (byte)0x81, (byte)0x34, (byte)0x03});
76            fail("IOE expected");
77        } catch (IOException e) {
78        }
79    }
80
81    /**
82     * Test #2 for <code>PolicyQualifierInfo</code> constructor<br>
83     * Assertion: throws <code>IOException</code> if byte array
84     * parameter does not represent a valid and parsable policy
85     * qualifier info
86     */
87    @TestTargetNew(
88        level = TestLevel.PARTIAL_COMPLETE,
89        notes = "Verifies IOException.",
90        method = "PolicyQualifierInfo",
91        args = {byte[].class}
92    )
93    public final void testPolicyQualifierInfo02() {
94        // get valid encoding
95        byte[] encoding = getDerEncoding();
96        // corrupt root seq length
97        encoding[1] = (byte)0x27;
98
99        try {
100            // pass invalid array
101            new PolicyQualifierInfo(encoding);
102            fail("IOE expected");
103        } catch (IOException e) {
104        }
105
106
107        // get valid encoding
108        encoding = getDerEncoding();
109        // corrupt policy qualifier ID:
110        //  - change OID to the Relative OID
111        encoding[2] = (byte)13;
112        try {
113            // pass invalid array
114            new PolicyQualifierInfo(encoding);
115            fail("IOE expected");
116        } catch (IOException e) {
117        }
118    }
119
120    /**
121     * Test #3 for <code>PolicyQualifierInfo</code> constructor<br>
122     * Assertion: Creates an instance of <code>PolicyQualifierInfo</code>
123     * from the encoded bytes
124     *
125     * @throws IOException
126     */
127    @TestTargetNew(
128        level = TestLevel.PARTIAL_COMPLETE,
129        notes = "",
130        method = "PolicyQualifierInfo",
131        args = {byte[].class}
132    )
133    public final void testPolicyQualifierInfo03() throws IOException {
134        // get valid encoding
135        byte[] encoding = getDerEncoding();
136        // pass valid array
137        new PolicyQualifierInfo(encoding);
138    }
139
140    /**
141     * Test #4 for <code>PolicyQualifierInfo</code> constructor<br>
142     * Assertion: The encoded byte array is copied on construction
143     *
144     * @throws IOException
145     */
146    @TestTargetNew(
147        level = TestLevel.PARTIAL_COMPLETE,
148        notes = "Verifies constructor with encoded byte array copied on construction.",
149        method = "PolicyQualifierInfo",
150        args = {byte[].class}
151    )
152    public final void testPolicyQualifierInfo04() throws IOException  {
153        // get valid encoding
154        byte[] encoding = getDerEncoding();
155        byte[] encodingCopy = encoding.clone();
156        // pass valid array
157        PolicyQualifierInfo i = new PolicyQualifierInfo(encodingCopy);
158        // get encoding
159        byte[] encodingRet = i.getEncoded();
160        // check returned array
161        assertTrue(Arrays.equals(encoding, encodingRet));
162        // modify input
163        encodingCopy[0] = (byte)0;
164        // get encoding again
165        byte[] encodingRet1 = i.getEncoded();
166        // check that above modification did not change
167        // internal state of the PolicyQualifierInfo instance
168        assertTrue(Arrays.equals(encoding, encodingRet1));
169    }
170
171    /**
172     * Test #1 for <code>getEncoded()</code> method
173     * Assertion: Returns the ASN.1 DER encoded form of
174     * this <code>PolicyQualifierInfo</code>
175     *
176     * @throws IOException
177     */
178    @TestTargetNew(
179        level = TestLevel.COMPLETE,
180        notes = "",
181        method = "getEncoded",
182        args = {}
183    )
184    public final void testGetEncoded01() throws IOException {
185        // get valid encoding
186        byte[] encoding = getDerEncoding();
187        // pass valid array
188        PolicyQualifierInfo i = new PolicyQualifierInfo(encoding);
189        // get encoding
190        byte[] encodingRet = i.getEncoded();
191        // check returned array
192        assertTrue(Arrays.equals(encoding, encodingRet));
193    }
194
195    /**
196     * Test #2 for <code>getEncoded()</code> method
197     * Assertion: a copy is returned each time
198     *
199     * @throws IOException
200     */
201    @TestTargetNew(
202        level = TestLevel.COMPLETE,
203        notes = "",
204        method = "getEncoded",
205        args = {}
206    )
207    public final void testGetEncoded02() throws IOException {
208        // get valid encoding
209        byte[] encoding = getDerEncoding();
210        byte[] encodingCopy = encoding.clone();
211        // pass valid array
212        PolicyQualifierInfo i = new PolicyQualifierInfo(encodingCopy);
213        // get encoding
214        byte[] encodingRet = i.getEncoded();
215        // modify returned array
216        encodingRet[0] = (byte)0;
217        // get encoding again
218        byte[] encodingRet1 = i.getEncoded();
219        // check that above modification did not change
220        // internal state of the PolicyQualifierInfo instance
221        assertTrue(Arrays.equals(encoding, encodingRet1));
222    }
223
224    /**
225     * Test #1 for <code>getPolicyQualifier()</code> method
226     * Assertion: Returns the ASN.1 DER encoded form of
227     * this <code>PolicyQualifierInfo</code>
228     *
229     * @throws IOException
230     */
231    @TestTargetNew(
232        level = TestLevel.COMPLETE,
233        notes = "",
234        method = "getPolicyQualifier",
235        args = {}
236    )
237    public final void testGetPolicyQualifier01() throws IOException {
238        // get valid encoding
239        byte[] encoding = getDerEncoding();
240        // get policy qualifier encoding
241        byte[] pqEncoding = new byte[28];
242        System.arraycopy(encoding, 12, pqEncoding, 0, pqEncoding.length);
243        // pass valid array
244        PolicyQualifierInfo i = new PolicyQualifierInfo(encoding);
245        // get encoding
246        byte[] pqEncodingRet = i.getPolicyQualifier();
247        // check returned array
248        assertTrue(Arrays.equals(pqEncoding, pqEncodingRet));
249    }
250
251    /**
252     * Test #2 for <code>getPolicyQualifier()</code> method
253     * Assertion: a copy is returned each time
254     *
255     * @throws IOException
256     */
257    @TestTargetNew(
258        level = TestLevel.COMPLETE,
259        notes = "",
260        method = "getPolicyQualifier",
261        args = {}
262    )
263    public final void testGetPolicyQualifier02() throws IOException {
264        // get valid encoding
265        byte[] encoding = getDerEncoding();
266        // get policy qualifier encoding
267        byte[] pqEncoding = new byte[28];
268        System.arraycopy(encoding, 12, pqEncoding, 0, pqEncoding.length);
269        // pass valid array
270        PolicyQualifierInfo i = new PolicyQualifierInfo(encoding);
271        // get encoding
272        byte[] pqEncodingRet = i.getPolicyQualifier();
273        // modify returned array
274        pqEncodingRet[0] = (byte)0;
275        // get encoding again
276        byte[] pqEncodingRet1 = i.getPolicyQualifier();
277        //
278        assertNotSame(pqEncodingRet, pqEncodingRet1);
279        // check that above modification did not change
280        // internal state of the PolicyQualifierInfo instance
281        assertTrue(Arrays.equals(pqEncoding, pqEncodingRet1));
282    }
283
284    /**
285     * Test for <code>getPolicyQualifierId()</code> method
286     * Assertion: Returns the <code>policyQualifierId</code>
287     * field of this <code>PolicyQualifierInfo</code>.
288     * The <code>policyQualifierId</code> is an Object Identifier (OID)
289     * represented by a set of nonnegative integers separated by periods
290     *
291     * @throws IOException
292     */
293    @TestTargetNew(
294        level = TestLevel.COMPLETE,
295        notes = "",
296        method = "getPolicyQualifierId",
297        args = {}
298    )
299    public final void testGetPolicyQualifierId() throws IOException {
300        // get valid encoding
301        byte[] encoding = getDerEncoding();
302        // pass valid array
303        PolicyQualifierInfo i = new PolicyQualifierInfo(encoding);
304        // get OID as String and check it
305        assertEquals("1.3.6.1.5.5.7.2.1", i.getPolicyQualifierId());
306
307        // get valid encoding
308        encoding = getDerEncoding();
309        // change OID to 1.3.98437.82818.1
310        encoding[5] = (byte)0x86;
311        encoding[6] = (byte)0x81;
312        encoding[8] = (byte)0x85;
313        encoding[9] = (byte)0x87;
314        i = new PolicyQualifierInfo(encoding);
315        // get OID as String and check it
316        assertEquals("1.3.98437.82818.1", i.getPolicyQualifierId());
317    }
318
319    /**
320     * Test for <code>toString()</code> method
321     * Assertion: returns description of the contents of this
322     * <code>PolicyQualifierInfo</code> as printable <code>String</code>
323     * @throws IOException
324     *
325     * @throws IOException
326     */
327    @TestTargetNew(
328        level = TestLevel.COMPLETE,
329        notes = "",
330        method = "toString",
331        args = {}
332    )
333    public final void testToString() throws IOException {
334        // get valid encoding
335        byte[] encoding = getDerEncoding();
336        // pass valid array
337        PolicyQualifierInfo i = new PolicyQualifierInfo(encoding);
338
339        assertNotNull(i.toString());
340    }
341
342    //
343    // Private stuff
344    //
345
346    /**
347     * Returns valid DER encoding for the following ASN.1 definition
348     * (as specified in RFC 3280 -
349     *  Internet X.509 Public Key Infrastructure.
350     *  Certificate and Certificate Revocation List (CRL) Profile.
351     *  http://www.ietf.org/rfc/rfc3280.txt):
352     *
353     *   PolicyQualifierInfo ::= SEQUENCE {
354     *      policyQualifierId       PolicyQualifierId,
355     *      qualifier               ANY DEFINED BY policyQualifierId
356     *   }
357     *
358     * where policyQualifierId (OID) is
359     *      1.3.6.1.5.5.7.2.1
360     * and qualifier (IA5String) is
361     *      "http://www.qq.com/stmt.txt"
362     *
363     * (data generated by own encoder during test development)
364     */
365    private static final byte[] getDerEncoding() {
366        // DO NOT MODIFY!
367        return  new byte[] {
368            (byte)0x30, (byte)0x26, // tag Seq, length
369              (byte)0x06, (byte)0x08, // tag OID, length
370                (byte)0x2b, (byte)0x06, (byte)0x01, (byte)0x05, // oid value
371                (byte)0x05, (byte)0x07, (byte)0x02, (byte)0x01, // oid value
372              (byte)0x16, (byte)0x1a, // tag IA5String, length
373                (byte)0x68, (byte)0x74, (byte)0x74, (byte)0x70,  // IA5String value
374                (byte)0x3a, (byte)0x2f, (byte)0x2f, (byte)0x77,  // IA5String value
375                (byte)0x77, (byte)0x77, (byte)0x2e, (byte)0x71,  // IA5String value
376                (byte)0x71, (byte)0x2e, (byte)0x63, (byte)0x6f,  // IA5String value
377                (byte)0x6d, (byte)0x2f, (byte)0x73, (byte)0x74,  // IA5String value
378                (byte)0x6d, (byte)0x74, (byte)0x2e, (byte)0x74,  // IA5String value
379                (byte)0x78, (byte)0x74   // IA5String value
380        };
381    }
382}
383