asn1: Add asn1_extract_blob()
[obnox/samba/samba-obnox.git] / lib / util / 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 "includes.h"
21 #include "../lib/util/asn1.h"
22
23 struct nesting {
24         off_t start;
25         size_t taglen; /* for parsing */
26         struct nesting *next;
27 };
28
29 /* allocate an asn1 structure */
30 struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx)
31 {
32         struct asn1_data *ret = talloc_zero(mem_ctx, struct asn1_data);
33         if (ret == NULL) {
34                 DEBUG(0,("asn1_init failed! out of memory\n"));
35         }
36         return ret;
37 }
38
39 /* free an asn1 structure */
40 void asn1_free(struct asn1_data *data)
41 {
42         talloc_free(data);
43 }
44
45 bool asn1_has_error(const struct asn1_data *data)
46 {
47         return data->has_error;
48 }
49
50 void asn1_set_error(struct asn1_data *data)
51 {
52         data->has_error = true;
53 }
54
55 /* write to the ASN1 buffer, advancing the buffer pointer */
56 bool asn1_write(struct asn1_data *data, const void *p, int len)
57 {
58         if (data->has_error) return false;
59
60         if ((len < 0) || (data->ofs + (size_t)len < data->ofs)) {
61                 data->has_error = true;
62                 return false;
63         }
64
65         if (data->length < data->ofs+len) {
66                 uint8_t *newp;
67                 newp = talloc_realloc(data, data->data, uint8_t, data->ofs+len);
68                 if (!newp) {
69                         data->has_error = true;
70                         return false;
71                 }
72                 data->data = newp;
73                 data->length = data->ofs+len;
74         }
75         memcpy(data->data + data->ofs, p, len);
76         data->ofs += len;
77         return true;
78 }
79
80 /* useful fn for writing a uint8_t */
81 bool asn1_write_uint8(struct asn1_data *data, uint8_t v)
82 {
83         return asn1_write(data, &v, 1);
84 }
85
86 /* push a tag onto the asn1 data buffer. Used for nested structures */
87 bool asn1_push_tag(struct asn1_data *data, uint8_t tag)
88 {
89         struct nesting *nesting;
90
91         if (!asn1_write_uint8(data, tag)) {
92                 return false;
93         }
94         nesting = talloc(data, struct nesting);
95         if (!nesting) {
96                 data->has_error = true;
97                 return false;
98         }
99
100         nesting->start = data->ofs;
101         nesting->next = data->nesting;
102         data->nesting = nesting;
103         return asn1_write_uint8(data, 0xff);
104 }
105
106 /* pop a tag */
107 bool asn1_pop_tag(struct asn1_data *data)
108 {
109         struct nesting *nesting;
110         size_t len;
111
112         if (data->has_error) {
113                 return false;
114         }
115
116         nesting = data->nesting;
117
118         if (!nesting) {
119                 data->has_error = true;
120                 return false;
121         }
122         len = data->ofs - (nesting->start+1);
123         /* yes, this is ugly. We don't know in advance how many bytes the length
124            of a tag will take, so we assumed 1 byte. If we were wrong then we 
125            need to correct our mistake */
126         if (len > 0xFFFFFF) {
127                 data->data[nesting->start] = 0x84;
128                 if (!asn1_write_uint8(data, 0)) return false;
129                 if (!asn1_write_uint8(data, 0)) return false;
130                 if (!asn1_write_uint8(data, 0)) return false;
131                 if (!asn1_write_uint8(data, 0)) return false;
132                 memmove(data->data+nesting->start+5, data->data+nesting->start+1, len);
133                 data->data[nesting->start+1] = (len>>24) & 0xFF;
134                 data->data[nesting->start+2] = (len>>16) & 0xFF;
135                 data->data[nesting->start+3] = (len>>8) & 0xFF;
136                 data->data[nesting->start+4] = len&0xff;
137         } else if (len > 0xFFFF) {
138                 data->data[nesting->start] = 0x83;
139                 if (!asn1_write_uint8(data, 0)) return false;
140                 if (!asn1_write_uint8(data, 0)) return false;
141                 if (!asn1_write_uint8(data, 0)) return false;
142                 memmove(data->data+nesting->start+4, data->data+nesting->start+1, len);
143                 data->data[nesting->start+1] = (len>>16) & 0xFF;
144                 data->data[nesting->start+2] = (len>>8) & 0xFF;
145                 data->data[nesting->start+3] = len&0xff;
146         } else if (len > 255) {
147                 data->data[nesting->start] = 0x82;
148                 if (!asn1_write_uint8(data, 0)) return false;
149                 if (!asn1_write_uint8(data, 0)) return false;
150                 memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);
151                 data->data[nesting->start+1] = len>>8;
152                 data->data[nesting->start+2] = len&0xff;
153         } else if (len > 127) {
154                 data->data[nesting->start] = 0x81;
155                 if (!asn1_write_uint8(data, 0)) return false;
156                 memmove(data->data+nesting->start+2, data->data+nesting->start+1, len);
157                 data->data[nesting->start+1] = len;
158         } else {
159                 data->data[nesting->start] = len;
160         }
161
162         data->nesting = nesting->next;
163         talloc_free(nesting);
164         return true;
165 }
166
167 /* "i" is the one's complement representation, as is the normal result of an
168  * implicit signed->unsigned conversion */
169
170 static bool push_int_bigendian(struct asn1_data *data, unsigned int i, bool negative)
171 {
172         uint8_t lowest = i & 0xFF;
173
174         i = i >> 8;
175         if (i != 0)
176                 if (!push_int_bigendian(data, i, negative))
177                         return false;
178
179         if (data->nesting->start+1 == data->ofs) {
180
181                 /* We did not write anything yet, looking at the highest
182                  * valued byte */
183
184                 if (negative) {
185                         /* Don't write leading 0xff's */
186                         if (lowest == 0xFF)
187                                 return true;
188
189                         if ((lowest & 0x80) == 0) {
190                                 /* The only exception for a leading 0xff is if
191                                  * the highest bit is 0, which would indicate
192                                  * a positive value */
193                                 if (!asn1_write_uint8(data, 0xff))
194                                         return false;
195                         }
196                 } else {
197                         if (lowest & 0x80) {
198                                 /* The highest bit of a positive integer is 1,
199                                  * this would indicate a negative number. Push
200                                  * a 0 to indicate a positive one */
201                                 if (!asn1_write_uint8(data, 0))
202                                         return false;
203                         }
204                 }
205         }
206
207         return asn1_write_uint8(data, lowest);
208 }
209
210 /* write an Integer without the tag framing. Needed for example for the LDAP
211  * Abandon Operation */
212
213 bool asn1_write_implicit_Integer(struct asn1_data *data, int i)
214 {
215         if (data->has_error) {
216                 return false;
217         }
218
219         if (i == -1) {
220                 /* -1 is special as it consists of all-0xff bytes. In
221                     push_int_bigendian this is the only case that is not
222                     properly handled, as all 0xff bytes would be handled as
223                     leading ones to be ignored. */
224                 return asn1_write_uint8(data, 0xff);
225         } else {
226                 return push_int_bigendian(data, i, i<0);
227         }
228 }
229
230
231 /* write an integer */
232 bool asn1_write_Integer(struct asn1_data *data, int i)
233 {
234         if (!asn1_push_tag(data, ASN1_INTEGER)) return false;
235         if (!asn1_write_implicit_Integer(data, i)) return false;
236         return asn1_pop_tag(data);
237 }
238
239 /* write a BIT STRING */
240 bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding)
241 {
242         if (!asn1_push_tag(data, ASN1_BIT_STRING)) return false;
243         if (!asn1_write_uint8(data, padding)) return false;
244         if (!asn1_write(data, p, length)) return false;
245         return asn1_pop_tag(data);
246 }
247
248 bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID)
249 {
250         unsigned int v, v2;
251         const char *p = (const char *)OID;
252         char *newp;
253         int i;
254
255         if (!isdigit(*p)) return false;
256         v = strtoul(p, &newp, 10);
257         if (newp[0] != '.') return false;
258         p = newp + 1;
259
260         if (!isdigit(*p)) return false;
261         v2 = strtoul(p, &newp, 10);
262         if (newp[0] != '.') return false;
263         p = newp + 1;
264
265         /*the ber representation can't use more space then the string one */
266         *blob = data_blob_talloc(mem_ctx, NULL, strlen(OID));
267         if (!blob->data) return false;
268
269         blob->data[0] = 40*v + v2;
270
271         i = 1;
272         while (*p) {
273                 if (!isdigit(*p)) return false;
274                 v = strtoul(p, &newp, 10);
275                 if (newp[0] == '.') {
276                         p = newp + 1;
277                         /* check for empty last component */
278                         if (!*p) return false;
279                 } else if (newp[0] == '\0') {
280                         p = newp;
281                 } else {
282                         data_blob_free(blob);
283                         return false;
284                 }
285                 if (v >= (1<<28)) blob->data[i++] = (0x80 | ((v>>28)&0x7f));
286                 if (v >= (1<<21)) blob->data[i++] = (0x80 | ((v>>21)&0x7f));
287                 if (v >= (1<<14)) blob->data[i++] = (0x80 | ((v>>14)&0x7f));
288                 if (v >= (1<<7)) blob->data[i++] = (0x80 | ((v>>7)&0x7f));
289                 blob->data[i++] = (v&0x7f);
290         }
291
292         blob->length = i;
293
294         return true;
295 }
296
297 /**
298  * Serialize partial OID string.
299  * Partial OIDs are in the form:
300  *   1:2.5.6:0x81
301  *   1:2.5.6:0x8182
302  */
303 bool ber_write_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *partial_oid)
304 {
305         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
306         char *oid = talloc_strdup(tmp_ctx, partial_oid);
307         char *p;
308
309         /* truncate partial part so ber_write_OID_String() works */
310         p = strchr(oid, ':');
311         if (p) {
312                 *p = '\0';
313                 p++;
314         }
315
316         if (!ber_write_OID_String(mem_ctx, blob, oid)) {
317                 talloc_free(tmp_ctx);
318                 return false;
319         }
320
321         /* Add partially encoded sub-identifier */
322         if (p) {
323                 DATA_BLOB tmp_blob = strhex_to_data_blob(tmp_ctx, p);
324                 if (!data_blob_append(mem_ctx, blob, tmp_blob.data,
325                                       tmp_blob.length)) {
326                         talloc_free(tmp_ctx);
327                         return false;
328                 }
329         }
330
331         talloc_free(tmp_ctx);
332
333         return true;
334 }
335
336 /* write an object ID to a ASN1 buffer */
337 bool asn1_write_OID(struct asn1_data *data, const char *OID)
338 {
339         DATA_BLOB blob;
340
341         if (!asn1_push_tag(data, ASN1_OID)) return false;
342
343         if (!ber_write_OID_String(NULL, &blob, OID)) {
344                 data->has_error = true;
345                 return false;
346         }
347
348         if (!asn1_write(data, blob.data, blob.length)) {
349                 data_blob_free(&blob);
350                 data->has_error = true;
351                 return false;
352         }
353         data_blob_free(&blob);
354         return asn1_pop_tag(data);
355 }
356
357 /* write an octet string */
358 bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length)
359 {
360         if (!asn1_push_tag(data, ASN1_OCTET_STRING)) return false;
361         if (!asn1_write(data, p, length)) return false;
362         return asn1_pop_tag(data);
363 }
364
365 /* write a LDAP string */
366 bool asn1_write_LDAPString(struct asn1_data *data, const char *s)
367 {
368         return asn1_write(data, s, strlen(s));
369 }
370
371 /* write a LDAP string from a DATA_BLOB */
372 bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s)
373 {
374         return asn1_write(data, s->data, s->length);
375 }
376
377 /* write a general string */
378 bool asn1_write_GeneralString(struct asn1_data *data, const char *s)
379 {
380         if (!asn1_push_tag(data, ASN1_GENERAL_STRING)) return false;
381         if (!asn1_write_LDAPString(data, s)) return false;
382         return asn1_pop_tag(data);
383 }
384
385 bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
386 {
387         if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false;
388         if (!asn1_write(data, blob->data, blob->length)) return false;
389         return asn1_pop_tag(data);
390 }
391
392 /* write a BOOLEAN */
393 bool asn1_write_BOOLEAN(struct asn1_data *data, bool v)
394 {
395         if (!asn1_push_tag(data, ASN1_BOOLEAN)) return false;
396         if (!asn1_write_uint8(data, v ? 0xFF : 0)) return false;
397         return asn1_pop_tag(data);
398 }
399
400 bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v)
401 {
402         uint8_t tmp = 0;
403         if (!asn1_start_tag(data, ASN1_BOOLEAN)) return false;
404         *v = false;
405         if (!asn1_read_uint8(data, &tmp)) return false;
406         if (tmp == 0xFF) {
407                 *v = true;
408         }
409         return asn1_end_tag(data);
410 }
411
412 /* write a BOOLEAN in a simple context */
413 bool asn1_write_BOOLEAN_context(struct asn1_data *data, bool v, int context)
414 {
415         if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(context))) return false;
416         if (!asn1_write_uint8(data, v ? 0xFF : 0)) return false;
417         return asn1_pop_tag(data);
418 }
419
420 bool asn1_read_BOOLEAN_context(struct asn1_data *data, bool *v, int context)
421 {
422         uint8_t tmp = 0;
423         if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(context))) return false;
424         *v = false;
425         if (!asn1_read_uint8(data, &tmp)) return false;
426         if (tmp == 0xFF) {
427                 *v = true;
428         }
429         return asn1_end_tag(data);
430 }
431
432 /* check a BOOLEAN */
433 bool asn1_check_BOOLEAN(struct asn1_data *data, bool v)
434 {
435         uint8_t b = 0;
436
437         if (!asn1_read_uint8(data, &b)) return false;
438         if (b != ASN1_BOOLEAN) {
439                 data->has_error = true;
440                 return false;
441         }
442         if (!asn1_read_uint8(data, &b)) return false;
443         if (b != v) {
444                 data->has_error = true;
445                 return false;
446         }
447         return !data->has_error;
448 }
449
450
451 /* load a struct asn1_data structure with a lump of data, ready to be parsed */
452 bool asn1_load(struct asn1_data *data, DATA_BLOB blob)
453 {
454         ZERO_STRUCTP(data);
455         data->data = (uint8_t *)talloc_memdup(data, blob.data, blob.length);
456         if (!data->data) {
457                 data->has_error = true;
458                 return false;
459         }
460         data->length = blob.length;
461         return true;
462 }
463
464 /* Peek into an ASN1 buffer, not advancing the pointer */
465 bool asn1_peek(struct asn1_data *data, void *p, int len)
466 {
467         if (data->has_error)
468                 return false;
469
470         if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len)
471                 return false;
472
473         if (data->ofs + len > data->length) {
474                 /* we need to mark the buffer as consumed, so the caller knows
475                    this was an out of data error, and not a decode error */
476                 data->ofs = data->length;
477                 return false;
478         }
479
480         memcpy(p, data->data + data->ofs, len);
481         return true;
482 }
483
484 /* read from a ASN1 buffer, advancing the buffer pointer */
485 bool asn1_read(struct asn1_data *data, void *p, int len)
486 {
487         if (!asn1_peek(data, p, len)) {
488                 data->has_error = true;
489                 return false;
490         }
491
492         data->ofs += len;
493         return true;
494 }
495
496 /* read a uint8_t from a ASN1 buffer */
497 bool asn1_read_uint8(struct asn1_data *data, uint8_t *v)
498 {
499         return asn1_read(data, v, 1);
500 }
501
502 bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v)
503 {
504         return asn1_peek(data, v, 1);
505 }
506
507 bool asn1_peek_tag(struct asn1_data *data, uint8_t tag)
508 {
509         uint8_t b;
510
511         if (asn1_tag_remaining(data) <= 0) {
512                 return false;
513         }
514
515         if (!asn1_peek_uint8(data, &b))
516                 return false;
517
518         return (b == tag);
519 }
520
521 /*
522  * just get the needed size the tag would consume
523  */
524 bool asn1_peek_tag_needed_size(struct asn1_data *data, uint8_t tag, size_t *size)
525 {
526         off_t start_ofs = data->ofs;
527         uint8_t b;
528         size_t taglen = 0;
529
530         if (data->has_error) {
531                 return false;
532         }
533
534         if (!asn1_read_uint8(data, &b)) {
535                 data->ofs = start_ofs;
536                 data->has_error = false;
537                 return false;
538         }
539
540         if (b != tag) {
541                 data->ofs = start_ofs;
542                 data->has_error = false;
543                 return false;
544         }
545
546         if (!asn1_read_uint8(data, &b)) {
547                 data->ofs = start_ofs;
548                 data->has_error = false;
549                 return false;
550         }
551
552         if (b & 0x80) {
553                 int n = b & 0x7f;
554                 if (!asn1_read_uint8(data, &b)) {
555                         data->ofs = start_ofs;
556                         data->has_error = false;
557                         return false;
558                 }
559                 if (n > 4) {
560                         /*
561                          * We should not allow more than 4 bytes
562                          * for the encoding of the tag length.
563                          *
564                          * Otherwise we'd overflow the taglen
565                          * variable on 32 bit systems.
566                          */
567                         data->ofs = start_ofs;
568                         data->has_error = false;
569                         return false;
570                 }
571                 taglen = b;
572                 while (n > 1) {
573                         if (!asn1_read_uint8(data, &b)) {
574                                 data->ofs = start_ofs;
575                                 data->has_error = false;
576                                 return false;
577                         }
578                         taglen = (taglen << 8) | b;
579                         n--;
580                 }
581         } else {
582                 taglen = b;
583         }
584
585         *size = (data->ofs - start_ofs) + taglen;
586
587         data->ofs = start_ofs;
588         data->has_error = false;
589         return true;
590 }
591
592 /* start reading a nested asn1 structure */
593 bool asn1_start_tag(struct asn1_data *data, uint8_t tag)
594 {
595         uint8_t b;
596         struct nesting *nesting;
597         
598         if (!asn1_read_uint8(data, &b))
599                 return false;
600
601         if (b != tag) {
602                 data->has_error = true;
603                 return false;
604         }
605         nesting = talloc(data, struct nesting);
606         if (!nesting) {
607                 data->has_error = true;
608                 return false;
609         }
610
611         if (!asn1_read_uint8(data, &b)) {
612                 return false;
613         }
614
615         if (b & 0x80) {
616                 int n = b & 0x7f;
617                 if (!asn1_read_uint8(data, &b))
618                         return false;
619                 nesting->taglen = b;
620                 while (n > 1) {
621                         if (!asn1_read_uint8(data, &b)) 
622                                 return false;
623                         nesting->taglen = (nesting->taglen << 8) | b;
624                         n--;
625                 }
626         } else {
627                 nesting->taglen = b;
628         }
629         nesting->start = data->ofs;
630         nesting->next = data->nesting;
631         data->nesting = nesting;
632         if (asn1_tag_remaining(data) == -1) {
633                 return false;
634         }
635         return !data->has_error;
636 }
637
638 /* stop reading a tag */
639 bool asn1_end_tag(struct asn1_data *data)
640 {
641         struct nesting *nesting;
642
643         /* make sure we read it all */
644         if (asn1_tag_remaining(data) != 0) {
645                 data->has_error = true;
646                 return false;
647         }
648
649         nesting = data->nesting;
650
651         if (!nesting) {
652                 data->has_error = true;
653                 return false;
654         }
655
656         data->nesting = nesting->next;
657         talloc_free(nesting);
658         return true;
659 }
660
661 /* work out how many bytes are left in this nested tag */
662 int asn1_tag_remaining(struct asn1_data *data)
663 {
664         int remaining;
665         if (data->has_error) {
666                 return -1;
667         }
668
669         if (!data->nesting) {
670                 data->has_error = true;
671                 return -1;
672         }
673         remaining = data->nesting->taglen - (data->ofs - data->nesting->start);
674         if (remaining > (data->length - data->ofs)) {
675                 data->has_error = true;
676                 return -1;
677         }
678         return remaining;
679 }
680
681 /**
682  * Internal implementation for reading binary OIDs
683  * Reading is done as far in the buffer as valid OID
684  * till buffer ends or not valid sub-identifier is found.
685  */
686 static bool _ber_read_OID_String_impl(TALLOC_CTX *mem_ctx, DATA_BLOB blob,
687                                       char **OID, size_t *bytes_eaten)
688 {
689         int i;
690         uint8_t *b;
691         unsigned int v;
692         char *tmp_oid = NULL;
693
694         if (blob.length < 2) return false;
695
696         b = blob.data;
697
698         tmp_oid = talloc_asprintf(mem_ctx, "%u",  b[0]/40);
699         if (!tmp_oid) goto nomem;
700         tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u",  b[0]%40);
701         if (!tmp_oid) goto nomem;
702
703         if (bytes_eaten != NULL) {
704                 *bytes_eaten = 0;
705         }
706
707         for(i = 1, v = 0; i < blob.length; i++) {
708                 v = (v<<7) | (b[i]&0x7f);
709                 if ( ! (b[i] & 0x80)) {
710                         tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u",  v);
711                         v = 0;
712                         if (bytes_eaten)
713                                 *bytes_eaten = i+1;
714                 }
715                 if (!tmp_oid) goto nomem;
716         }
717
718         *OID = tmp_oid;
719         return true;
720
721 nomem:
722         return false;
723 }
724
725 /* read an object ID from a data blob */
726 bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **OID)
727 {
728         size_t bytes_eaten;
729
730         if (!_ber_read_OID_String_impl(mem_ctx, blob, OID, &bytes_eaten))
731                 return false;
732
733         return (bytes_eaten == blob.length);
734 }
735
736 /**
737  * Deserialize partial OID string.
738  * Partial OIDs are in the form:
739  *   1:2.5.6:0x81
740  *   1:2.5.6:0x8182
741  */
742 bool ber_read_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob,
743                                  char **partial_oid)
744 {
745         size_t bytes_left;
746         size_t bytes_eaten;
747         char *identifier = NULL;
748         char *tmp_oid = NULL;
749
750         if (!_ber_read_OID_String_impl(mem_ctx, blob, &tmp_oid, &bytes_eaten))
751                 return false;
752
753         if (bytes_eaten < blob.length) {
754                 bytes_left = blob.length - bytes_eaten;
755                 identifier = hex_encode_talloc(mem_ctx, &blob.data[bytes_eaten], bytes_left);
756                 if (!identifier)        goto nomem;
757
758                 *partial_oid = talloc_asprintf_append_buffer(tmp_oid, ":0x%s", identifier);
759                 if (!*partial_oid)      goto nomem;
760                 TALLOC_FREE(identifier);
761         } else {
762                 *partial_oid = tmp_oid;
763         }
764
765         return true;
766
767 nomem:
768         TALLOC_FREE(identifier);
769         TALLOC_FREE(tmp_oid);
770         return false;
771 }
772
773 /* read an object ID from a ASN1 buffer */
774 bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **OID)
775 {
776         DATA_BLOB blob;
777         int len;
778
779         if (!asn1_start_tag(data, ASN1_OID)) return false;
780
781         len = asn1_tag_remaining(data);
782         if (len < 0) {
783                 data->has_error = true;
784                 return false;
785         }
786
787         blob = data_blob(NULL, len);
788         if (!blob.data) {
789                 data->has_error = true;
790                 return false;
791         }
792
793         if (!asn1_read(data, blob.data, len)) return false;
794         if (!asn1_end_tag(data)) {
795                 data_blob_free(&blob);
796                 return false;
797         }
798
799         if (!ber_read_OID_String(mem_ctx, blob, OID)) {
800                 data->has_error = true;
801                 data_blob_free(&blob);
802                 return false;
803         }
804
805         data_blob_free(&blob);
806         return true;
807 }
808
809 /* check that the next object ID is correct */
810 bool asn1_check_OID(struct asn1_data *data, const char *OID)
811 {
812         char *id;
813
814         if (!asn1_read_OID(data, data, &id)) return false;
815
816         if (strcmp(id, OID) != 0) {
817                 talloc_free(id);
818                 data->has_error = true;
819                 return false;
820         }
821         talloc_free(id);
822         return true;
823 }
824
825 /* read a LDAPString from a ASN1 buffer */
826 bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s)
827 {
828         int len;
829         len = asn1_tag_remaining(data);
830         if (len < 0) {
831                 data->has_error = true;
832                 return false;
833         }
834         *s = talloc_array(mem_ctx, char, len+1);
835         if (! *s) {
836                 data->has_error = true;
837                 return false;
838         }
839         (*s)[len] = 0;
840         return asn1_read(data, *s, len);
841 }
842
843
844 /* read a GeneralString from a ASN1 buffer */
845 bool asn1_read_GeneralString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s)
846 {
847         if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return false;
848         if (!asn1_read_LDAPString(data, mem_ctx, s)) return false;
849         return asn1_end_tag(data);
850 }
851
852
853 /* read a octet string blob */
854 bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
855 {
856         int len;
857         ZERO_STRUCTP(blob);
858         if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return false;
859         len = asn1_tag_remaining(data);
860         if (len < 0) {
861                 data->has_error = true;
862                 return false;
863         }
864         *blob = data_blob_talloc(mem_ctx, NULL, len+1);
865         if (!blob->data || blob->length < len) {
866                 data->has_error = true;
867                 return false;
868         }
869         if (!asn1_read(data, blob->data, len)) goto err;
870         if (!asn1_end_tag(data)) goto err;
871         blob->length--;
872         blob->data[len] = 0;
873         return true;
874
875   err:
876
877         data_blob_free(blob);
878         *blob = data_blob_null;
879         return false;
880 }
881
882 bool asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
883 {
884         int len;
885         ZERO_STRUCTP(blob);
886         if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false;
887         len = asn1_tag_remaining(data);
888         if (len < 0) {
889                 data->has_error = true;
890                 return false;
891         }
892         *blob = data_blob(NULL, len);
893         if ((len != 0) && (!blob->data)) {
894                 data->has_error = true;
895                 return false;
896         }
897         if (!asn1_read(data, blob->data, len)) return false;
898         return asn1_end_tag(data);
899 }
900
901 /* read an integer without tag*/
902 bool asn1_read_implicit_Integer(struct asn1_data *data, int *i)
903 {
904         uint8_t b;
905         bool first_byte = true;
906         *i = 0;
907
908         while (!data->has_error && asn1_tag_remaining(data)>0) {
909                 if (!asn1_read_uint8(data, &b)) return false;
910                 if (first_byte) {
911                         if (b & 0x80) {
912                                 /* Number is negative.
913                                    Set i to -1 for sign extend. */
914                                 *i = -1;
915                         }
916                         first_byte = false;
917                 }
918                 *i = (*i << 8) + b;
919         }
920         return !data->has_error;        
921         
922 }
923
924 /* read an integer */
925 bool asn1_read_Integer(struct asn1_data *data, int *i)
926 {
927         *i = 0;
928
929         if (!asn1_start_tag(data, ASN1_INTEGER)) return false;
930         if (!asn1_read_implicit_Integer(data, i)) return false;
931         return asn1_end_tag(data);      
932 }
933
934 /* read a BIT STRING */
935 bool asn1_read_BitString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, uint8_t *padding)
936 {
937         int len;
938         ZERO_STRUCTP(blob);
939         if (!asn1_start_tag(data, ASN1_BIT_STRING)) return false;
940         len = asn1_tag_remaining(data);
941         if (len < 0) {
942                 data->has_error = true;
943                 return false;
944         }
945         if (!asn1_read_uint8(data, padding)) return false;
946
947         *blob = data_blob_talloc(mem_ctx, NULL, len+1);
948         if (!blob->data || blob->length < len) {
949                 data->has_error = true;
950                 return false;
951         }
952         if (asn1_read(data, blob->data, len - 1)) {
953                 blob->length--;
954                 blob->data[len] = 0;
955                 asn1_end_tag(data);
956         }
957
958         if (data->has_error) {
959                 data_blob_free(blob);
960                 *blob = data_blob_null;
961                 *padding = 0;
962                 return false;
963         }
964         return true;
965 }
966
967 /* read an integer */
968 bool asn1_read_enumerated(struct asn1_data *data, int *v)
969 {
970         *v = 0;
971         
972         if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false;
973         while (!data->has_error && asn1_tag_remaining(data)>0) {
974                 uint8_t b;
975                 if (!asn1_read_uint8(data, &b)) {
976                         return false;
977                 }
978                 *v = (*v << 8) + b;
979         }
980         return asn1_end_tag(data);      
981 }
982
983 /* check a enumerated value is correct */
984 bool asn1_check_enumerated(struct asn1_data *data, int v)
985 {
986         uint8_t b;
987         if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false;
988         if (!asn1_read_uint8(data, &b)) return false;
989         if (!asn1_end_tag(data)) return false;
990
991         if (v != b)
992                 data->has_error = false;
993
994         return !data->has_error;
995 }
996
997 /* write an enumerated value to the stream */
998 bool asn1_write_enumerated(struct asn1_data *data, uint8_t v)
999 {
1000         if (!asn1_push_tag(data, ASN1_ENUMERATED)) return false;
1001         if (!asn1_write_uint8(data, v)) return false;
1002         return asn1_pop_tag(data);
1003 }
1004
1005 /*
1006   Get us the data just written without copying
1007 */
1008 bool asn1_blob(const struct asn1_data *asn1, DATA_BLOB *blob)
1009 {
1010         if (asn1->has_error) {
1011                 return false;
1012         }
1013         if (asn1->nesting != NULL) {
1014                 return false;
1015         }
1016         blob->data = asn1->data;
1017         blob->length = asn1->length;
1018         return true;
1019 }
1020
1021 bool asn1_extract_blob(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
1022                        DATA_BLOB *pblob)
1023 {
1024         DATA_BLOB blob;
1025
1026         if (!asn1_blob(asn1, &blob)) {
1027                 return false;
1028         }
1029
1030         *pblob = (DATA_BLOB) { .length = blob.length };
1031         pblob->data = talloc_move(mem_ctx, &blob.data);
1032
1033         /*
1034          * Stop access from here on
1035          */
1036         asn1->has_error = true;
1037
1038         return true;
1039 }
1040
1041 /*
1042   Fill in an asn1 struct without making a copy
1043 */
1044 void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len)
1045 {
1046         ZERO_STRUCTP(data);
1047         data->data = buf;
1048         data->length = len;
1049 }
1050
1051 int asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size)
1052 {
1053         struct asn1_data asn1;
1054         size_t size;
1055         bool ok;
1056
1057         ZERO_STRUCT(asn1);
1058         asn1.data = blob.data;
1059         asn1.length = blob.length;
1060
1061         ok = asn1_peek_tag_needed_size(&asn1, tag, &size);
1062         if (!ok) {
1063                 return EMSGSIZE;
1064         }
1065
1066         if (size > blob.length) {
1067                 *packet_size = size;
1068                 return EAGAIN;
1069         }               
1070
1071         *packet_size = size;
1072         return 0;
1073 }