OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
DER_Encode.c
Go to the documentation of this file.
1/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
2
3/*
4 * DER_Encode.h - DER encoding routines
5 *
6 * Created Dec. 2 2005 by dmitch
7 */
8
9#include "DER_Encode.h"
10#include "asn1Types.h"
11#include "libDER_config.h"
12#include "DER_Decode.h"
13
14#ifndef DER_ENCODE_ENABLE
15#error Please define DER_ENCODE_ENABLE.
16#endif
17
18#if DER_ENCODE_ENABLE
19
20/* calculate size of encoded tag */
21static DERSize DERLengthOfTag(
22 DERTag tag)
23{
24 DERSize rtn = 1;
25
26 tag &= ASN1_TAGNUM_MASK;
27 if (tag >= 0x1F) {
28 /* Shift 7-bit digits out of the tag integer until it's zero. */
29 while(tag != 0) {
30 rtn++;
31 tag >>= 7;
32 }
33 }
34
35 return rtn;
36}
37
38/* encode tag */
39static DERReturn DEREncodeTag(
40 DERTag tag,
41 DERByte *buf, /* encoded length goes here */
42 DERSize *inOutLen) /* IN/OUT */
43{
44 DERSize outLen = DERLengthOfTag(tag);
45 DERTag tagNumber = tag & ASN1_TAGNUM_MASK;
46 DERByte tag1 = (tag >> (sizeof(DERTag) * 8 - 8)) & 0xE0;
47
48 if(outLen > *inOutLen) {
49 return DR_BufOverflow;
50 }
51
52 if(outLen == 1) {
53 /* short form */
54 *buf = (DERByte)(tag1 | tagNumber);
55 }
56 else {
57 /* long form */
58 DERByte *tagBytes = buf + outLen; // l.s. digit of tag
59 *buf = tag1 | 0x1F; // tag class / method indicator
60 *--tagBytes = tagNumber & 0x7F;
61 tagNumber >>= 7;
62 while(tagNumber != 0) {
63 *--tagBytes = (tagNumber & 0x7F) | 0x80;
64 tagNumber >>= 7;
65 }
66 }
67 *inOutLen = outLen;
68 return DR_Success;
69}
70
71/* calculate size of encoded length */
73 DERSize length)
74{
75 DERSize rtn;
76
77 if(length < 0x80) {
78 /* short form length */
79 return 1;
80 }
81
82 /* long form - one length-of-length byte plus length bytes */
83 rtn = 1;
84 while(length != 0) {
85 rtn++;
86 length >>= 8;
87 }
88 return rtn;
89}
90
91/* encode length */
93 DERSize length,
94 DERByte *buf, /* encoded length goes here */
95 DERSize *inOutLen) /* IN/OUT */
96{
97 DERByte *lenBytes;
98 DERSize outLen = DERLengthOfLength(length);
99
100 if(outLen > *inOutLen) {
101 return DR_BufOverflow;
102 }
103
104 if(length < 0x80) {
105 /* short form */
106 *buf = (DERByte)length;
107 *inOutLen = 1;
108 return DR_Success;
109 }
110
111 /* long form */
112 *buf = (DERByte)((outLen - 1) | 0x80); // length of length, long form indicator
113 lenBytes = buf + outLen - 1; // l.s. digit of length
114 while(length != 0) {
115 *lenBytes-- = (DERByte)length;
116 length >>= 8;
117 }
118 *inOutLen = outLen;
119 return DR_Success;
120}
121
123 DERTag tag,
124 DERSize length)
125{
126 return DERLengthOfTag(tag) + DERLengthOfLength(length) + length;
127}
128
130 DERTag tag,
131 DERSize length,
132 const DERByte *src,
133 DERByte *derOut, /* encoded item goes here */
134 DERSize *inOutLen) /* IN/OUT */
135{
136 DERReturn drtn;
137 DERSize itemLen;
138 DERByte *currPtr = derOut;
139 DERSize bytesLeft = DERLengthOfItem(tag, length);
140 if(bytesLeft > *inOutLen) {
141 return DR_BufOverflow;
142 }
143 *inOutLen = bytesLeft;
144
145 /* top level tag */
146 itemLen = bytesLeft;
147 drtn = DEREncodeTag(tag, currPtr, &itemLen);
148 if(drtn) {
149 return drtn;
150 }
151 currPtr += itemLen;
152 bytesLeft -= itemLen;
153 itemLen = bytesLeft;
154 drtn = DEREncodeLength(length, currPtr, &itemLen);
155 if(drtn) {
156 return drtn;
157 }
158 currPtr += itemLen;
159 bytesLeft -= itemLen;
160 DERMemmove(currPtr, src, length);
161
162 return DR_Success;
163}
164
165static /* calculate the content length of an encoded sequence */
166DERSize DERContentLengthOfEncodedSequence(
167 const void *src, /* generally a ptr to a struct full of
168 * DERItems */
169 DERShort numItems, /* size of itemSpecs[] */
170 const DERItemSpec *itemSpecs)
171{
172 DERSize contentLen = 0;
173 unsigned dex;
174 DERSize thisContentLen;
175
176 /* find length of each item */
177 for(dex=0; dex<numItems; dex++) {
178 const DERItemSpec *currItemSpec = &itemSpecs[dex];
179 DERShort currOptions = currItemSpec->options;
180 const DERByte *byteSrc = (const DERByte *)src + currItemSpec->offset;
181 const DERItem *itemSrc = (const DERItem *)byteSrc;
182
183 if(currOptions & DER_ENC_WRITE_DER) {
184 /* easy case - no encode */
185 contentLen += itemSrc->length;
186 continue;
187 }
188
189 if ((currOptions & DER_DEC_OPTIONAL) && itemSrc->length == 0) {
190 /* If an optional item isn't present we don't encode a
191 tag and len. */
192 continue;
193 }
194
195 /*
196 * length of this item =
197 * tag (one byte) +
198 * length of length +
199 * content length +
200 * optional zero byte for signed integer
201 */
202 contentLen += DERLengthOfTag(currItemSpec->tag);
203
204 /* check need for pad byte before calculating lengthOfLength... */
205 thisContentLen = itemSrc->length;
206 if((currOptions & DER_ENC_SIGNED_INT) &&
207 (itemSrc->length != 0)) {
208 if(itemSrc->data[0] & 0x80) {
209 /* insert zero keep it positive */
210 thisContentLen++;
211 }
212 }
213 contentLen += DERLengthOfLength(thisContentLen);
214 contentLen += thisContentLen;
215 }
216 return contentLen;
217}
218
220 DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */
221 const void *src, /* generally a ptr to a struct full of
222 * DERItems */
223 DERShort numItems, /* size of itemSpecs[] */
224 const DERItemSpec *itemSpecs,
225 DERByte *derOut, /* encoded data written here */
226 DERSize *inOutLen) /* IN/OUT */
227{
228 const DERByte *endPtr = derOut + *inOutLen;
229 DERByte *currPtr = derOut;
230 DERSize bytesLeft = *inOutLen;
231 DERSize contentLen;
232 DERReturn drtn;
233 DERSize itemLen;
234 unsigned dex;
235
236 /* top level tag */
237 itemLen = bytesLeft;
238 drtn = DEREncodeTag(topTag, currPtr, &itemLen);
239 if(drtn) {
240 return drtn;
241 }
242 currPtr += itemLen;
243 bytesLeft -= itemLen;
244 if(currPtr >= endPtr) {
245 return DR_BufOverflow;
246 }
247
248 /* content length */
249 contentLen = DERContentLengthOfEncodedSequence(src, numItems, itemSpecs);
250 itemLen = bytesLeft;
251 drtn = DEREncodeLength(contentLen, currPtr, &itemLen);
252 if(drtn) {
253 return drtn;
254 }
255 currPtr += itemLen;
256 bytesLeft -= itemLen;
257 if(currPtr + contentLen > endPtr) {
258 return DR_BufOverflow;
259 }
260 /* we don't have to check for overflow any more */
261
262 /* grind thru the items */
263 for(dex=0; dex<numItems; dex++) {
264 const DERItemSpec *currItemSpec = &itemSpecs[dex];
265 DERShort currOptions = currItemSpec->options;
266 const DERByte *byteSrc = (const DERByte *)src + currItemSpec->offset;
267 const DERItem *itemSrc = (const DERItem *)byteSrc;
268 int prependZero = 0;
269
270 if(currOptions & DER_ENC_WRITE_DER) {
271 /* easy case */
272 DERMemmove(currPtr, itemSrc->data, itemSrc->length);
273 currPtr += itemSrc->length;
274 bytesLeft -= itemSrc->length;
275 continue;
276 }
277
278 if ((currOptions & DER_DEC_OPTIONAL) && itemSrc->length == 0) {
279 /* If an optional item isn't present we skip it. */
280 continue;
281 }
282
283 /* encode one item: first the tag */
284 itemLen = bytesLeft;
285 drtn = DEREncodeTag(currItemSpec->tag, currPtr, &itemLen);
286 if(drtn) {
287 return drtn;
288 }
289 currPtr += itemLen;
290 bytesLeft -= itemLen;
291
292 /* do we need to prepend a zero to content? */
293 contentLen = itemSrc->length;
294 if((currOptions & DER_ENC_SIGNED_INT) &&
295 (itemSrc->length != 0)) {
296 if(itemSrc->data[0] & 0x80) {
297 /* insert zero keep it positive */
298 contentLen++;
299 prependZero = 1;
300 }
301 }
302
303 /* encode content length */
304 itemLen = bytesLeft;
305 drtn = DEREncodeLength(contentLen, currPtr, &itemLen);
306 if(drtn) {
307 return drtn;
308 }
309 currPtr += itemLen;
310 bytesLeft -= itemLen;
311
312 /* now the content, with possible leading zero added */
313 if(prependZero) {
314 *currPtr++ = 0;
315 bytesLeft--;
316 }
317 DERMemmove(currPtr, itemSrc->data, itemSrc->length);
318 currPtr += itemSrc->length;
319 bytesLeft -= itemSrc->length;
320 }
321 *inOutLen = (currPtr - derOut);
322 return DR_Success;
323}
324
325/* calculate the length of an encoded sequence. */
327 DERTag topTag,
328 const void *src, /* generally a ptr to a struct full of
329 * DERItems */
330 DERShort numItems, /* size of itemSpecs[] */
331 const DERItemSpec *itemSpecs)
332{
333 DERSize contentLen = DERContentLengthOfEncodedSequence(
334 src, numItems, itemSpecs);
335
336 return DERLengthOfTag(topTag) +
337 DERLengthOfLength(contentLen) +
338 contentLen;
339}
340
341#endif /* DER_ENCODE_ENABLE */
342
#define DER_DEC_OPTIONAL
Definition DER_Decode.h:137
DERReturn DEREncodeSequence(DERTag topTag, const void *src, DERShort numItems, const DERItemSpec *itemSpecs, DERByte *derOut, DERSize *inOutLen)
DERReturn DEREncodeLength(DERSize length, DERByte *buf, DERSize *inOutLen)
DERSize DERLengthOfEncodedSequence(DERTag topTag, const void *src, DERShort numItems, const DERItemSpec *itemSpecs)
DERReturn DEREncodeItem(DERTag tag, DERSize length, const DERByte *src, DERByte *derOut, DERSize *inOutLen)
#define DER_ENC_WRITE_DER
Definition DER_Encode.h:63
DERSize DERLengthOfItem(DERTag tag, DERSize length)
#define DER_ENC_SIGNED_INT
Definition DER_Encode.h:60
DERSize DERLengthOfLength(DERSize length)
#define ASN1_TAGNUM_MASK
Definition asn1Types.h:69
DERReturn
Definition libDER.h:20
@ DR_Success
Definition libDER.h:21
@ DR_BufOverflow
Definition libDER.h:28
size_t DERSize
uint16_t DERShort
#define DERMemmove(dst, src, len)
uint64_t DERTag
uint8_t DERByte
DERByte * data
Definition libDER.h:36
DERSize length
Definition libDER.h:37
DERShort options
Definition libDER.h:48
DERSize offset
Definition libDER.h:46