1 /* der-decoder.c - Distinguished Encoding Rules Encoder
2  * Copyright (C) 2001, 2004, 2008, 2012 g10 Code GmbH
3  *
4  * This file is part of KSBA.
5  *
6  * KSBA is free software; you can redistribute it and/or modify
7  * it under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * KSBA is distributed in the hope that it will be useful, but WITHOUT
22  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
24  * License for more details.
25  *
26  * You should have received a copies of the GNU General Public License
27  * and the GNU Lesser General Public License along with this program;
28  * if not, see <http://www.gnu.org/licenses/>.
29  */
30 
31 #include <config.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <assert.h>
36 #include "util.h"
37 
38 #include "ksba.h"
39 #include "asn1-func.h"
40 #include "ber-help.h"
41 #include "der-encoder.h"
42 #include "convert.h"
43 
44 struct der_encoder_s {
45   AsnNode module;    /* the ASN.1 structure */
46   ksba_writer_t writer;
47   const char *last_errdesc; /* string with the error description */
48   AsnNode root;   /* of the expanded parse tree */
49   int debug;
50 };
51 
52 /* To be useful for the DER encoder we store all data direct as the
53    binary image, so we use the VALTYPE_MEM */
54 static gpg_error_t
55 store_value (AsnNode node, const void *buffer, size_t length)
56 {
57   _ksba_asn_set_value (node, VALTYPE_MEM, buffer, length);
58   return 0;
59 }
60 
61 static void
62 clear_value (AsnNode node)
63 {
64   _ksba_asn_set_value (node, VALTYPE_NULL, NULL, 0);
65 }
66 
67 
68 
69 
70 DerEncoder
71 _ksba_der_encoder_new (void)
72 {
73   DerEncoder d;
74 
75   d = xtrycalloc (1, sizeof *d);
76   if (!d)
77     return NULL;
78 
79   return d;
80 }
81 
82 void
83 _ksba_der_encoder_release (DerEncoder d)
84 {
85   xfree (d);
86 }
87 
88 
89 /**
90  * _ksba_der_encoder_set_module:
91  * @d: Decoder object
92  * @module: ASN.1 Parse tree
93  *
94  * Initialize the decoder with the ASN.1 module.  Note, that this is a
95  * shallow copy of the module.  Fixme: What about ref-counting of
96  * AsnNodes?
97  *
98  * Return value: 0 on success or an error code
99  **/
100 gpg_error_t
101 _ksba_der_encoder_set_module (DerEncoder d, ksba_asn_tree_t module)
102 {
103   if (!d || !module)
104     return gpg_error (GPG_ERR_INV_VALUE);
105   if (d->module)
106     return gpg_error (GPG_ERR_CONFLICT); /* module already set */
107 
108   d->module = module->parse_tree;
109   return 0;
110 }
111 
112 
113 gpg_error_t
114 _ksba_der_encoder_set_writer (DerEncoder d, ksba_writer_t w)
115 {
116   if (!d || !w)
117     return gpg_error (GPG_ERR_INV_VALUE);
118   if (d->writer)
119     return gpg_error (GPG_ERR_CONFLICT); /* reader already set */
120 
121   d->writer = w;
122   return 0;
123 }
124 
125 
126 
127 /*
128   Helpers to construct and write out objects
129 */
130 
131 
132 /* Create and write a
133 
134   AlgorithmIdentifier ::= SEQUENCE {
135       algorithm    OBJECT IDENTIFIER,
136       parameters   ANY DEFINED BY algorithm OPTIONAL
137   }
138 
139   where parameters will be set to NULL if parm is NULL or to an octet
140   string with the given parm.  As a special hack parameter will not be
141   written if PARM is given but parmlen is 0.  */
142 gpg_error_t
143 _ksba_der_write_algorithm_identifier (ksba_writer_t w, const char *oid,
144                                       const void *parm, size_t parmlen)
145 {
146   gpg_error_t err;
147   unsigned char *buf;
148   size_t len;
149   int no_null = (parm && !parmlen);
150 
151   err = ksba_oid_from_str (oid, &buf, &len);
152   if (err)
153     return err;
154 
155   /* write the sequence */
156   /* fixme: the the length to encode the TLV values are actually not
157      just 2 byte each but depend on the length of the values - for
158      our purposes the static values do work.  */
159   err = _ksba_ber_write_tl (w, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1,
160                             (no_null? 2:4) + len + (parm? parmlen:0));
161   if (err)
162     goto leave;
163 
164   /* the OBJECT ID header and the value */
165   err = _ksba_ber_write_tl (w, TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, len);
166   if (!err)
167     err = ksba_writer_write (w, buf, len);
168   if (err)
169     goto leave;
170 
171   /* Write the parameter */
172   if (no_null)
173     ;
174   else if (parm)
175     {
176       err = _ksba_ber_write_tl (w, TYPE_OCTET_STRING, CLASS_UNIVERSAL,
177                                 0, parmlen);
178       if (!err)
179         err = ksba_writer_write (w, parm, parmlen);
180     }
181   else
182     {
183       err = _ksba_ber_write_tl (w, TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
184     }
185 
186  leave:
187   xfree (buf);
188   return err;
189 }
190 
191 
192 
193 
194 
195 /*************************************************
196  ***  Copy data from a tree image to the tree  ***
197  *************************************************/
198 
199 /* Copy all values from the tree SRC (with values store in SRCIMAGE)
200    to the tree DST */
201 gpg_error_t
202 _ksba_der_copy_tree (AsnNode dst_root,
203                      AsnNode src_root, const unsigned char *src_image)
204 {
205   AsnNode s, d;
206 
207   s = src_root;
208   d = dst_root;
209   /* note: we use the is_any flags becuase an inserted copy may have
210      already changed the any tag to the actual type */
211   while (s && d && (s->type == d->type || d->flags.is_any))
212     {
213       if (d->flags.is_any)
214         d->type = s->type;
215 
216       if (s->flags.in_array && s->right)
217         {
218           if (!_ksba_asn_insert_copy (d))
219             return gpg_error (GPG_ERR_ENOMEM);
220         }
221 
222       if ( !_ksba_asn_is_primitive (s->type) )
223         ;
224       else if (s->off == -1)
225         clear_value (d);
226       else
227         store_value (d, src_image + s->off + s->nhdr, s->len);
228 
229       s = _ksba_asn_walk_tree (src_root, s);
230       d = _ksba_asn_walk_tree (dst_root, d);
231     }
232 
233   if (s || d)
234     {
235 /*        fputs ("ksba_der_copy_tree: trees don't match\nSOURCE TREE:\n", stderr); */
236 /*        _ksba_asn_node_dump_all (src_root, stderr); */
237 /*        fputs ("DESTINATION TREE:\n", stderr); */
238 /*        _ksba_asn_node_dump_all (dst_root, stderr); */
239       return gpg_error (GPG_ERR_ENCODING_PROBLEM);
240     }
241   return 0;
242 }
243 
244 
245 
246 /*********************************************
247  ********** Store data in a tree *************
248  *********************************************/
249 
250 
251 gpg_error_t
252 _ksba_der_store_time (AsnNode node, const ksba_isotime_t atime)
253 {
254   char buf[50], *p;
255   int need_gen;
256   gpg_error_t err;
257 
258   /* First check that ATIME is indeed as formatted as expected. */
259   err = _ksba_assert_time_format (atime);
260   if (err)
261     return err;
262 
263   memcpy (buf, atime, 8);
264   memcpy (buf+8, atime+9, 6);
265   strcpy (buf+14, "Z");
266 
267   /* We need to use generalized time beginning with the year 2050. */
268   need_gen = (_ksba_cmp_time (atime, "20500101T000000") >= 0);
269 
270   if (node->type == TYPE_ANY)
271     node->type = need_gen? TYPE_GENERALIZED_TIME : TYPE_UTC_TIME;
272   else if (node->type == TYPE_CHOICE)
273     { /* find a suitable choice to store the value */
274       AsnNode n;
275 
276       for (n=node->down; n; n=n->right)
277         {
278           if ( (need_gen && n->type == TYPE_GENERALIZED_TIME)
279                || (!need_gen && n->type == TYPE_UTC_TIME))
280             {
281               node = n;
282               break;
283             }
284         }
285     }
286 
287   if (node->type == TYPE_GENERALIZED_TIME
288       || node->type == TYPE_UTC_TIME)
289     {
290       p = node->type == TYPE_UTC_TIME? (buf+2):buf;
291       return store_value (node, p, strlen (p));
292     }
293   else
294     return gpg_error (GPG_ERR_INV_VALUE);
295 }
296 
297 /* Store the utf-8 STRING in NODE. */
298 gpg_error_t
299 _ksba_der_store_string (AsnNode node, const char *string)
300 {
301   if (node->type == TYPE_CHOICE)
302     {
303       /* find a suitable choice to store the value */
304     }
305 
306 
307   if (node->type == TYPE_PRINTABLE_STRING)
308     {
309       return store_value (node, string, strlen (string));
310     }
311   else
312     return gpg_error (GPG_ERR_INV_VALUE);
313 }
314 
315 
316 /* Store the integer VALUE in NODE.  VALUE is assumed to be a DER
317    encoded integer prefixed with 4 bytes given its length in network
318    byte order. */
319 gpg_error_t
320 _ksba_der_store_integer (AsnNode node, const unsigned char *value)
321 {
322   if (node->type == TYPE_INTEGER)
323     {
324       size_t len;
325 
326       len = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
327       return store_value (node, value+4, len);
328     }
329   else
330     return gpg_error (GPG_ERR_INV_VALUE);
331 }
332 
333 gpg_error_t
334 _ksba_der_store_oid (AsnNode node, const char *oid)
335 {
336   gpg_error_t err;
337 
338   if (node->type == TYPE_ANY)
339     node->type = TYPE_OBJECT_ID;
340 
341   if (node->type == TYPE_OBJECT_ID)
342     {
343       unsigned char *buf;
344       size_t len;
345 
346       err = ksba_oid_from_str (oid, &buf, &len);
347       if (err)
348         return err;
349       err = store_value (node, buf, len);
350       xfree (buf);
351       return err;
352     }
353   else
354     return gpg_error (GPG_ERR_INV_VALUE);
355 }
356 
357 
358 gpg_error_t
359 _ksba_der_store_octet_string (AsnNode node, const char *buf, size_t len)
360 {
361   if (node->type == TYPE_ANY)
362     node->type = TYPE_OCTET_STRING;
363 
364   if (node->type == TYPE_OCTET_STRING)
365     {
366       return store_value (node, buf, len);
367     }
368   else
369     return gpg_error (GPG_ERR_INV_VALUE);
370 }
371 
372 
373 gpg_error_t
374 _ksba_der_store_sequence (AsnNode node, const unsigned char *buf, size_t len)
375 {
376   if (node->type == TYPE_ANY)
377     node->type = TYPE_PRE_SEQUENCE;
378 
379   if (node->type == TYPE_SEQUENCE || node->type == TYPE_PRE_SEQUENCE)
380     {
381       return store_value (node, buf, len);
382     }
383   else
384     return gpg_error (GPG_ERR_INV_VALUE);
385 }
386 
387 
388 gpg_error_t
389 _ksba_der_store_null (AsnNode node)
390 {
391   if (node->type == TYPE_ANY)
392     node->type = TYPE_NULL;
393 
394   if (node->type == TYPE_NULL)
395     {
396       clear_value (node);
397       return 0;
398     }
399   else
400     return gpg_error (GPG_ERR_INV_VALUE);
401 }
402 
403 
404 /*
405    Actual DER encoder
406 */
407 
408 /* We have a value for this node.  Calculate the length of the header
409    and store it in node->nhdr and store the length of the value in
410    node->value. We assume that this is a primitive node and has a
411    value of type VALTYPE_MEM. */
412 static void
413 set_nhdr_and_len (AsnNode node, unsigned long length)
414 {
415   int buflen = 0;
416 
417   if (node->type == TYPE_SET_OF || node->type == TYPE_SEQUENCE_OF)
418     buflen++;
419   else if (node->type == TYPE_TAG)
420     buflen++;
421   else if (node->type < 0x1f || node->type == TYPE_PRE_SEQUENCE)
422     buflen++;
423   else
424     {
425       never_reached ();
426       /* Fixme: tags with values above 31 are not yet implemented */
427     }
428 
429   if (!node->type /*&& !class*/)
430     buflen++; /* end tag */
431   else if (node->type == TYPE_NULL /*&& !class*/)
432     buflen++; /* NULL tag */
433   else if (!length)
434     buflen++; /* indefinite length */
435   else if (length < 128)
436     buflen++;
437   else
438     {
439       buflen += (length <= 0xff ? 2:
440                  length <= 0xffff ? 3:
441                  length <= 0xffffff ? 4: 5);
442     }
443 
444   node->len = length;
445   node->nhdr = buflen;
446 }
447 
448 /* Like above but put now put it into buffer.  return the number of
449    bytes copied.  There is no need to do length checking here */
450 static size_t
451 copy_nhdr_and_len (unsigned char *buffer, AsnNode node)
452 {
453   unsigned char *p = buffer;
454   int tag, class;
455   unsigned long length;
456 
457   tag = node->type;
458   class = CLASS_UNIVERSAL;
459   length = node->len;
460 
461   if (tag == TYPE_SET_OF)
462     tag = TYPE_SET;
463   else if (tag == TYPE_SEQUENCE_OF)
464     tag = TYPE_SEQUENCE;
465   else if (tag == TYPE_PRE_SEQUENCE)
466     tag = TYPE_SEQUENCE;
467   else if (tag == TYPE_TAG)
468     {
469       class = CLASS_CONTEXT;  /* Hmmm: we no way to handle other classes */
470       tag = node->value.v_ulong;
471     }
472   if (tag < 0x1f)
473     {
474       *p = (class << 6) | tag;
475       if (!_ksba_asn_is_primitive (tag))
476         *p |= 0x20;
477       p++;
478     }
479   else
480     {
481       /* fixme: Not_Implemented*/
482     }
483 
484   if (!tag && !class)
485     *p++ = 0; /* end tag */
486   else if (tag == TYPE_NULL && !class)
487     *p++ = 0; /* NULL tag */
488   else if (!length)
489     *p++ = 0x80; /* indefinite length - can't happen! */
490   else if (length < 128)
491     *p++ = length;
492   else
493     {
494       int i;
495 
496       /* fixme: if we know the sizeof an ulong we could support larger
497          objects - however this is pretty ridiculous */
498       i = (length <= 0xff ? 1:
499            length <= 0xffff ? 2:
500            length <= 0xffffff ? 3: 4);
501 
502       *p++ = (0x80 | i);
503       if (i > 3)
504         *p++ = length >> 24;
505       if (i > 2)
506         *p++ = length >> 16;
507       if (i > 1)
508         *p++ = length >> 8;
509       *p++ = length;
510     }
511 
512   return p - buffer;
513 }
514 
515 
516 
517 static unsigned long
518 sum_up_lengths (AsnNode root)
519 {
520   AsnNode n;
521   unsigned long len = 0;
522 
523   if (root->type == TYPE_NULL)
524     return root->nhdr;
525 
526   if (!(n=root->down) || _ksba_asn_is_primitive (root->type))
527     len = root->len;
528   else
529     {
530       for (; n; n = n->right)
531         len += sum_up_lengths (n);
532     }
533   if ( !_ksba_asn_is_primitive (root->type)
534        && root->type != TYPE_CHOICE
535        && len
536        && !root->flags.is_implicit)
537     { /* this is a constructed one */
538       set_nhdr_and_len (root, len);
539     }
540 
541   return len? (len + root->nhdr):0;
542 }
543 
544 /* Create a DER encoding from the value tree ROOT and return an
545    allocated image of appropriate length in r_image and r_imagelen.
546    The value tree is modified so that it can be used the same way as a
547    parsed one, i.e the elements off, and len are set to point into
548    image.  */
549 gpg_error_t
550 _ksba_der_encode_tree (AsnNode root,
551                        unsigned char **r_image, size_t *r_imagelen)
552 {
553   AsnNode n;
554   unsigned char *image;
555   size_t imagelen, len;
556 
557   /* clear out all fields */
558   for (n=root; n ; n = _ksba_asn_walk_tree (root, n))
559     {
560       n->off = -1;
561       n->len = 0;
562       n->nhdr = 0;
563     }
564 
565   /* Set default values */
566   /* FIXME */
567 
568   /* calculate the length of the headers.  These are the tag and
569      length fields of all primitive elements */
570   for (n=root; n ; n = _ksba_asn_walk_tree (root, n))
571     {
572       if (_ksba_asn_is_primitive (n->type)
573           && !n->flags.is_implicit
574           && ((n->valuetype == VALTYPE_MEM && n->value.v_mem.len)
575               || n->type == TYPE_NULL))
576         set_nhdr_and_len (n, n->value.v_mem.len);
577     }
578 
579   /* Now calculate the length of all constructed types */
580   imagelen = sum_up_lengths (root);
581 
582 #if 0
583   /* set off to zero, so that it can be dumped */
584   for (n=root; n ; n = _ksba_asn_walk_tree (root, n))
585       n->off = 0;
586   fputs ("DER encoded value Tree:\n", stderr);
587   _ksba_asn_node_dump_all (root, stderr);
588   for (n=root; n ; n = _ksba_asn_walk_tree (root, n))
589       n->off = -1;
590 #endif
591 
592   /* now we can create an encoding in image */
593   image = xtrymalloc (imagelen);
594   if (!image)
595     return gpg_error (GPG_ERR_ENOMEM);
596   len = 0;
597   for (n=root; n ; n = _ksba_asn_walk_tree (root, n))
598     {
599       size_t nbytes;
600 
601       if (!n->nhdr)
602         continue;
603       assert (n->off == -1);
604       assert (len < imagelen);
605       n->off = len;
606       nbytes = copy_nhdr_and_len (image+len, n);
607       len += nbytes;
608       if ( _ksba_asn_is_primitive (n->type)
609            && n->valuetype == VALTYPE_MEM
610            && n->value.v_mem.len )
611         {
612           nbytes = n->value.v_mem.len;
613           assert (len + nbytes <= imagelen);
614           memcpy (image+len, n->value.v_mem.buf, nbytes);
615           len += nbytes;
616         }
617     }
618 
619   assert (len == imagelen);
620 
621   *r_image = image;
622   if (r_imagelen)
623     *r_imagelen = imagelen;
624   return 0;
625 }
626