Mercurial > dropbear
comparison libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c @ 1511:5916af64acd4 fuzz
merge from main
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sat, 17 Feb 2018 19:29:51 +0800 |
parents | 6dba84798cd5 |
children | e9dba7abd939 |
comparison
equal
deleted
inserted
replaced
1457:32f990cc96b1 | 1511:5916af64acd4 |
---|---|
3 * LibTomCrypt is a library that provides various cryptographic | 3 * LibTomCrypt is a library that provides various cryptographic |
4 * algorithms in a highly modular and flexible manner. | 4 * algorithms in a highly modular and flexible manner. |
5 * | 5 * |
6 * The library is free for all purposes without any express | 6 * The library is free for all purposes without any express |
7 * guarantee it works. | 7 * guarantee it works. |
8 * | |
9 * Tom St Denis, [email protected], http://libtom.org | |
10 */ | 8 */ |
11 #include "tomcrypt.h" | 9 #include "tomcrypt.h" |
12 | 10 |
13 /** | 11 /** |
14 @file der_decode_sequence_flexi.c | 12 @file der_decode_sequence_flexi.c |
15 ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis | 13 ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis |
16 */ | 14 */ |
17 | 15 |
18 #ifdef LTC_DER | 16 #ifdef LTC_DER |
19 | 17 |
20 static unsigned long fetch_length(const unsigned char *in, unsigned long inlen) | 18 static unsigned long _fetch_length(const unsigned char *in, unsigned long inlen, unsigned long *data_offset) |
21 { | 19 { |
22 unsigned long x, y, z; | 20 unsigned long x, z; |
23 | 21 |
24 y = 0; | 22 *data_offset = 0; |
25 | 23 |
26 /* skip type and read len */ | 24 /* skip type and read len */ |
27 if (inlen < 2) { | 25 if (inlen < 2) { |
28 return 0xFFFFFFFF; | 26 return 0xFFFFFFFF; |
29 } | 27 } |
30 ++in; ++y; | 28 ++in; ++(*data_offset); |
31 | 29 |
32 /* read len */ | 30 /* read len */ |
33 x = *in++; ++y; | 31 x = *in++; ++(*data_offset); |
34 | 32 |
35 /* <128 means literal */ | 33 /* <128 means literal */ |
36 if (x < 128) { | 34 if (x < 128) { |
37 return x+y; | 35 return x+*data_offset; |
38 } | 36 } |
39 x &= 0x7F; /* the lower 7 bits are the length of the length */ | 37 x &= 0x7F; /* the lower 7 bits are the length of the length */ |
40 inlen -= 2; | 38 inlen -= 2; |
41 | 39 |
42 /* len means len of len! */ | 40 /* len means len of len! */ |
43 if (x == 0 || x > 4 || x > inlen) { | 41 if (x == 0 || x > 4 || x > inlen) { |
44 return 0xFFFFFFFF; | 42 return 0xFFFFFFFF; |
45 } | 43 } |
46 | 44 |
47 y += x; | 45 *data_offset += x; |
48 z = 0; | 46 z = 0; |
49 while (x--) { | 47 while (x--) { |
50 z = (z<<8) | ((unsigned long)*in); | 48 z = (z<<8) | ((unsigned long)*in); |
51 ++in; | 49 ++in; |
52 } | 50 } |
53 return z+y; | 51 return z+*data_offset; |
54 } | 52 } |
55 | 53 |
56 /** | 54 static int _new_element(ltc_asn1_list **l) |
55 { | |
56 /* alloc new link */ | |
57 if (*l == NULL) { | |
58 *l = XCALLOC(1, sizeof(ltc_asn1_list)); | |
59 if (*l == NULL) { | |
60 return CRYPT_MEM; | |
61 } | |
62 } else { | |
63 (*l)->next = XCALLOC(1, sizeof(ltc_asn1_list)); | |
64 if ((*l)->next == NULL) { | |
65 return CRYPT_MEM; | |
66 } | |
67 (*l)->next->prev = *l; | |
68 *l = (*l)->next; | |
69 } | |
70 return CRYPT_OK; | |
71 } | |
72 | |
73 /** | |
57 ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. | 74 ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. |
58 @param in The input buffer | 75 @param in The input buffer |
59 @param inlen [in/out] The length of the input buffer and on output the amount of decoded data | 76 @param inlen [in/out] The length of the input buffer and on output the amount of decoded data |
60 @param out [out] A pointer to the linked list | 77 @param out [out] A pointer to the linked list |
61 @return CRYPT_OK on success. | 78 @return CRYPT_OK on success. |
62 */ | 79 */ |
63 int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out) | 80 int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out) |
64 { | 81 { |
65 ltc_asn1_list *l; | 82 ltc_asn1_list *l; |
66 unsigned long err, type, len, totlen, x, y; | 83 unsigned long err, type, len, totlen, data_offset; |
67 void *realloc_tmp; | 84 void *realloc_tmp; |
68 | 85 |
69 LTC_ARGCHK(in != NULL); | 86 LTC_ARGCHK(in != NULL); |
70 LTC_ARGCHK(inlen != NULL); | 87 LTC_ARGCHK(inlen != NULL); |
71 LTC_ARGCHK(out != NULL); | 88 LTC_ARGCHK(out != NULL); |
72 | 89 |
73 l = NULL; | 90 l = NULL; |
74 totlen = 0; | 91 totlen = 0; |
75 | 92 |
93 if (*inlen == 0) { | |
94 /* alloc new link */ | |
95 if ((err = _new_element(&l)) != CRYPT_OK) { | |
96 goto error; | |
97 } | |
98 } | |
99 | |
76 /* scan the input and and get lengths and what not */ | 100 /* scan the input and and get lengths and what not */ |
77 while (*inlen) { | 101 while (*inlen) { |
78 /* read the type byte */ | 102 /* read the type byte */ |
79 type = *in; | 103 type = *in; |
80 | 104 |
81 /* fetch length */ | 105 /* fetch length */ |
82 len = fetch_length(in, *inlen); | 106 len = _fetch_length(in, *inlen, &data_offset); |
83 if (len > *inlen) { | 107 if (len > *inlen) { |
84 err = CRYPT_INVALID_PACKET; | 108 err = CRYPT_INVALID_PACKET; |
85 goto error; | 109 goto error; |
86 } | 110 } |
87 | 111 |
88 /* alloc new link */ | 112 /* alloc new link */ |
89 if (l == NULL) { | 113 if ((err = _new_element(&l)) != CRYPT_OK) { |
90 l = XCALLOC(1, sizeof(*l)); | 114 goto error; |
91 if (l == NULL) { | 115 } |
92 err = CRYPT_MEM; | 116 |
93 goto error; | 117 if ((type & 0x20) && (type != 0x30) && (type != 0x31)) { |
94 } | 118 /* constructed, use the 'used' field to store the original identifier */ |
95 } else { | 119 l->used = type; |
96 l->next = XCALLOC(1, sizeof(*l)); | 120 /* treat constructed elements like SETs */ |
97 if (l->next == NULL) { | 121 type = 0x20; |
98 err = CRYPT_MEM; | 122 } |
99 goto error; | 123 else if ((type & 0xC0) == 0x80) { |
100 } | 124 /* context-specific, use the 'used' field to store the original identifier */ |
101 l->next->prev = l; | 125 l->used = type; |
102 l = l->next; | 126 /* context-specific elements are treated as opaque data */ |
103 } | 127 type = 0x80; |
104 | 128 } |
105 /* now switch on type */ | 129 |
130 /* now switch on type */ | |
106 switch (type) { | 131 switch (type) { |
107 case 0x01: /* BOOLEAN */ | 132 case 0x01: /* BOOLEAN */ |
108 l->type = LTC_ASN1_BOOLEAN; | 133 l->type = LTC_ASN1_BOOLEAN; |
109 l->size = 1; | 134 l->size = 1; |
110 l->data = XCALLOC(1, sizeof(int)); | 135 l->data = XCALLOC(1, sizeof(int)); |
111 | 136 |
112 if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) { | 137 if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) { |
113 goto error; | 138 goto error; |
114 } | 139 } |
115 | 140 |
116 if ((err = der_length_boolean(&len)) != CRYPT_OK) { | 141 if ((err = der_length_boolean(&len)) != CRYPT_OK) { |
117 goto error; | 142 goto error; |
118 } | 143 } |
119 break; | 144 break; |
120 | 145 |
123 l->type = LTC_ASN1_INTEGER; | 148 l->type = LTC_ASN1_INTEGER; |
124 l->size = 1; | 149 l->size = 1; |
125 if ((err = mp_init(&l->data)) != CRYPT_OK) { | 150 if ((err = mp_init(&l->data)) != CRYPT_OK) { |
126 goto error; | 151 goto error; |
127 } | 152 } |
128 | 153 |
129 /* decode field */ | 154 /* decode field */ |
130 if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) { | 155 if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) { |
131 goto error; | 156 goto error; |
132 } | 157 } |
133 | 158 |
134 /* calc length of object */ | 159 /* calc length of object */ |
135 if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) { | 160 if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) { |
136 goto error; | 161 goto error; |
137 } | 162 } |
138 break; | 163 break; |
144 | 169 |
145 if ((l->data = XCALLOC(1, l->size)) == NULL) { | 170 if ((l->data = XCALLOC(1, l->size)) == NULL) { |
146 err = CRYPT_MEM; | 171 err = CRYPT_MEM; |
147 goto error; | 172 goto error; |
148 } | 173 } |
149 | 174 |
150 if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { | 175 if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { |
151 goto error; | 176 goto error; |
152 } | 177 } |
153 | 178 |
154 if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) { | 179 if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) { |
155 goto error; | 180 goto error; |
156 } | 181 } |
157 break; | 182 break; |
158 | 183 |
164 | 189 |
165 if ((l->data = XCALLOC(1, l->size)) == NULL) { | 190 if ((l->data = XCALLOC(1, l->size)) == NULL) { |
166 err = CRYPT_MEM; | 191 err = CRYPT_MEM; |
167 goto error; | 192 goto error; |
168 } | 193 } |
169 | 194 |
170 if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { | 195 if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { |
171 goto error; | 196 goto error; |
172 } | 197 } |
173 | 198 |
174 if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) { | 199 if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) { |
175 goto error; | 200 goto error; |
176 } | 201 } |
177 break; | 202 break; |
178 | 203 |
179 case 0x05: /* NULL */ | 204 case 0x05: /* NULL */ |
180 | 205 |
181 /* valid NULL is 0x05 0x00 */ | 206 /* valid NULL is 0x05 0x00 */ |
182 if (in[0] != 0x05 || in[1] != 0x00) { | 207 if (in[0] != 0x05 || in[1] != 0x00) { |
183 err = CRYPT_INVALID_PACKET; | 208 err = CRYPT_INVALID_PACKET; |
184 goto error; | 209 goto error; |
185 } | 210 } |
186 | 211 |
187 /* simple to store ;-) */ | 212 /* simple to store ;-) */ |
188 l->type = LTC_ASN1_NULL; | 213 l->type = LTC_ASN1_NULL; |
189 l->data = NULL; | 214 l->data = NULL; |
190 l->size = 0; | 215 l->size = 0; |
191 len = 2; | 216 len = 2; |
192 | 217 |
193 break; | 218 break; |
194 | 219 |
195 case 0x06: /* OID */ | 220 case 0x06: /* OID */ |
196 | 221 |
197 /* init field */ | 222 /* init field */ |
198 l->type = LTC_ASN1_OBJECT_IDENTIFIER; | 223 l->type = LTC_ASN1_OBJECT_IDENTIFIER; |
199 l->size = len; | 224 l->size = len; |
200 | 225 |
201 if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) { | 226 if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) { |
202 err = CRYPT_MEM; | 227 err = CRYPT_MEM; |
203 goto error; | 228 goto error; |
204 } | 229 } |
205 | 230 |
206 if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) { | 231 if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) { |
207 goto error; | 232 goto error; |
208 } | 233 } |
209 | 234 |
210 if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) { | 235 if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) { |
211 goto error; | 236 goto error; |
212 } | 237 } |
213 | 238 |
214 /* resize it to save a bunch of mem */ | 239 /* resize it to save a bunch of mem */ |
215 if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) { | 240 if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) { |
216 /* out of heap but this is not an error */ | 241 /* out of heap but this is not an error */ |
217 break; | 242 break; |
218 } | 243 } |
219 l->data = realloc_tmp; | 244 l->data = realloc_tmp; |
220 break; | 245 break; |
221 | 246 |
222 case 0x0C: /* UTF8 */ | 247 case 0x0C: /* UTF8 */ |
223 | 248 |
224 /* init field */ | 249 /* init field */ |
225 l->type = LTC_ASN1_UTF8_STRING; | 250 l->type = LTC_ASN1_UTF8_STRING; |
226 l->size = len; | 251 l->size = len; |
227 | 252 |
228 if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) { | 253 if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) { |
229 err = CRYPT_MEM; | 254 err = CRYPT_MEM; |
230 goto error; | 255 goto error; |
231 } | 256 } |
232 | 257 |
233 if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { | 258 if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { |
234 goto error; | 259 goto error; |
235 } | 260 } |
236 | 261 |
237 if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) { | 262 if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) { |
238 goto error; | 263 goto error; |
239 } | 264 } |
240 break; | 265 break; |
241 | 266 |
242 case 0x13: /* PRINTABLE */ | 267 case 0x13: /* PRINTABLE */ |
243 | 268 |
244 /* init field */ | 269 /* init field */ |
245 l->type = LTC_ASN1_PRINTABLE_STRING; | 270 l->type = LTC_ASN1_PRINTABLE_STRING; |
246 l->size = len; | 271 l->size = len; |
247 | 272 |
248 if ((l->data = XCALLOC(1, l->size)) == NULL) { | 273 if ((l->data = XCALLOC(1, l->size)) == NULL) { |
249 err = CRYPT_MEM; | 274 err = CRYPT_MEM; |
250 goto error; | 275 goto error; |
251 } | 276 } |
252 | 277 |
253 if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { | 278 if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { |
254 goto error; | 279 goto error; |
255 } | 280 } |
256 | 281 |
257 if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) { | 282 if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) { |
258 goto error; | 283 goto error; |
259 } | 284 } |
260 break; | 285 break; |
261 | 286 |
287 case 0x14: /* TELETEXT */ | |
288 | |
289 /* init field */ | |
290 l->type = LTC_ASN1_TELETEX_STRING; | |
291 l->size = len; | |
292 | |
293 if ((l->data = XCALLOC(1, l->size)) == NULL) { | |
294 err = CRYPT_MEM; | |
295 goto error; | |
296 } | |
297 | |
298 if ((err = der_decode_teletex_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { | |
299 goto error; | |
300 } | |
301 | |
302 if ((err = der_length_teletex_string(l->data, l->size, &len)) != CRYPT_OK) { | |
303 goto error; | |
304 } | |
305 break; | |
306 | |
262 case 0x16: /* IA5 */ | 307 case 0x16: /* IA5 */ |
263 | 308 |
264 /* init field */ | 309 /* init field */ |
265 l->type = LTC_ASN1_IA5_STRING; | 310 l->type = LTC_ASN1_IA5_STRING; |
266 l->size = len; | 311 l->size = len; |
267 | 312 |
268 if ((l->data = XCALLOC(1, l->size)) == NULL) { | 313 if ((l->data = XCALLOC(1, l->size)) == NULL) { |
269 err = CRYPT_MEM; | 314 err = CRYPT_MEM; |
270 goto error; | 315 goto error; |
271 } | 316 } |
272 | 317 |
273 if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { | 318 if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { |
274 goto error; | 319 goto error; |
275 } | 320 } |
276 | 321 |
277 if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) { | 322 if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) { |
278 goto error; | 323 goto error; |
279 } | 324 } |
280 break; | 325 break; |
281 | 326 |
282 case 0x17: /* UTC TIME */ | 327 case 0x17: /* UTC TIME */ |
283 | 328 |
284 /* init field */ | 329 /* init field */ |
285 l->type = LTC_ASN1_UTCTIME; | 330 l->type = LTC_ASN1_UTCTIME; |
286 l->size = 1; | 331 l->size = 1; |
287 | 332 |
288 if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) { | 333 if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) { |
289 err = CRYPT_MEM; | 334 err = CRYPT_MEM; |
290 goto error; | 335 goto error; |
291 } | 336 } |
292 | 337 |
293 len = *inlen; | 338 len = *inlen; |
294 if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) { | 339 if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) { |
295 goto error; | 340 goto error; |
296 } | 341 } |
297 | 342 |
298 if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) { | 343 if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) { |
299 goto error; | 344 goto error; |
300 } | 345 } |
301 break; | 346 break; |
302 | 347 |
348 case 0x18: | |
349 l->type = LTC_ASN1_GENERALIZEDTIME; | |
350 l->size = len; | |
351 | |
352 if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) { | |
353 err = CRYPT_MEM; | |
354 goto error; | |
355 } | |
356 | |
357 if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) { | |
358 goto error; | |
359 } | |
360 | |
361 if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) { | |
362 goto error; | |
363 } | |
364 | |
365 break; | |
366 | |
367 case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */ | |
303 case 0x30: /* SEQUENCE */ | 368 case 0x30: /* SEQUENCE */ |
304 case 0x31: /* SET */ | 369 case 0x31: /* SET */ |
305 | 370 |
306 /* init field */ | 371 /* init field */ |
307 l->type = (type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET; | 372 if (type == 0x20) { |
308 | 373 l->type = LTC_ASN1_CONSTRUCTED; |
309 /* we have to decode the SEQUENCE header and get it's length */ | 374 } |
310 | 375 else if (type == 0x30) { |
311 /* move past type */ | 376 l->type = LTC_ASN1_SEQUENCE; |
312 ++in; --(*inlen); | 377 } |
313 | 378 else { |
314 /* read length byte */ | 379 l->type = LTC_ASN1_SET; |
315 x = *in++; --(*inlen); | 380 } |
316 | 381 |
317 /* smallest SEQUENCE/SET header */ | 382 if ((l->data = XMALLOC(len)) == NULL) { |
318 y = 2; | 383 err = CRYPT_MEM; |
319 | 384 goto error; |
320 /* now if it's > 127 the next bytes are the length of the length */ | 385 } |
321 if (x > 128) { | 386 |
322 x &= 0x7F; | 387 XMEMCPY(l->data, in, len); |
323 in += x; | 388 l->size = len; |
324 *inlen -= x; | 389 |
325 | 390 |
326 /* update sequence header len */ | 391 /* jump to the start of the data */ |
327 y += x; | 392 in += data_offset; |
328 } | 393 *inlen -= data_offset; |
329 | 394 len = len - data_offset; |
395 | |
330 /* Sequence elements go as child */ | 396 /* Sequence elements go as child */ |
331 len = len - y; | |
332 if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) { | 397 if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) { |
333 goto error; | 398 goto error; |
334 } | 399 } |
335 | 400 |
336 /* len update */ | 401 /* len update */ |
337 totlen += y; | 402 totlen += data_offset; |
338 | 403 |
339 /* link them up y0 */ | 404 /* the flexi decoder can also do nothing, so make sure a child has been allocated */ |
340 l->child->parent = l; | 405 if (l->child) { |
341 | 406 /* link them up y0 */ |
407 l->child->parent = l; | |
408 } | |
409 | |
342 break; | 410 break; |
411 | |
412 case 0x80: /* Context-specific */ | |
413 l->type = LTC_ASN1_CONTEXT_SPECIFIC; | |
414 | |
415 if ((l->data = XCALLOC(1, len - data_offset)) == NULL) { | |
416 err = CRYPT_MEM; | |
417 goto error; | |
418 } | |
419 | |
420 XMEMCPY(l->data, in + data_offset, len - data_offset); | |
421 l->size = len - data_offset; | |
422 | |
423 break; | |
424 | |
343 default: | 425 default: |
344 /* invalid byte ... this is a soft error */ | 426 /* invalid byte ... this is a soft error */ |
345 /* remove link */ | 427 /* remove link */ |
346 l = l->prev; | 428 if (l->prev) { |
347 XFREE(l->next); | 429 l = l->prev; |
348 l->next = NULL; | 430 XFREE(l->next); |
431 l->next = NULL; | |
432 } | |
349 goto outside; | 433 goto outside; |
350 } | 434 } |
351 | 435 |
352 /* advance pointers */ | 436 /* advance pointers */ |
353 totlen += len; | 437 totlen += len; |
354 in += len; | 438 in += len; |
355 *inlen -= len; | 439 *inlen -= len; |
356 } | 440 } |
357 | 441 |
358 outside: | 442 outside: |
359 | 443 |
360 /* rewind l please */ | 444 /* in case we processed anything */ |
361 while (l->prev != NULL || l->parent != NULL) { | 445 if (totlen) { |
362 if (l->parent != NULL) { | 446 /* rewind l please */ |
363 l = l->parent; | 447 while (l->prev != NULL || l->parent != NULL) { |
364 } else { | 448 if (l->parent != NULL) { |
365 l = l->prev; | 449 l = l->parent; |
366 } | 450 } else { |
367 } | 451 l = l->prev; |
368 | 452 } |
453 } | |
454 } | |
455 | |
369 /* return */ | 456 /* return */ |
370 *out = l; | 457 *out = l; |
371 *inlen = totlen; | 458 *inlen = totlen; |
372 return CRYPT_OK; | 459 return CRYPT_OK; |
373 | 460 |
379 } | 466 } |
380 | 467 |
381 #endif | 468 #endif |
382 | 469 |
383 | 470 |
384 /* $Source$ */ | 471 /* ref: $Format:%D$ */ |
385 /* $Revision$ */ | 472 /* git commit: $Format:%H$ */ |
386 /* $Date$ */ | 473 /* commit time: $Format:%ai$ */ |