1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.apksig.internal.asn1.ber;
18 
19 import com.android.apksig.internal.asn1.Asn1Type;
20 import com.android.apksig.internal.asn1.Asn1TagClass;
21 
22 /**
23  * ASN.1 Basic Encoding Rules (BER) constants and helper methods. See {@code X.690}.
24  */
25 public abstract class BerEncoding {
BerEncoding()26     private BerEncoding() {}
27 
28     /**
29      * Constructed vs primitive flag in the first identifier byte.
30      */
31     public static final int ID_FLAG_CONSTRUCTED_ENCODING = 1 << 5;
32 
33     /**
34      * Tag class: UNIVERSAL
35      */
36     public static final int TAG_CLASS_UNIVERSAL = 0;
37 
38     /**
39      * Tag class: APPLICATION
40      */
41     public static final int TAG_CLASS_APPLICATION = 1;
42 
43     /**
44      * Tag class: CONTEXT SPECIFIC
45      */
46     public static final int TAG_CLASS_CONTEXT_SPECIFIC = 2;
47 
48     /**
49      * Tag class: PRIVATE
50      */
51     public static final int TAG_CLASS_PRIVATE = 3;
52 
53     /**
54      * Tag number: INTEGER
55      */
56     public static final int TAG_NUMBER_INTEGER = 0x2;
57 
58     /**
59      * Tag number: OCTET STRING
60      */
61     public static final int TAG_NUMBER_OCTET_STRING = 0x4;
62 
63     /**
64      * Tag number: NULL
65      */
66     public static final int TAG_NUMBER_NULL = 0x05;
67 
68     /**
69      * Tag number: OBJECT IDENTIFIER
70      */
71     public static final int TAG_NUMBER_OBJECT_IDENTIFIER = 0x6;
72 
73     /**
74      * Tag number: SEQUENCE
75      */
76     public static final int TAG_NUMBER_SEQUENCE = 0x10;
77 
78     /**
79      * Tag number: SET
80      */
81     public static final int TAG_NUMBER_SET = 0x11;
82 
getTagNumber(Asn1Type dataType)83     public static int getTagNumber(Asn1Type dataType) {
84         switch (dataType) {
85             case INTEGER:
86                 return TAG_NUMBER_INTEGER;
87             case OBJECT_IDENTIFIER:
88                 return TAG_NUMBER_OBJECT_IDENTIFIER;
89             case OCTET_STRING:
90                 return TAG_NUMBER_OCTET_STRING;
91             case SET_OF:
92                 return TAG_NUMBER_SET;
93             case SEQUENCE:
94             case SEQUENCE_OF:
95                 return TAG_NUMBER_SEQUENCE;
96             default:
97                 throw new IllegalArgumentException("Unsupported data type: " + dataType);
98         }
99     }
100 
getTagClass(Asn1TagClass tagClass)101     public static int getTagClass(Asn1TagClass tagClass) {
102         switch (tagClass) {
103             case APPLICATION:
104                 return TAG_CLASS_APPLICATION;
105             case CONTEXT_SPECIFIC:
106                 return TAG_CLASS_CONTEXT_SPECIFIC;
107             case PRIVATE:
108                 return TAG_CLASS_PRIVATE;
109             case UNIVERSAL:
110                 return TAG_CLASS_UNIVERSAL;
111             default:
112                 throw new IllegalArgumentException("Unsupported tag class: " + tagClass);
113         }
114     }
115 
tagClassToString(int typeClass)116     public static String tagClassToString(int typeClass) {
117         switch (typeClass) {
118             case TAG_CLASS_APPLICATION:
119                 return "APPLICATION";
120             case TAG_CLASS_CONTEXT_SPECIFIC:
121                 return "";
122             case TAG_CLASS_PRIVATE:
123                 return "PRIVATE";
124             case TAG_CLASS_UNIVERSAL:
125                 return "UNIVERSAL";
126             default:
127                 throw new IllegalArgumentException("Unsupported type class: " + typeClass);
128         }
129     }
130 
tagClassAndNumberToString(int tagClass, int tagNumber)131     public static String tagClassAndNumberToString(int tagClass, int tagNumber) {
132         String classString = tagClassToString(tagClass);
133         String numberString = tagNumberToString(tagNumber);
134         return classString.isEmpty() ? numberString : classString + " " + numberString;
135     }
136 
137 
tagNumberToString(int tagNumber)138     public static String tagNumberToString(int tagNumber) {
139         switch (tagNumber) {
140             case TAG_NUMBER_INTEGER:
141                 return "INTEGER";
142             case TAG_NUMBER_OCTET_STRING:
143                 return "OCTET STRING";
144             case TAG_NUMBER_NULL:
145                 return "NULL";
146             case TAG_NUMBER_OBJECT_IDENTIFIER:
147                 return "OBJECT IDENTIFIER";
148             case TAG_NUMBER_SEQUENCE:
149                 return "SEQUENCE";
150             case TAG_NUMBER_SET:
151                 return "SET";
152             default:
153                 return "0x" + Integer.toHexString(tagNumber);
154         }
155     }
156 
157     /**
158      * Returns {@code true} if the provided first identifier byte indicates that the data value uses
159      * constructed encoding for its contents, or {@code false} if the data value uses primitive
160      * encoding for its contents.
161      */
isConstructed(byte firstIdentifierByte)162     public static boolean isConstructed(byte firstIdentifierByte) {
163         return (firstIdentifierByte & ID_FLAG_CONSTRUCTED_ENCODING) != 0;
164     }
165 
166     /**
167      * Returns the tag class encoded in the provided first identifier byte. See {@code TAG_CLASS}
168      * constants.
169      */
getTagClass(byte firstIdentifierByte)170     public static int getTagClass(byte firstIdentifierByte) {
171         return (firstIdentifierByte & 0xff) >> 6;
172     }
173 
setTagClass(byte firstIdentifierByte, int tagClass)174     public static byte setTagClass(byte firstIdentifierByte, int tagClass) {
175         return (byte) ((firstIdentifierByte & 0x3f) | (tagClass << 6));
176     }
177 
178     /**
179      * Returns the tag number encoded in the provided first identifier byte. See {@code TAG_NUMBER}
180      * constants.
181      */
getTagNumber(byte firstIdentifierByte)182     public static int getTagNumber(byte firstIdentifierByte) {
183         return firstIdentifierByte & 0x1f;
184     }
185 
setTagNumber(byte firstIdentifierByte, int tagNumber)186     public static byte setTagNumber(byte firstIdentifierByte, int tagNumber) {
187         return (byte) ((firstIdentifierByte & ~0x1f) | tagNumber);
188     }
189 }
190