blob: d0c5e9539963f323d80e1ed269bdd4555efb1615 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Stepan M. Mishura
*/
package org.apache.harmony.security.tests.asn1.der;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import junit.framework.TestCase;
import org.apache.harmony.security.asn1.ASN1Boolean;
import org.apache.harmony.security.asn1.ASN1Constants;
import org.apache.harmony.security.asn1.ASN1Exception;
import org.apache.harmony.security.asn1.ASN1Implicit;
import org.apache.harmony.security.asn1.ASN1OctetString;
import org.apache.harmony.security.asn1.ASN1SequenceOf;
import org.apache.harmony.security.asn1.ASN1Type;
import org.apache.harmony.security.asn1.DerInputStream;
import org.apache.harmony.security.asn1.DerOutputStream;
/**
* ASN.1 DER test for Implicitly tagged type
*
* @see http://asn1.elibel.tm.fr/en/standards/index.htm
*/
public class ImplicitTest extends TestCase {
private static ASN1SequenceOf sequence = new ASN1SequenceOf(ASN1Boolean
.getInstance());
private static Object[][] taggedType = {
// format: object to encode / ASN.1 tagged type / byte array
//
// Boolean = false
//
// [UNIVERSAL 5] Boolean
{
Boolean.FALSE,
new byte[] { 0x05, 0x01, 0x00 },
new ASN1Implicit(ASN1Constants.CLASS_UNIVERSAL, 5,
ASN1Boolean.getInstance()) },
// [APPLICATION 5] Boolean
{
Boolean.FALSE,
new byte[] { 0x45, 0x01, 0x00 },
new ASN1Implicit(ASN1Constants.CLASS_APPLICATION, 5,
ASN1Boolean.getInstance()) },
// [CONTEXT-SPECIFIC 5] Boolean
{
Boolean.FALSE,
new byte[] { (byte) 0x85, 0x01, 0x00 },
new ASN1Implicit(ASN1Constants.CLASS_CONTEXTSPECIFIC, 5,
ASN1Boolean.getInstance()) },
// [5] Boolean (default = CONTEXT-SPECIFIC)
{ Boolean.FALSE, new byte[] { (byte) 0x85, 0x01, 0x00 },
new ASN1Implicit(5, ASN1Boolean.getInstance()) },
// [PRIVATE 5] Boolean
{
Boolean.FALSE,
new byte[] { (byte) 0xC5, 0x01, 0x00 },
new ASN1Implicit(ASN1Constants.CLASS_PRIVATE, 5,
ASN1Boolean.getInstance()) },
//
// Boolean = true
//
// [UNIVERSAL 5] Boolean
{
Boolean.TRUE,
new byte[] { 0x05, 0x01, (byte) 0xFF },
new ASN1Implicit(ASN1Constants.CLASS_UNIVERSAL, 5,
ASN1Boolean.getInstance()) },
// [APPLICATION 5] Boolean
{
Boolean.TRUE,
new byte[] { 0x45, 0x01, (byte) 0xFF },
new ASN1Implicit(ASN1Constants.CLASS_APPLICATION, 5,
ASN1Boolean.getInstance()) },
// [CONTEXT-SPECIFIC 5] Boolean
{
Boolean.TRUE,
new byte[] { (byte) 0x85, 0x01, (byte) 0xFF },
new ASN1Implicit(ASN1Constants.CLASS_CONTEXTSPECIFIC, 5,
ASN1Boolean.getInstance()) },
// [5] Boolean (default = CONTEXT-SPECIFIC)
{
Boolean.TRUE,
new byte[] { (byte) 0x85, 0x01, (byte) 0xFF },
new ASN1Implicit(ASN1Constants.CLASS_CONTEXTSPECIFIC, 5,
ASN1Boolean.getInstance()) },
// [PRIVATE 5] Boolean
{
Boolean.TRUE,
new byte[] { (byte) 0xC5, 0x01, (byte) 0xFF },
new ASN1Implicit(ASN1Constants.CLASS_PRIVATE, 5,
ASN1Boolean.getInstance()) },
//
// SequenceOf - testing constructed ASN.1 type
//
// [UNIVERSAL 5] SequenceOf
{
new ArrayList(),
new byte[] { 0x25, 0x00 },
new ASN1Implicit(ASN1Constants.CLASS_UNIVERSAL, 5, sequence) },
// [APPLICATION 5] SequenceOf
{
new ArrayList(),
new byte[] { 0x65, 0x00 },
new ASN1Implicit(ASN1Constants.CLASS_APPLICATION, 5,
sequence) },
// [CONTEXT-SPECIFIC 5] SequenceOf
{
new ArrayList(),
new byte[] { (byte) 0xA5, 0x00 },
new ASN1Implicit(ASN1Constants.CLASS_CONTEXTSPECIFIC, 5,
sequence) },
// [5] SequenceOf (default = CONTEXT-SPECIFIC)
{
new ArrayList(),
new byte[] { (byte) 0xA5, 0x00 },
new ASN1Implicit(ASN1Constants.CLASS_CONTEXTSPECIFIC, 5,
sequence) },
// [PRIVATE 5] SequenceOf
{ new ArrayList(), new byte[] { (byte) 0xE5, 0x00 },
new ASN1Implicit(ASN1Constants.CLASS_PRIVATE, 5, sequence) } };
public void testDecode_Valid() throws IOException {
for (int i = 0; i < taggedType.length; i++) {
DerInputStream in = new DerInputStream((byte[]) taggedType[i][1]);
assertEquals("Test case: " + i, taggedType[i][0],
((ASN1Type) taggedType[i][2]).decode(in));
}
}
// FIXME need testcase for decoding invalid encodings
public void testEncode() throws IOException {
for (int i = 0; i < taggedType.length; i++) {
DerOutputStream out = new DerOutputStream(
(ASN1Type) taggedType[i][2], taggedType[i][0]);
assertTrue("Test case: " + i, Arrays.equals(
(byte[]) taggedType[i][1], out.encoded));
}
}
/**
* Tests 2 consecutive implicit string type tagging
* <p/>
* TYPE1 = [1] IMPLICIT OCTET STRING
* TYPE2 = [2] IMPLICIT TYPE1
*/
public void testConsecutiveStringTagging() throws Exception {
ASN1Implicit type1 = new ASN1Implicit(1, ASN1OctetString.getInstance());
ASN1Implicit type2 = new ASN1Implicit(2, type1);
byte[] primitiveEncoding = new byte[] {
// tag: class(CONTEXT SPECIFIC) + number (2)
(byte) 0x82,
// length
0x03,
// value
0x00, 0x01, 0x02 };
byte[] constructedEncoding = new byte[] {
// tag: class(CONTEXT SPECIFIC) + constructed +number (2)
(byte) 0xA2,
// length
0x00 };
byte[] array = new byte[] { 0x00, 0x01, 0x02 };
// decode primitive
assertTrue(Arrays.equals(array, (byte[]) type2
.decode(primitiveEncoding)));
// encode primitive
assertTrue(Arrays.equals(primitiveEncoding, type2.encode(array)));
// decode constructed
try {
type2.decode(constructedEncoding);
fail("No expected ASN1Exception");
} catch (ASN1Exception e) {
// FIXME any other check instead of comparing the message???
assertEquals(
"ASN.1 octetstring: constructed identifier at [0]. Not valid for DER.",
e.getMessage());
}
}
}