1*54925bf6Swillf /* ... copyright ... */
2*54925bf6Swillf
3*54925bf6Swillf /* Novell key-format scheme:
4*54925bf6Swillf
5*54925bf6Swillf KrbKeySet ::= SEQUENCE {
6*54925bf6Swillf attribute-major-vno [0] UInt16,
7*54925bf6Swillf attribute-minor-vno [1] UInt16,
8*54925bf6Swillf kvno [2] UInt32,
9*54925bf6Swillf mkvno [3] UInt32 OPTIONAL,
10*54925bf6Swillf keys [4] SEQUENCE OF KrbKey,
11*54925bf6Swillf ...
12*54925bf6Swillf }
13*54925bf6Swillf
14*54925bf6Swillf KrbKey ::= SEQUENCE {
15*54925bf6Swillf salt [0] KrbSalt OPTIONAL,
16*54925bf6Swillf key [1] EncryptionKey,
17*54925bf6Swillf s2kparams [2] OCTET STRING OPTIONAL,
18*54925bf6Swillf ...
19*54925bf6Swillf }
20*54925bf6Swillf
21*54925bf6Swillf KrbSalt ::= SEQUENCE {
22*54925bf6Swillf type [0] Int32,
23*54925bf6Swillf salt [1] OCTET STRING OPTIONAL
24*54925bf6Swillf }
25*54925bf6Swillf
26*54925bf6Swillf EncryptionKey ::= SEQUENCE {
27*54925bf6Swillf keytype [0] Int32,
28*54925bf6Swillf keyvalue [1] OCTET STRING
29*54925bf6Swillf }
30*54925bf6Swillf
31*54925bf6Swillf */
32*54925bf6Swillf
33*54925bf6Swillf #include <k5-int.h>
34*54925bf6Swillf #include <kdb.h>
35*54925bf6Swillf
36*54925bf6Swillf #include "krbasn1.h"
37*54925bf6Swillf #include "asn1_encode.h"
38*54925bf6Swillf #include "asn1_decode.h"
39*54925bf6Swillf #include "asn1_make.h"
40*54925bf6Swillf #include "asn1_get.h"
41*54925bf6Swillf
42*54925bf6Swillf #define asn1_encode_sequence_of_keys krb5int_ldap_encode_sequence_of_keys
43*54925bf6Swillf #define asn1_decode_sequence_of_keys krb5int_ldap_decode_sequence_of_keys
44*54925bf6Swillf
45*54925bf6Swillf #define cleanup(err) \
46*54925bf6Swillf { \
47*54925bf6Swillf ret = err; \
48*54925bf6Swillf goto last; \
49*54925bf6Swillf }
50*54925bf6Swillf
51*54925bf6Swillf #define checkerr \
52*54925bf6Swillf if (ret != 0) \
53*54925bf6Swillf goto last
54*54925bf6Swillf
55*54925bf6Swillf /************************************************************************/
56*54925bf6Swillf /* Encode the Principal's keys */
57*54925bf6Swillf /************************************************************************/
58*54925bf6Swillf
59*54925bf6Swillf static asn1_error_code
asn1_encode_key(asn1buf * buf,krb5_key_data key_data,unsigned int * retlen)60*54925bf6Swillf asn1_encode_key(asn1buf *buf,
61*54925bf6Swillf krb5_key_data key_data,
62*54925bf6Swillf unsigned int *retlen)
63*54925bf6Swillf {
64*54925bf6Swillf asn1_error_code ret = 0;
65*54925bf6Swillf unsigned int length, sum = 0;
66*54925bf6Swillf
67*54925bf6Swillf /* Encode the key type and value. */
68*54925bf6Swillf {
69*54925bf6Swillf unsigned int key_len = 0;
70*54925bf6Swillf /* key value */
71*54925bf6Swillf ret = asn1_encode_octetstring (buf,
72*54925bf6Swillf key_data.key_data_length[0],
73*54925bf6Swillf key_data.key_data_contents[0],
74*54925bf6Swillf &length); checkerr;
75*54925bf6Swillf key_len += length;
76*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length); checkerr;
77*54925bf6Swillf key_len += length;
78*54925bf6Swillf /* key type */
79*54925bf6Swillf ret = asn1_encode_integer (buf, key_data.key_data_type[0], &length);
80*54925bf6Swillf checkerr;
81*54925bf6Swillf key_len += length;
82*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr;
83*54925bf6Swillf key_len += length;
84*54925bf6Swillf
85*54925bf6Swillf ret = asn1_make_sequence(buf, key_len, &length); checkerr;
86*54925bf6Swillf key_len += length;
87*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, key_len, &length); checkerr;
88*54925bf6Swillf key_len += length;
89*54925bf6Swillf
90*54925bf6Swillf sum += key_len;
91*54925bf6Swillf }
92*54925bf6Swillf /* Encode the salt type and value (optional) */
93*54925bf6Swillf if (key_data.key_data_ver > 1) {
94*54925bf6Swillf unsigned int salt_len = 0;
95*54925bf6Swillf /* salt value (optional) */
96*54925bf6Swillf if (key_data.key_data_length[1] > 0) {
97*54925bf6Swillf ret = asn1_encode_octetstring (buf,
98*54925bf6Swillf key_data.key_data_length[1],
99*54925bf6Swillf key_data.key_data_contents[1],
100*54925bf6Swillf &length); checkerr;
101*54925bf6Swillf salt_len += length;
102*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length);
103*54925bf6Swillf checkerr;
104*54925bf6Swillf salt_len += length;
105*54925bf6Swillf }
106*54925bf6Swillf /* salt type */
107*54925bf6Swillf ret = asn1_encode_integer (buf, key_data.key_data_type[1], &length);
108*54925bf6Swillf checkerr;
109*54925bf6Swillf salt_len += length;
110*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr;
111*54925bf6Swillf salt_len += length;
112*54925bf6Swillf
113*54925bf6Swillf ret = asn1_make_sequence(buf, salt_len, &length); checkerr;
114*54925bf6Swillf salt_len += length;
115*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, salt_len, &length); checkerr;
116*54925bf6Swillf salt_len += length;
117*54925bf6Swillf
118*54925bf6Swillf sum += salt_len;
119*54925bf6Swillf }
120*54925bf6Swillf
121*54925bf6Swillf ret = asn1_make_sequence(buf, sum, &length); checkerr;
122*54925bf6Swillf sum += length;
123*54925bf6Swillf
124*54925bf6Swillf *retlen = sum;
125*54925bf6Swillf
126*54925bf6Swillf last:
127*54925bf6Swillf return ret;
128*54925bf6Swillf }
129*54925bf6Swillf
130*54925bf6Swillf /* Major version and minor version are both '1' - first version */
131*54925bf6Swillf /* asn1_error_code asn1_encode_sequence_of_keys (krb5_key_data *key_data, */
132*54925bf6Swillf krb5_error_code
asn1_encode_sequence_of_keys(krb5_key_data * key_data,krb5_int16 n_key_data,krb5_int32 mkvno,krb5_data ** code)133*54925bf6Swillf asn1_encode_sequence_of_keys (krb5_key_data *key_data,
134*54925bf6Swillf krb5_int16 n_key_data,
135*54925bf6Swillf krb5_int32 mkvno, /* Master key version number */
136*54925bf6Swillf krb5_data **code)
137*54925bf6Swillf {
138*54925bf6Swillf asn1_error_code ret = 0;
139*54925bf6Swillf asn1buf *buf = NULL;
140*54925bf6Swillf unsigned int length, sum = 0;
141*54925bf6Swillf unsigned long tmp_ul;
142*54925bf6Swillf
143*54925bf6Swillf *code = NULL;
144*54925bf6Swillf
145*54925bf6Swillf if (n_key_data == 0) cleanup (ASN1_MISSING_FIELD);
146*54925bf6Swillf
147*54925bf6Swillf /* Allocate the buffer */
148*54925bf6Swillf ret = asn1buf_create(&buf);
149*54925bf6Swillf checkerr;
150*54925bf6Swillf
151*54925bf6Swillf /* Sequence of keys */
152*54925bf6Swillf {
153*54925bf6Swillf int i;
154*54925bf6Swillf unsigned int seq_len = 0;
155*54925bf6Swillf
156*54925bf6Swillf for (i = n_key_data - 1; i >= 0; i--) {
157*54925bf6Swillf ret = asn1_encode_key (buf, key_data[i], &length); checkerr;
158*54925bf6Swillf seq_len += length;
159*54925bf6Swillf }
160*54925bf6Swillf ret = asn1_make_sequence(buf, seq_len, &length); checkerr;
161*54925bf6Swillf seq_len += length;
162*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 4, seq_len, &length); checkerr;
163*54925bf6Swillf seq_len += length;
164*54925bf6Swillf
165*54925bf6Swillf sum += seq_len;
166*54925bf6Swillf }
167*54925bf6Swillf
168*54925bf6Swillf /* mkvno */
169*54925bf6Swillf if (mkvno < 0)
170*54925bf6Swillf cleanup (ASN1_BAD_FORMAT);
171*54925bf6Swillf tmp_ul = (unsigned long)mkvno;
172*54925bf6Swillf ret = asn1_encode_unsigned_integer (buf, tmp_ul, &length); checkerr;
173*54925bf6Swillf sum += length;
174*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 3, length, &length); checkerr;
175*54925bf6Swillf sum += length;
176*54925bf6Swillf
177*54925bf6Swillf /* kvno (assuming all keys in array have same version) */
178*54925bf6Swillf if (key_data[0].key_data_kvno < 0)
179*54925bf6Swillf cleanup (ASN1_BAD_FORMAT);
180*54925bf6Swillf tmp_ul = (unsigned long)key_data[0].key_data_kvno;
181*54925bf6Swillf ret = asn1_encode_unsigned_integer (buf, tmp_ul, &length);
182*54925bf6Swillf checkerr;
183*54925bf6Swillf sum += length;
184*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 2, length, &length); checkerr;
185*54925bf6Swillf sum += length;
186*54925bf6Swillf
187*54925bf6Swillf /* attribute-minor-vno == 1 */
188*54925bf6Swillf ret = asn1_encode_unsigned_integer (buf, 1, &length); checkerr;
189*54925bf6Swillf sum += length;
190*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length); checkerr;
191*54925bf6Swillf sum += length;
192*54925bf6Swillf
193*54925bf6Swillf /* attribute-major-vno == 1 */
194*54925bf6Swillf ret = asn1_encode_unsigned_integer (buf, 1, &length); checkerr;
195*54925bf6Swillf sum += length;
196*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr;
197*54925bf6Swillf sum += length;
198*54925bf6Swillf
199*54925bf6Swillf ret = asn1_make_sequence(buf, sum, &length); checkerr;
200*54925bf6Swillf sum += length;
201*54925bf6Swillf
202*54925bf6Swillf /* The reverse encoding is straightened out here */
203*54925bf6Swillf ret = asn12krb5_buf (buf, code); checkerr;
204*54925bf6Swillf
205*54925bf6Swillf last:
206*54925bf6Swillf asn1buf_destroy (&buf);
207*54925bf6Swillf
208*54925bf6Swillf if (ret != 0 && *code != NULL) {
209*54925bf6Swillf if ((*code)->data != NULL)
210*54925bf6Swillf free ((*code)->data);
211*54925bf6Swillf free (*code);
212*54925bf6Swillf }
213*54925bf6Swillf
214*54925bf6Swillf return ret;
215*54925bf6Swillf }
216*54925bf6Swillf
217*54925bf6Swillf /************************************************************************/
218*54925bf6Swillf /* Decode the Principal's keys */
219*54925bf6Swillf /************************************************************************/
220*54925bf6Swillf
221*54925bf6Swillf #define safe_syncbuf(outer,inner) \
222*54925bf6Swillf if (! ((inner)->next == (inner)->bound + 1 && \
223*54925bf6Swillf (inner)->next == (outer)->next + buflen)) \
224*54925bf6Swillf cleanup (ASN1_BAD_LENGTH); \
225*54925bf6Swillf asn1buf_sync((outer), (inner), 0, 0, 0, 0, 0);
226*54925bf6Swillf
227*54925bf6Swillf static asn1_error_code
decode_tagged_integer(asn1buf * buf,asn1_tagnum expectedtag,long * val)228*54925bf6Swillf decode_tagged_integer (asn1buf *buf, asn1_tagnum expectedtag, long *val)
229*54925bf6Swillf {
230*54925bf6Swillf int buflen;
231*54925bf6Swillf asn1_error_code ret = 0;
232*54925bf6Swillf asn1buf tmp, subbuf;
233*54925bf6Swillf taginfo t;
234*54925bf6Swillf
235*54925bf6Swillf /* Work on a copy of 'buf' */
236*54925bf6Swillf ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
237*54925bf6Swillf ret = asn1_get_tag_2(&tmp, &t); checkerr;
238*54925bf6Swillf if (t.tagnum != expectedtag)
239*54925bf6Swillf cleanup (ASN1_MISSING_FIELD);
240*54925bf6Swillf
241*54925bf6Swillf buflen = t.length;
242*54925bf6Swillf ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
243*54925bf6Swillf ret = asn1_decode_integer(&subbuf, val); checkerr;
244*54925bf6Swillf
245*54925bf6Swillf safe_syncbuf(&tmp, &subbuf);
246*54925bf6Swillf *buf = tmp;
247*54925bf6Swillf
248*54925bf6Swillf last:
249*54925bf6Swillf return ret;
250*54925bf6Swillf }
251*54925bf6Swillf
252*54925bf6Swillf #if 0 /* not currently used */
253*54925bf6Swillf static asn1_error_code
254*54925bf6Swillf decode_tagged_unsigned_integer (asn1buf *buf, int expectedtag, unsigned long *val)
255*54925bf6Swillf {
256*54925bf6Swillf int buflen;
257*54925bf6Swillf asn1_error_code ret = 0;
258*54925bf6Swillf asn1buf tmp, subbuf;
259*54925bf6Swillf taginfo t;
260*54925bf6Swillf
261*54925bf6Swillf /* Work on a copy of 'buf' */
262*54925bf6Swillf ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
263*54925bf6Swillf ret = asn1_get_tag_2(&tmp, &t); checkerr;
264*54925bf6Swillf if (t.tagnum != expectedtag)
265*54925bf6Swillf cleanup (ASN1_MISSING_FIELD);
266*54925bf6Swillf
267*54925bf6Swillf buflen = t.length;
268*54925bf6Swillf ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
269*54925bf6Swillf ret = asn1_decode_unsigned_integer(&subbuf, val); checkerr;
270*54925bf6Swillf
271*54925bf6Swillf safe_syncbuf(&tmp, &subbuf);
272*54925bf6Swillf *buf = tmp;
273*54925bf6Swillf
274*54925bf6Swillf last:
275*54925bf6Swillf return ret;
276*54925bf6Swillf }
277*54925bf6Swillf #endif
278*54925bf6Swillf
279*54925bf6Swillf static asn1_error_code
decode_tagged_octetstring(asn1buf * buf,asn1_tagnum expectedtag,unsigned int * len,asn1_octet ** val)280*54925bf6Swillf decode_tagged_octetstring (asn1buf *buf, asn1_tagnum expectedtag,
281*54925bf6Swillf unsigned int *len, asn1_octet **val)
282*54925bf6Swillf {
283*54925bf6Swillf int buflen;
284*54925bf6Swillf asn1_error_code ret = 0;
285*54925bf6Swillf asn1buf tmp, subbuf;
286*54925bf6Swillf taginfo t;
287*54925bf6Swillf
288*54925bf6Swillf *val = NULL;
289*54925bf6Swillf
290*54925bf6Swillf /* Work on a copy of 'buf' */
291*54925bf6Swillf ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
292*54925bf6Swillf ret = asn1_get_tag_2(&tmp, &t); checkerr;
293*54925bf6Swillf if (t.tagnum != expectedtag)
294*54925bf6Swillf cleanup (ASN1_MISSING_FIELD);
295*54925bf6Swillf
296*54925bf6Swillf buflen = t.length;
297*54925bf6Swillf ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
298*54925bf6Swillf ret = asn1_decode_octetstring (&subbuf, len, val); checkerr;
299*54925bf6Swillf
300*54925bf6Swillf safe_syncbuf(&tmp, &subbuf);
301*54925bf6Swillf *buf = tmp;
302*54925bf6Swillf
303*54925bf6Swillf last:
304*54925bf6Swillf if (ret != 0 && *val != NULL)
305*54925bf6Swillf free (*val);
306*54925bf6Swillf return ret;
307*54925bf6Swillf }
308*54925bf6Swillf
asn1_decode_key(asn1buf * buf,krb5_key_data * key)309*54925bf6Swillf static asn1_error_code asn1_decode_key(asn1buf *buf, krb5_key_data *key)
310*54925bf6Swillf {
311*54925bf6Swillf int buflen, seqindef;
312*54925bf6Swillf unsigned int length;
313*54925bf6Swillf asn1_error_code ret;
314*54925bf6Swillf asn1buf subbuf;
315*54925bf6Swillf taginfo t;
316*54925bf6Swillf
317*54925bf6Swillf key->key_data_contents[0] = NULL;
318*54925bf6Swillf key->key_data_contents[1] = NULL;
319*54925bf6Swillf
320*54925bf6Swillf ret = asn1_get_sequence(buf, &length, &seqindef); checkerr;
321*54925bf6Swillf buflen = length;
322*54925bf6Swillf ret = asn1buf_imbed(&subbuf, buf, length, seqindef); checkerr;
323*54925bf6Swillf
324*54925bf6Swillf asn1_get_tag_2(&subbuf, &t);
325*54925bf6Swillf /* Salt */
326*54925bf6Swillf if (t.tagnum == 0) {
327*54925bf6Swillf int buflen;
328*54925bf6Swillf asn1buf slt;
329*54925bf6Swillf unsigned long keytype;
330*54925bf6Swillf unsigned int keylen;
331*54925bf6Swillf
332*54925bf6Swillf key->key_data_ver = 2;
333*54925bf6Swillf asn1_get_sequence(&subbuf, &length, &seqindef);
334*54925bf6Swillf buflen = length;
335*54925bf6Swillf asn1buf_imbed(&slt, &subbuf, length, seqindef);
336*54925bf6Swillf
337*54925bf6Swillf ret = decode_tagged_integer (&slt, 0, (long *) &keytype);
338*54925bf6Swillf key->key_data_type[1] = keytype; /* XXX range check?? */
339*54925bf6Swillf checkerr;
340*54925bf6Swillf
341*54925bf6Swillf if (asn1buf_remains(&slt, 0) != 0) { /* Salt value is optional */
342*54925bf6Swillf ret = decode_tagged_octetstring (&slt, 1, &keylen,
343*54925bf6Swillf &key->key_data_contents[1]); checkerr;
344*54925bf6Swillf }
345*54925bf6Swillf safe_syncbuf (&subbuf, &slt);
346*54925bf6Swillf key->key_data_length[1] = keylen; /* XXX range check?? */
347*54925bf6Swillf
348*54925bf6Swillf ret = asn1_get_tag_2(&subbuf, &t); checkerr;
349*54925bf6Swillf } else
350*54925bf6Swillf key->key_data_ver = 1;
351*54925bf6Swillf
352*54925bf6Swillf /* Key */
353*54925bf6Swillf {
354*54925bf6Swillf int buflen;
355*54925bf6Swillf asn1buf kbuf;
356*54925bf6Swillf long lval;
357*54925bf6Swillf unsigned int ival;
358*54925bf6Swillf
359*54925bf6Swillf if (t.tagnum != 1)
360*54925bf6Swillf cleanup (ASN1_MISSING_FIELD);
361*54925bf6Swillf
362*54925bf6Swillf ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr;
363*54925bf6Swillf buflen = length;
364*54925bf6Swillf ret = asn1buf_imbed(&kbuf, &subbuf, length, seqindef); checkerr;
365*54925bf6Swillf
366*54925bf6Swillf ret = decode_tagged_integer (&kbuf, 0, &lval);
367*54925bf6Swillf checkerr;
368*54925bf6Swillf key->key_data_type[0] = lval; /* XXX range check? */
369*54925bf6Swillf
370*54925bf6Swillf ret = decode_tagged_octetstring (&kbuf, 1, &ival,
371*54925bf6Swillf &key->key_data_contents[0]); checkerr;
372*54925bf6Swillf key->key_data_length[0] = ival; /* XXX range check? */
373*54925bf6Swillf
374*54925bf6Swillf safe_syncbuf (&subbuf, &kbuf);
375*54925bf6Swillf }
376*54925bf6Swillf
377*54925bf6Swillf safe_syncbuf (buf, &subbuf);
378*54925bf6Swillf
379*54925bf6Swillf last:
380*54925bf6Swillf if (ret != 0) {
381*54925bf6Swillf if (key->key_data_contents[0] != NULL) {
382*54925bf6Swillf free (key->key_data_contents[0]);
383*54925bf6Swillf key->key_data_contents[0] = NULL;
384*54925bf6Swillf }
385*54925bf6Swillf if (key->key_data_contents[1] != NULL) {
386*54925bf6Swillf free (key->key_data_contents[1]);
387*54925bf6Swillf key->key_data_contents[1] = NULL;
388*54925bf6Swillf }
389*54925bf6Swillf }
390*54925bf6Swillf return ret;
391*54925bf6Swillf }
392*54925bf6Swillf
393*54925bf6Swillf /* asn1_error_code asn1_decode_sequence_of_keys (krb5_data *in, */
asn1_decode_sequence_of_keys(krb5_data * in,krb5_key_data ** out,krb5_int16 * n_key_data,int * mkvno)394*54925bf6Swillf krb5_error_code asn1_decode_sequence_of_keys (krb5_data *in,
395*54925bf6Swillf krb5_key_data **out,
396*54925bf6Swillf krb5_int16 *n_key_data,
397*54925bf6Swillf int *mkvno)
398*54925bf6Swillf {
399*54925bf6Swillf asn1_error_code ret;
400*54925bf6Swillf asn1buf buf, subbuf;
401*54925bf6Swillf int seqindef;
402*54925bf6Swillf unsigned int length;
403*54925bf6Swillf taginfo t;
404*54925bf6Swillf int kvno, maj, min;
405*54925bf6Swillf long lval;
406*54925bf6Swillf
407*54925bf6Swillf *n_key_data = 0;
408*54925bf6Swillf *out = NULL;
409*54925bf6Swillf
410*54925bf6Swillf ret = asn1buf_wrap_data(&buf, in); checkerr;
411*54925bf6Swillf
412*54925bf6Swillf ret = asn1_get_sequence(&buf, &length, &seqindef); checkerr;
413*54925bf6Swillf ret = asn1buf_imbed(&subbuf, &buf, length, seqindef); checkerr;
414*54925bf6Swillf
415*54925bf6Swillf /* attribute-major-vno */
416*54925bf6Swillf ret = decode_tagged_integer (&subbuf, 0, &lval); checkerr;
417*54925bf6Swillf maj = lval; /* XXX range check? */
418*54925bf6Swillf
419*54925bf6Swillf /* attribute-minor-vno */
420*54925bf6Swillf ret = decode_tagged_integer (&subbuf, 1, &lval); checkerr;
421*54925bf6Swillf min = lval; /* XXX range check? */
422*54925bf6Swillf
423*54925bf6Swillf if (maj != 1 || min != 1)
424*54925bf6Swillf cleanup (ASN1_BAD_FORMAT);
425*54925bf6Swillf
426*54925bf6Swillf /* kvno (assuming all keys in array have same version) */
427*54925bf6Swillf ret = decode_tagged_integer (&subbuf, 2, &lval); checkerr;
428*54925bf6Swillf kvno = lval; /* XXX range check? */
429*54925bf6Swillf
430*54925bf6Swillf /* mkvno (optional) */
431*54925bf6Swillf ret = decode_tagged_integer (&subbuf, 3, &lval); checkerr;
432*54925bf6Swillf *mkvno = lval; /* XXX range check? */
433*54925bf6Swillf
434*54925bf6Swillf ret = asn1_get_tag_2(&subbuf, &t); checkerr;
435*54925bf6Swillf
436*54925bf6Swillf /* Sequence of keys */
437*54925bf6Swillf {
438*54925bf6Swillf int i, buflen;
439*54925bf6Swillf asn1buf keyseq;
440*54925bf6Swillf if (t.tagnum != 4)
441*54925bf6Swillf cleanup (ASN1_MISSING_FIELD);
442*54925bf6Swillf ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr;
443*54925bf6Swillf buflen = length;
444*54925bf6Swillf ret = asn1buf_imbed(&keyseq, &subbuf, length, seqindef); checkerr;
445*54925bf6Swillf for (i = 1, *out = NULL; ; i++) {
446*54925bf6Swillf krb5_key_data *tmp;
447*54925bf6Swillf tmp = (krb5_key_data *) realloc (*out, i * sizeof (krb5_key_data));
448*54925bf6Swillf if (tmp == NULL)
449*54925bf6Swillf cleanup (ENOMEM);
450*54925bf6Swillf *out = tmp;
451*54925bf6Swillf (*out)[i - 1].key_data_kvno = kvno;
452*54925bf6Swillf ret = asn1_decode_key(&keyseq, &(*out)[i - 1]); checkerr;
453*54925bf6Swillf (*n_key_data)++;
454*54925bf6Swillf if (asn1buf_remains(&keyseq, 0) == 0)
455*54925bf6Swillf break; /* Not freeing the last key structure */
456*54925bf6Swillf }
457*54925bf6Swillf safe_syncbuf (&subbuf, &keyseq);
458*54925bf6Swillf }
459*54925bf6Swillf
460*54925bf6Swillf /*
461*54925bf6Swillf * There could be other data inside the outermost sequence ... tags we don't
462*54925bf6Swillf * know about. So, not invoking "safe_syncbuf(&buf,&subbuf)"
463*54925bf6Swillf */
464*54925bf6Swillf
465*54925bf6Swillf last:
466*54925bf6Swillf if (ret != 0) {
467*54925bf6Swillf int i;
468*54925bf6Swillf for (i = 0; i < *n_key_data; i++) {
469*54925bf6Swillf if ((*out)[i].key_data_contents[0] != NULL)
470*54925bf6Swillf free ((*out)[i].key_data_contents[0]);
471*54925bf6Swillf if ((*out)[i].key_data_contents[1] != NULL)
472*54925bf6Swillf free ((*out)[i].key_data_contents[1]);
473*54925bf6Swillf }
474*54925bf6Swillf free (*out);
475*54925bf6Swillf *out = NULL;
476*54925bf6Swillf }
477*54925bf6Swillf
478*54925bf6Swillf return ret;
479*54925bf6Swillf }
480