comparison libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence.c @ 285:1b9e69c058d2

propagate from branch 'au.asn.ucc.matt.ltc.dropbear' (head 20dccfc09627970a312d77fb41dc2970b62689c3) to branch 'au.asn.ucc.matt.dropbear' (head fdf4a7a3b97ae5046139915de7e40399cceb2c01)
author Matt Johnston <matt@ucc.asn.au>
date Wed, 08 Mar 2006 13:23:58 +0000
parents
children
comparison
equal deleted inserted replaced
281:997e6f7dc01e 285:1b9e69c058d2
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, [email protected], http://libtomcrypt.org
10 */
11 #include "tomcrypt.h"
12 #include <stdarg.h>
13
14
15 /**
16 @file der_decode_sequence.c
17 ASN.1 DER, decode a SEQUENCE, Tom St Denis
18 */
19
20 #ifdef LTC_DER
21
22 /**
23 Decode a SEQUENCE
24 @param in The DER encoded input
25 @param inlen The size of the input
26 @param list The list of items to decode
27 @param outlen The number of items in the list
28 @return CRYPT_OK on success
29 */
30 int der_decode_sequence(const unsigned char *in, unsigned long inlen,
31 ltc_asn1_list *list, unsigned long outlen)
32 {
33 int err, type;
34 unsigned long size, x, y, z, i, blksize;
35 void *data;
36
37 LTC_ARGCHK(in != NULL);
38 LTC_ARGCHK(list != NULL);
39
40 /* get blk size */
41 if (inlen < 2) {
42 return CRYPT_INVALID_PACKET;
43 }
44
45 /* sequence type? */
46 x = 0;
47 if (in[x++] != 0x30) {
48 return CRYPT_INVALID_PACKET;
49 }
50
51 if (in[x] < 128) {
52 blksize = in[x++];
53 } else if (in[x] & 0x80) {
54 if (in[x] < 0x81 || in[x] > 0x83) {
55 return CRYPT_INVALID_PACKET;
56 }
57 y = in[x++] & 0x7F;
58
59 /* would reading the len bytes overrun? */
60 if (x + y > inlen) {
61 return CRYPT_INVALID_PACKET;
62 }
63
64 /* read len */
65 blksize = 0;
66 while (y--) {
67 blksize = (blksize << 8) | (unsigned long)in[x++];
68 }
69 }
70
71 /* would this blksize overflow? */
72 if (x + blksize > inlen) {
73 return CRYPT_INVALID_PACKET;
74 }
75
76 /* ok read data */
77 inlen = blksize;
78 for (i = 0; i < outlen; i++) {
79 type = list[i].type;
80 size = list[i].size;
81 data = list[i].data;
82
83 if (type == LTC_ASN1_EOL) {
84 break;
85 }
86
87 switch (type) {
88 case LTC_ASN1_INTEGER:
89 z = inlen;
90 if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
91 goto LBL_ERR;
92 }
93 if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
94 goto LBL_ERR;
95 }
96 x += z;
97 inlen -= z;
98 break;
99
100
101 case LTC_ASN1_SHORT_INTEGER:
102 z = inlen;
103 if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
104 goto LBL_ERR;
105 }
106 if ((err = der_length_short_integer(size, &z)) != CRYPT_OK) {
107 goto LBL_ERR;
108 }
109 x += z;
110 inlen -= z;
111 break;
112
113 case LTC_ASN1_BIT_STRING:
114 z = inlen;
115 if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
116 goto LBL_ERR;
117 }
118 list[i].size = size;
119 if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
120 goto LBL_ERR;
121 }
122 x += z;
123 inlen -= z;
124 break;
125
126 case LTC_ASN1_OCTET_STRING:
127 z = inlen;
128 if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
129 goto LBL_ERR;
130 }
131 list[i].size = size;
132 if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
133 goto LBL_ERR;
134 }
135 x += z;
136 inlen -= z;
137 break;
138
139 case LTC_ASN1_NULL:
140 if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
141 err = CRYPT_INVALID_PACKET;
142 goto LBL_ERR;
143 }
144 x += 2;
145 inlen -= 2;
146 break;
147
148 case LTC_ASN1_OBJECT_IDENTIFIER:
149 z = inlen;
150 if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
151 goto LBL_ERR;
152 }
153 list[i].size = size;
154 if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
155 goto LBL_ERR;
156 }
157 x += z;
158 inlen -= z;
159 break;
160
161 case LTC_ASN1_IA5_STRING:
162 z = inlen;
163 if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
164 goto LBL_ERR;
165 }
166 list[i].size = size;
167 if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
168 goto LBL_ERR;
169 }
170 x += z;
171 inlen -= z;
172 break;
173
174
175 case LTC_ASN1_PRINTABLE_STRING:
176 z = inlen;
177 if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
178 goto LBL_ERR;
179 }
180 list[i].size = size;
181 if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
182 goto LBL_ERR;
183 }
184 x += z;
185 inlen -= z;
186 break;
187
188 case LTC_ASN1_UTCTIME:
189 z = inlen;
190 if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
191 goto LBL_ERR;
192 }
193 x += z;
194 inlen -= z;
195 break;
196
197 case LTC_ASN1_SEQUENCE:
198 z = inlen;
199 if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
200 goto LBL_ERR;
201 }
202 if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
203 goto LBL_ERR;
204 }
205 x += z;
206 inlen -= z;
207 break;
208
209
210 case LTC_ASN1_CHOICE:
211 z = inlen;
212 if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
213 goto LBL_ERR;
214 }
215 x += z;
216 inlen -= z;
217 break;
218
219 default:
220 err = CRYPT_INVALID_ARG;
221 goto LBL_ERR;
222 }
223 }
224 err = CRYPT_OK;
225
226 LBL_ERR:
227 return err;
228 }
229
230 #endif
231
232 /* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence.c,v $ */
233 /* $Revision: 1.8 $ */
234 /* $Date: 2005/06/18 19:20:23 $ */