Convert all remaining macro-coded ASN.1 encoders
[krb5.git] / src / lib / krb5 / asn.1 / ldap_key_seq.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* ... copyright ... */
3
4 /*
5  * Novell key-format scheme:
6  *
7  * KrbKeySet ::= SEQUENCE {
8  * attribute-major-vno       [0] UInt16,
9  * attribute-minor-vno       [1] UInt16,
10  * kvno                      [2] UInt32,
11  * mkvno                     [3] UInt32 OPTIONAL,
12  * keys                      [4] SEQUENCE OF KrbKey,
13  * ...
14  * }
15  *
16  * KrbKey ::= SEQUENCE {
17  * salt      [0] KrbSalt OPTIONAL,
18  * key       [1] EncryptionKey,
19  * s2kparams [2] OCTET STRING OPTIONAL,
20  *  ...
21  * }
22  *
23  * KrbSalt ::= SEQUENCE {
24  * type      [0] Int32,
25  * salt      [1] OCTET STRING OPTIONAL
26  * }
27  *
28  * EncryptionKey ::= SEQUENCE {
29  * keytype   [0] Int32,
30  * keyvalue  [1] OCTET STRING
31  * }
32  *
33  */
34
35 #include <k5-int.h>
36 #include <kdb.h>
37
38 #include "krbasn1.h"
39 #include "asn1_encode.h"
40 #include "asn1_decode.h"
41 #include "asn1_make.h"
42 #include "asn1_get.h"
43
44 #ifdef ENABLE_LDAP
45
46 /************************************************************************/
47 /* Encode the Principal's keys                                          */
48 /************************************************************************/
49
50 /*
51  * Imports from asn1_k_encode.c.
52  * XXX Must be manually synchronized for now.
53  */
54 IMPORT_TYPE(octetstring, unsigned char *);
55 IMPORT_TYPE(int32, krb5_int32);
56
57 DEFINTTYPE(int16, krb5_int16);
58 DEFINTTYPE(ui_2, krb5_ui_2);
59
60 static const struct field_info krbsalt_fields[] = {
61     FIELDOF_NORM(krb5_key_data, int16, key_data_type[1], 0, 0),
62     FIELDOF_OPTSTRINGL(krb5_key_data, octetstring, key_data_contents[1],
63                        ui_2, key_data_length[1], 1, 0, 1),
64 };
65 static unsigned int
66 optional_krbsalt (const void *p)
67 {
68     const krb5_key_data *k = p;
69     unsigned int optional = 0;
70
71     if (k->key_data_length[1] > 0)
72         optional |= (1u << 1);
73
74     return optional;
75 }
76 DEFSEQTYPE(krbsalt, krb5_key_data, krbsalt_fields, optional_krbsalt);
77 static const struct field_info encryptionkey_fields[] = {
78     FIELDOF_NORM(krb5_key_data, int16, key_data_type[0], 0, 0),
79     FIELDOF_STRINGL(krb5_key_data, octetstring, key_data_contents[0],
80                     ui_2, key_data_length[0], 1, 0),
81 };
82 DEFSEQTYPE(encryptionkey, krb5_key_data, encryptionkey_fields, 0);
83
84 static const struct field_info key_data_fields[] = {
85     FIELDOF_ENCODEAS(krb5_key_data, krbsalt, 0, 0),
86     FIELDOF_ENCODEAS(krb5_key_data, encryptionkey, 1, 0),
87 #if 0 /* We don't support this field currently.  */
88     FIELDOF_blah(krb5_key_data, s2kparams, ...),
89 #endif
90 };
91 DEFSEQTYPE(key_data, krb5_key_data, key_data_fields, 0);
92 DEFPTRTYPE(ptr_key_data, key_data);
93
94 DEFFIELDTYPE(key_data_kvno, krb5_key_data,
95              FIELDOF_NORM(krb5_key_data, int16, key_data_kvno, -1, 0));
96 DEFPTRTYPE(ptr_key_data_kvno, key_data_kvno);
97
98 static const struct field_info ldap_key_seq_fields[] = {
99     FIELD_INT_IMM(1, 0, 0),
100     FIELD_INT_IMM(1, 1, 0),
101     FIELDOF_NORM(ldap_seqof_key_data, ptr_key_data_kvno, key_data, 2, 0),
102     FIELDOF_NORM(ldap_seqof_key_data, int32, mkvno, 3, 0), /* mkvno */
103     FIELDOF_SEQOF_LEN(ldap_seqof_key_data, ptr_key_data, key_data, n_key_data,
104                       int16, 4, 0),
105 };
106 DEFSEQTYPE(ldap_key_seq, ldap_seqof_key_data, ldap_key_seq_fields, 0);
107
108 /* Export a function to do the whole encoding.  */
109 MAKE_FULL_ENCODER(krb5int_ldap_encode_sequence_of_keys, ldap_key_seq);
110
111 /************************************************************************/
112 /* Decode the Principal's keys                                          */
113 /************************************************************************/
114
115 #define cleanup(err)                            \
116     {                                           \
117         ret = err;                              \
118         goto last;                              \
119     }
120
121 #define checkerr                                \
122     if (ret != 0)                               \
123         goto last
124
125 #define safe_syncbuf(outer,inner,buflen)                \
126     if (! ((inner)->next == (inner)->bound + 1 &&       \
127            (inner)->next == (outer)->next + buflen))    \
128         cleanup (ASN1_BAD_LENGTH);                      \
129     asn1buf_sync((outer), (inner), 0, 0, 0, 0, 0);
130
131 static asn1_error_code
132 decode_tagged_integer (asn1buf *buf, asn1_tagnum expectedtag, long *val)
133 {
134     int buflen;
135     asn1_error_code ret = 0;
136     asn1buf tmp, subbuf;
137     taginfo t;
138
139     /* Work on a copy of 'buf' */
140     ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
141     ret = asn1_get_tag_2(&tmp, &t); checkerr;
142     if (t.tagnum != expectedtag)
143         cleanup (ASN1_MISSING_FIELD);
144
145     buflen = t.length;
146     ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
147     ret = asn1_decode_integer(&subbuf, val); checkerr;
148
149     safe_syncbuf(&tmp, &subbuf, buflen);
150     *buf = tmp;
151
152 last:
153     return ret;
154 }
155
156 #if 0 /* not currently used */
157 static asn1_error_code
158 decode_tagged_unsigned_integer (asn1buf *buf, int expectedtag, unsigned long *val)
159 {
160     int buflen;
161     asn1_error_code ret = 0;
162     asn1buf tmp, subbuf;
163     taginfo t;
164
165     /* Work on a copy of 'buf' */
166     ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
167     ret = asn1_get_tag_2(&tmp, &t); checkerr;
168     if (t.tagnum != expectedtag)
169         cleanup (ASN1_MISSING_FIELD);
170
171     buflen = t.length;
172     ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
173     ret = asn1_decode_unsigned_integer(&subbuf, val); checkerr;
174
175     safe_syncbuf(&tmp, &subbuf, buflen);
176     *buf = tmp;
177
178 last:
179     return ret;
180 }
181 #endif
182
183 static asn1_error_code
184 decode_tagged_octetstring (asn1buf *buf, asn1_tagnum expectedtag,
185                            unsigned int *len,
186                            asn1_octet **val)
187 {
188     int buflen;
189     asn1_error_code ret = 0;
190     asn1buf tmp, subbuf;
191     taginfo t;
192
193     *val = NULL;
194
195     /* Work on a copy of 'buf' */
196     ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
197     ret = asn1_get_tag_2(&tmp, &t); checkerr;
198     if (t.tagnum != expectedtag)
199         cleanup (ASN1_MISSING_FIELD);
200
201     buflen = t.length;
202     ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
203     ret = asn1_decode_octetstring (&subbuf, len, val); checkerr;
204
205     safe_syncbuf(&tmp, &subbuf, buflen);
206     *buf = tmp;
207
208 last:
209     if (ret != 0)
210         free (*val);
211     return ret;
212 }
213
214 static asn1_error_code
215 asn1_decode_key(asn1buf *buf, krb5_key_data *key)
216 {
217     int full_buflen, seqindef;
218     unsigned int length;
219     asn1_error_code ret;
220     asn1buf subbuf;
221     taginfo t;
222
223     key->key_data_contents[0] = NULL;
224     key->key_data_contents[1] = NULL;
225
226     ret = asn1_get_sequence(buf, &length, &seqindef); checkerr;
227     full_buflen = length;
228     ret = asn1buf_imbed(&subbuf, buf, length, seqindef); checkerr;
229
230     asn1_get_tag_2(&subbuf, &t);
231     /* Salt */
232     if (t.tagnum == 0) {
233         int salt_buflen;
234         asn1buf slt;
235         long keytype;
236         unsigned int keylen;
237
238         key->key_data_ver = 2;
239         asn1_get_sequence(&subbuf, &length, &seqindef);
240         salt_buflen = length;
241         asn1buf_imbed(&slt, &subbuf, length, seqindef);
242
243         ret = decode_tagged_integer (&slt, 0, &keytype);
244         key->key_data_type[1] = keytype; /* XXX range check?? */
245         checkerr;
246
247         if (asn1buf_remains(&slt, 0) != 0) { /* Salt value is optional */
248             ret = decode_tagged_octetstring (&slt, 1, &keylen,
249                                              &key->key_data_contents[1]);
250             checkerr;
251         } else
252             keylen = 0;
253         safe_syncbuf (&subbuf, &slt, salt_buflen);
254         key->key_data_length[1] = keylen; /* XXX range check?? */
255
256         ret = asn1_get_tag_2(&subbuf, &t); checkerr;
257     } else
258         key->key_data_ver = 1;
259
260     /* Key */
261     {
262         int key_buflen;
263         asn1buf kbuf;
264         long lval;
265         unsigned int ival;
266
267         if (t.tagnum != 1)
268             cleanup (ASN1_MISSING_FIELD);
269
270         ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr;
271         key_buflen = length;
272         ret = asn1buf_imbed(&kbuf, &subbuf, length, seqindef); checkerr;
273
274         ret = decode_tagged_integer (&kbuf, 0, &lval);
275         checkerr;
276         key->key_data_type[0] = lval; /* XXX range check? */
277
278         ret = decode_tagged_octetstring (&kbuf, 1, &ival,
279                                          &key->key_data_contents[0]); checkerr;
280         key->key_data_length[0] = ival; /* XXX range check? */
281
282         safe_syncbuf (&subbuf, &kbuf, key_buflen);
283     }
284
285     safe_syncbuf (buf, &subbuf, full_buflen);
286
287 last:
288     if (ret != 0) {
289         free (key->key_data_contents[0]);
290         key->key_data_contents[0] = NULL;
291         free (key->key_data_contents[1]);
292         key->key_data_contents[1] = NULL;
293     }
294     return ret;
295 }
296
297 krb5_error_code
298 krb5int_ldap_decode_sequence_of_keys (krb5_data *in, ldap_seqof_key_data **rep)
299 {
300     ldap_seqof_key_data *repval;
301     krb5_key_data **out;
302     krb5_int16 *n_key_data;
303     int *mkvno;
304
305     asn1_error_code ret;
306     asn1buf buf, subbuf;
307     int seqindef;
308     unsigned int length;
309     taginfo t;
310     int kvno, maj, min;
311     long lval;
312
313     repval = calloc(1,sizeof(ldap_seqof_key_data));
314     *rep = repval;
315     out = &repval->key_data;
316     n_key_data = &repval->n_key_data;
317     mkvno = &repval->mkvno;
318
319     *n_key_data = 0;
320     *out = NULL;
321
322     ret = asn1buf_wrap_data(&buf, in); checkerr;
323
324     ret = asn1_get_sequence(&buf, &length, &seqindef); checkerr;
325     ret = asn1buf_imbed(&subbuf, &buf, length, seqindef); checkerr;
326
327     /* attribute-major-vno */
328     ret = decode_tagged_integer (&subbuf, 0, &lval); checkerr;
329     maj = lval;                 /* XXX range check? */
330
331     /* attribute-minor-vno */
332     ret = decode_tagged_integer (&subbuf, 1, &lval); checkerr;
333     min = lval;                 /* XXX range check? */
334
335     if (maj != 1 || min != 1)
336         cleanup (ASN1_BAD_FORMAT);
337
338     /* kvno (assuming all keys in array have same version) */
339     ret = decode_tagged_integer (&subbuf, 2, &lval); checkerr;
340     kvno = lval;                /* XXX range check? */
341
342     /* mkvno (optional) */
343     ret = decode_tagged_integer (&subbuf, 3, &lval); checkerr;
344     *mkvno = lval;              /* XXX range check? */
345
346     ret = asn1_get_tag_2(&subbuf, &t); checkerr;
347
348     /* Sequence of keys */
349     {
350         int i, seq_buflen;
351         asn1buf keyseq;
352         if (t.tagnum != 4)
353             cleanup (ASN1_MISSING_FIELD);
354         ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr;
355         seq_buflen = length;
356         ret = asn1buf_imbed(&keyseq, &subbuf, length, seqindef); checkerr;
357         for (i = 1, *out = NULL; ; i++) {
358             krb5_key_data *tmp;
359             tmp = (krb5_key_data *) realloc (*out, i * sizeof (krb5_key_data));
360             if (tmp == NULL)
361                 cleanup (ENOMEM);
362             *out = tmp;
363             (*out)[i - 1].key_data_kvno = kvno;
364             ret = asn1_decode_key(&keyseq, &(*out)[i - 1]); checkerr;
365             (*n_key_data)++;
366             if (asn1buf_remains(&keyseq, 0) == 0)
367                 break; /* Not freeing the last key structure */
368         }
369         safe_syncbuf (&subbuf, &keyseq, seq_buflen);
370     }
371
372     /*
373      * There could be other data inside the outermost sequence ... tags we don't
374      * know about. So, not invoking "safe_syncbuf(&buf,&subbuf)"
375      */
376
377 last:
378     if (ret != 0) {
379         int i;
380         for (i = 0; i < *n_key_data; i++) {
381             free ((*out)[i].key_data_contents[0]);
382             free ((*out)[i].key_data_contents[1]);
383         }
384         free (*out);
385         *out = NULL;
386     }
387
388     return ret;
389 }
390 #endif