1/*
2 *  ccder.h
3 *  corecrypto
4 *
5 *  Created by Michael Brouwer on 2/28/12.
6 *  Copyright 2012 Apple Inc. All rights reserved.
7 *
8 */
9
10#ifndef _CORECRYPTO_CCDER_H_
11#define _CORECRYPTO_CCDER_H_
12
13#include <corecrypto/ccasn1.h>
14#include <corecrypto/ccn.h>
15
16#define CCDER_MULTIBYTE_TAGS  1
17
18#ifdef CCDER_MULTIBYTE_TAGS
19typedef unsigned long ccder_tag;
20#else
21typedef uint8_t ccder_tag;
22#endif
23
24/* DER types to be used with ccder_decode and ccder_encode functions. */
25enum {
26    CCDER_EOL               = CCASN1_EOL,
27    CCDER_BOOLEAN           = CCASN1_BOOLEAN,
28    CCDER_INTEGER           = CCASN1_INTEGER,
29    CCDER_BIT_STRING        = CCASN1_BIT_STRING,
30    CCDER_OCTET_STRING      = CCASN1_OCTET_STRING,
31    CCDER_NULL              = CCASN1_NULL,
32    CCDER_OBJECT_IDENTIFIER = CCASN1_OBJECT_IDENTIFIER,
33    CCDER_OBJECT_DESCRIPTOR = CCASN1_OBJECT_DESCRIPTOR,
34    /* External or instance-of 0x08 */
35    CCDER_REAL              = CCASN1_REAL,
36    CCDER_ENUMERATED        = CCASN1_ENUMERATED,
37    CCDER_EMBEDDED_PDV      = CCASN1_EMBEDDED_PDV,
38    CCDER_UTF8_STRING       = CCASN1_UTF8_STRING,
39    /*                         0x0d */
40    /*                         0x0e */
41    /*                         0x0f */
42    CCDER_SEQUENCE          = CCASN1_SEQUENCE,
43    CCDER_SET               = CCASN1_SET,
44    CCDER_NUMERIC_STRING    = CCASN1_NUMERIC_STRING,
45    CCDER_PRINTABLE_STRING  = CCASN1_PRINTABLE_STRING,
46    CCDER_T61_STRING        = CCASN1_T61_STRING,
47    CCDER_VIDEOTEX_STRING   = CCASN1_VIDEOTEX_STRING,
48    CCDER_IA5_STRING        = CCASN1_IA5_STRING,
49    CCDER_UTC_TIME          = CCASN1_UTC_TIME,
50    CCDER_GENERALIZED_TIME  = CCASN1_GENERALIZED_TIME,
51    CCDER_GRAPHIC_STRING    = CCASN1_GRAPHIC_STRING,
52    CCDER_VISIBLE_STRING    = CCASN1_VISIBLE_STRING,
53    CCDER_GENERAL_STRING    = CCASN1_GENERAL_STRING,
54    CCDER_UNIVERSAL_STRING  = CCASN1_UNIVERSAL_STRING,
55    /*                         0x1d */
56    CCDER_BMP_STRING        = CCASN1_BMP_STRING,
57    CCDER_HIGH_TAG_NUMBER   = CCASN1_HIGH_TAG_NUMBER,
58    CCDER_TELETEX_STRING    = CCDER_T61_STRING,
59
60#ifdef CCDER_MULTIBYTE_TAGS
61    CCDER_TAG_MASK          = ((ccder_tag)~0),
62    CCDER_TAGNUM_MASK       = ((ccder_tag)~((ccder_tag)7 << (sizeof(ccder_tag) * 8 - 3))),
63
64    CCDER_METHOD_MASK       = ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 3)),
65    CCDER_PRIMITIVE         = ((ccder_tag)0 << (sizeof(ccder_tag) * 8 - 3)),
66    CCDER_CONSTRUCTED       = ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 3)),
67
68    CCDER_CLASS_MASK        = ((ccder_tag)3 << (sizeof(ccder_tag) * 8 - 2)),
69    CCDER_UNIVERSAL         = ((ccder_tag)0 << (sizeof(ccder_tag) * 8 - 2)),
70    CCDER_APPLICATION       = ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 2)),
71    CCDER_CONTEXT_SPECIFIC  = ((ccder_tag)2 << (sizeof(ccder_tag) * 8 - 2)),
72    CCDER_PRIVATE           = ((ccder_tag)3 << (sizeof(ccder_tag) * 8 - 2)),
73#else
74    CCDER_TAG_MASK			= CCASN1_TAG_MASK,
75    CCDER_TAGNUM_MASK		= CCASN1_TAGNUM_MASK,
76
77    CCDER_METHOD_MASK		= CCASN1_METHOD_MASK,
78    CCDER_PRIMITIVE         = CCASN1_PRIMITIVE,
79    CCDER_CONSTRUCTED		= CCASN1_CONSTRUCTED,
80
81    CCDER_CLASS_MASK		= CCASN1_CLASS_MASK,
82    CCDER_UNIVERSAL         = CCASN1_UNIVERSAL,
83    CCDER_APPLICATION		= CCASN1_APPLICATION,
84    CCDER_CONTEXT_SPECIFIC	= CCASN1_CONTEXT_SPECIFIC,
85    CCDER_PRIVATE			= CCASN1_PRIVATE,
86#endif
87    CCDER_CONSTRUCTED_SET   = CCDER_SET | CCDER_CONSTRUCTED,
88    CCDER_CONSTRUCTED_SEQUENCE = CCDER_SEQUENCE | CCDER_CONSTRUCTED,
89};
90
91
92#pragma mark ccder_sizeof_ functions
93
94inline CC_CONST
95size_t ccder_sizeof_tag(ccder_tag tag);
96
97inline CC_CONST
98size_t ccder_sizeof_len(size_t len);
99
100/* Returns the size of an asn1 encoded item of length l in bytes,
101 assuming a 1 byte tag. */
102inline CC_CONST
103size_t ccder_sizeof(ccder_tag tag, size_t len);
104
105inline CC_CONST
106size_t ccder_sizeof_oid(ccoid_t oid);
107
108#pragma mark ccder_encode_ functions.
109
110/* Encode a tag backwards, der_end should point to one byte past the end of
111   destination for the tag, returns a pointer to the first byte of the tag.
112   Returns NULL if there is an encoding error. */
113inline CC_NONNULL2
114uint8_t *ccder_encode_tag(ccder_tag tag, const uint8_t *der, uint8_t *der_end);
115
116/* Returns a pointer to the start of the len field.  returns NULL if there
117 is an encoding error. */
118inline CC_NONNULL2
119uint8_t *
120ccder_encode_len(size_t len, const uint8_t *der, uint8_t *der_end);
121
122/* der_end should point to the first byte of the content of this der item. */
123inline CC_NONNULL3
124uint8_t *
125ccder_encode_tl(ccder_tag tag, size_t len, const uint8_t *der, uint8_t *der_end);
126
127inline CC_PURE CC_NONNULL2
128uint8_t *
129ccder_encode_body_nocopy(size_t size, const uint8_t *der, uint8_t *der_end);
130
131/* Encode the tag and length of a constructed object.  der is the lower
132   bound, der_end is one byte paste where we want to write the length and
133   body_end is one byte past the end of the body of the der object we are
134   encoding the tag and length of. */
135inline CC_NONNULL((2,3))
136uint8_t *
137ccder_encode_constructed_tl(ccder_tag tag, const uint8_t *body_end,
138                            const uint8_t *der, uint8_t *der_end);
139
140/* Encodes oid into der and returns
141 der + ccder_sizeof_oid(oid). */
142inline CC_NONNULL1 CC_NONNULL2
143uint8_t *ccder_encode_oid(ccoid_t oid, const uint8_t *der, uint8_t *der_end);
144
145inline CC_NONNULL((3,4))
146uint8_t *ccder_encode_implicit_integer(ccder_tag implicit_tag,
147                                       cc_size n, const cc_unit *s,
148                                       const uint8_t *der, uint8_t *der_end);
149
150inline CC_NONNULL((2,3))
151uint8_t *ccder_encode_integer(cc_size n, const cc_unit *s,
152                              const uint8_t *der, uint8_t *der_end);
153
154inline CC_NONNULL3
155uint8_t *ccder_encode_implicit_uint64(ccder_tag implicit_tag,
156                                      uint64_t value,
157                                      const uint8_t *der, uint8_t *der_end);
158
159inline CC_NONNULL3
160uint8_t *ccder_encode_uint64(uint64_t value,
161                             const uint8_t *der, uint8_t *der_end);
162
163inline CC_NONNULL((3,4))
164uint8_t *ccder_encode_implicit_octet_string(ccder_tag implicit_tag,
165                                            cc_size n, const cc_unit *s,
166                                            const uint8_t *der,
167                                            uint8_t *der_end);
168
169inline CC_NONNULL((2,3))
170uint8_t *ccder_encode_octet_string(cc_size n, const cc_unit *s,
171                                   const uint8_t *der, uint8_t *der_end);
172
173inline CC_NONNULL((3,4))
174uint8_t *ccder_encode_implicit_raw_octet_string(ccder_tag implicit_tag,
175                                                size_t s_size, const uint8_t *s,
176                                                const uint8_t *der,
177                                                uint8_t *der_end);
178
179inline CC_NONNULL((2,3))
180uint8_t *ccder_encode_raw_octet_string(size_t s_size, const uint8_t *s,
181                                       const uint8_t *der, uint8_t *der_end);
182
183/* ccder_encode_body COPIES the body into the der.
184   It's inefficient – especially when you already have to convert to get to
185   the form for the body.
186   see encode integer for the right way to unify conversion and insertion */
187inline CC_NONNULL3
188uint8_t *
189ccder_encode_body(size_t size, const uint8_t* body,
190                  const uint8_t *der, uint8_t *der_end);
191
192#pragma mark ccder_decode_ functions.
193
194/* Returns a pointer to the start of the length field, and returns the decoded tag in tag.
195 returns NULL if there is a decoding error. */
196inline CC_NONNULL((1,3))
197const uint8_t *ccder_decode_tag(ccder_tag *tagp, const uint8_t *der, const uint8_t *der_end);
198
199inline CC_NONNULL((1,3))
200const uint8_t *ccder_decode_len(size_t *lenp, const uint8_t *der, const uint8_t *der_end);
201
202/* Returns a pointer to the start of the der object, and returns the length in len.
203 returns NULL if there is a decoding error. */
204inline CC_NONNULL((2,4))
205const uint8_t *ccder_decode_tl(ccder_tag expected_tag, size_t *lenp,
206                               const uint8_t *der, const uint8_t *der_end);
207
208inline CC_NONNULL((2,3))
209const uint8_t *
210ccder_decode_constructed_tl(ccder_tag expected_tag, const uint8_t **body_end,
211                            const uint8_t *der, const uint8_t *der_end);
212
213inline CC_NONNULL((1,3))
214const uint8_t *
215ccder_decode_sequence_tl(const uint8_t **body_end,
216                         const uint8_t *der, const uint8_t *der_end);
217
218inline CC_NONNULL((2,4))
219const uint8_t *ccder_decode_uint(cc_size n, cc_unit *r,
220                                 const uint8_t *der, const uint8_t *der_end);
221
222inline CC_NONNULL((1,3))
223const uint8_t *ccder_decode_uint64(uint64_t* r,
224                                   const uint8_t *der, const uint8_t *der_end);
225
226/* Decode SEQUENCE { r, s -- (unsigned)integer } in der into r and s.
227   Returns NULL on decode errors, returns pointer just past the end of the
228   sequence of integers otherwise. */
229inline CC_NONNULL((2,3,5))
230const uint8_t *ccder_decode_seqii(cc_size n, cc_unit *r, cc_unit *s,
231                                  const uint8_t *der, const uint8_t *der_end);
232inline CC_NONNULL_ALL
233const uint8_t *ccder_decode_oid(ccoid_t *oidp,
234                                const uint8_t *der, const uint8_t *der_end);
235
236#ifndef CCDER_MULTIBYTE_TAGS
237#include <corecrypto/ccder_decode_constructed_tl.h>
238#include <corecrypto/ccder_decode_len.h>
239#include <corecrypto/ccder_decode_oid.h>
240#include <corecrypto/ccder_decode_seqii.h>
241#include <corecrypto/ccder_decode_sequence_tl.h>
242#include <corecrypto/ccder_decode_tag.h>
243#include <corecrypto/ccder_decode_tl.h>
244#include <corecrypto/ccder_decode_uint.h>
245#include <corecrypto/ccder_encode_body_nocopy.h>
246#include <corecrypto/ccder_encode_constructed_tl.h>
247#include <corecrypto/ccder_encode_implicit_integer.h>
248#include <corecrypto/ccder_encode_implicit_octet_string.h>
249#include <corecrypto/ccder_encode_implicit_uint64.h>
250#include <corecrypto/ccder_encode_integer.h>
251#include <corecrypto/ccder_encode_len.h>
252#include <corecrypto/ccder_encode_octet_string.h>
253#include <corecrypto/ccder_encode_oid.h>
254#include <corecrypto/ccder_encode_tag.h>
255#include <corecrypto/ccder_encode_tl.h>
256#include <corecrypto/ccder_encode_uint64.h>
257#include <corecrypto/ccder_sizeof.h>
258#include <corecrypto/ccder_sizeof_len.h>
259#include <corecrypto/ccder_sizeof_oid.h>
260#include <corecrypto/ccder_sizeof_tag.h>
261#endif
262
263#endif /* _CORECRYPTO_CCDER_H_ */
264