cifs-utils: allow specifying rootsbindir at configure time
[jlayton/cifs-utils.git] / asn1.c
1 /* 
2    Unix SMB/CIFS implementation.
3    simple ASN1 routines
4    Copyright (C) Andrew Tridgell 2001
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <string.h>
21 #include <talloc.h>
22 #include <stdint.h>
23
24 #include "replace.h"
25 #include "data_blob.h"
26 #include "asn1.h"
27
28 /* allocate an asn1 structure */
29 struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx)
30 {
31         struct asn1_data *ret = talloc_zero(mem_ctx, struct asn1_data);
32         return ret;
33 }
34
35 /* free an asn1 structure */
36 void asn1_free(struct asn1_data *data)
37 {
38         talloc_free(data);
39 }
40
41 /* write to the ASN1 buffer, advancing the buffer pointer */
42 bool asn1_write(struct asn1_data *data, const void *p, int len)
43 {
44         if (data->has_error) return false;
45         if (data->length < data->ofs+len) {
46                 uint8_t *newp;
47                 newp = talloc_realloc(data, data->data, uint8_t, data->ofs+len);
48                 if (!newp) {
49                         asn1_free(data);
50                         data->has_error = true;
51                         return false;
52                 }
53                 data->data = newp;
54                 data->length = data->ofs+len;
55         }
56         memcpy(data->data + data->ofs, p, len);
57         data->ofs += len;
58         return true;
59 }
60
61 /* useful fn for writing a uint8_t */
62 bool asn1_write_uint8(struct asn1_data *data, uint8_t v)
63 {
64         return asn1_write(data, &v, 1);
65 }
66
67 /* push a tag onto the asn1 data buffer. Used for nested structures */
68 bool asn1_push_tag(struct asn1_data *data, uint8_t tag)
69 {
70         struct nesting *nesting;
71
72         asn1_write_uint8(data, tag);
73         nesting = talloc(data, struct nesting);
74         if (!nesting) {
75                 data->has_error = true;
76                 return false;
77         }
78
79         nesting->start = data->ofs;
80         nesting->next = data->nesting;
81         data->nesting = nesting;
82         return asn1_write_uint8(data, 0xff);
83 }
84
85 /* pop a tag */
86 bool asn1_pop_tag(struct asn1_data *data)
87 {
88         struct nesting *nesting;
89         size_t len;
90
91         nesting = data->nesting;
92
93         if (!nesting) {
94                 data->has_error = true;
95                 return false;
96         }
97         len = data->ofs - (nesting->start+1);
98         /* yes, this is ugly. We don't know in advance how many bytes the length
99            of a tag will take, so we assumed 1 byte. If we were wrong then we 
100            need to correct our mistake */
101         if (len > 0xFFFFFF) {
102                 data->data[nesting->start] = 0x84;
103                 if (!asn1_write_uint8(data, 0)) return false;
104                 if (!asn1_write_uint8(data, 0)) return false;
105                 if (!asn1_write_uint8(data, 0)) return false;
106                 if (!asn1_write_uint8(data, 0)) return false;
107                 memmove(data->data+nesting->start+5, data->data+nesting->start+1, len);
108                 data->data[nesting->start+1] = (len>>24) & 0xFF;
109                 data->data[nesting->start+2] = (len>>16) & 0xFF;
110                 data->data[nesting->start+3] = (len>>8) & 0xFF;
111                 data->data[nesting->start+4] = len&0xff;
112         } else if (len > 0xFFFF) {
113                 data->data[nesting->start] = 0x83;
114                 if (!asn1_write_uint8(data, 0)) return false;
115                 if (!asn1_write_uint8(data, 0)) return false;
116                 if (!asn1_write_uint8(data, 0)) return false;
117                 memmove(data->data+nesting->start+4, data->data+nesting->start+1, len);
118                 data->data[nesting->start+1] = (len>>16) & 0xFF;
119                 data->data[nesting->start+2] = (len>>8) & 0xFF;
120                 data->data[nesting->start+3] = len&0xff;
121         } else if (len > 255) {
122                 data->data[nesting->start] = 0x82;
123                 if (!asn1_write_uint8(data, 0)) return false;
124                 if (!asn1_write_uint8(data, 0)) return false;
125                 memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);
126                 data->data[nesting->start+1] = len>>8;
127                 data->data[nesting->start+2] = len&0xff;
128         } else if (len > 127) {
129                 data->data[nesting->start] = 0x81;
130                 if (!asn1_write_uint8(data, 0)) return false;
131                 memmove(data->data+nesting->start+2, data->data+nesting->start+1, len);
132                 data->data[nesting->start+1] = len;
133         } else {
134                 data->data[nesting->start] = len;
135         }
136
137         data->nesting = nesting->next;
138         talloc_free(nesting);
139         return true;
140 }
141
142 /* "i" is the one's complement representation, as is the normal result of an
143  * implicit signed->unsigned conversion */
144
145 static bool push_int_bigendian(struct asn1_data *data, unsigned int i, bool negative)
146 {
147         uint8_t lowest = i & 0xFF;
148
149         i = i >> 8;
150         if (i != 0)
151                 if (!push_int_bigendian(data, i, negative))
152                         return false;
153
154         if (data->nesting->start+1 == data->ofs) {
155
156                 /* We did not write anything yet, looking at the highest
157                  * valued byte */
158
159                 if (negative) {
160                         /* Don't write leading 0xff's */
161                         if (lowest == 0xFF)
162                                 return true;
163
164                         if ((lowest & 0x80) == 0) {
165                                 /* The only exception for a leading 0xff is if
166                                  * the highest bit is 0, which would indicate
167                                  * a positive value */
168                                 if (!asn1_write_uint8(data, 0xff))
169                                         return false;
170                         }
171                 } else {
172                         if (lowest & 0x80) {
173                                 /* The highest bit of a positive integer is 1,
174                                  * this would indicate a negative number. Push
175                                  * a 0 to indicate a positive one */
176                                 if (!asn1_write_uint8(data, 0))
177                                         return false;
178                         }
179                 }
180         }
181
182         return asn1_write_uint8(data, lowest);
183 }
184
185 /* write an Integer without the tag framing. Needed for example for the LDAP
186  * Abandon Operation */
187
188 bool asn1_write_implicit_Integer(struct asn1_data *data, int i)
189 {
190         if (i == -1) {
191                 /* -1 is special as it consists of all-0xff bytes. In
192                     push_int_bigendian this is the only case that is not
193                     properly handled, as all 0xff bytes would be handled as
194                     leading ones to be ignored. */
195                 return asn1_write_uint8(data, 0xff);
196         } else {
197                 return push_int_bigendian(data, i, i<0);
198         }
199 }
200
201
202 /* write an integer */
203 bool asn1_write_Integer(struct asn1_data *data, int i)
204 {
205         if (!asn1_push_tag(data, ASN1_INTEGER)) return false;
206         if (!asn1_write_implicit_Integer(data, i)) return false;
207         return asn1_pop_tag(data);
208 }
209
210 /* write a BIT STRING */
211 bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding)
212 {
213         if (!asn1_push_tag(data, ASN1_BIT_STRING)) return false;
214         if (!asn1_write_uint8(data, padding)) return false;
215         if (!asn1_write(data, p, length)) return false;
216         return asn1_pop_tag(data);
217 }
218
219 bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID)
220 {
221         unsigned int v, v2;
222         const char *p = (const char *)OID;
223         char *newp;
224         int i;
225
226         v = strtoul(p, &newp, 10);
227         if (newp[0] != '.') return false;
228         p = newp + 1;
229
230         v2 = strtoul(p, &newp, 10);
231         if (newp[0] != '.') return false;
232         p = newp + 1;
233
234         /*the ber representation can't use more space then the string one */
235         *blob = data_blob_talloc(mem_ctx, NULL, strlen(OID));
236         if (!blob->data) return false;
237
238         blob->data[0] = 40*v + v2;
239
240         i = 1;
241         while (*p) {
242                 v = strtoul(p, &newp, 10);
243                 if (newp[0] == '.') {
244                         p = newp + 1;
245                 } else if (newp[0] == '\0') {
246                         p = newp;
247                 } else {
248                         data_blob_free(blob);
249                         return false;
250                 }
251                 if (v >= (1<<28)) blob->data[i++] = (0x80 | ((v>>28)&0x7f));
252                 if (v >= (1<<21)) blob->data[i++] = (0x80 | ((v>>21)&0x7f));
253                 if (v >= (1<<14)) blob->data[i++] = (0x80 | ((v>>14)&0x7f));
254                 if (v >= (1<<7)) blob->data[i++] = (0x80 | ((v>>7)&0x7f));
255                 blob->data[i++] = (v&0x7f);
256         }
257
258         blob->length = i;
259
260         return true;
261 }
262
263 /* write an object ID to a ASN1 buffer */
264 bool asn1_write_OID(struct asn1_data *data, const char *OID)
265 {
266         DATA_BLOB blob;
267
268         if (!asn1_push_tag(data, ASN1_OID)) return false;
269
270         if (!ber_write_OID_String(NULL, &blob, OID)) {
271                 data->has_error = true;
272                 return false;
273         }
274
275         if (!asn1_write(data, blob.data, blob.length)) {
276                 data_blob_free(&blob);
277                 data->has_error = true;
278                 return false;
279         }
280         data_blob_free(&blob);
281         return asn1_pop_tag(data);
282 }
283
284 /* write an octet string */
285 bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length)
286 {
287         asn1_push_tag(data, ASN1_OCTET_STRING);
288         asn1_write(data, p, length);
289         asn1_pop_tag(data);
290         return !data->has_error;
291 }
292
293 /* write a LDAP string */
294 bool asn1_write_LDAPString(struct asn1_data *data, const char *s)
295 {
296         asn1_write(data, s, strlen(s));
297         return !data->has_error;
298 }
299
300 /* write a LDAP string from a DATA_BLOB */
301 bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s)
302 {
303         asn1_write(data, s->data, s->length);
304         return !data->has_error;
305 }
306
307 /* write a general string */
308 bool asn1_write_GeneralString(struct asn1_data *data, const char *s)
309 {
310         asn1_push_tag(data, ASN1_GENERAL_STRING);
311         asn1_write_LDAPString(data, s);
312         asn1_pop_tag(data);
313         return !data->has_error;
314 }
315
316 bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
317 {
318         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num));
319         asn1_write(data, blob->data, blob->length);
320         asn1_pop_tag(data);
321         return !data->has_error;
322 }
323
324 /* write a BOOLEAN */
325 bool asn1_write_BOOLEAN(struct asn1_data *data, bool v)
326 {
327         asn1_push_tag(data, ASN1_BOOLEAN);
328         asn1_write_uint8(data, v ? 0xFF : 0);
329         asn1_pop_tag(data);
330         return !data->has_error;
331 }
332
333 bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v)
334 {
335         uint8_t tmp = 0;
336         asn1_start_tag(data, ASN1_BOOLEAN);
337         asn1_read_uint8(data, &tmp);
338         if (tmp == 0xFF) {
339                 *v = true;
340         } else {
341                 *v = false;
342         }
343         asn1_end_tag(data);
344         return !data->has_error;
345 }
346
347 /* write a BOOLEAN in a simple context */
348 bool asn1_write_BOOLEAN_context(struct asn1_data *data, bool v, int context)
349 {
350         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(context));
351         asn1_write_uint8(data, v ? 0xFF : 0);
352         asn1_pop_tag(data);
353         return !data->has_error;
354 }
355
356 bool asn1_read_BOOLEAN_context(struct asn1_data *data, bool *v, int context)
357 {
358         uint8_t tmp = 0;
359         asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(context));
360         asn1_read_uint8(data, &tmp);
361         if (tmp == 0xFF) {
362                 *v = true;
363         } else {
364                 *v = false;
365         }
366         asn1_end_tag(data);
367         return !data->has_error;
368 }
369
370 /* check a BOOLEAN */
371 bool asn1_check_BOOLEAN(struct asn1_data *data, bool v)
372 {
373         uint8_t b = 0;
374
375         asn1_read_uint8(data, &b);
376         if (b != ASN1_BOOLEAN) {
377                 data->has_error = true;
378                 return false;
379         }
380         asn1_read_uint8(data, &b);
381         if (b != v) {
382                 data->has_error = true;
383                 return false;
384         }
385         return !data->has_error;
386 }
387
388
389 /* load a struct asn1_data structure with a lump of data, ready to be parsed */
390 bool asn1_load(struct asn1_data *data, DATA_BLOB blob)
391 {
392         ZERO_STRUCTP(data);
393         data->data = (uint8_t *)talloc_memdup(data, blob.data, blob.length);
394         if (!data->data) {
395                 data->has_error = true;
396                 return false;
397         }
398         data->length = blob.length;
399         return true;
400 }
401
402 /* Peek into an ASN1 buffer, not advancing the pointer */
403 bool asn1_peek(struct asn1_data *data, void *p, int len)
404 {
405         if (data->has_error)
406                 return false;
407
408         if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len)
409                 return false;
410
411         if (data->ofs + len > data->length) {
412                 /* we need to mark the buffer as consumed, so the caller knows
413                    this was an out of data error, and not a decode error */
414                 data->ofs = data->length;
415                 return false;
416         }
417
418         memcpy(p, data->data + data->ofs, len);
419         return true;
420 }
421
422 /* read from a ASN1 buffer, advancing the buffer pointer */
423 bool asn1_read(struct asn1_data *data, void *p, int len)
424 {
425         if (!asn1_peek(data, p, len)) {
426                 data->has_error = true;
427                 return false;
428         }
429
430         data->ofs += len;
431         return true;
432 }
433
434 /* read a uint8_t from a ASN1 buffer */
435 bool asn1_read_uint8(struct asn1_data *data, uint8_t *v)
436 {
437         return asn1_read(data, v, 1);
438 }
439
440 bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v)
441 {
442         return asn1_peek(data, v, 1);
443 }
444
445 bool asn1_peek_tag(struct asn1_data *data, uint8_t tag)
446 {
447         uint8_t b;
448
449         if (asn1_tag_remaining(data) <= 0) {
450                 return false;
451         }
452
453         if (!asn1_peek_uint8(data, &b))
454                 return false;
455
456         return (b == tag);
457 }
458
459 /* start reading a nested asn1 structure */
460 bool asn1_start_tag(struct asn1_data *data, uint8_t tag)
461 {
462         uint8_t b;
463         struct nesting *nesting;
464         
465         if (!asn1_read_uint8(data, &b))
466                 return false;
467
468         if (b != tag) {
469                 data->has_error = true;
470                 return false;
471         }
472         nesting = talloc(data, struct nesting);
473         if (!nesting) {
474                 data->has_error = true;
475                 return false;
476         }
477
478         if (!asn1_read_uint8(data, &b)) {
479                 return false;
480         }
481
482         if (b & 0x80) {
483                 int n = b & 0x7f;
484                 if (!asn1_read_uint8(data, &b))
485                         return false;
486                 nesting->taglen = b;
487                 while (n > 1) {
488                         if (!asn1_read_uint8(data, &b)) 
489                                 return false;
490                         nesting->taglen = (nesting->taglen << 8) | b;
491                         n--;
492                 }
493         } else {
494                 nesting->taglen = b;
495         }
496         nesting->start = data->ofs;
497         nesting->next = data->nesting;
498         data->nesting = nesting;
499         if (asn1_tag_remaining(data) == -1) {
500                 return false;
501         }
502         return !data->has_error;
503 }
504
505 /* stop reading a tag */
506 bool asn1_end_tag(struct asn1_data *data)
507 {
508         struct nesting *nesting;
509
510         /* make sure we read it all */
511         if (asn1_tag_remaining(data) != 0) {
512                 data->has_error = true;
513                 return false;
514         }
515
516         nesting = data->nesting;
517
518         if (!nesting) {
519                 data->has_error = true;
520                 return false;
521         }
522
523         data->nesting = nesting->next;
524         talloc_free(nesting);
525         return true;
526 }
527
528 /* work out how many bytes are left in this nested tag */
529 int asn1_tag_remaining(struct asn1_data *data)
530 {
531         int remaining;
532         if (data->has_error) {
533                 return -1;
534         }
535
536         if (!data->nesting) {
537                 data->has_error = true;
538                 return -1;
539         }
540         remaining = data->nesting->taglen - (data->ofs - data->nesting->start);
541         if (remaining > (data->length - data->ofs)) {
542                 data->has_error = true;
543                 return -1;
544         }
545         return remaining;
546 }
547
548 /**
549  * Internal implementation for reading binary OIDs
550  * Reading is done as far in the buffer as valid OID
551  * till buffer ends or not valid sub-identifier is found.
552  */
553 static bool _ber_read_OID_String_impl(TALLOC_CTX *mem_ctx, DATA_BLOB blob,
554                                         const char **OID, size_t *bytes_eaten)
555 {
556         int i;
557         uint8_t *b;
558         unsigned int v;
559         char *tmp_oid = NULL;
560
561         if (blob.length < 2) return false;
562
563         b = blob.data;
564
565         tmp_oid = talloc_asprintf(mem_ctx, "%u",  b[0]/40);
566         if (!tmp_oid) goto nomem;
567         tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u",  b[0]%40);
568         if (!tmp_oid) goto nomem;
569
570         for(i = 1, v = 0; i < blob.length; i++) {
571                 v = (v<<7) | (b[i]&0x7f);
572                 if ( ! (b[i] & 0x80)) {
573                         tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u",  v);
574                         v = 0;
575                         if (bytes_eaten)
576                                 *bytes_eaten = i+1;
577                 }
578                 if (!tmp_oid) goto nomem;
579         }
580
581         *OID = tmp_oid;
582         return true;
583
584 nomem:
585         return false;
586 }
587
588 /* read an object ID from a data blob */
589 bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID)
590 {
591         size_t bytes_eaten = 0;
592
593         if (!_ber_read_OID_String_impl(mem_ctx, blob, OID, &bytes_eaten))
594                 return false;
595
596         return (bytes_eaten == blob.length);
597 }
598
599 /* read an object ID from a ASN1 buffer */
600 bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, const char **OID)
601 {
602         DATA_BLOB blob;
603         int len;
604
605         if (!asn1_start_tag(data, ASN1_OID)) return false;
606
607         len = asn1_tag_remaining(data);
608         if (len < 0) {
609                 data->has_error = true;
610                 return false;
611         }
612
613         blob = data_blob(NULL, len);
614         if (!blob.data) {
615                 data->has_error = true;
616                 return false;
617         }
618
619         asn1_read(data, blob.data, len);
620         asn1_end_tag(data);
621         if (data->has_error) {
622                 data_blob_free(&blob);
623                 return false;
624         }
625
626         if (!ber_read_OID_String(mem_ctx, blob, OID)) {
627                 data->has_error = true;
628                 data_blob_free(&blob);
629                 return false;
630         }
631
632         data_blob_free(&blob);
633         return true;
634 }
635
636 /* check that the next object ID is correct */
637 bool asn1_check_OID(struct asn1_data *data, const char *OID)
638 {
639         const char *id;
640
641         if (!asn1_read_OID(data, data, &id)) return false;
642
643         if (strcmp(id, OID) != 0) {
644                 talloc_free(discard_const(id));
645                 data->has_error = true;
646                 return false;
647         }
648         talloc_free(discard_const(id));
649         return true;
650 }
651
652 /* read a LDAPString from a ASN1 buffer */
653 bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s)
654 {
655         int len;
656         len = asn1_tag_remaining(data);
657         if (len < 0) {
658                 data->has_error = true;
659                 return false;
660         }
661         *s = talloc_array(mem_ctx, char, len+1);
662         if (! *s) {
663                 data->has_error = true;
664                 return false;
665         }
666         asn1_read(data, *s, len);
667         (*s)[len] = 0;
668         return !data->has_error;
669 }
670
671
672 /* read a GeneralString from a ASN1 buffer */
673 bool asn1_read_GeneralString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s)
674 {
675         if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return false;
676         if (!asn1_read_LDAPString(data, mem_ctx, s)) return false;
677         return asn1_end_tag(data);
678 }
679
680
681 /* read a octet string blob */
682 bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
683 {
684         int len;
685         ZERO_STRUCTP(blob);
686         if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return false;
687         len = asn1_tag_remaining(data);
688         if (len < 0) {
689                 data->has_error = true;
690                 return false;
691         }
692         *blob = data_blob_talloc(mem_ctx, NULL, len+1);
693         if (!blob->data) {
694                 data->has_error = true;
695                 return false;
696         }
697         asn1_read(data, blob->data, len);
698         asn1_end_tag(data);
699         blob->length--;
700         blob->data[len] = 0;
701         
702         if (data->has_error) {
703                 data_blob_free(blob);
704                 *blob = data_blob_null;
705                 return false;
706         }
707         return true;
708 }
709
710 bool asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
711 {
712         int len;
713         ZERO_STRUCTP(blob);
714         if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false;
715         len = asn1_tag_remaining(data);
716         if (len < 0) {
717                 data->has_error = true;
718                 return false;
719         }
720         *blob = data_blob(NULL, len);
721         if ((len != 0) && (!blob->data)) {
722                 data->has_error = true;
723                 return false;
724         }
725         asn1_read(data, blob->data, len);
726         asn1_end_tag(data);
727         return !data->has_error;
728 }
729
730 /* read an integer without tag*/
731 bool asn1_read_implicit_Integer(struct asn1_data *data, int *i)
732 {
733         uint8_t b;
734         *i = 0;
735
736         while (!data->has_error && asn1_tag_remaining(data)>0) {
737                 if (!asn1_read_uint8(data, &b)) return false;
738                 *i = (*i << 8) + b;
739         }
740         return !data->has_error;        
741         
742 }
743
744 /* read an integer */
745 bool asn1_read_Integer(struct asn1_data *data, int *i)
746 {
747         *i = 0;
748
749         if (!asn1_start_tag(data, ASN1_INTEGER)) return false;
750         if (!asn1_read_implicit_Integer(data, i)) return false;
751         return asn1_end_tag(data);      
752 }
753
754 /* read a BIT STRING */
755 bool asn1_read_BitString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, uint8_t *padding)
756 {
757         int len;
758         ZERO_STRUCTP(blob);
759         if (!asn1_start_tag(data, ASN1_BIT_STRING)) return false;
760         len = asn1_tag_remaining(data);
761         if (len < 0) {
762                 data->has_error = true;
763                 return false;
764         }
765         if (!asn1_read_uint8(data, padding)) return false;
766
767         *blob = data_blob_talloc(mem_ctx, NULL, len);
768         if (!blob->data) {
769                 data->has_error = true;
770                 return false;
771         }
772         if (asn1_read(data, blob->data, len - 1)) {
773                 blob->length--;
774                 blob->data[len] = 0;
775                 asn1_end_tag(data);
776         }
777
778         if (data->has_error) {
779                 data_blob_free(blob);
780                 *blob = data_blob_null;
781                 *padding = 0;
782                 return false;
783         }
784         return true;
785 }
786
787 /* read an integer */
788 bool asn1_read_enumerated(struct asn1_data *data, int *v)
789 {
790         *v = 0;
791         
792         if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false;
793         while (!data->has_error && asn1_tag_remaining(data)>0) {
794                 uint8_t b;
795                 asn1_read_uint8(data, &b);
796                 *v = (*v << 8) + b;
797         }
798         return asn1_end_tag(data);      
799 }
800
801 /* check a enumerated value is correct */
802 bool asn1_check_enumerated(struct asn1_data *data, int v)
803 {
804         uint8_t b;
805         if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false;
806         asn1_read_uint8(data, &b);
807         asn1_end_tag(data);
808
809         if (v != b)
810                 data->has_error = false;
811
812         return !data->has_error;
813 }
814
815 /* write an enumerated value to the stream */
816 bool asn1_write_enumerated(struct asn1_data *data, uint8_t v)
817 {
818         if (!asn1_push_tag(data, ASN1_ENUMERATED)) return false;
819         asn1_write_uint8(data, v);
820         asn1_pop_tag(data);
821         return !data->has_error;
822 }
823
824 /*
825   Get us the data just written without copying
826 */
827 bool asn1_blob(const struct asn1_data *asn1, DATA_BLOB *blob)
828 {
829         if (asn1->has_error) {
830                 return false;
831         }
832         if (asn1->nesting != NULL) {
833                 return false;
834         }
835         blob->data = asn1->data;
836         blob->length = asn1->length;
837         return true;
838 }
839
840 /*
841   Fill in an asn1 struct without making a copy
842 */
843 void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len)
844 {
845         ZERO_STRUCTP(data);
846         data->data = buf;
847         data->length = len;
848 }
849