1 /* Copyright (c) (2012-2019,2021,2022) Apple Inc. All rights reserved. 2 * 3 * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which 4 * is contained in the License.txt file distributed with corecrypto) and only to 5 * people who accept that license. IMPORTANT: Any license rights granted to you by 6 * Apple Inc. (if any) are limited to internal use within your organization only on 7 * devices and computers you own or control, for the sole purpose of verifying the 8 * security characteristics and correct functioning of the Apple Software. You may 9 * not, directly or indirectly, redistribute the Apple Software or any portions thereof. 10 */ 11 12 #ifndef _CORECRYPTO_CCDER_H_ 13 #define _CORECRYPTO_CCDER_H_ 14 15 #include <corecrypto/cc.h> 16 #include <corecrypto/ccasn1.h> 17 #include <corecrypto/ccn.h> 18 #include <corecrypto/ccder_blob.h> 19 20 /* DER types to be used with ccder_decode and ccder_encode functions. */ 21 #define CCDER_EOL CCASN1_EOL 22 #define CCDER_BOOLEAN CCASN1_BOOLEAN 23 #define CCDER_INTEGER CCASN1_INTEGER 24 #define CCDER_BIT_STRING CCASN1_BIT_STRING 25 #define CCDER_OCTET_STRING CCASN1_OCTET_STRING 26 #define CCDER_NULL CCASN1_NULL 27 #define CCDER_OBJECT_IDENTIFIER CCASN1_OBJECT_IDENTIFIER 28 #define CCDER_OBJECT_DESCRIPTOR CCASN1_OBJECT_DESCRIPTOR 29 /* External or instance-of 0x08 */ 30 #define CCDER_REAL CCASN1_REAL 31 #define CCDER_ENUMERATED CCASN1_ENUMERATED 32 #define CCDER_EMBEDDED_PDV CCASN1_EMBEDDED_PDV 33 #define CCDER_UTF8_STRING CCASN1_UTF8_STRING 34 /* 0x0d */ 35 /* 0x0e */ 36 /* 0x0f */ 37 #define CCDER_SEQUENCE CCASN1_SEQUENCE 38 #define CCDER_SET CCASN1_SET 39 #define CCDER_NUMERIC_STRING CCASN1_NUMERIC_STRING 40 #define CCDER_PRINTABLE_STRING CCASN1_PRINTABLE_STRING 41 #define CCDER_T61_STRING CCASN1_T61_STRING 42 #define CCDER_VIDEOTEX_STRING CCASN1_VIDEOTEX_STRING 43 #define CCDER_IA5_STRING CCASN1_IA5_STRING 44 #define CCDER_UTC_TIME CCASN1_UTC_TIME 45 #define CCDER_GENERALIZED_TIME CCASN1_GENERALIZED_TIME 46 #define CCDER_GRAPHIC_STRING CCASN1_GRAPHIC_STRING 47 #define CCDER_VISIBLE_STRING CCASN1_VISIBLE_STRING 48 #define CCDER_GENERAL_STRING CCASN1_GENERAL_STRING 49 #define CCDER_UNIVERSAL_STRING CCASN1_UNIVERSAL_STRING 50 /* 0x1d */ 51 #define CCDER_BMP_STRING CCASN1_BMP_STRING 52 #define CCDER_HIGH_TAG_NUMBER CCASN1_HIGH_TAG_NUMBER 53 #define CCDER_TELETEX_STRING CCDER_T61_STRING 54 55 #ifdef CCDER_MULTIBYTE_TAGS 56 #define CCDER_TAG_MASK ((ccder_tag)~0) 57 #define CCDER_TAGNUM_MASK ((ccder_tag) ~((ccder_tag)7 << (sizeof(ccder_tag) * 8 - 3))) 58 59 #define CCDER_METHOD_MASK ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 3)) 60 #define CCDER_PRIMITIVE ((ccder_tag)0 << (sizeof(ccder_tag) * 8 - 3)) 61 #define CCDER_CONSTRUCTED ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 3)) 62 63 #define CCDER_CLASS_MASK ((ccder_tag)3 << (sizeof(ccder_tag) * 8 - 2)) 64 #define CCDER_UNIVERSAL ((ccder_tag)0 << (sizeof(ccder_tag) * 8 - 2)) 65 #define CCDER_APPLICATION ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 2)) 66 #define CCDER_CONTEXT_SPECIFIC ((ccder_tag)2 << (sizeof(ccder_tag) * 8 - 2)) 67 #define CCDER_PRIVATE ((ccder_tag)3 << (sizeof(ccder_tag) * 8 - 2)) 68 #else /* !CCDER_MULTIBYTE_TAGS */ 69 #define CCDER_TAG_MASK CCASN1_TAG_MASK 70 #define CCDER_TAGNUM_MASK CCASN1_TAGNUM_MASK 71 72 #define CCDER_METHOD_MASK CCASN1_METHOD_MASK 73 #define CCDER_PRIMITIVE CCASN1_PRIMITIVE 74 #define CCDER_CONSTRUCTED CCASN1_CONSTRUCTED 75 76 #define CCDER_CLASS_MASK CCASN1_CLASS_MASK 77 #define CCDER_UNIVERSAL CCASN1_UNIVERSAL 78 #define CCDER_APPLICATION CCASN1_APPLICATION 79 #define CCDER_CONTEXT_SPECIFIC CCASN1_CONTEXT_SPECIFIC 80 #define CCDER_PRIVATE CCASN1_PRIVATE 81 #endif /* !CCDER_MULTIBYTE_TAGS */ 82 #define CCDER_CONSTRUCTED_SET (CCDER_SET | CCDER_CONSTRUCTED) 83 #define CCDER_CONSTRUCTED_SEQUENCE (CCDER_SEQUENCE | CCDER_CONSTRUCTED) 84 85 // MARK: - ccder_sizeof_ functions 86 87 /* Returns the size of an asn1 encoded item of length l in bytes. */ 88 CC_CONST 89 size_t ccder_sizeof(ccder_tag tag, size_t len); 90 91 CC_NONNULL_ALL 92 size_t ccder_sizeof_overflow(ccder_tag tag, size_t nbytes, bool *overflowed); 93 94 CC_PURE 95 size_t ccder_sizeof_implicit_integer(ccder_tag implicit_tag, cc_size n, const cc_unit *s); 96 97 CC_PURE 98 size_t ccder_sizeof_implicit_octet_string(ccder_tag implicit_tag, cc_size n, const cc_unit *s); 99 100 CC_CONST 101 size_t ccder_sizeof_implicit_raw_octet_string(ccder_tag implicit_tag, size_t s_size); 102 103 CC_NONNULL_ALL 104 size_t ccder_sizeof_implicit_raw_octet_string_overflow(ccder_tag implicit_tag, size_t s_size, bool *overflowed); 105 106 CC_CONST 107 size_t ccder_sizeof_implicit_uint64(ccder_tag implicit_tag, uint64_t value); 108 109 CC_PURE 110 size_t ccder_sizeof_integer(cc_size n, const cc_unit *s); 111 112 CC_CONST 113 size_t ccder_sizeof_len(size_t len); 114 115 CC_PURE 116 size_t ccder_sizeof_octet_string(cc_size n, const cc_unit *s); 117 118 CC_PURE 119 size_t ccder_sizeof_oid(ccoid_t oid); 120 121 CC_CONST 122 size_t ccder_sizeof_raw_octet_string(size_t s_size); 123 124 CC_CONST 125 size_t ccder_sizeof_tag(ccder_tag tag); 126 127 CC_CONST 128 size_t ccder_sizeof_uint64(uint64_t value); 129 130 CC_PURE 131 size_t ccder_sizeof_eckey(size_t priv_size, ccoid_t oid, size_t pub_size); 132 133 /* alias of ccder_sizeof_eckey */ 134 CC_PURE 135 size_t ccder_encode_eckey_size(size_t priv_size, ccoid_t oid, size_t pub_size); 136 137 /* All of the original functions are unavailable in a ptrcheck build. */ 138 // MARK: - Encode/decode functions, unavailable in ptrcheck 139 140 /* Encode a tag backwards, der_end should point to one byte past the end of 141 destination for the tag, returns a pointer to the first byte of the tag. 142 Returns NULL if there is an encoding error. */ 143 CC_NONNULL((2)) cc_ptrcheck_unavailable() 144 uint8_t *ccder_encode_tag(ccder_tag tag, const uint8_t *der, uint8_t *der_end); 145 146 /* Returns a pointer to the start of the len field. returns NULL if there 147 is an encoding error. */ 148 CC_NONNULL((2)) cc_ptrcheck_unavailable() 149 uint8_t *ccder_encode_len(size_t len, const uint8_t *der, uint8_t *der_end); 150 151 /* der_end should point to the first byte of the content of this der item. */ 152 CC_NONNULL((3)) cc_ptrcheck_unavailable() 153 uint8_t *ccder_encode_tl(ccder_tag tag, size_t len, const uint8_t *der, uint8_t *der_end); 154 155 CC_PURE CC_NONNULL((2)) cc_ptrcheck_unavailable() 156 uint8_t *ccder_encode_body_nocopy(size_t size, const uint8_t *der, uint8_t *der_end); 157 158 /* Encode the tag and length of a constructed object. der is the lower 159 bound, der_end is one byte paste where we want to write the length and 160 body_end is one byte past the end of the body of the der object we are 161 encoding the tag and length of. */ 162 CC_NONNULL((2, 3)) cc_ptrcheck_unavailable() 163 uint8_t *ccder_encode_constructed_tl(ccder_tag tag, const uint8_t *body_end, const uint8_t *der, uint8_t *der_end); 164 165 /* Encodes oid into der and returns der + ccder_sizeof_oid(oid). */ 166 CC_NONNULL((1, 2)) cc_ptrcheck_unavailable() 167 uint8_t *ccder_encode_oid(ccoid_t oid, const uint8_t *der, uint8_t *der_end); 168 169 CC_NONNULL((3, 4)) cc_ptrcheck_unavailable() 170 uint8_t *ccder_encode_implicit_integer(ccder_tag implicit_tag, cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end); 171 172 CC_NONNULL((2, 3)) cc_ptrcheck_unavailable() 173 uint8_t *ccder_encode_integer(cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end); 174 175 CC_NONNULL((3)) cc_ptrcheck_unavailable() 176 uint8_t *ccder_encode_implicit_uint64(ccder_tag implicit_tag, uint64_t value, const uint8_t *der, uint8_t *der_end); 177 178 CC_NONNULL((2)) cc_ptrcheck_unavailable() 179 uint8_t *ccder_encode_uint64(uint64_t value, const uint8_t *der, uint8_t *der_end); 180 181 CC_NONNULL((3, 4)) cc_ptrcheck_unavailable() 182 uint8_t *ccder_encode_implicit_octet_string(ccder_tag implicit_tag, cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end); 183 184 CC_NONNULL((2, 3)) cc_ptrcheck_unavailable() 185 uint8_t *ccder_encode_octet_string(cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end); 186 187 CC_NONNULL((3, 4)) cc_ptrcheck_unavailable() 188 uint8_t *ccder_encode_implicit_raw_octet_string(ccder_tag implicit_tag, 189 size_t s_size, 190 const uint8_t *s, 191 const uint8_t *der, 192 uint8_t *der_end); 193 194 CC_NONNULL((2, 3)) cc_ptrcheck_unavailable() 195 uint8_t *ccder_encode_raw_octet_string(size_t s_size, const uint8_t *s, const uint8_t *der, uint8_t *der_end); 196 197 CC_NONNULL((2, 5, 6)) cc_ptrcheck_unavailable() 198 uint8_t *ccder_encode_eckey(size_t priv_size, 199 const uint8_t *priv_key, 200 ccoid_t oid, 201 size_t pub_size, 202 const uint8_t *pub_key, 203 uint8_t *der, 204 uint8_t *der_end); 205 206 /* ccder_encode_body COPIES the body into the der. 207 It's inefficient – especially when you already have to convert to get to 208 the form for the body. 209 see encode integer for the right way to unify conversion and insertion */ 210 CC_NONNULL((3)) cc_ptrcheck_unavailable() 211 uint8_t *ccder_encode_body(size_t size, const uint8_t *body, const uint8_t *der, uint8_t *der_end); 212 213 /* Returns a pointer to the start of the length field, and returns the decoded tag in tag. 214 returns NULL if there is a decoding error. */ 215 CC_NONNULL((1, 3)) cc_ptrcheck_unavailable() 216 const uint8_t *ccder_decode_tag(ccder_tag *tagp, const uint8_t *der, const uint8_t *der_end); 217 218 CC_NONNULL((1, 3)) cc_ptrcheck_unavailable() 219 const uint8_t *ccder_decode_len(size_t *lenp, const uint8_t *der, const uint8_t *der_end); 220 221 /*! 222 @function ccder_decode_len_strict 223 @abstract Decode the length of a DER encoded item 224 225 @param lenp Pointer to the length of the DER item 226 @param der Beginning of input DER buffer 227 @param der_end End of input DER buffer 228 229 @result First byte after the parsed length or NULL if the length is not valid (i.e. when the length isn't DER encoded) 230 */ 231 CC_NONNULL((1, 3)) cc_ptrcheck_unavailable() 232 const uint8_t *ccder_decode_len_strict(size_t *lenp, const uint8_t *der, const uint8_t *der_end); 233 234 /* Returns a pointer to the start of the der object, and returns the length in len. 235 returns NULL if there is a decoding error. */ 236 CC_NONNULL((2, 4)) cc_ptrcheck_unavailable() 237 const uint8_t *ccder_decode_tl(ccder_tag expected_tag, size_t *lenp, const uint8_t *der, const uint8_t *der_end); 238 239 /*! 240 @function ccder_decode_tl_strict 241 @abstract Decode a tag and length from a DER object given an expected tag. 242 243 @param expected_tag Tag of expected DER object pointed to by `der` 244 @param lenp Output length of DER object 245 @param der Beginning of input DER buffer 246 @param der_end End of input DER buffer 247 248 @result Pointer to the DER object with the length contained in `lenp` otherwise NULL. 249 */ 250 CC_NONNULL((2, 4)) cc_ptrcheck_unavailable() 251 const uint8_t *ccder_decode_tl_strict(ccder_tag expected_tag, size_t *lenp, const uint8_t *der, const uint8_t *der_end); 252 253 CC_NONNULL((2, 4)) cc_ptrcheck_unavailable() 254 const uint8_t *ccder_decode_constructed_tl(ccder_tag expected_tag, 255 const uint8_t **body_end, 256 const uint8_t *der, 257 const uint8_t *der_end); 258 259 /*! 260 @function ccder_decode_constructed_tl_strict 261 @abstract Decode a tag and length from a contstructed DER object given an expected tag. 262 263 @param expected_tag Tag of expected DER object pointed to by `der` 264 @param body_end Pointer to hold the end of the sequence 265 @param der Beginning of input DER buffer 266 @param der_end End of input DER buffer 267 268 @result Pointer to the first DER object within the constructed object and the length of the total constructed object 269 contained in `lenp`; NULL otherwise. 270 */ 271 CC_NONNULL((2, 4)) cc_ptrcheck_unavailable() 272 const uint8_t *ccder_decode_constructed_tl_strict(ccder_tag expected_tag, const uint8_t **body_end, const uint8_t *der, const uint8_t *der_end); 273 274 CC_NONNULL((1, 3)) cc_ptrcheck_unavailable() 275 const uint8_t *ccder_decode_sequence_tl(const uint8_t **body_end, const uint8_t *der, const uint8_t *der_end); 276 277 /*! 278 @function ccder_decode_sequence_tl_strict 279 @abstract Decode a DER sequence. 280 281 @param body_end Pointer to hold the end of the sequence 282 @param der Beginning of input DER buffer 283 @param der_end End of input DER buffer 284 285 @result Pointer to the first DER object within the sequence otherwise NULL. 286 */ 287 CC_NONNULL((1, 3)) cc_ptrcheck_unavailable() 288 const uint8_t *ccder_decode_sequence_tl_strict(const uint8_t **body_end, const uint8_t *der, const uint8_t *der_end); 289 290 /*! 291 @function ccder_decode_uint_n 292 @abstract length in cc_unit of a der unsigned integer after skipping the leading zeroes 293 294 @param der Beginning of input DER buffer 295 @param der_end End of input DER buffer 296 @param n Output the number of cc_unit required to represent the number 297 298 @result First byte after the parsed integer or 299 NULL if the integer is not valid (negative) or reach der_end when reading the integer 300 */ 301 CC_NONNULL((3)) cc_ptrcheck_unavailable() 302 const uint8_t *ccder_decode_uint_n(cc_size *n, const uint8_t *der, const uint8_t *der_end); 303 304 /*! 305 @function ccder_decode_uint 306 @abstract Represent in cc_unit a ber unsigned integer after skipping the leading zeroes 307 308 @param der Beginning of input BER buffer 309 @param der_end End of input BER buffer 310 @param n Number of cc_unit allocated for r 311 @param r Allocated array of cc_unit to copy the integer into. 312 313 @result First byte after the parsed integer or 314 NULL if the integer is not valid (negative) 315 reach der_end when reading the integer 316 n cc_unit is not enough to represent the integer 317 */ 318 CC_NONNULL((4)) cc_ptrcheck_unavailable() 319 const uint8_t *ccder_decode_uint(cc_size n, cc_unit *r, const uint8_t *der, const uint8_t *der_end); 320 321 /*! 322 @function ccder_decode_uint_strict 323 @abstract Represent in cc_unit a der unsigned integer after skipping the leading zeroes 324 325 @param n Number of cc_unit allocated for r 326 @param r Allocated array of cc_unit to copy the integer into. 327 @param der Beginning of input DER buffer 328 @param der_end End of input DER buffer 329 330 @result First byte after the parsed integer or NULL if the integer is not valid. 331 */ 332 CC_NONNULL((4)) cc_ptrcheck_unavailable() 333 const uint8_t *ccder_decode_uint_strict(cc_size n, cc_unit *r, const uint8_t *der, const uint8_t *der_end); 334 335 CC_NONNULL((3)) cc_ptrcheck_unavailable() 336 const uint8_t *ccder_decode_uint64(uint64_t *r, const uint8_t *der, const uint8_t *der_end); 337 338 /* Decode SEQUENCE { r, s -- (unsigned)integer } in ber into r and s. 339 Returns NULL on decode errors, returns pointer just past the end of the 340 sequence of integers otherwise. */ 341 CC_NONNULL((2, 3, 5)) cc_ptrcheck_unavailable() 342 const uint8_t *ccder_decode_seqii(cc_size n, cc_unit *r, cc_unit *s, const uint8_t *der, const uint8_t *der_end); 343 344 /*! 345 @function ccder_decode_seqii_strict 346 @abstract Parse a DER sequence of two integers. 347 348 @param n The maximum unit size of the integers. 349 @param r First integer output 350 @param s Second integer output 351 @param der Beginning of input DER buffer 352 @param der_end End of input DER buffer 353 354 @result Null on error, otherwise a pointer just past the end of the sequence buffer 355 */ 356 CC_NONNULL((2, 3, 5)) cc_ptrcheck_unavailable() 357 const uint8_t *ccder_decode_seqii_strict(cc_size n, cc_unit *r, cc_unit *s, const uint8_t *der, const uint8_t *der_end); 358 359 /*! 360 @function ccder_decode_oid 361 @abstract Parse a DER sequence representing an oid. 362 363 @param oidp Pointer to OID 364 @param der Beginning of input DER buffer 365 @param der_end End of input DER buffer 366 367 @result Null on error, otherwise a pointer just past the end of the sequence buffer. 368 369 @warning In case of error, *oidp is set to NULL. 370 Otherwise, *oidp is a pointer to a buffer of "unsigned char" of size >= 2. 371 */ 372 CC_NONNULL((1, 3)) cc_ptrcheck_unavailable() 373 const uint8_t *ccder_decode_oid(ccoid_t *oidp, const uint8_t *der, const uint8_t *der_end); 374 375 CC_NONNULL((1, 2, 4)) cc_ptrcheck_unavailable() 376 const uint8_t *ccder_decode_bitstring(const uint8_t **bit_string, size_t *bit_length, const uint8_t *der, const uint8_t *der_end); 377 378 CC_NONNULL((1, 2, 3, 4, 5, 6, 7)) cc_ptrcheck_unavailable() 379 const uint8_t *ccder_decode_eckey(uint64_t *version, 380 size_t *priv_size, 381 const uint8_t **priv_key, 382 ccoid_t *oid, 383 size_t *pub_size, 384 const uint8_t **pub_key, 385 const uint8_t *der, 386 const uint8_t *der_end); 387 388 // MARK: - 389 390 #define CC_EC_OID_SECP192R1 \ 391 { \ 392 ((unsigned char *)"\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x01") \ 393 } 394 #define CC_EC_OID_SECP256R1 \ 395 { \ 396 ((unsigned char *)"\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07") \ 397 } 398 #define CC_EC_OID_SECP224R1 \ 399 { \ 400 ((unsigned char *)"\x06\x05\x2B\x81\x04\x00\x21") \ 401 } 402 #define CC_EC_OID_SECP384R1 \ 403 { \ 404 ((unsigned char *)"\x06\x05\x2B\x81\x04\x00\x22") \ 405 } 406 #define CC_EC_OID_SECP521R1 \ 407 { \ 408 ((unsigned char *)"\x06\x05\x2B\x81\x04\x00\x23") \ 409 } 410 411 #endif /* _CORECRYPTO_CCDER_H_ */ 412