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 | |