"Fossies" - the Fresh Open Source Software Archive

Member "libksba-1.5.0/src/cms-parser.c" (18 Nov 2020, 29049 Bytes) of package /linux/privat/libksba-1.5.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "cms-parser.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.4.0_vs_1.5.0.

    1 /* cms-parse.c - parse cryptographic message syntax
    2  *      Copyright (C) 2001, 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 /*
   32    We handle CMS by using a handcrafted parser for the outer
   33    structures and the generic parser of the parts we can handle in
   34    memory.  Extending the generic parser to allow hooks for indefinite
   35    length objects and to auto select the object depending on the
   36    content type OID is too complicated.
   37 */
   38 
   39 
   40 #include <config.h>
   41 #include <stdio.h>
   42 #include <stdlib.h>
   43 #include <string.h>
   44 #include <assert.h>
   45 #include "util.h"
   46 
   47 #include "cms.h"
   48 #include "asn1-func.h" /* need some constants */
   49 #include "ber-decoder.h"
   50 #include "ber-help.h"
   51 #include "keyinfo.h"
   52 
   53 static int
   54 read_byte (ksba_reader_t reader)
   55 {
   56   unsigned char buf;
   57   size_t nread;
   58   int rc;
   59 
   60   do
   61     rc = ksba_reader_read (reader, &buf, 1, &nread);
   62   while (!rc && !nread);
   63   return rc? -1: buf;
   64 }
   65 
   66 /* read COUNT bytes into buffer.  Return 0 on success */
   67 static int
   68 read_buffer (ksba_reader_t reader, char *buffer, size_t count)
   69 {
   70   size_t nread;
   71 
   72   while (count)
   73     {
   74       if (ksba_reader_read (reader, buffer, count, &nread))
   75         return -1;
   76       buffer += nread;
   77       count -= nread;
   78     }
   79   return 0;
   80 }
   81 
   82 /* Create a new decoder and run it for the given element */
   83 static gpg_error_t
   84 create_and_run_decoder (ksba_reader_t reader, const char *elem_name,
   85                         unsigned int flags,
   86                         AsnNode *r_root,
   87                         unsigned char **r_image, size_t *r_imagelen)
   88 {
   89   gpg_error_t err;
   90   ksba_asn_tree_t cms_tree;
   91   BerDecoder decoder;
   92 
   93   err = ksba_asn_create_tree ("cms", &cms_tree);
   94   if (err)
   95     return err;
   96 
   97   decoder = _ksba_ber_decoder_new ();
   98   if (!decoder)
   99     {
  100       ksba_asn_tree_release (cms_tree);
  101       return gpg_error (GPG_ERR_ENOMEM);
  102     }
  103 
  104   err = _ksba_ber_decoder_set_reader (decoder, reader);
  105   if (err)
  106     {
  107       ksba_asn_tree_release (cms_tree);
  108       _ksba_ber_decoder_release (decoder);
  109       return err;
  110     }
  111 
  112   err = _ksba_ber_decoder_set_module (decoder, cms_tree);
  113   if (err)
  114     {
  115       ksba_asn_tree_release (cms_tree);
  116       _ksba_ber_decoder_release (decoder);
  117       return err;
  118     }
  119 
  120   err = _ksba_ber_decoder_decode (decoder, elem_name, flags,
  121                                   r_root, r_image, r_imagelen);
  122 
  123   _ksba_ber_decoder_release (decoder);
  124   ksba_asn_tree_release (cms_tree);
  125   return err;
  126 }
  127 
  128 
  129 
  130 /* Parse this structure and return the oid of the content.  The read
  131    position is then located at the value of content.  This fucntion is
  132    the core for parsing ContentInfo and EncapsulatedContentInfo.
  133 
  134    ContentInfo ::= SEQUENCE {
  135       contentType ContentType,
  136       content [0] EXPLICIT ANY DEFINED BY contentType
  137    }
  138    ContentType ::= OBJECT IDENTIFIER
  139 
  140    Returns: 0 on success or an error code. Other values are returned
  141    by the parameters.
  142 
  143 */
  144 static gpg_error_t
  145 parse_content_info (ksba_reader_t reader,
  146                     unsigned long *r_len, int *r_ndef,
  147                     char **r_oid, int *has_content)
  148 {
  149   struct tag_info ti;
  150   gpg_error_t err;
  151   int content_ndef;
  152   unsigned long content_len;
  153   unsigned char oidbuf[100]; /* pretty large for an OID */
  154   char *oid = NULL;
  155 
  156   /* read the sequence triplet */
  157   err = _ksba_ber_read_tl (reader, &ti);
  158   if (err)
  159     return err;
  160   if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
  161          && ti.is_constructed) )
  162     return gpg_error (GPG_ERR_INV_CMS_OBJ);
  163   content_len = ti.length;
  164   content_ndef = ti.ndef;
  165   if (!content_ndef && content_len < 3)
  166     return gpg_error (GPG_ERR_TOO_SHORT); /* to encode an OID */
  167 
  168   /* read the OID */
  169   err = _ksba_ber_read_tl (reader, &ti);
  170   if (err)
  171     return err;
  172   if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OBJECT_ID
  173          && !ti.is_constructed && ti.length) )
  174     return gpg_error (GPG_ERR_INV_CMS_OBJ);
  175   if (!content_ndef)
  176     {
  177       if (content_len < ti.nhdr)
  178         return gpg_error (GPG_ERR_BAD_BER); /* triplet header larger that sequence */
  179       content_len -= ti.nhdr;
  180       if (content_len < ti.length)
  181         return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */
  182       content_len -= ti.length;
  183     }
  184 
  185   if (ti.length >= DIM(oidbuf))
  186     return gpg_error (GPG_ERR_TOO_LARGE);
  187   err = read_buffer (reader, oidbuf, ti.length);
  188   if (err)
  189     return err;
  190   oid = ksba_oid_to_str (oidbuf, ti.length);
  191   if (!oid)
  192     return gpg_error (GPG_ERR_ENOMEM);
  193 
  194   if (!content_ndef && !content_len)
  195     { /* no data */
  196       *has_content = 0;
  197     }
  198   else
  199     { /* now read the explicit tag 0 which is optional */
  200       err = _ksba_ber_read_tl (reader, &ti);
  201       if (err)
  202         {
  203           xfree (oid);
  204           return err;
  205         }
  206 
  207       if ( ti.class == CLASS_CONTEXT && ti.tag == 0 && ti.is_constructed )
  208         {
  209           *has_content = 1;
  210         }
  211       else if ( ti.class == CLASS_UNIVERSAL && ti.tag == 0 && !ti.is_constructed )
  212         {
  213           *has_content = 0; /* this is optional - allow NUL tag */
  214         }
  215       else /* neither [0] nor NULL */
  216         {
  217           xfree (oid);
  218           return gpg_error (GPG_ERR_INV_CMS_OBJ);
  219         }
  220       if (!content_ndef)
  221         {
  222           if (content_len < ti.nhdr)
  223             return gpg_error (GPG_ERR_BAD_BER); /* triplet header larger that sequence */
  224           content_len -= ti.nhdr;
  225           if (!ti.ndef && content_len < ti.length)
  226             return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */
  227         }
  228     }
  229   *r_len = content_len;
  230   *r_ndef = content_ndef;
  231   *r_oid = oid;
  232   return 0;
  233 }
  234 
  235 
  236 /* Parse this structure and return the oid of the content as well as
  237    the algorithm identifier.  The read position is then located at the
  238    value of the octect string.
  239 
  240    EncryptedContentInfo ::= SEQUENCE {
  241      contentType OBJECT IDENTIFIER,
  242      contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
  243      encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL }
  244 
  245    Returns: 0 on success or an error code. Other values are returned
  246    by the parameters.
  247 */
  248 static gpg_error_t
  249 parse_encrypted_content_info (ksba_reader_t reader,
  250                               unsigned long *r_len, int *r_ndef,
  251                               char **r_cont_oid, char **r_algo_oid,
  252                               char **r_algo_parm, size_t *r_algo_parmlen,
  253                               int *has_content)
  254 {
  255   struct tag_info ti;
  256   gpg_error_t err;
  257   int content_ndef;
  258   unsigned long content_len;
  259   unsigned char tmpbuf[500]; /* for OID or algorithmIdentifier */
  260   char *cont_oid = NULL;
  261   char *algo_oid = NULL;
  262   char *algo_parm = NULL;
  263   size_t algo_parmlen;
  264   size_t nread;
  265 
  266   /* Fixme: release oids in case of errors */
  267 
  268   /* read the sequence triplet */
  269   err = _ksba_ber_read_tl (reader, &ti);
  270   if (err)
  271     return err;
  272   if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
  273          && ti.is_constructed) )
  274     return gpg_error (GPG_ERR_INV_CMS_OBJ);
  275   content_len = ti.length;
  276   content_ndef = ti.ndef;
  277   if (!content_ndef && content_len < 3)
  278     return gpg_error (GPG_ERR_TOO_SHORT); /* to encode an OID */
  279 
  280   /* read the OID */
  281   err = _ksba_ber_read_tl (reader, &ti);
  282   if (err)
  283     return err;
  284   if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OBJECT_ID
  285          && !ti.is_constructed && ti.length) )
  286     return gpg_error (GPG_ERR_INV_CMS_OBJ);
  287   if (!content_ndef)
  288     {
  289       if (content_len < ti.nhdr)
  290         return gpg_error (GPG_ERR_BAD_BER); /* triplet header larger that sequence */
  291       content_len -= ti.nhdr;
  292       if (content_len < ti.length)
  293         return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */
  294       content_len -= ti.length;
  295     }
  296   if (ti.length >= DIM(tmpbuf))
  297     return gpg_error (GPG_ERR_TOO_LARGE);
  298   err = read_buffer (reader, tmpbuf, ti.length);
  299   if (err)
  300     return err;
  301   cont_oid = ksba_oid_to_str (tmpbuf, ti.length);
  302   if (!cont_oid)
  303     return gpg_error (GPG_ERR_ENOMEM);
  304 
  305   /* read the algorithmIdentifier */
  306   err = _ksba_ber_read_tl (reader, &ti);
  307   if (err)
  308     return err;
  309   if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
  310          && ti.is_constructed) )
  311     return gpg_error (GPG_ERR_INV_CMS_OBJ);
  312   if (!content_ndef)
  313     {
  314       if (content_len < ti.nhdr)
  315         return gpg_error (GPG_ERR_BAD_BER); /* triplet header larger that sequence */
  316       content_len -= ti.nhdr;
  317       if (content_len < ti.length)
  318         return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */
  319       content_len -= ti.length;
  320     }
  321   if (ti.nhdr + ti.length >= DIM(tmpbuf))
  322     return gpg_error (GPG_ERR_TOO_LARGE);
  323   memcpy (tmpbuf, ti.buf, ti.nhdr);
  324   err = read_buffer (reader, tmpbuf+ti.nhdr, ti.length);
  325   if (err)
  326     return err;
  327   err = _ksba_parse_algorithm_identifier2 (tmpbuf, ti.nhdr+ti.length,
  328                                            &nread,&algo_oid,
  329                                            &algo_parm, &algo_parmlen);
  330   if (err)
  331     return err;
  332   assert (nread <= ti.nhdr + ti.length);
  333   if (nread < ti.nhdr + ti.length)
  334     return gpg_error (GPG_ERR_TOO_SHORT);
  335 
  336   /* the optional encryptedDataInfo */
  337   *has_content = 0;
  338   if (content_ndef || content_len)
  339     { /* now read the implicit tag 0.  Actually this is optional but
  340          in that case we don't expect to have a content_len - well, it
  341          may be the end tag */
  342       err = _ksba_ber_read_tl (reader, &ti);
  343       if (err)
  344         {
  345           xfree (cont_oid);
  346           xfree (algo_oid);
  347           return err;
  348         }
  349 
  350       /* Note: the tag may either denote a constructed or a primitve
  351          object.  Actually this should match the use of NDEF header
  352          but we don't ceck that */
  353       if ( ti.class == CLASS_CONTEXT && ti.tag == 0 )
  354         {
  355           *has_content = 1;
  356           if (!content_ndef)
  357             {
  358               if (content_len < ti.nhdr)
  359                 return gpg_error (GPG_ERR_BAD_BER);
  360               content_len -= ti.nhdr;
  361               if (!ti.ndef && content_len < ti.length)
  362                 return gpg_error (GPG_ERR_BAD_BER);
  363             }
  364         }
  365       else /* not what we want - push it back */
  366         {
  367           *has_content = 0;
  368           err = ksba_reader_unread (reader, ti.buf, ti.nhdr);
  369           if (err)
  370             return err;
  371         }
  372     }
  373   *r_len = content_len;
  374   *r_ndef = content_ndef;
  375   *r_cont_oid = cont_oid;
  376   *r_algo_oid = algo_oid;
  377   *r_algo_parm = algo_parm;
  378   *r_algo_parmlen = algo_parmlen;
  379   return 0;
  380 }
  381 
  382 
  383 
  384 /* Parse this structure and return the oid of the content.  The read
  385    position is then located at the value of content.
  386 
  387    ContentInfo ::= SEQUENCE {
  388       contentType ContentType,
  389       content [0] EXPLICIT ANY DEFINED BY contentType
  390    }
  391    ContentType ::= OBJECT IDENTIFIER
  392 
  393    Returns: 0 on success or an error code.  On success the OID and the
  394    length values are stored in the cms structure.
  395 */
  396 gpg_error_t
  397 _ksba_cms_parse_content_info (ksba_cms_t cms)
  398 {
  399   gpg_error_t err;
  400   int has_content;
  401   int content_ndef;
  402   unsigned long content_len;
  403   char *oid;
  404 
  405   err = parse_content_info (cms->reader, &content_len, &content_ndef,
  406                             &oid, &has_content);
  407   if (err)
  408     { /* return a more meaningful error message.  This way the caller
  409          can pass arbitrary data to the function and get back an error
  410          that this is not CMS instead of the the not very detailed BER
  411          Error. */
  412       if (gpg_err_code (err) == GPG_ERR_BAD_BER
  413           || gpg_err_code (err) == GPG_ERR_INV_CMS_OBJ
  414           || gpg_err_code (err) == GPG_ERR_TOO_SHORT)
  415         err = gpg_error (GPG_ERR_NO_CMS_OBJ);
  416       return err;
  417     }
  418   if (!has_content)
  419     return gpg_error (GPG_ERR_NO_CMS_OBJ); /* It is not optional here */
  420   cms->content.length = content_len;
  421   cms->content.ndef = content_ndef;
  422   xfree (cms->content.oid);
  423   cms->content.oid = oid;
  424   return 0;
  425 }
  426 
  427 
  428 
  429 /* parse a SEQUENCE and the first element which is expected to be the
  430    CMS version.  Return the version and the length info */
  431 static gpg_error_t
  432 parse_cms_version (ksba_reader_t reader, int *r_version,
  433                    unsigned long *r_len, int *r_ndef)
  434 {
  435   struct tag_info ti;
  436   gpg_error_t err;
  437   unsigned long data_len;
  438   int data_ndef;
  439   int c;
  440 
  441   /* read the sequence triplet */
  442   err = _ksba_ber_read_tl (reader, &ti);
  443   if (err)
  444     return err;
  445   if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
  446          && ti.is_constructed) )
  447     return gpg_error (GPG_ERR_INV_CMS_OBJ);
  448   data_len = ti.length;
  449   data_ndef = ti.ndef;
  450   if (!data_ndef && data_len < 3)
  451     return gpg_error (GPG_ERR_TOO_SHORT); /*to encode the version*/
  452 
  453   /* read the version integer */
  454   err = _ksba_ber_read_tl (reader, &ti);
  455   if (err)
  456     return err;
  457   if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_INTEGER
  458          && !ti.is_constructed && ti.length) )
  459     return gpg_error (GPG_ERR_INV_CMS_OBJ);
  460   if (!data_ndef)
  461     {
  462       if (data_len < ti.nhdr)
  463         return gpg_error (GPG_ERR_BAD_BER); /* triplet header larger that sequence */
  464       data_len -= ti.nhdr;
  465       if (data_len < ti.length)
  466         return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */
  467       data_len -= ti.length;
  468     }
  469   if (ti.length != 1)
  470     return gpg_error (GPG_ERR_UNSUPPORTED_CMS_VERSION);
  471   if ( (c=read_byte (reader)) == -1)
  472     {
  473       err = ksba_reader_error (reader);
  474       return err? err : gpg_error (GPG_ERR_GENERAL);
  475     }
  476   if ( !(c == 0 || c == 1 || c == 2 || c == 3 || c == 4) )
  477     return gpg_error (GPG_ERR_UNSUPPORTED_CMS_VERSION);
  478   *r_version = c;
  479   *r_len = data_len;
  480   *r_ndef = data_ndef;
  481   return 0;
  482 }
  483 
  484 
  485 
  486 
  487 /* Parse a structure:
  488 
  489    SignedData ::= SEQUENCE {
  490      version INTEGER  { v0(0), v1(1), v2(2), v3(3), v4(4) }),
  491      digestAlgorithms SET OF AlgorithmIdentifier,
  492      encapContentInfo EncapsulatedContentInfo,
  493      certificates [0] IMPLICIT CertificateSet OPTIONAL,
  494      crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
  495      signerInfos SignerInfos }
  496 
  497    AlgorithmIdentifier ::= SEQUENCE {
  498     algorithm    OBJECT IDENTIFIER,
  499     parameters   ANY DEFINED BY algorithm OPTIONAL
  500    }
  501 
  502 */
  503 gpg_error_t
  504 _ksba_cms_parse_signed_data_part_1 (ksba_cms_t cms)
  505 {
  506   struct tag_info ti;
  507   gpg_error_t err;
  508   int signed_data_ndef;
  509   unsigned long signed_data_len;
  510   int algo_set_ndef;
  511   unsigned long algo_set_len;
  512   int encap_cont_ndef;
  513   unsigned long encap_cont_len;
  514   int has_content;
  515   char *oid;
  516   char *p, *buffer;
  517   unsigned long off, len;
  518 
  519   err = parse_cms_version (cms->reader, &cms->cms_version,
  520                            &signed_data_len, &signed_data_ndef);
  521   if (err)
  522     return err;
  523 
  524   /* read the SET OF algorithmIdentifiers */
  525   err = _ksba_ber_read_tl (cms->reader, &ti);
  526   if (err)
  527     return err;
  528   if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SET
  529          && ti.is_constructed) )
  530     return gpg_error (GPG_ERR_INV_CMS_OBJ);  /* not the expected SET tag */
  531   if (!signed_data_ndef)
  532     {
  533       if (signed_data_len < ti.nhdr)
  534         return gpg_error (GPG_ERR_BAD_BER); /* triplet header larger that sequence */
  535       signed_data_len -= ti.nhdr;
  536       if (!ti.ndef && signed_data_len < ti.length)
  537         return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */
  538       signed_data_len -= ti.length;
  539     }
  540   algo_set_len = ti.length;
  541   algo_set_ndef = ti.ndef;
  542 
  543   /* fixme: we are not able to read ndef length algorithm indentifiers. */
  544   if (algo_set_ndef)
  545     return gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
  546   /* read the entire sequence into a buffer (add one to avoid malloc(0)) */
  547   buffer = xtrymalloc (algo_set_len + 1);
  548   if (!buffer)
  549     return gpg_error (GPG_ERR_ENOMEM);
  550   if (read_buffer (cms->reader, buffer, algo_set_len))
  551     {
  552       xfree (buffer);
  553       err = ksba_reader_error (cms->reader);
  554       return err? err: gpg_error (GPG_ERR_GENERAL);
  555     }
  556   p = buffer;
  557   while (algo_set_len)
  558     {
  559       size_t nread;
  560       struct oidlist_s *ol;
  561 
  562       err = _ksba_parse_algorithm_identifier (p, algo_set_len, &nread, &oid);
  563       if (err)
  564         {
  565           xfree (buffer);
  566           return err;
  567         }
  568       assert (nread <= algo_set_len);
  569       algo_set_len -= nread;
  570       p += nread;
  571       /* store the oid */
  572       ol = xtrymalloc (sizeof *ol);
  573       if (!ol)
  574         {
  575           xfree (oid);
  576           return gpg_error (GPG_ERR_ENOMEM);
  577         }
  578       ol->oid = oid;
  579       ol->next = cms->digest_algos;
  580       cms->digest_algos = ol;
  581     }
  582   xfree (buffer); buffer = NULL;
  583 
  584   /* Now for the encapsulatedContentInfo */
  585   off = ksba_reader_tell (cms->reader);
  586   err = parse_content_info (cms->reader,
  587                             &encap_cont_len, &encap_cont_ndef,
  588                             &oid, &has_content);
  589   if (err)
  590     return err;
  591   cms->inner_cont_len = encap_cont_len;
  592   cms->inner_cont_ndef = encap_cont_ndef;
  593   cms->inner_cont_oid = oid;
  594   cms->detached_data = !has_content;
  595   if (!signed_data_ndef)
  596     {
  597       len = ksba_reader_tell (cms->reader) - off;
  598       if (signed_data_len < len)
  599         return gpg_error (GPG_ERR_BAD_BER); /* parsed content info larger that sequence */
  600       signed_data_len -= len;
  601       if (!encap_cont_ndef && signed_data_len < encap_cont_len)
  602         return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */
  603     }
  604 
  605   /* We have to stop here so that the caller can set up the hashing etc. */
  606   return 0;
  607 }
  608 
  609 /* Continue parsing of the structure we started to parse with the
  610    part_1 function.  We expect to be right at the certificates tag.  */
  611 gpg_error_t
  612 _ksba_cms_parse_signed_data_part_2 (ksba_cms_t cms)
  613 {
  614   struct tag_info ti;
  615   gpg_error_t err;
  616   struct signer_info_s *si, **si_tail;
  617 
  618   /* read the next triplet which is either a [0], a [1] or a SET OF
  619      (signerInfo) */
  620   err = _ksba_ber_read_tl (cms->reader, &ti);
  621   if (err)
  622     return err;
  623   if (ti.class == CLASS_UNIVERSAL && !ti.tag && !ti.is_constructed)
  624     {
  625       /* well, there might be still an end tag pending; eat it -
  626          fixme: we should keep track of this to catch invalid
  627          encodings */
  628       err = _ksba_ber_read_tl (cms->reader, &ti);
  629       if (err)
  630         return err;
  631     }
  632 
  633   if (ti.class == CLASS_CONTEXT && ti.tag == 0 && ti.is_constructed)
  634     {  /* Implicit SET OF certificateSet with elements of CHOICE, but
  635           we assume the first choice which is a Certificate; all other
  636           choices are obsolete.  We are now parsing a set of
  637           certificates which we do by utilizing the ksba_cert code. */
  638       ksba_cert_t cert;
  639       int expect_endtag;
  640 
  641       expect_endtag = !!ti.ndef;
  642 
  643       for (;;)
  644         {
  645           struct certlist_s *cl;
  646 
  647           /* First see whether this is really a sequence */
  648           err = _ksba_ber_read_tl (cms->reader, &ti);
  649           if (err)
  650             return err;
  651           if (expect_endtag && !ti.class && !ti.tag)
  652             {
  653               /* This is an end tag.  Read the next tag but don't fail
  654                  if this is just an EOF.  */
  655               err = _ksba_ber_read_tl (cms->reader, &ti);
  656               if (err)
  657                 {
  658                   if (gpg_err_code (err) == GPG_ERR_EOF)
  659                     err = 0;
  660                   return err;
  661                 }
  662               break;
  663             }
  664           if (!(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
  665                 && ti.is_constructed))
  666             break; /* not a sequence, so we are ready with the set */
  667 
  668           /* We must unread so that the standard parser sees the sequence */
  669           err = ksba_reader_unread (cms->reader, ti.buf, ti.nhdr);
  670           if (err)
  671             return err;
  672           /* Use the standard certificate parser */
  673           err = ksba_cert_new (&cert);
  674           if (err)
  675             return err;
  676           err = ksba_cert_read_der (cert, cms->reader);
  677           if (err)
  678             {
  679               ksba_cert_release (cert);
  680               return err;
  681             }
  682           cl = xtrycalloc (1, sizeof *cl);
  683           if (!cl)
  684             {
  685               ksba_cert_release (cert);
  686               return gpg_error (GPG_ERR_ENOMEM);
  687             }
  688           cl->cert = cert;
  689           cl->next = cms->cert_list;
  690           cms->cert_list = cl;
  691         }
  692     }
  693 
  694   if (ti.class == CLASS_CONTEXT && ti.tag == 1 && ti.is_constructed)
  695     {  /* implicit SET OF certificateList.  We should delegate the
  696           parsing to a - not yet existing - ksba_crl module.  CRLs are
  697           quite important for other applications too so we should
  698           provide a nice interface */
  699       int expect_endtag;
  700 
  701 
  702       expect_endtag = !!ti.ndef;
  703 
  704       /* FIXME this is just dummy read code */
  705        /* fprintf (stderr,"WARNING: Can't handle CRLs yet\n"); */
  706       for (;;)
  707         {
  708           /* first see whether this is really a sequence */
  709           err = _ksba_ber_read_tl (cms->reader, &ti);
  710           if (err)
  711             return err;
  712           if (expect_endtag && !ti.class && !ti.tag)
  713             {
  714               /* This is an end tag.  Read the next tag but don't fail
  715                  if this is just an EOF.  */
  716               err = _ksba_ber_read_tl (cms->reader, &ti);
  717               if (err)
  718                 {
  719                   if (gpg_err_code (err) == GPG_ERR_EOF)
  720                     err = 0;
  721                   return err;
  722                 }
  723               break;
  724             }
  725           if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
  726                  && ti.is_constructed))
  727             break; /* not a sequence, so we are ready with the set */
  728 
  729           while (ti.length)
  730             {
  731               size_t n, nread;
  732               char dummy[256];
  733 
  734               n = ti.length > DIM(dummy) ? DIM(dummy): ti.length;
  735               err = ksba_reader_read (cms->reader, dummy, n, &nread);
  736               if (err)
  737                 return err;
  738               ti.length -= nread;
  739             }
  740         }
  741     }
  742 
  743   /* expect a SET OF signerInfo */
  744   if ( !(ti.class == CLASS_UNIVERSAL
  745          && ti.tag == TYPE_SET && ti.is_constructed))
  746     return gpg_error (GPG_ERR_INV_CMS_OBJ);
  747 
  748   si_tail = &cms->signer_info;
  749 
  750   while (ti.length)
  751     {
  752       size_t off1, off2;
  753 
  754       off1 = ksba_reader_tell (cms->reader);
  755       si = xtrycalloc (1, sizeof *si);
  756       if (!si)
  757         return gpg_error (GPG_ERR_ENOMEM);
  758 
  759       err = create_and_run_decoder (cms->reader,
  760                                     "CryptographicMessageSyntax.SignerInfo",
  761                                     0,
  762                                     &si->root, &si->image, &si->imagelen);
  763       /* The signerInfo might be an empty set in the case of a certs-only
  764          signature.  Thus we have to allow for EOF here */
  765       if (gpg_err_code (err) == GPG_ERR_EOF)
  766         {
  767       xfree (si);
  768           err = 0;
  769           break;
  770         }
  771       if (err)
  772     {
  773       xfree (si);
  774       return err;
  775     }
  776 
  777       *si_tail = si;
  778       si_tail = &si->next;
  779 
  780       off2 = ksba_reader_tell (cms->reader);
  781       if ( (off2 - off1) > ti.length )
  782         ti.length = 0;
  783       else
  784         ti.length -= off2 - off1;
  785     }
  786 
  787   return 0;
  788 }
  789 
  790 
  791 
  792 
  793 
  794 /* Parse the structure:
  795 
  796    EnvelopedData ::= SEQUENCE {
  797      version INTEGER  { v0(0), v1(1), v2(2), v3(3), v4(4) }),
  798      originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
  799      recipientInfos RecipientInfos,
  800      encryptedContentInfo EncryptedContentInfo,
  801      unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
  802 
  803    OriginatorInfo ::= SEQUENCE {
  804      certs [0] IMPLICIT CertificateSet OPTIONAL,
  805      crls [1] IMPLICIT CertificateRevocationLists OPTIONAL }
  806 
  807    RecipientInfos ::= SET OF RecipientInfo
  808 
  809    EncryptedContentInfo ::= SEQUENCE {
  810      contentType ContentType,
  811      contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
  812      encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
  813 
  814    EncryptedContent ::= OCTET STRING
  815 
  816  We stop parsing so that the next read will be the first byte of the
  817  encryptedContent or (if there is no content) the unprotectedAttrs.
  818 */
  819 gpg_error_t
  820 _ksba_cms_parse_enveloped_data_part_1 (ksba_cms_t cms)
  821 {
  822   struct tag_info ti;
  823   gpg_error_t err;
  824   int env_data_ndef;
  825   unsigned long env_data_len;
  826   int encr_cont_ndef = 0;
  827   unsigned long encr_cont_len = 0;
  828   int has_content = 0;
  829   unsigned long off, len;
  830   char *cont_oid = NULL;
  831   char *algo_oid = NULL;
  832   char *algo_parm = NULL;
  833   size_t algo_parmlen = 0;
  834   struct value_tree_s *vt, **vtend;
  835 
  836   /* get the version */
  837   err = parse_cms_version (cms->reader, &cms->cms_version,
  838                            &env_data_len, &env_data_ndef);
  839   if (err)
  840     return err;
  841 
  842   /* read the next triplet which is either a [0] for originatorInfos
  843      or a SET_OF (recipientInfo) */
  844   err = _ksba_ber_read_tl (cms->reader, &ti);
  845   if (err)
  846     return err;
  847 
  848   if (ti.class == CLASS_CONTEXT && ti.tag == 0 && ti.is_constructed)
  849     { /* originatorInfo - but we skip it for now */
  850       /* well, raise an error */
  851       return gpg_error (GPG_ERR_UNSUPPORTED_CMS_OBJ);
  852     }
  853 
  854   /* Next one is the SET OF RecipientInfo:
  855    * RecipientInfo ::= CHOICE {
  856    *     ktri KeyTransRecipientInfo,
  857    *     kari [1] KeyAgreeRecipientInfo,
  858    *     kekri [2] KEKRecipientInfo
  859    * }  */
  860   if ( !(ti.class == CLASS_UNIVERSAL
  861          && ti.tag == TYPE_SET && ti.is_constructed))
  862     return gpg_error (GPG_ERR_INV_CMS_OBJ);
  863 
  864 
  865   vtend = &cms->recp_info;
  866   if (ti.ndef)
  867     {
  868       for (;;)
  869         {
  870           struct tag_info ti2;
  871 
  872           err = _ksba_ber_read_tl (cms->reader, &ti2);
  873           if (err)
  874             return err;
  875 
  876           if (!ti2.class && !ti2.tag)
  877             break; /* End tag found: ready.  */
  878 
  879           /* Not an end tag:  Push it back and run the decoder.  */
  880           err = ksba_reader_unread (cms->reader, ti2.buf, ti2.nhdr);
  881           if (err)
  882             return err;
  883 
  884           vt = xtrycalloc (1, sizeof *vt);
  885           if (!vt)
  886             return gpg_error_from_syserror ();
  887 
  888           err = create_and_run_decoder
  889             (cms->reader,
  890              "CryptographicMessageSyntax.RecipientInfo",
  891              BER_DECODER_FLAG_FAST_STOP,
  892              &vt->root, &vt->image, &vt->imagelen);
  893           if (err)
  894             {
  895               xfree (vt);
  896               return err;
  897             }
  898 
  899           *vtend = vt;
  900           vtend = &vt->next;
  901         }
  902     }
  903   else
  904     {
  905       while (ti.length)
  906         {
  907           size_t off1, off2;
  908 
  909           off1 = ksba_reader_tell (cms->reader);
  910           vt = xtrycalloc (1, sizeof *vt);
  911           if (!vt)
  912             return gpg_error_from_syserror ();
  913 
  914           err = create_and_run_decoder
  915             (cms->reader,
  916              "CryptographicMessageSyntax.RecipientInfo",
  917              BER_DECODER_FLAG_FAST_STOP,
  918              &vt->root, &vt->image, &vt->imagelen);
  919           if (err)
  920             {
  921               xfree (vt);
  922               return err;
  923             }
  924 
  925           *vtend = vt;
  926           vtend = &vt->next;
  927 
  928           off2 = ksba_reader_tell (cms->reader);
  929           if ( (off2 - off1) > ti.length )
  930             ti.length = 0;
  931           else
  932             ti.length -= off2 - off1;
  933         }
  934     }
  935 
  936   /* Now for the encryptedContentInfo */
  937   off = ksba_reader_tell (cms->reader);
  938   err = parse_encrypted_content_info (cms->reader,
  939                                       &encr_cont_len, &encr_cont_ndef,
  940                                       &cont_oid,
  941                                       &algo_oid,
  942                                       &algo_parm, &algo_parmlen,
  943                                       &has_content);
  944   if (err)
  945     return err;
  946   cms->inner_cont_len = encr_cont_len;
  947   cms->inner_cont_ndef = encr_cont_ndef;
  948   cms->inner_cont_oid = cont_oid;
  949   cms->detached_data = !has_content;
  950   cms->encr_algo_oid = algo_oid;
  951   cms->encr_iv = algo_parm; algo_parm = NULL;
  952   cms->encr_ivlen = algo_parmlen;
  953   if (!env_data_ndef)
  954     {
  955       len = ksba_reader_tell (cms->reader) - off;
  956       if (env_data_len < len)
  957         return gpg_error (GPG_ERR_BAD_BER); /* parsed content info larger that sequence */
  958       env_data_len -= len;
  959       if (!encr_cont_ndef && env_data_len < encr_cont_len)
  960         return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */
  961     }
  962 
  963   return 0;
  964 }
  965 
  966 
  967 /* handle the unprotected attributes */
  968 gpg_error_t
  969 _ksba_cms_parse_enveloped_data_part_2 (ksba_cms_t cms)
  970 {
  971   (void)cms;
  972   /* FIXME */
  973   return 0;
  974 }