slowr | 60d4d10 | 2017-08-16 18:33:58 -0700 | [diff] [blame] | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
Dimitrios Mavrommatis | 96b255a | 2017-12-06 13:09:25 -0800 | [diff] [blame] | 4 | package org.onosproject.xran.asn1lib.ber; |
slowr | 60d4d10 | 2017-08-16 18:33:58 -0700 | [diff] [blame] | 5 | |
| 6 | import java.io.EOFException; |
| 7 | import java.io.IOException; |
| 8 | import java.io.InputStream; |
| 9 | import java.io.Serializable; |
| 10 | |
| 11 | public class BerTag implements Serializable { |
| 12 | |
| 13 | public static final int UNIVERSAL_CLASS = 0x00; |
| 14 | public static final int APPLICATION_CLASS = 0x40; |
| 15 | public static final int CONTEXT_CLASS = 0x80; |
| 16 | public static final int PRIVATE_CLASS = 0xc0; |
| 17 | public static final int PRIMITIVE = 0x00; |
| 18 | public static final int CONSTRUCTED = 0x20; |
| 19 | public static final int BOOLEAN_TAG = 1; |
| 20 | public static final int INTEGER_TAG = 2; |
| 21 | public static final int BIT_STRING_TAG = 3; |
| 22 | public static final int OCTET_STRING_TAG = 4; |
| 23 | public static final int NULL_TAG = 5; |
| 24 | public static final int OBJECT_IDENTIFIER_TAG = 6; |
| 25 | public static final int OBJECT_DESCRIPTOR_TAG = 7; |
| 26 | public static final int REAL_TAG = 9; |
| 27 | public static final int ENUMERATED_TAG = 10; |
| 28 | public static final int EMBEDDED_PDV_TAG = 11; |
| 29 | public static final int UTF8_STRING_TAG = 12; |
| 30 | public static final int TIME_TAG = 14; |
| 31 | public static final int NUMERIC_STRING_TAG = 18; |
| 32 | public static final int PRINTABLE_STRING_TAG = 19; |
| 33 | public static final int TELETEX_STRING_TAG = 20; |
| 34 | public static final int VIDEOTEX_STRING_TAG = 21; |
| 35 | public static final int IA5_STRING_TAG = 22; |
| 36 | public static final int UTC_TIME_TAG = 23; |
| 37 | public static final int GENERALIZED_TIME_TAG = 24; |
| 38 | public static final int GRAPHIC_STRING_TAG = 25; |
| 39 | public static final int VISIBLE_STRING_TAG = 26; |
| 40 | public static final int GENERAL_STRING_TAG = 27; |
| 41 | public static final int UNIVERSAL_STRING_TAG = 28; |
| 42 | public static final int BMP_STRING_TAG = 30; |
| 43 | public static final int DATE_TAG = 31; |
| 44 | public static final int TIME_OF_DAY_TAG = 32; |
| 45 | public static final int DATE_TIME_TAG = 33; |
| 46 | public static final int DURATION_TAG = 34; |
| 47 | private static final long serialVersionUID = 1L; |
| 48 | public byte[] tagBytes = null; |
| 49 | public int tagClass; |
| 50 | public int primitive; |
| 51 | public int tagNumber; |
| 52 | |
| 53 | public BerTag(int identifierClass, int primitive, int tagNumber) { |
| 54 | this.tagClass = identifierClass; |
| 55 | this.primitive = primitive; |
| 56 | this.tagNumber = tagNumber; |
| 57 | code(); |
| 58 | } |
| 59 | |
| 60 | public BerTag() { |
| 61 | } |
| 62 | |
| 63 | private void code() { |
| 64 | if (tagNumber < 31) { |
| 65 | tagBytes = new byte[1]; |
| 66 | tagBytes[0] = (byte) (tagClass | primitive | tagNumber); |
| 67 | } else { |
| 68 | int tagLength = 1; |
| 69 | while (tagNumber > (Math.pow(2, (7 * tagLength)) - 1)) { |
| 70 | tagLength++; |
| 71 | } |
| 72 | |
| 73 | tagBytes = new byte[1 + tagLength]; |
| 74 | tagBytes[0] = (byte) (tagClass | primitive | 31); |
| 75 | |
| 76 | for (int j = 1; j <= (tagLength - 1); j++) { |
| 77 | tagBytes[j] = (byte) (((tagNumber >> (7 * (tagLength - j))) & 0xff) | 0x80); |
| 78 | } |
| 79 | |
| 80 | tagBytes[tagLength] = (byte) (tagNumber & 0x7f); |
| 81 | |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | public int encode(BerByteArrayOutputStream os) throws IOException { |
| 86 | if (tagBytes == null) { |
| 87 | code(); |
| 88 | } |
| 89 | for (int i = (tagBytes.length - 1); i >= 0; i--) { |
| 90 | os.write(tagBytes[i]); |
| 91 | } |
| 92 | return tagBytes.length; |
| 93 | } |
| 94 | |
| 95 | public int decode(InputStream is) throws IOException { |
| 96 | int nextByte = is.read(); |
| 97 | if (nextByte == -1) { |
| 98 | throw new EOFException("Unexpected end of input stream."); |
| 99 | } |
| 100 | |
| 101 | tagClass = nextByte & 0xC0; |
| 102 | primitive = nextByte & 0x20; |
| 103 | tagNumber = nextByte & 0x1f; |
| 104 | |
| 105 | int codeLength = 1; |
| 106 | |
| 107 | if (tagNumber == 0x1f) { |
| 108 | tagNumber = 0; |
| 109 | |
| 110 | int counter = 0; |
| 111 | |
| 112 | do { |
| 113 | nextByte = is.read(); |
| 114 | if (nextByte == -1) { |
| 115 | throw new EOFException("Unexpected end of input stream."); |
| 116 | } |
| 117 | |
| 118 | codeLength++; |
| 119 | if (counter >= 6) { |
| 120 | throw new IOException("Invalid Tag"); |
| 121 | } |
| 122 | tagNumber = tagNumber << 7; |
| 123 | tagNumber |= (nextByte & 0x7f); |
| 124 | counter++; |
| 125 | } while ((nextByte & 0x80) == 0x80); |
| 126 | |
| 127 | } |
| 128 | |
| 129 | return codeLength; |
| 130 | } |
| 131 | |
| 132 | /** |
| 133 | * Decodes the Identifier from the ByteArrayInputStream and throws an Exception if it is not equal to itself. |
| 134 | * Returns the number of bytes read from the InputStream. |
| 135 | * |
| 136 | * @param is the input stream to read the identifier from. |
| 137 | * @return the length of the identifier read. |
| 138 | * @throws IOException if an exception occurs reading the identifier from the stream. |
| 139 | */ |
| 140 | public int decodeAndCheck(InputStream is) throws IOException { |
| 141 | |
| 142 | for (Byte identifierByte : tagBytes) { |
| 143 | int nextByte = is.read(); |
| 144 | if (nextByte == -1) { |
| 145 | throw new EOFException("Unexpected end of input stream."); |
| 146 | } |
| 147 | |
| 148 | if (nextByte != (identifierByte & 0xff)) { |
| 149 | throw new IOException("Identifier does not match!"); |
| 150 | } |
| 151 | } |
| 152 | return tagBytes.length; |
| 153 | } |
| 154 | |
| 155 | public boolean equals(int identifierClass, int primitive, int tagNumber) { |
| 156 | return (this.tagNumber == tagNumber && this.tagClass == identifierClass && this.primitive == primitive); |
| 157 | } |
| 158 | |
| 159 | @Override |
| 160 | public boolean equals(Object obj) { |
| 161 | if (!(obj instanceof BerTag)) { |
| 162 | return false; |
| 163 | } |
| 164 | if (obj == this) { |
| 165 | return true; |
| 166 | } |
| 167 | BerTag berIdentifier = (BerTag) obj; |
| 168 | return (tagNumber == berIdentifier.tagNumber && tagClass == berIdentifier.tagClass |
| 169 | && primitive == berIdentifier.primitive); |
| 170 | } |
| 171 | |
| 172 | @Override |
| 173 | public int hashCode() { |
| 174 | int hash = 17; |
| 175 | hash = hash * 31 + tagNumber; |
| 176 | hash = hash * 31 + tagClass; |
| 177 | hash = hash * 31 + primitive; |
| 178 | return hash; |
| 179 | } |
| 180 | |
| 181 | @Override |
| 182 | public String toString() { |
| 183 | return "identifier class: " + tagClass + ", primitive: " + primitive + ", tag number: " + tagNumber; |
| 184 | } |
| 185 | |
| 186 | } |