1 /* 2 * libpri: An implementation of Primary Rate ISDN 3 * 4 * Copyright (C) 2009 Digium, Inc. 5 * 6 * Richard Mudgett <rmudgett@digium.com> 7 * 8 * See http://www.asterisk.org for more information about 9 * the Asterisk project. Please do not directly contact 10 * any of the maintainers of this project for assistance; 11 * the project provides a web site, mailing lists and IRC 12 * channels for your use. 13 * 14 * This program is free software, distributed under the terms of 15 * the GNU General Public License Version 2 as published by the 16 * Free Software Foundation. See the LICENSE file included with 17 * this program for more details. 18 * 19 * In addition, when this program is distributed with Asterisk in 20 * any form that would qualify as a 'combined work' or as a 21 * 'derivative work' (but not mere aggregation), you can redistribute 22 * and/or modify the combination under the terms of the license 23 * provided with that copy of Asterisk, instead of the license 24 * terms granted here. 25 */ 26 27 /*! 28 * \file 29 * \brief ASN.1 definitions and prototypes 30 * 31 * \details 32 * This file contains all ASN.1 primitive data structures and 33 * definitions needed for ROSE component encoding and decoding. 34 * 35 * ROSE - Remote Operations Service Element 36 * ASN.1 - Abstract Syntax Notation 1 37 * APDU - Application Protocol Data Unit 38 * 39 * \author Richard Mudgett <rmudgett@digium.com> 40 */ 41 42 #ifndef _LIBPRI_ASN1_H 43 #define _LIBPRI_ASN1_H 44 45 #include <string.h> 46 #include <sys/types.h> 47 48 #ifdef __cplusplus 49 extern "C" { 50 #endif 51 52 /* ------------------------------------------------------------------- */ 53 54 /*! ASN.1 Identifier Octet - Tag class bits */ 55 #define ASN1_CLASS_MASK 0xc0 56 #define ASN1_CLASS_UNIVERSAL 0x00 /*!< Universal primitive data types */ 57 #define ASN1_CLASS_APPLICATION 0x40 /*!< Application wide data tag */ 58 #define ASN1_CLASS_CONTEXT_SPECIFIC 0x80 /*!< Context specifc data tag */ 59 #define ASN1_CLASS_PRIVATE 0xc0 /*!< Private organization data tag */ 60 61 /*! ASN.1 Identifier Octet - Primitive/Constructor bit */ 62 #define ASN1_PC_MASK 0x20 63 #define ASN1_PC_PRIMITIVE 0x00 64 #define ASN1_PC_CONSTRUCTED 0x20 65 66 /*! ASN.1 Identifier Octet - Universal data types */ 67 #define ASN1_TYPE_MASK 0x1f 68 #define ASN1_TYPE_INDEF_TERM 0x00 /* 0 */ 69 #define ASN1_TYPE_BOOLEAN 0x01 /* 1 */ 70 #define ASN1_TYPE_INTEGER 0x02 /* 2 */ 71 #define ASN1_TYPE_BIT_STRING 0x03 /* 3 */ 72 #define ASN1_TYPE_OCTET_STRING 0x04 /* 4 */ 73 #define ASN1_TYPE_NULL 0x05 /* 5 */ 74 #define ASN1_TYPE_OBJECT_IDENTIFIER 0x06 /* 6 */ 75 #define ASN1_TYPE_OBJECT_DESCRIPTOR 0x07 /* 7 */ 76 #define ASN1_TYPE_EXTERN 0x08 /* 8 */ 77 #define ASN1_TYPE_REAL 0x09 /* 9 */ 78 #define ASN1_TYPE_ENUMERATED 0x0a /* 10 */ 79 #define ASN1_TYPE_EMBEDDED_PDV 0x0b /* 11 */ 80 #define ASN1_TYPE_UTF8_STRING 0x0c /* 12 */ 81 #define ASN1_TYPE_RELATIVE_OID 0x0d /* 13 */ 82 /* 0x0e & 0x0f are reserved for future ASN.1 editions */ 83 #define ASN1_TYPE_SEQUENCE 0x10 /* 16 */ 84 #define ASN1_TYPE_SET 0x11 /* 17 */ 85 #define ASN1_TYPE_NUMERIC_STRING 0x12 /* 18 */ 86 #define ASN1_TYPE_PRINTABLE_STRING 0x13 /* 19 */ 87 #define ASN1_TYPE_TELETEX_STRING 0x14 /* 20 */ 88 #define ASN1_TYPE_VIDEOTEX_STRING 0x15 /* 21 */ 89 #define ASN1_TYPE_IA5_STRING 0x16 /* 22 */ 90 #define ASN1_TYPE_UTC_TIME 0x17 /* 23 */ 91 #define ASN1_TYPE_GENERALIZED_TIME 0x18 /* 24 */ 92 #define ASN1_TYPE_GRAPHIC_STRING 0x19 /* 25 */ 93 #define ASN1_TYPE_VISIBLE_STRING 0x1a /* 26 */ 94 #define ASN1_TYPE_ISO646_STRING 0x1a /* 26 */ 95 #define ASN1_TYPE_GENERAL_STRING 0x1b /* 27 */ 96 #define ASN1_TYPE_UNIVERSAL_STRING 0x1c /* 28 */ 97 #define ASN1_TYPE_CHAR_STRING 0x1d /* 29 */ 98 #define ASN1_TYPE_BMP_STRING 0x1e /* 30 */ 99 #define ASN1_TYPE_EXTENSION 0x1f /* 31 */ 100 101 #define ASN1_TAG_SEQUENCE (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_SEQUENCE) 102 #define ASN1_TAG_SET (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_SET) 103 104 #define ASN1_INDEF_TERM (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_INDEF_TERM) 105 #define ASN1_INDEF_TERM_LEN 2 106 107 struct asn1_oid { 108 /*! \brief Number of subidentifier values in OID list */ 109 u_int16_t num_values; 110 111 /*! 112 * \brief OID subidentifier value list 113 * \note The first value is really the first two OID subidentifiers. 114 * They are compressed using this formula: 115 * First_Value = (First_Subidentifier * 40) + Second_Subidentifier 116 */ 117 u_int16_t value[10]; 118 }; 119 120 #define ASN1_CALL(new_pos, do_it) \ 121 do \ 122 { \ 123 (new_pos) = (do_it); \ 124 if (!(new_pos)) { \ 125 return NULL; \ 126 } \ 127 } while (0) 128 129 /*! \brief Determine the ending position of the set or sequence to verify the length. */ 130 #define ASN1_END_SETUP(component_end, offset, length, pos, end) \ 131 do { \ 132 if ((length) < 0) { \ 133 (offset) = ASN1_INDEF_TERM_LEN; \ 134 (component_end) = (end); \ 135 } else { \ 136 (offset) = 0; \ 137 (component_end) = (pos) + (length); \ 138 } \ 139 } while (0) 140 141 /*! \brief Account for the indefinite length terminator of the set or sequence. */ 142 #define ASN1_END_FIXUP(ctrl, pos, offset, component_end, end) \ 143 do { \ 144 if (offset) { \ 145 ASN1_CALL((pos), asn1_dec_indef_end_fixup((ctrl), (pos), (end))); \ 146 } else if ((pos) != (component_end)) { \ 147 if ((ctrl)->debug & PRI_DEBUG_APDU) { \ 148 pri_message((ctrl), \ 149 " Skipping unused constructed component octets!\n"); \ 150 } \ 151 (pos) = (component_end); \ 152 } \ 153 } while (0) 154 155 #define ASN1_DID_NOT_EXPECT_TAG(ctrl, tag) \ 156 do { \ 157 if ((ctrl)->debug & PRI_DEBUG_APDU) { \ 158 pri_message((ctrl), " Did not expect: %s\n", asn1_tag2str(tag)); \ 159 } \ 160 } while (0) 161 162 #define ASN1_CHECK_TAG(ctrl, actual_tag, match_tag, expected_tag) \ 163 do { \ 164 if ((match_tag) != (expected_tag)) { \ 165 ASN1_DID_NOT_EXPECT_TAG((ctrl), (actual_tag)); \ 166 return NULL; \ 167 } \ 168 } while (0) 169 170 171 const unsigned char *asn1_dec_tag(const unsigned char *tag_pos, const unsigned char *end, 172 unsigned *tag); 173 const unsigned char *asn1_dec_length(const unsigned char *len_pos, 174 const unsigned char *end, int *length); 175 const unsigned char *asn1_dec_indef_end_fixup(struct pri *ctrl, const unsigned char *pos, 176 const unsigned char *end); 177 178 const unsigned char *asn1_dec_boolean(struct pri *ctrl, const char *name, unsigned tag, 179 const unsigned char *pos, const unsigned char *end, int32_t *value); 180 const unsigned char *asn1_dec_int(struct pri *ctrl, const char *name, unsigned tag, 181 const unsigned char *pos, const unsigned char *end, int32_t *value); 182 const unsigned char *asn1_dec_null(struct pri *ctrl, const char *name, unsigned tag, 183 const unsigned char *pos, const unsigned char *end); 184 const unsigned char *asn1_dec_oid(struct pri *ctrl, const char *name, unsigned tag, 185 const unsigned char *pos, const unsigned char *end, struct asn1_oid *oid); 186 const unsigned char *asn1_dec_string_bin(struct pri *ctrl, const char *name, 187 unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size, 188 unsigned char *str, size_t *str_len); 189 const unsigned char *asn1_dec_string_max(struct pri *ctrl, const char *name, 190 unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size, 191 unsigned char *str, size_t *str_len); 192 193 const char *asn1_tag2str(unsigned tag); 194 void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1, 195 const unsigned char *end); 196 197 198 #define ASN1_LEN_FORM_SHORT 1 /*!< Hint that the final length will be less than 128 octets */ 199 #define ASN1_LEN_FORM_LONG_U8 2 /*!< Hint that the final length will be less than 256 octets */ 200 #define ASN1_LEN_FORM_LONG_U16 3 /*!< Hint that the final length will be less than 65536 octets */ 201 #define ASN1_LEN_INIT(len_pos, end, form_hint) \ 202 do { \ 203 if ((end) < (len_pos) + (form_hint)) { \ 204 return NULL; \ 205 } \ 206 *(len_pos) = (form_hint); \ 207 (len_pos) += (form_hint); \ 208 } while (0) 209 210 #define ASN1_LEN_FIXUP(len_pos, component_end, end) \ 211 ASN1_CALL((component_end), asn1_enc_length_fixup((len_pos), (component_end), (end))) 212 213 /*! \brief Use to begin encoding explicit tags, SET, and SEQUENCE constructed groupings. */ 214 #define ASN1_CONSTRUCTED_BEGIN(len_pos_save, pos, end, tag) \ 215 do { \ 216 if ((end) < (pos) + (1 + ASN1_LEN_FORM_SHORT)) { \ 217 return NULL; \ 218 } \ 219 *(pos)++ = (tag) | ASN1_PC_CONSTRUCTED; \ 220 (len_pos_save) = (pos); \ 221 *(pos) = ASN1_LEN_FORM_SHORT; \ 222 (pos) += ASN1_LEN_FORM_SHORT; \ 223 } while (0) 224 225 /*! \brief Use to end encoding explicit tags, SET, and SEQUENCE constructed groupings. */ 226 #define ASN1_CONSTRUCTED_END(len_pos, component_end, end) \ 227 ASN1_CALL((component_end), asn1_enc_length_fixup((len_pos), (component_end), (end))) 228 229 #define ASN1_ENC_ERROR(ctrl, msg) \ 230 pri_error((ctrl), "%s error: %s\n", __FUNCTION__, (msg)) 231 232 unsigned char *asn1_enc_length(unsigned char *len_pos, unsigned char *end, 233 size_t str_len); 234 unsigned char *asn1_enc_length_fixup(unsigned char *len_pos, 235 unsigned char *component_end, unsigned char *end); 236 237 unsigned char *asn1_enc_boolean(unsigned char *pos, unsigned char *end, unsigned tag, 238 int32_t value); 239 unsigned char *asn1_enc_int(unsigned char *pos, unsigned char *end, unsigned tag, 240 int32_t value); 241 unsigned char *asn1_enc_null(unsigned char *pos, unsigned char *end, unsigned tag); 242 unsigned char *asn1_enc_oid(unsigned char *pos, unsigned char *end, unsigned tag, 243 const struct asn1_oid *oid); 244 unsigned char *asn1_enc_string_bin(unsigned char *pos, unsigned char *end, unsigned tag, 245 const unsigned char *str, size_t str_len); 246 unsigned char *asn1_enc_string_max(unsigned char *pos, unsigned char *end, unsigned tag, 247 const unsigned char *str, size_t max_len); 248 249 /* ------------------------------------------------------------------- */ 250 251 #ifdef __cplusplus 252 } 253 #endif 254 255 #endif /* _LIBPRI_ASN1_H */ 256 /* ------------------------------------------------------------------- */ 257 /* end asn1.h */ 258