| 1 | /****************************************************************************** |
| 2 | * Copyright (c) 2000-2016 Ericsson Telecom AB |
| 3 | * All rights reserved. This program and the accompanying materials |
| 4 | * are made available under the terms of the Eclipse Public License v1.0 |
| 5 | * which accompanies this distribution, and is available at |
| 6 | * http://www.eclipse.org/legal/epl-v10.html |
| 7 | * |
| 8 | * Contributors: |
| 9 | * Balasko, Jeno |
| 10 | * Forstner, Matyas |
| 11 | * Raduly, Csaba |
| 12 | * Szabo, Janos Zoltan – initial implementation |
| 13 | * |
| 14 | ******************************************************************************/ |
| 15 | #ifndef _BER_HH |
| 16 | #define _BER_HH |
| 17 | |
| 18 | /** @name BER encoding subtypes |
| 19 | @{ |
| 20 | */ |
| 21 | /// Canonical Encoding Rules |
| 22 | #define BER_ENCODE_CER 1 |
| 23 | /// Distinguished Encoding Rules |
| 24 | #define BER_ENCODE_DER 2 |
| 25 | /** @} */ |
| 26 | |
| 27 | /** @name BER decoding options |
| 28 | @{ |
| 29 | */ |
| 30 | /// Short length form is acceptable |
| 31 | #define BER_ACCEPT_SHORT 0x01 |
| 32 | /// Long length form is acceptable |
| 33 | #define BER_ACCEPT_LONG 0x02 |
| 34 | /// Indefinite form is acceptable |
| 35 | #define BER_ACCEPT_INDEFINITE 0x04 |
| 36 | /// Definite forms (short or long) are acceptable |
| 37 | #define BER_ACCEPT_DEFINITE 0x03 |
| 38 | /// All forms are acceptable |
| 39 | #define BER_ACCEPT_ALL 0x07 |
| 40 | /** @} */ |
| 41 | |
| 42 | #include "Types.h" |
| 43 | #include "Encdec.hh" |
| 44 | |
| 45 | /** |
| 46 | * \defgroup BER BER-related stuff. |
| 47 | * |
| 48 | * @{ |
| 49 | */ |
| 50 | |
| 51 | /** @brief ASN.1 tag */ |
| 52 | enum ASN_Tagclass_t { |
| 53 | ASN_TAG_UNDEF, |
| 54 | ASN_TAG_UNIV, /**< UNIVERSAL */ |
| 55 | ASN_TAG_APPL, /**< APPLICATION */ |
| 56 | ASN_TAG_CONT, /**< context-specific */ |
| 57 | ASN_TAG_PRIV /**< PRIVATE */ |
| 58 | }; |
| 59 | |
| 60 | typedef unsigned int ASN_Tagnumber_t; |
| 61 | |
| 62 | /** @brief ASN.1 identifier |
| 63 | * |
| 64 | * Contains two thirds of the T from a TLV |
| 65 | */ |
| 66 | struct ASN_Tag_t { |
| 67 | ASN_Tagclass_t tagclass; /**< Tag class */ |
| 68 | ASN_Tagnumber_t tagnumber; /**< Tag value. For UNIVERSAL, the values are predefined */ |
| 69 | |
| 70 | /** Creates a user-friendly representation of the tag. After using, |
| 71 | * you have to Free() this string. */ |
| 72 | char* print() const; |
| 73 | }; |
| 74 | |
| 75 | /** @brief BER encoding information |
| 76 | * |
| 77 | * There is one object for each predefined (UNIVERSAL) type. |
| 78 | * Also, the compiler writes an object of this type for each user-defined type |
| 79 | * into the generated code in Common::Type::generate_code_berdescriptor() . |
| 80 | */ |
| 81 | struct ASN_BERdescriptor_t { |
| 82 | /** Number of tags. |
| 83 | * |
| 84 | * For the UNIVERSAL classes, this is usually 1 (except for CHOICE and ANY) |
| 85 | */ |
| 86 | size_t n_tags; |
| 87 | /** This array contains the tags. Index 0 is the innermost tag. */ |
| 88 | const ASN_Tag_t *tags; |
| 89 | |
| 90 | /** Creates a user-friendly representation of tags. After using, you |
| 91 | * have to Free() this string. */ |
| 92 | char* print_tags() const; |
| 93 | }; |
| 94 | |
| 95 | struct TTCN_Typedescriptor_t; |
| 96 | |
| 97 | extern const ASN_BERdescriptor_t BOOLEAN_ber_; |
| 98 | extern const ASN_BERdescriptor_t INTEGER_ber_; |
| 99 | extern const ASN_BERdescriptor_t BITSTRING_ber_; |
| 100 | extern const ASN_BERdescriptor_t OCTETSTRING_ber_; |
| 101 | extern const ASN_BERdescriptor_t ASN_NULL_ber_; |
| 102 | extern const ASN_BERdescriptor_t OBJID_ber_; |
| 103 | extern const ASN_BERdescriptor_t ObjectDescriptor_ber_; |
| 104 | extern const ASN_BERdescriptor_t FLOAT_ber_; |
| 105 | extern const ASN_BERdescriptor_t ENUMERATED_ber_; |
| 106 | extern const ASN_BERdescriptor_t UTF8String_ber_; |
| 107 | extern const ASN_BERdescriptor_t ASN_ROID_ber_; |
| 108 | extern const ASN_BERdescriptor_t SEQUENCE_ber_; |
| 109 | extern const ASN_BERdescriptor_t SET_ber_; |
| 110 | extern const ASN_BERdescriptor_t CHOICE_ber_; |
| 111 | extern const ASN_BERdescriptor_t ASN_ANY_ber_; |
| 112 | extern const ASN_BERdescriptor_t NumericString_ber_; |
| 113 | extern const ASN_BERdescriptor_t PrintableString_ber_; |
| 114 | extern const ASN_BERdescriptor_t TeletexString_ber_; |
| 115 | extern const ASN_BERdescriptor_t VideotexString_ber_; |
| 116 | extern const ASN_BERdescriptor_t IA5String_ber_; |
| 117 | extern const ASN_BERdescriptor_t ASN_UTCTime_ber_; |
| 118 | extern const ASN_BERdescriptor_t ASN_GeneralizedTime_ber_; |
| 119 | extern const ASN_BERdescriptor_t GraphicString_ber_; |
| 120 | extern const ASN_BERdescriptor_t VisibleString_ber_; |
| 121 | extern const ASN_BERdescriptor_t GeneralString_ber_; |
| 122 | extern const ASN_BERdescriptor_t UniversalString_ber_; |
| 123 | extern const ASN_BERdescriptor_t BMPString_ber_; |
| 124 | extern const ASN_BERdescriptor_t EXTERNAL_ber_; |
| 125 | extern const ASN_BERdescriptor_t EMBEDDED_PDV_ber_; |
| 126 | extern const ASN_BERdescriptor_t CHARACTER_STRING_ber_; |
| 127 | |
| 128 | /** An unsigned long long with 7 bits set (0x7F) in the most significant byte. |
| 129 | * Used when decoding objid values. */ |
| 130 | extern const unsigned long long unsigned_llong_7msb; |
| 131 | |
| 132 | /** An unsigned long with 8 bits set (0xFF) in the most significant byte. |
| 133 | * Used when decoding integers. */ |
| 134 | extern const unsigned long unsigned_long_8msb; |
| 135 | |
| 136 | /** How many bits are needed minimally to represent the given |
| 137 | * (nonnegative integral) value. Returned value is greater than or |
| 138 | * equal to 1. */ |
| 139 | template<typename T> |
| 140 | size_t min_needed_bits(T p) |
| 141 | { |
| 142 | if(p==0) return 1; |
| 143 | register size_t n=0; |
| 144 | register T tmp=p; |
| 145 | while(tmp!=0) n++, tmp/=2; |
| 146 | return n; |
| 147 | } |
| 148 | |
| 149 | /** This struct represents a BER TLV. |
| 150 | * |
| 151 | * It represents a "deconstructed" (cooked) representation of |
| 152 | * a BER encoding. */ |
| 153 | struct ASN_BER_TLV_t { |
| 154 | boolean isConstructed; /**< Primitive/Constructed bit. */ |
| 155 | boolean V_tlvs_selected; /**< How the data is stored in \p V. */ |
| 156 | boolean isLenDefinite; /**< \c false for indefinite form */ |
| 157 | boolean isLenShort; /**< \c true for short form (0-127) */ |
| 158 | /** Is \p tagclass and \p tagnumber valid. |
| 159 | * ASN_BER_str2TLV function sets this. */ |
| 160 | boolean isTagComplete; |
| 161 | boolean isComplete; |
| 162 | ASN_Tagclass_t tagclass; /**< UNIV/APP/context/PRIVATE */ |
| 163 | ASN_Tagnumber_t tagnumber; |
| 164 | size_t Tlen; /** Length of T part. May be >1 for tag values >30 */ |
| 165 | size_t Llen; /** Length of L part. */ |
| 166 | unsigned char *Tstr; /** Encoded T part. */ |
| 167 | unsigned char *Lstr; /** Encoded L part. */ |
| 168 | union { /* depends on V_tlvs_selected */ |
| 169 | struct { |
| 170 | size_t Vlen; |
| 171 | unsigned char *Vstr; |
| 172 | } str; /**< V_tlvs_selected==FALSE */ |
| 173 | struct { |
| 174 | size_t n_tlvs; |
| 175 | ASN_BER_TLV_t **tlvs; |
| 176 | } tlvs; /**< V_tlvs_selected==TRUE */ |
| 177 | } V; |
| 178 | |
| 179 | /** Creates a new constructed TLV which contains one TLV (\a |
| 180 | * p_tlv). Or, if the parameter is NULL, then an empty constructed |
| 181 | * TLV is created. */ |
| 182 | static ASN_BER_TLV_t* construct(ASN_BER_TLV_t *p_tlv); |
| 183 | /** Creates a new non-constructed TLV with the given V-part. |
| 184 | * Tagclass and -number are set to UNIV-0. If \a p_Vstr is NULL |
| 185 | * then allocates a \a p_Vlen size buffer for Vstr. |
| 186 | * Takes over ownership of \a p_Vstr */ |
| 187 | static ASN_BER_TLV_t* construct(size_t p_Vlen, unsigned char *p_Vstr); |
| 188 | /** Creates a new non-constructed TLV with empty T, L and V part. */ |
| 189 | static ASN_BER_TLV_t* construct(); |
| 190 | /** Frees the given \a p_tlv recursively. Tstr, Lstr and |
| 191 | * Vstr/tlvs. If \a no_str is TRUE, then only the tlvs are deleted, |
| 192 | * the strings (Tstr, Lstr, Vstr) are not. This is useful during |
| 193 | * decoding, when the Xstr points into a buffer.*/ |
| 194 | static void destruct(ASN_BER_TLV_t *p_tlv, boolean no_str=FALSE); |
| 195 | /** Checks the 'constructed' flag. If fails, raises an EncDec |
| 196 | * error. */ |
| 197 | void chk_constructed_flag(boolean flag_expected) const; |
| 198 | /** Adds \a p_tlv to this (constructed) TLV. |
| 199 | * @pre isConstructed is \c true |
| 200 | * @pre V_tlvs_selected is \c true */ |
| 201 | void add_TLV(ASN_BER_TLV_t *p_tlv); |
| 202 | /** Adds a new UNIVERSAL 0 TLV to this (constructed) TLV. */ |
| 203 | void add_UNIV0_TLV(); |
| 204 | /** Returns the length (in bytes) of the full TLV. */ |
| 205 | size_t get_len() const; |
| 206 | /** Adds T and L part to TLV. It adds trailing UNI-0 TLV (two zero |
| 207 | * octets) if the length form is indefinite. Precondition: |
| 208 | * isConstructed (and V_tlvs_selected) and V-part are valid. */ |
| 209 | void add_TL(ASN_Tagclass_t p_tagclass, |
| 210 | ASN_Tagnumber_t p_tagnumber, |
| 211 | unsigned coding); |
| 212 | /** Puts the TLV in buffer \a p_buf. */ |
| 213 | void put_in_buffer(TTCN_Buffer& p_buf); |
| 214 | /** Gets the octet in position \a pos. Works also for constructed TLVs. */ |
| 215 | unsigned char get_pos(size_t pos) const; |
| 216 | private: |
| 217 | unsigned char _get_pos(size_t& pos, boolean& success) const; |
| 218 | public: |
| 219 | /** Compares the TLVs as described in X.690 11.6. Returns -1 if this |
| 220 | * less than, 0 if equal to, 1 if greater than other. */ |
| 221 | int compare(const ASN_BER_TLV_t *other) const; |
| 222 | /** Sorts its TLVs according to their octetstring representation, as |
| 223 | * described in X.690 11.6. */ |
| 224 | void sort_tlvs(); |
| 225 | /** Compares the TLVs according their tags as described in X.680 |
| 226 | * 8.6. Returns -1 if this less than, 0 if equal to, 1 if greater |
| 227 | * than other. */ |
| 228 | int compare_tags(const ASN_BER_TLV_t *other) const; |
| 229 | /** Sorts its TLVs according to their tags, as described in X.690 |
| 230 | * 10.3. */ |
| 231 | void sort_tlvs_tag(); |
| 232 | }; |
| 233 | |
| 234 | /** |
| 235 | * Searches the T, L and V parts of the TLV represented in \a s, and |
| 236 | * stores it in \a tlv. Returns FALSE if there isn't a complete |
| 237 | * TLV-structure in \a s, TRUE otherwise. |
| 238 | */ |
| 239 | boolean ASN_BER_str2TLV(size_t p_len_s, |
| 240 | const unsigned char* p_str, |
| 241 | ASN_BER_TLV_t& tlv, |
| 242 | unsigned L_form); |
| 243 | |
| 244 | /** |
| 245 | * Adds the T and L part of the TLV. If there are multiple tags, then |
| 246 | * adds them all. Precondition: the following fields are ready of \a |
| 247 | * p_tlv: isConstructed, V_tlvs_selected, isLenDefinite, isLenShort |
| 248 | * and V. If tagclass and tagnumber are UNIVERSAL 0, then replaces |
| 249 | * them, otherwise 'wraps' p_tlv in a new TLV. |
| 250 | */ |
| 251 | ASN_BER_TLV_t* ASN_BER_V2TLV(ASN_BER_TLV_t* p_tlv, |
| 252 | const TTCN_Typedescriptor_t& p_td, |
| 253 | unsigned coding); |
| 254 | |
| 255 | /** @} end of BER group */ |
| 256 | |
| 257 | #endif // _BER_HH |