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. */
88CC_CONST
89size_t ccder_sizeof(ccder_tag tag, size_t len);
90
91CC_NONNULL_ALL
92size_t ccder_sizeof_overflow(ccder_tag tag, size_t nbytes, bool *overflowed);
93
94CC_PURE
95size_t ccder_sizeof_implicit_integer(ccder_tag implicit_tag, cc_size n, const cc_unit *s);
96
97CC_PURE
98size_t ccder_sizeof_implicit_octet_string(ccder_tag implicit_tag, cc_size n, const cc_unit *s);
99
100CC_CONST
101size_t ccder_sizeof_implicit_raw_octet_string(ccder_tag implicit_tag, size_t s_size);
102
103CC_NONNULL_ALL
104size_t ccder_sizeof_implicit_raw_octet_string_overflow(ccder_tag implicit_tag, size_t s_size, bool *overflowed);
105
106CC_CONST
107size_t ccder_sizeof_implicit_uint64(ccder_tag implicit_tag, uint64_t value);
108
109CC_PURE
110size_t ccder_sizeof_integer(cc_size n, const cc_unit *s);
111
112CC_CONST
113size_t ccder_sizeof_len(size_t len);
114
115CC_PURE
116size_t ccder_sizeof_octet_string(cc_size n, const cc_unit *s);
117
118CC_PURE
119size_t ccder_sizeof_oid(ccoid_t oid);
120
121CC_CONST
122size_t ccder_sizeof_raw_octet_string(size_t s_size);
123
124CC_CONST
125size_t ccder_sizeof_tag(ccder_tag tag);
126
127CC_CONST
128size_t ccder_sizeof_uint64(uint64_t value);
129
130CC_PURE
131size_t ccder_sizeof_eckey(size_t priv_size, ccoid_t oid, size_t pub_size);
132
133/* alias of ccder_sizeof_eckey */
134CC_PURE
135size_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. */
143CC_NONNULL((2)) cc_ptrcheck_unavailable()
144uint8_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. */
148CC_NONNULL((2)) cc_ptrcheck_unavailable()
149uint8_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. */
152CC_NONNULL((3)) cc_ptrcheck_unavailable()
153uint8_t *ccder_encode_tl(ccder_tag tag, size_t len, const uint8_t *der, uint8_t *der_end);
154
155CC_PURE CC_NONNULL((2)) cc_ptrcheck_unavailable()
156uint8_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. */
162CC_NONNULL((2, 3)) cc_ptrcheck_unavailable()
163uint8_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). */
166CC_NONNULL((1, 2)) cc_ptrcheck_unavailable()
167uint8_t *ccder_encode_oid(ccoid_t oid, const uint8_t *der, uint8_t *der_end);
168
169CC_NONNULL((3, 4)) cc_ptrcheck_unavailable()
170uint8_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
172CC_NONNULL((2, 3)) cc_ptrcheck_unavailable()
173uint8_t *ccder_encode_integer(cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end);
174
175CC_NONNULL((3)) cc_ptrcheck_unavailable()
176uint8_t *ccder_encode_implicit_uint64(ccder_tag implicit_tag, uint64_t value, const uint8_t *der, uint8_t *der_end);
177
178CC_NONNULL((2)) cc_ptrcheck_unavailable()
179uint8_t *ccder_encode_uint64(uint64_t value, const uint8_t *der, uint8_t *der_end);
180
181CC_NONNULL((3, 4)) cc_ptrcheck_unavailable()
182uint8_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
184CC_NONNULL((2, 3)) cc_ptrcheck_unavailable()
185uint8_t *ccder_encode_octet_string(cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end);
186
187CC_NONNULL((3, 4)) cc_ptrcheck_unavailable()
188uint8_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
194CC_NONNULL((2, 3)) cc_ptrcheck_unavailable()
195uint8_t *ccder_encode_raw_octet_string(size_t s_size, const uint8_t *s, const uint8_t *der, uint8_t *der_end);
196
197CC_NONNULL((2, 5, 6)) cc_ptrcheck_unavailable()
198uint8_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 */
210CC_NONNULL((3)) cc_ptrcheck_unavailable()
211uint8_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. */
215CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
216const uint8_t *ccder_decode_tag(ccder_tag *tagp, const uint8_t *der, const uint8_t *der_end);
217
218CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
219const 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 */
231CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
232const 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. */
236CC_NONNULL((2, 4)) cc_ptrcheck_unavailable()
237const 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 */
250CC_NONNULL((2, 4)) cc_ptrcheck_unavailable()
251const uint8_t *ccder_decode_tl_strict(ccder_tag expected_tag, size_t *lenp, const uint8_t *der, const uint8_t *der_end);
252
253CC_NONNULL((2, 4)) cc_ptrcheck_unavailable()
254const 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 */
271CC_NONNULL((2, 4)) cc_ptrcheck_unavailable()
272const 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
274CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
275const 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 */
287CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
288const 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 */
301CC_NONNULL((3)) cc_ptrcheck_unavailable()
302const 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
314NULL 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 */
318CC_NONNULL((4)) cc_ptrcheck_unavailable()
319const 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 */
332CC_NONNULL((4)) cc_ptrcheck_unavailable()
333const uint8_t *ccder_decode_uint_strict(cc_size n, cc_unit *r, const uint8_t *der, const uint8_t *der_end);
334
335CC_NONNULL((3)) cc_ptrcheck_unavailable()
336const 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. */
341CC_NONNULL((2, 3, 5)) cc_ptrcheck_unavailable()
342const 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 */
356CC_NONNULL((2, 3, 5)) cc_ptrcheck_unavailable()
357const 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 */
372CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
373const uint8_t *ccder_decode_oid(ccoid_t *oidp, const uint8_t *der, const uint8_t *der_end);
374
375CC_NONNULL((1, 2, 4)) cc_ptrcheck_unavailable()
376const uint8_t *ccder_decode_bitstring(const uint8_t **bit_string, size_t *bit_length, const uint8_t *der, const uint8_t *der_end);
377
378CC_NONNULL((1, 2, 3, 4, 5, 6, 7)) cc_ptrcheck_unavailable()
379const 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