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: BOOLEAN 55 */ 56 public static final int TAG_NUMBER_BOOLEAN = 0x1; 57 58 /** 59 * Tag number: INTEGER 60 */ 61 public static final int TAG_NUMBER_INTEGER = 0x2; 62 63 /** 64 * Tag number: BIT STRING 65 */ 66 public static final int TAG_NUMBER_BIT_STRING = 0x3; 67 68 /** 69 * Tag number: OCTET STRING 70 */ 71 public static final int TAG_NUMBER_OCTET_STRING = 0x4; 72 73 /** 74 * Tag number: NULL 75 */ 76 public static final int TAG_NUMBER_NULL = 0x05; 77 78 /** 79 * Tag number: OBJECT IDENTIFIER 80 */ 81 public static final int TAG_NUMBER_OBJECT_IDENTIFIER = 0x6; 82 83 /** 84 * Tag number: SEQUENCE 85 */ 86 public static final int TAG_NUMBER_SEQUENCE = 0x10; 87 88 /** 89 * Tag number: SET 90 */ 91 public static final int TAG_NUMBER_SET = 0x11; 92 93 /** 94 * Tag number: UTC_TIME 95 */ 96 public final static int TAG_NUMBER_UTC_TIME = 0x17; 97 98 /** 99 * Tag number: GENERALIZED_TIME 100 */ 101 public final static int TAG_NUMBER_GENERALIZED_TIME = 0x18; 102 getTagNumber(Asn1Type dataType)103 public static int getTagNumber(Asn1Type dataType) { 104 switch (dataType) { 105 case INTEGER: 106 return TAG_NUMBER_INTEGER; 107 case OBJECT_IDENTIFIER: 108 return TAG_NUMBER_OBJECT_IDENTIFIER; 109 case OCTET_STRING: 110 return TAG_NUMBER_OCTET_STRING; 111 case BIT_STRING: 112 return TAG_NUMBER_BIT_STRING; 113 case SET_OF: 114 return TAG_NUMBER_SET; 115 case SEQUENCE: 116 case SEQUENCE_OF: 117 return TAG_NUMBER_SEQUENCE; 118 case UTC_TIME: 119 return TAG_NUMBER_UTC_TIME; 120 case GENERALIZED_TIME: 121 return TAG_NUMBER_GENERALIZED_TIME; 122 case BOOLEAN: 123 return TAG_NUMBER_BOOLEAN; 124 default: 125 throw new IllegalArgumentException("Unsupported data type: " + dataType); 126 } 127 } 128 getTagClass(Asn1TagClass tagClass)129 public static int getTagClass(Asn1TagClass tagClass) { 130 switch (tagClass) { 131 case APPLICATION: 132 return TAG_CLASS_APPLICATION; 133 case CONTEXT_SPECIFIC: 134 return TAG_CLASS_CONTEXT_SPECIFIC; 135 case PRIVATE: 136 return TAG_CLASS_PRIVATE; 137 case UNIVERSAL: 138 return TAG_CLASS_UNIVERSAL; 139 default: 140 throw new IllegalArgumentException("Unsupported tag class: " + tagClass); 141 } 142 } 143 tagClassToString(int typeClass)144 public static String tagClassToString(int typeClass) { 145 switch (typeClass) { 146 case TAG_CLASS_APPLICATION: 147 return "APPLICATION"; 148 case TAG_CLASS_CONTEXT_SPECIFIC: 149 return ""; 150 case TAG_CLASS_PRIVATE: 151 return "PRIVATE"; 152 case TAG_CLASS_UNIVERSAL: 153 return "UNIVERSAL"; 154 default: 155 throw new IllegalArgumentException("Unsupported type class: " + typeClass); 156 } 157 } 158 tagClassAndNumberToString(int tagClass, int tagNumber)159 public static String tagClassAndNumberToString(int tagClass, int tagNumber) { 160 String classString = tagClassToString(tagClass); 161 String numberString = tagNumberToString(tagNumber); 162 return classString.isEmpty() ? numberString : classString + " " + numberString; 163 } 164 165 tagNumberToString(int tagNumber)166 public static String tagNumberToString(int tagNumber) { 167 switch (tagNumber) { 168 case TAG_NUMBER_INTEGER: 169 return "INTEGER"; 170 case TAG_NUMBER_OCTET_STRING: 171 return "OCTET STRING"; 172 case TAG_NUMBER_BIT_STRING: 173 return "BIT STRING"; 174 case TAG_NUMBER_NULL: 175 return "NULL"; 176 case TAG_NUMBER_OBJECT_IDENTIFIER: 177 return "OBJECT IDENTIFIER"; 178 case TAG_NUMBER_SEQUENCE: 179 return "SEQUENCE"; 180 case TAG_NUMBER_SET: 181 return "SET"; 182 case TAG_NUMBER_BOOLEAN: 183 return "BOOLEAN"; 184 case TAG_NUMBER_GENERALIZED_TIME: 185 return "GENERALIZED TIME"; 186 case TAG_NUMBER_UTC_TIME: 187 return "UTC TIME"; 188 default: 189 return "0x" + Integer.toHexString(tagNumber); 190 } 191 } 192 193 /** 194 * Returns {@code true} if the provided first identifier byte indicates that the data value uses 195 * constructed encoding for its contents, or {@code false} if the data value uses primitive 196 * encoding for its contents. 197 */ isConstructed(byte firstIdentifierByte)198 public static boolean isConstructed(byte firstIdentifierByte) { 199 return (firstIdentifierByte & ID_FLAG_CONSTRUCTED_ENCODING) != 0; 200 } 201 202 /** 203 * Returns the tag class encoded in the provided first identifier byte. See {@code TAG_CLASS} 204 * constants. 205 */ getTagClass(byte firstIdentifierByte)206 public static int getTagClass(byte firstIdentifierByte) { 207 return (firstIdentifierByte & 0xff) >> 6; 208 } 209 setTagClass(byte firstIdentifierByte, int tagClass)210 public static byte setTagClass(byte firstIdentifierByte, int tagClass) { 211 return (byte) ((firstIdentifierByte & 0x3f) | (tagClass << 6)); 212 } 213 214 /** 215 * Returns the tag number encoded in the provided first identifier byte. See {@code TAG_NUMBER} 216 * constants. 217 */ getTagNumber(byte firstIdentifierByte)218 public static int getTagNumber(byte firstIdentifierByte) { 219 return firstIdentifierByte & 0x1f; 220 } 221 setTagNumber(byte firstIdentifierByte, int tagNumber)222 public static byte setTagNumber(byte firstIdentifierByte, int tagNumber) { 223 return (byte) ((firstIdentifierByte & ~0x1f) | tagNumber); 224 } 225 } 226