LCOV - code coverage report
Current view: top level - src - keyinfo.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 328 753 43.6 %
Date: 2016-12-09 14:04:45 Functions: 14 17 82.4 %

          Line data    Source code
       1             : /* keyinfo.c - Parse and build a keyInfo structure
       2             :  * Copyright (C) 2001, 2002, 2007, 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             : /* Instead of using the ASN parser - which is easily possible - we use
      32             :    a simple handcoded one to speed up the operation and to make it
      33             :    more robust. */
      34             : 
      35             : #include <config.h>
      36             : #include <stdio.h>
      37             : #include <stdlib.h>
      38             : #include <string.h>
      39             : #include <assert.h>
      40             : 
      41             : #include "util.h"
      42             : #include "asn1-func.h"
      43             : #include "keyinfo.h"
      44             : #include "shared.h"
      45             : #include "convert.h"
      46             : #include "ber-help.h"
      47             : 
      48             : 
      49             : /* Constants used for the public key algorithms.  */
      50             : typedef enum
      51             :   {
      52             :     PKALGO_RSA,
      53             :     PKALGO_DSA,
      54             :     PKALGO_ECC
      55             :   }
      56             : pkalgo_t;
      57             : 
      58             : 
      59             : struct algo_table_s {
      60             :   const char *oidstring;
      61             :   const unsigned char *oid;  /* NULL indicattes end of table */
      62             :   int                  oidlen;
      63             :   int supported;
      64             :   pkalgo_t pkalgo;
      65             :   const char *algo_string;
      66             :   const char *elem_string; /* parameter name or '-' */
      67             :   const char *ctrl_string; /* expected tag values (value > 127 are raw data)*/
      68             :   const char *parmelem_string; /* parameter name or '-'. */
      69             :   const char *parmctrl_string; /* expected tag values.  */
      70             :   const char *digest_string; /* The digest algo if included in the OID. */
      71             : };
      72             : 
      73             : 
      74             : 
      75             : static const struct algo_table_s pk_algo_table[] = {
      76             : 
      77             :   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.1 */
      78             :     "1.2.840.113549.1.1.1", /* rsaEncryption (RSAES-PKCA1-v1.5) */
      79             :     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01", 9,
      80             :     1, PKALGO_RSA, "rsa", "-ne", "\x30\x02\x02" },
      81             : 
      82             :   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.7 */
      83             :     "1.2.840.113549.1.1.7", /* RSAES-OAEP */
      84             :     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x07", 9,
      85             :     0, PKALGO_RSA, "rsa", "-ne", "\x30\x02\x02"}, /* (patent problems) */
      86             : 
      87             :   { /* */
      88             :     "2.5.8.1.1", /* rsa (ambiguous due to missing padding rules)*/
      89             :     "\x55\x08\x01\x01", 4,
      90             :     1, PKALGO_RSA, "ambiguous-rsa", "-ne", "\x30\x02\x02" },
      91             : 
      92             :   { /* iso.member-body.us.x9-57.x9cm.1 */
      93             :     "1.2.840.10040.4.1", /*  dsa */
      94             :     "\x2a\x86\x48\xce\x38\x04\x01", 7,
      95             :     1, PKALGO_DSA, "dsa", "y", "\x02", "-pqg", "\x30\x02\x02\x02" },
      96             : 
      97             :   { /* iso.member-body.us.ansi-x9-62.2.1 */
      98             :     "1.2.840.10045.2.1", /*  ecPublicKey */
      99             :     "\x2a\x86\x48\xce\x3d\x02\x01", 7,
     100             :     1, PKALGO_ECC, "ecc", "q", "\x80" },
     101             : 
     102             :   {NULL}
     103             : };
     104             : 
     105             : 
     106             : static const struct algo_table_s sig_algo_table[] = {
     107             :   {  /* iso.member-body.us.rsadsi.pkcs.pkcs-1.5 */
     108             :     "1.2.840.113549.1.1.5", /* sha1WithRSAEncryption */
     109             :     "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05", 9,
     110             :     1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha1" },
     111             :   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.4 */
     112             :     "1.2.840.113549.1.1.4", /* md5WithRSAEncryption */
     113             :     "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04", 9,
     114             :     1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "md5" },
     115             :   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.2 */
     116             :     "1.2.840.113549.1.1.2", /* md2WithRSAEncryption */
     117             :     "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02", 9,
     118             :     0, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "md2" },
     119             :   { /* iso.member-body.us.x9-57.x9cm.1 */
     120             :     "1.2.840.10040.4.3", /* dsa */
     121             :     "\x2a\x86\x48\xce\x38\x04\x01", 7,
     122             :     1, PKALGO_DSA, "dsa", "-rs", "\x30\x02\x02" },
     123             :   { /* iso.member-body.us.x9-57.x9cm.3 */
     124             :     "1.2.840.10040.4.3", /*  dsaWithSha1 */
     125             :     "\x2a\x86\x48\xce\x38\x04\x03", 7,
     126             :     1, PKALGO_DSA, "dsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha1" },
     127             :   { /* Teletrust signature algorithm.  */
     128             :     "1.3.36.8.5.1.2.2", /* dsaWithRIPEMD160 */
     129             :     "\x2b\x24\x08\x05\x01\x02\x02", 7,
     130             :     1, PKALGO_DSA, "dsa", "-rs", "\x30\x02\x02", NULL, NULL, "rmd160" },
     131             :   { /* NIST Algorithm */
     132             :     "2.16.840.1.101.3.4.3.1", /* dsaWithSha224 */
     133             :     "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x03\x01", 11,
     134             :     1, PKALGO_DSA, "dsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha224" },
     135             :   { /* NIST Algorithm (the draft also used .1 but we better use .2) */
     136             :     "2.16.840.1.101.3.4.3.2", /* dsaWithSha256 */
     137             :     "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x03\x01", 11,
     138             :     1, PKALGO_DSA, "dsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha256" },
     139             : 
     140             :   { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha1 */
     141             :     "1.2.840.10045.4.1", /*  ecdsa */
     142             :     "\x2a\x86\x48\xce\x3d\x04\x01", 7,
     143             :     1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha1" },
     144             : 
     145             :   { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-specified */
     146             :     "1.2.840.10045.4.3",
     147             :     "\x2a\x86\x48\xce\x3d\x04\x03", 7,
     148             :     1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, NULL },
     149             :   /* The digest algorithm is given by the parameter.  */
     150             : 
     151             : 
     152             :   { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha224 */
     153             :     "1.2.840.10045.4.3.1",
     154             :     "\x2a\x86\x48\xce\x3d\x04\x03\x01", 8,
     155             :     1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha224" },
     156             : 
     157             :   { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha256 */
     158             :     "1.2.840.10045.4.3.2",
     159             :     "\x2a\x86\x48\xce\x3d\x04\x03\x02", 8,
     160             :     1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha256" },
     161             : 
     162             :   { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha384 */
     163             :     "1.2.840.10045.4.3.3",
     164             :     "\x2a\x86\x48\xce\x3d\x04\x03\x03", 8,
     165             :     1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha384" },
     166             : 
     167             :   { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha512 */
     168             :     "1.2.840.10045.4.3.4",
     169             :     "\x2a\x86\x48\xce\x3d\x04\x03\x04", 8,
     170             :     1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha512" },
     171             : 
     172             :   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.1 */
     173             :     "1.2.840.113549.1.1.1", /* rsaEncryption used without hash algo*/
     174             :     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01", 9,
     175             :     1, PKALGO_RSA, "rsa", "s", "\x82" },
     176             :   { /* from NIST's OIW - actually belongs in a pure hash table */
     177             :     "1.3.14.3.2.26",  /* sha1 */
     178             :     "\x2B\x0E\x03\x02\x1A", 5,
     179             :     0, PKALGO_RSA, "sha-1", "", "", NULL, NULL, "sha1" },
     180             : 
     181             :   { /* As used by telesec cards */
     182             :     "1.3.36.3.3.1.2",  /* rsaSignatureWithripemd160 */
     183             :     "\x2b\x24\x03\x03\x01\x02", 6,
     184             :     1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "rmd160" },
     185             : 
     186             :   { /* from NIST's OIW - used by TU Darmstadt */
     187             :     "1.3.14.3.2.29",  /* sha-1WithRSAEncryption */
     188             :     "\x2B\x0E\x03\x02\x1D", 5,
     189             :     1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha1" },
     190             : 
     191             :   { /* from PKCS#1  */
     192             :     "1.2.840.113549.1.1.11", /* sha256WithRSAEncryption */
     193             :     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b", 9,
     194             :     1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha256" },
     195             : 
     196             :   { /* from PKCS#1  */
     197             :     "1.2.840.113549.1.1.12", /* sha384WithRSAEncryption */
     198             :     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0c", 9,
     199             :     1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha384" },
     200             : 
     201             :   { /* from PKCS#1  */
     202             :     "1.2.840.113549.1.1.13", /* sha512WithRSAEncryption */
     203             :     "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0d", 9,
     204             :     1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha512" },
     205             : 
     206             :   { /* TeleTrust signature scheme with RSA signature and DSI according
     207             :        to ISO/IEC 9796-2 with random number and RIPEMD-160.  I am not
     208             :        sure for what this is good; thus disabled. */
     209             :     "1.3.36.3.4.3.2.2",     /* sigS_ISO9796-2rndWithrsa_ripemd160 */
     210             :     "\x2B\x24\x03\x04\x03\x02\x02", 7,
     211             :     0, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "rmd160" },
     212             : 
     213             :   {NULL}
     214             : };
     215             : 
     216             : static const struct algo_table_s enc_algo_table[] = {
     217             :   { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.1 */
     218             :     "1.2.840.113549.1.1.1", /* rsaEncryption (RSAES-PKCA1-v1.5) */
     219             :     "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01", 9,
     220             :     1, PKALGO_RSA, "rsa", "a", "\x82" },
     221             :   {NULL}
     222             : };
     223             : 
     224             : 
     225             : /* This tables maps names of ECC curves names to OIDs.  A similar
     226             :    table is used by lib gcrypt.  */
     227             : static const struct
     228             : {
     229             :   const char *oid;
     230             :   const char *name;
     231             : } curve_names[] =
     232             :   {
     233             :     { "1.3.6.1.4.1.3029.1.5.1", "Curve25519" },
     234             :     { "1.3.6.1.4.1.11591.15.1", "Ed25519"    },
     235             : 
     236             :     { "1.2.840.10045.3.1.1", "NIST P-192" },
     237             :     { "1.2.840.10045.3.1.1", "nistp192"   },
     238             :     { "1.2.840.10045.3.1.1", "prime192v1" },
     239             :     { "1.2.840.10045.3.1.1", "secp192r1"  },
     240             : 
     241             :     { "1.3.132.0.33",        "NIST P-224" },
     242             :     { "1.3.132.0.33",        "nistp224"   },
     243             :     { "1.3.132.0.33",        "secp224r1"  },
     244             : 
     245             :     { "1.2.840.10045.3.1.7", "NIST P-256" },
     246             :     { "1.2.840.10045.3.1.7", "nistp256"   },
     247             :     { "1.2.840.10045.3.1.7", "prime256v1" },
     248             :     { "1.2.840.10045.3.1.7", "secp256r1"  },
     249             : 
     250             :     { "1.3.132.0.34",        "NIST P-384" },
     251             :     { "1.3.132.0.34",        "nistp384"   },
     252             :     { "1.3.132.0.34",        "secp384r1"  },
     253             : 
     254             :     { "1.3.132.0.35",        "NIST P-521" },
     255             :     { "1.3.132.0.35",        "nistp521"   },
     256             :     { "1.3.132.0.35",        "secp521r1"  },
     257             : 
     258             :     { "1.3.36.3.3.2.8.1.1.1" , "brainpoolP160r1" },
     259             :     { "1.3.36.3.3.2.8.1.1.3" , "brainpoolP192r1" },
     260             :     { "1.3.36.3.3.2.8.1.1.5" , "brainpoolP224r1" },
     261             :     { "1.3.36.3.3.2.8.1.1.7" , "brainpoolP256r1" },
     262             :     { "1.3.36.3.3.2.8.1.1.9" , "brainpoolP320r1" },
     263             :     { "1.3.36.3.3.2.8.1.1.11", "brainpoolP384r1" },
     264             :     { "1.3.36.3.3.2.8.1.1.13", "brainpoolP512r1" },
     265             : 
     266             : 
     267             :     { "1.2.643.2.2.35.1",    "GOST2001-CryptoPro-A" },
     268             :     { "1.2.643.2.2.35.2",    "GOST2001-CryptoPro-B" },
     269             :     { "1.2.643.2.2.35.3",    "GOST2001-CryptoPro-C" },
     270             :     { "1.2.643.7.1.2.1.2.1", "GOST2012-tc26-A"      },
     271             :     { "1.2.643.7.1.2.1.2.2", "GOST2012-tc26-B"      },
     272             : 
     273             :     { "1.3.132.0.10",        "secp256k1" },
     274             : 
     275             :     { NULL, NULL}
     276             :   };
     277             : 
     278             : 
     279             : 
     280             : 
     281             : 
     282             : struct stringbuf {
     283             :   size_t len;
     284             :   size_t size;
     285             :   char *buf;
     286             :   int out_of_core;
     287             : };
     288             : 
     289             : 
     290             : #define TLV_LENGTH(prefix) do {         \
     291             :   if (!prefix ## len)                    \
     292             :     return gpg_error (GPG_ERR_INV_KEYINFO);  \
     293             :   c = *(prefix)++; prefix ## len--;           \
     294             :   if (c == 0x80)                  \
     295             :     return gpg_error (GPG_ERR_NOT_DER_ENCODED);  \
     296             :   if (c == 0xff)                  \
     297             :     return gpg_error (GPG_ERR_BAD_BER);        \
     298             :                                   \
     299             :   if ( !(c & 0x80) )              \
     300             :     len = c;                      \
     301             :   else                            \
     302             :     {                             \
     303             :       int count = c & 0x7f;       \
     304             :                                   \
     305             :       for (len=0; count; count--) \
     306             :         {                         \
     307             :           len <<= 8;              \
     308             :           if (!prefix ## len)            \
     309             :             return gpg_error (GPG_ERR_BAD_BER);\
     310             :           c = *(prefix)++; prefix ## len--;   \
     311             :           len |= c & 0xff;        \
     312             :         }                         \
     313             :     }                             \
     314             :   if (len > prefix ## len)               \
     315             :     return gpg_error (GPG_ERR_INV_KEYINFO);  \
     316             : } while (0)
     317             : 
     318             : 
     319             : /* Given a string BUF of length BUFLEN with either the name of an ECC
     320             :    curve or its OID in dotted form return the DER encoding of the OID.
     321             :    The caller must free the result.  On error NULL is returned.  */
     322             : static unsigned char *
     323           0 : get_ecc_curve_oid (const unsigned char *buf, size_t buflen, size_t *r_oidlen)
     324             : {
     325             :   unsigned char *der_oid;
     326             : 
     327             :   /* Skip an optional "oid." prefix. */
     328           0 :   if (buflen > 4 && buf[3] == '.' && digitp (buf+4)
     329           0 :       && ((buf[0] == 'o' && buf[1] == 'i' && buf[2] == 'd')
     330           0 :           ||(buf[0] == 'O' && buf[1] == 'I' && buf[2] == 'D')))
     331             :     {
     332           0 :       buf += 4;
     333           0 :       buflen -= 4;
     334             :     }
     335             : 
     336             :   /* If it does not look like an OID - map it through the table.  */
     337           0 :   if (buflen && !digitp (buf))
     338             :     {
     339             :       int i;
     340             : 
     341           0 :       for (i=0; curve_names[i].oid; i++)
     342           0 :         if (buflen == strlen (curve_names[i].name)
     343           0 :             && !memcmp (buf, curve_names[i].name, buflen))
     344           0 :           break;
     345           0 :       if (!curve_names[i].oid)
     346           0 :         return NULL; /* Not found.  */
     347           0 :       buf = curve_names[i].oid;
     348           0 :       buflen = strlen (curve_names[i].oid);
     349             :     }
     350             : 
     351           0 :   if (_ksba_oid_from_buf (buf, buflen, &der_oid, r_oidlen))
     352           0 :     return NULL;
     353           0 :   return der_oid;
     354             : }
     355             : 
     356             : 
     357             : 
     358             : /* Return the OFF and the LEN of algorithm within DER.  Do some checks
     359             :    and return the number of bytes read in r_nread, adding this to der
     360             :    does point into the BIT STRING.
     361             : 
     362             :    mode 0: just get the algorithm identifier. FIXME: should be able to
     363             :            handle BER Encoding.
     364             :    mode 1: as described.
     365             :  */
     366             : static gpg_error_t
     367          11 : get_algorithm (int mode, const unsigned char *der, size_t derlen,
     368             :                size_t *r_nread, size_t *r_pos, size_t *r_len, int *r_bitstr,
     369             :                size_t *r_parm_pos, size_t *r_parm_len, int *r_parm_type)
     370             : {
     371             :   int c;
     372          11 :   const unsigned char *start = der;
     373             :   const unsigned char *startseq;
     374             :   unsigned long seqlen, len;
     375             : 
     376          11 :   *r_bitstr = 0;
     377          11 :   if (r_parm_pos)
     378          10 :     *r_parm_pos = 0;
     379          11 :   if (r_parm_len)
     380          10 :     *r_parm_len = 0;
     381          11 :   if (r_parm_type)
     382          10 :     *r_parm_type = 0;
     383             :   /* get the inner sequence */
     384          11 :   if (!derlen)
     385           0 :     return gpg_error (GPG_ERR_INV_KEYINFO);
     386          11 :   c = *der++; derlen--;
     387          11 :   if ( c != 0x30 )
     388           0 :     return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */
     389          11 :   TLV_LENGTH(der);
     390          11 :   seqlen = len;
     391          11 :   startseq = der;
     392             : 
     393             :   /* get the object identifier */
     394          11 :   if (!derlen)
     395           0 :     return gpg_error (GPG_ERR_INV_KEYINFO);
     396          11 :   c = *der++; derlen--;
     397          11 :   if ( c != 0x06 )
     398           0 :     return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not an OBJECT IDENTIFIER */
     399          11 :   TLV_LENGTH(der);
     400             : 
     401             :   /* der does now point to an oid of length LEN */
     402          11 :   *r_pos = der - start;
     403          11 :   *r_len = len;
     404             : /*    { */
     405             : /*      char *p = ksba_oid_to_str (der, len); */
     406             : /*      printf ("algorithm: %s\n", p); */
     407             : /*      xfree (p); */
     408             : /*    } */
     409          11 :   der += len;
     410          11 :   derlen -= len;
     411          11 :   seqlen -= der - startseq;;
     412             : 
     413             :   /* Parse the parameter.  */
     414          11 :   if (seqlen)
     415             :     {
     416          11 :       const unsigned char *startparm = der;
     417             : 
     418          11 :       if (!derlen)
     419           0 :         return gpg_error (GPG_ERR_INV_KEYINFO);
     420          11 :       c = *der++; derlen--;
     421          11 :       if ( c == 0x05 )
     422             :         {
     423             :           /*printf ("parameter: NULL \n"); the usual case */
     424          11 :           if (!derlen)
     425           0 :             return gpg_error (GPG_ERR_INV_KEYINFO);
     426          11 :           c = *der++; derlen--;
     427          11 :           if (c)
     428           0 :             return gpg_error (GPG_ERR_BAD_BER);  /* NULL must have a
     429             :                                                     length of 0 */
     430          11 :           seqlen -= 2;
     431             :         }
     432           0 :       else if (r_parm_pos && r_parm_len && c == 0x04)
     433             :         {
     434             :           /*  This is an octet string parameter and we need it.  */
     435           0 :           if (r_parm_type)
     436           0 :             *r_parm_type = TYPE_OCTET_STRING;
     437           0 :           TLV_LENGTH(der);
     438           0 :           *r_parm_pos = der - start;
     439           0 :           *r_parm_len = len;
     440           0 :           seqlen -= der - startparm;
     441           0 :           der += len;
     442           0 :           derlen -= len;
     443           0 :           seqlen -= len;
     444             :         }
     445           0 :       else if (r_parm_pos && r_parm_len && c == 0x06)
     446             :         {
     447             :           /*  This is an object identifier.  */
     448           0 :           if (r_parm_type)
     449           0 :             *r_parm_type = TYPE_OBJECT_ID;
     450           0 :           TLV_LENGTH(der);
     451           0 :           *r_parm_pos = der - start;
     452           0 :           *r_parm_len = len;
     453           0 :           seqlen -= der - startparm;
     454           0 :           der += len;
     455           0 :           derlen -= len;
     456           0 :           seqlen -= len;
     457             :         }
     458           0 :       else if (r_parm_pos && r_parm_len && c == 0x30)
     459             :         {
     460             :           /*  This is a sequence. */
     461           0 :           if (r_parm_type)
     462           0 :             *r_parm_type = TYPE_SEQUENCE;
     463           0 :           TLV_LENGTH(der);
     464           0 :           *r_parm_pos = startparm - start;
     465           0 :           *r_parm_len = len + (der - startparm);
     466           0 :           seqlen -= der - startparm;
     467           0 :           der += len;
     468           0 :           derlen -= len;
     469           0 :           seqlen -= len;
     470             :         }
     471             :       else
     472             :         {
     473             : /*            printf ("parameter: with tag %02x - ignored\n", c); */
     474           0 :           TLV_LENGTH(der);
     475           0 :           seqlen -= der - startparm;
     476             :           /* skip the value */
     477           0 :           der += len;
     478           0 :           derlen -= len;
     479           0 :           seqlen -= len;
     480             :         }
     481             :     }
     482             : 
     483          11 :   if (seqlen)
     484           0 :     return gpg_error (GPG_ERR_INV_KEYINFO);
     485             : 
     486          11 :   if (mode)
     487             :     {
     488             :       /* move forward to the BIT_STR */
     489           7 :       if (!derlen)
     490           0 :         return gpg_error (GPG_ERR_INV_KEYINFO);
     491           7 :       c = *der++; derlen--;
     492             : 
     493           7 :       if (c == 0x03)
     494           7 :         *r_bitstr = 1; /* BIT STRING */
     495           0 :       else if (c == 0x04)
     496             :         ; /* OCTECT STRING */
     497             :       else
     498           0 :         return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a BIT STRING */
     499           7 :       TLV_LENGTH(der);
     500             :     }
     501             : 
     502          11 :   *r_nread = der - start;
     503          11 :   return 0;
     504             : }
     505             : 
     506             : 
     507             : gpg_error_t
     508           3 : _ksba_parse_algorithm_identifier (const unsigned char *der, size_t derlen,
     509             :                                   size_t *r_nread, char **r_oid)
     510             : {
     511           3 :   return _ksba_parse_algorithm_identifier2 (der, derlen,
     512             :                                             r_nread, r_oid, NULL, NULL);
     513             : }
     514             : 
     515             : gpg_error_t
     516           4 : _ksba_parse_algorithm_identifier2 (const unsigned char *der, size_t derlen,
     517             :                                    size_t *r_nread, char **r_oid,
     518             :                                    char **r_parm, size_t *r_parmlen)
     519             : {
     520             :   gpg_error_t err;
     521             :   int is_bitstr;
     522             :   size_t nread, off, len, off2, len2;
     523             :   int parm_type;
     524             : 
     525             :   /* fixme: get_algorithm might return the error invalid keyinfo -
     526             :      this should be invalid algorithm identifier */
     527           4 :   *r_oid = NULL;
     528           4 :   *r_nread = 0;
     529           4 :   off2 = len2 = 0;
     530           4 :   err = get_algorithm (0, der, derlen, &nread, &off, &len, &is_bitstr,
     531             :                        &off2, &len2, &parm_type);
     532           4 :   if (err)
     533           0 :     return err;
     534           4 :   *r_nread = nread;
     535           4 :   *r_oid = ksba_oid_to_str (der+off, len);
     536           4 :   if (!*r_oid)
     537           0 :     return gpg_error (GPG_ERR_ENOMEM);
     538             : 
     539             :   /* Special hack for ecdsaWithSpecified.  We replace the returned OID
     540             :      by the one in the parameter. */
     541           4 :   if (off2 && len2 && parm_type == TYPE_SEQUENCE
     542           0 :       && !strcmp (*r_oid, "1.2.840.10045.4.3"))
     543             :     {
     544           0 :       xfree (*r_oid);
     545           0 :       *r_oid = NULL;
     546           0 :       err = get_algorithm (0, der+off2, len2, &nread, &off, &len, &is_bitstr,
     547             :                            NULL, NULL, NULL);
     548           0 :       if (err)
     549             :         {
     550           0 :           *r_nread = 0;
     551           0 :           return err;
     552             :         }
     553           0 :       *r_oid = ksba_oid_to_str (der+off2+off, len);
     554           0 :       if (!*r_oid)
     555             :         {
     556           0 :           *r_nread = 0;
     557           0 :           return gpg_error (GPG_ERR_ENOMEM);
     558             :         }
     559             : 
     560           0 :       off2 = len2 = 0; /* So that R_PARM is set to NULL.  */
     561             :     }
     562             : 
     563           4 :   if (r_parm && r_parmlen)
     564             :     {
     565           1 :       if (off2 && len2)
     566             :         {
     567           0 :           *r_parm = xtrymalloc (len2);
     568           0 :           if (!*r_parm)
     569             :             {
     570           0 :               xfree (*r_oid);
     571           0 :               *r_oid = NULL;
     572           0 :               return gpg_error (GPG_ERR_ENOMEM);
     573             :             }
     574           0 :           memcpy (*r_parm, der+off2, len2);
     575           0 :           *r_parmlen = len2;
     576             :         }
     577             :       else
     578             :         {
     579           1 :           *r_parm = NULL;
     580           1 :           *r_parmlen = 0;
     581             :         }
     582             :     }
     583           4 :   return 0;
     584             : }
     585             : 
     586             : 
     587             : 
     588             : static void
     589           7 : init_stringbuf (struct stringbuf *sb, int initiallen)
     590             : {
     591           7 :   sb->len = 0;
     592           7 :   sb->size = initiallen;
     593           7 :   sb->out_of_core = 0;
     594             :   /* allocate one more, so that get_stringbuf can append a nul */
     595           7 :   sb->buf = xtrymalloc (initiallen+1);
     596           7 :   if (!sb->buf)
     597           0 :       sb->out_of_core = 1;
     598           7 : }
     599             : 
     600             : static void
     601         111 : put_stringbuf_mem (struct stringbuf *sb, const char *text, size_t n)
     602             : {
     603         111 :   if (sb->out_of_core)
     604           0 :     return;
     605             : 
     606         111 :   if (sb->len + n >= sb->size)
     607             :     {
     608             :       char *p;
     609             : 
     610           7 :       sb->size += n + 100;
     611           7 :       p = xtryrealloc (sb->buf, sb->size);
     612           7 :       if ( !p)
     613             :         {
     614           0 :           sb->out_of_core = 1;
     615           0 :           return;
     616             :         }
     617           7 :       sb->buf = p;
     618             :     }
     619         111 :   memcpy (sb->buf+sb->len, text, n);
     620         111 :   sb->len += n;
     621             : }
     622             : 
     623             : static void
     624          77 : put_stringbuf (struct stringbuf *sb, const char *text)
     625             : {
     626          77 :   put_stringbuf_mem (sb, text,strlen (text));
     627          77 : }
     628             : 
     629             : static void
     630          34 : put_stringbuf_mem_sexp (struct stringbuf *sb, const char *text, size_t length)
     631             : {
     632             :   char buf[20];
     633          34 :   sprintf (buf,"%u:", (unsigned int)length);
     634          34 :   put_stringbuf (sb, buf);
     635          34 :   put_stringbuf_mem (sb, text, length);
     636          34 : }
     637             : 
     638             : static void
     639          21 : put_stringbuf_sexp (struct stringbuf *sb, const char *text)
     640             : {
     641          21 :   put_stringbuf_mem_sexp (sb, text, strlen (text));
     642          21 : }
     643             : 
     644             : 
     645             : static char *
     646           7 : get_stringbuf (struct stringbuf *sb)
     647             : {
     648             :   char *p;
     649             : 
     650           7 :   if (sb->out_of_core)
     651             :     {
     652           0 :       xfree (sb->buf); sb->buf = NULL;
     653           0 :       return NULL;
     654             :     }
     655             : 
     656           7 :   sb->buf[sb->len] = 0;
     657           7 :   p = sb->buf;
     658           7 :   sb->buf = NULL;
     659           7 :   sb->out_of_core = 1; /* make sure the caller does an init before reuse */
     660           7 :   return p;
     661             : }
     662             : 
     663             : 
     664             : /* Assume that der is a buffer of length DERLEN with a DER encoded
     665             :  Asn.1 structure like this:
     666             : 
     667             :   keyInfo ::= SEQUENCE {
     668             :                  SEQUENCE {
     669             :                     algorithm    OBJECT IDENTIFIER,
     670             :                     parameters   ANY DEFINED BY algorithm OPTIONAL }
     671             :                  publicKey  BIT STRING }
     672             : 
     673             :   The function parses this structure and create a SEXP suitable to be
     674             :   used as a public key in Libgcrypt.  The S-Exp will be returned in a
     675             :   string which the caller must free.
     676             : 
     677             :   We don't pass an ASN.1 node here but a plain memory block.  */
     678             : 
     679             : gpg_error_t
     680           6 : _ksba_keyinfo_to_sexp (const unsigned char *der, size_t derlen,
     681             :                        ksba_sexp_t *r_string)
     682             : {
     683             :   gpg_error_t err;
     684             :   int c;
     685             :   size_t nread, off, len, parm_off, parm_len;
     686             :   int parm_type;
     687           6 :   char *parm_oid = NULL;
     688             :   int algoidx;
     689             :   int is_bitstr;
     690           6 :   const unsigned char *parmder = NULL;
     691           6 :   size_t parmderlen = 0;
     692             :   const unsigned char *ctrl;
     693             :   const char *elem;
     694             :   struct stringbuf sb;
     695             : 
     696           6 :   *r_string = NULL;
     697             : 
     698             :   /* check the outer sequence */
     699           6 :   if (!derlen)
     700           0 :     return gpg_error (GPG_ERR_INV_KEYINFO);
     701           6 :   c = *der++; derlen--;
     702           6 :   if ( c != 0x30 )
     703           0 :     return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */
     704           6 :   TLV_LENGTH(der);
     705             :   /* and now the inner part */
     706           6 :   err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr,
     707             :                        &parm_off, &parm_len, &parm_type);
     708           6 :   if (err)
     709           0 :     return err;
     710             : 
     711             :   /* look into our table of supported algorithms */
     712           6 :   for (algoidx=0; pk_algo_table[algoidx].oid; algoidx++)
     713             :     {
     714           6 :       if ( len == pk_algo_table[algoidx].oidlen
     715           6 :            && !memcmp (der+off, pk_algo_table[algoidx].oid, len))
     716           6 :         break;
     717             :     }
     718           6 :   if (!pk_algo_table[algoidx].oid)
     719           0 :     return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
     720           6 :   if (!pk_algo_table[algoidx].supported)
     721           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     722             : 
     723           6 :   if (parm_off && parm_len && parm_type == TYPE_OBJECT_ID)
     724           0 :     parm_oid = ksba_oid_to_str (der+parm_off, parm_len);
     725           6 :   else if (parm_off && parm_len)
     726             :     {
     727           0 :       parmder = der + parm_off;
     728           0 :       parmderlen = parm_len;
     729             :     }
     730             : 
     731           6 :   der += nread;
     732           6 :   derlen -= nread;
     733             : 
     734           6 :   if (is_bitstr)
     735             :     { /* Funny: X.509 defines the signature value as a bit string but
     736             :          CMS as an octet string - for ease of implementation we always
     737             :          allow both */
     738           6 :       if (!derlen)
     739             :         {
     740           0 :           xfree (parm_oid);
     741           0 :           return gpg_error (GPG_ERR_INV_KEYINFO);
     742             :         }
     743           6 :       c = *der++; derlen--;
     744           6 :       if (c)
     745           0 :         fprintf (stderr, "warning: number of unused bits is not zero\n");
     746             :     }
     747             : 
     748             :   /* fixme: we should calculate the initial length form the size of the
     749             :      sequence, so that we don't need a realloc later */
     750           6 :   init_stringbuf (&sb, 100);
     751           6 :   put_stringbuf (&sb, "(10:public-key(");
     752             : 
     753             :   /* fixme: we can also use the oidstring here and prefix it with
     754             :      "oid." - this way we can pass more information into Libgcrypt or
     755             :      whatever library is used */
     756           6 :   put_stringbuf_sexp (&sb, pk_algo_table[algoidx].algo_string);
     757             : 
     758             :   /* Insert the curve name for ECC. */
     759           6 :   if (pk_algo_table[algoidx].pkalgo == PKALGO_ECC && parm_oid)
     760             :     {
     761           0 :       put_stringbuf (&sb, "(");
     762           0 :       put_stringbuf_sexp (&sb, "curve");
     763           0 :       put_stringbuf_sexp (&sb, parm_oid);
     764           0 :       put_stringbuf (&sb, ")");
     765             :     }
     766             : 
     767             :   /* If parameters are given and we have a description for them, parse
     768             :      them. */
     769           6 :   if (parmder && parmderlen
     770           0 :       && pk_algo_table[algoidx].parmelem_string
     771           0 :       && pk_algo_table[algoidx].parmctrl_string)
     772             :     {
     773           0 :       elem = pk_algo_table[algoidx].parmelem_string;
     774           0 :       ctrl = pk_algo_table[algoidx].parmctrl_string;
     775           0 :       for (; *elem; ctrl++, elem++)
     776             :         {
     777             :           int is_int;
     778             : 
     779           0 :           if ( (*ctrl & 0x80) && !elem[1] )
     780             :             {
     781             :               /* Hack to allow reading a raw value.  */
     782           0 :               is_int = 1;
     783           0 :               len = parmderlen;
     784             :             }
     785             :           else
     786             :             {
     787           0 :               if (!parmderlen)
     788             :                 {
     789           0 :                   xfree (parm_oid);
     790           0 :                   return gpg_error (GPG_ERR_INV_KEYINFO);
     791             :                 }
     792           0 :               c = *parmder++; parmderlen--;
     793           0 :               if ( c != *ctrl )
     794             :                 {
     795           0 :                   xfree (parm_oid);
     796           0 :                   return gpg_error (GPG_ERR_UNEXPECTED_TAG);
     797             :                 }
     798           0 :               is_int = c == 0x02;
     799           0 :               TLV_LENGTH (parmder);
     800             :             }
     801           0 :           if (is_int && *elem != '-')  /* Take this integer.  */
     802             :             {
     803             :               char tmp[2];
     804             : 
     805           0 :               put_stringbuf (&sb, "(");
     806           0 :               tmp[0] = *elem; tmp[1] = 0;
     807           0 :               put_stringbuf_sexp (&sb, tmp);
     808           0 :               put_stringbuf_mem_sexp (&sb, parmder, len);
     809           0 :               parmder += len;
     810           0 :               parmderlen -= len;
     811           0 :               put_stringbuf (&sb, ")");
     812             :             }
     813             :         }
     814             :     }
     815             : 
     816             : 
     817             :   /* FIXME: We don't release the stringbuf in case of error
     818             :      better let the macro jump to a label */
     819           6 :   elem = pk_algo_table[algoidx].elem_string;
     820           6 :   ctrl = pk_algo_table[algoidx].ctrl_string;
     821          24 :   for (; *elem; ctrl++, elem++)
     822             :     {
     823             :       int is_int;
     824             : 
     825          18 :       if ( (*ctrl & 0x80) && !elem[1] )
     826             :         {
     827             :           /* Hack to allow reading a raw value.  */
     828           0 :           is_int = 1;
     829           0 :           len = derlen;
     830             :         }
     831             :       else
     832             :         {
     833          18 :           if (!derlen)
     834             :             {
     835           0 :               xfree (parm_oid);
     836           0 :               return gpg_error (GPG_ERR_INV_KEYINFO);
     837             :             }
     838          18 :           c = *der++; derlen--;
     839          18 :           if ( c != *ctrl )
     840             :             {
     841           0 :               xfree (parm_oid);
     842           0 :               return gpg_error (GPG_ERR_UNEXPECTED_TAG);
     843             :             }
     844          18 :           is_int = c == 0x02;
     845          18 :           TLV_LENGTH (der);
     846             :         }
     847          18 :       if (is_int && *elem != '-')  /* Take this integer.  */
     848             :         {
     849             :           char tmp[2];
     850             : 
     851          12 :           put_stringbuf (&sb, "(");
     852          12 :           tmp[0] = *elem; tmp[1] = 0;
     853          12 :           put_stringbuf_sexp (&sb, tmp);
     854          12 :           put_stringbuf_mem_sexp (&sb, der, len);
     855          12 :           der += len;
     856          12 :           derlen -= len;
     857          12 :           put_stringbuf (&sb, ")");
     858             :         }
     859             :     }
     860           6 :   put_stringbuf (&sb, "))");
     861           6 :   xfree (parm_oid);
     862             : 
     863           6 :   *r_string = get_stringbuf (&sb);
     864           6 :   if (!*r_string)
     865           0 :     return gpg_error (GPG_ERR_ENOMEM);
     866             : 
     867           6 :   return 0;
     868             : }
     869             : 
     870             : 
     871             : /* Match the algorithm string given in BUF which is of length BUFLEN
     872             :    with the known algorithms from our table and returns the table
     873             :    entries for the DER encoded OID.  If WITH_SIG is true, the table of
     874             :    signature algorithms is consulted first.  */
     875             : static const unsigned char *
     876           6 : oid_from_buffer (const unsigned char *buf, int buflen, int *oidlen,
     877             :                  pkalgo_t *r_pkalgo, int with_sig)
     878             : {
     879             :   int i;
     880             : 
     881             :   /* Ignore an optional "oid." prefix. */
     882           6 :   if (buflen > 4 && buf[3] == '.' && digitp (buf+4)
     883           0 :       && ((buf[0] == 'o' && buf[1] == 'i' && buf[2] == 'd')
     884           0 :           ||(buf[0] == 'O' && buf[1] == 'I' && buf[2] == 'D')))
     885             :     {
     886           0 :       buf += 4;
     887           0 :       buflen -= 4;
     888             :     }
     889             : 
     890           6 :   if (with_sig)
     891             :     {
     892             :       /* Scan the signature table first. */
     893           0 :       for (i=0; sig_algo_table[i].oid; i++)
     894             :         {
     895           0 :           if (!sig_algo_table[i].supported)
     896           0 :             continue;
     897           0 :           if (buflen == strlen (sig_algo_table[i].oidstring)
     898           0 :               && !memcmp (buf, sig_algo_table[i].oidstring, buflen))
     899           0 :             break;
     900           0 :           if (buflen == strlen (sig_algo_table[i].algo_string)
     901           0 :               && !memcmp (buf, sig_algo_table[i].algo_string, buflen))
     902           0 :             break;
     903             :         }
     904           0 :       if (sig_algo_table[i].oid)
     905             :         {
     906           0 :           *r_pkalgo = sig_algo_table[i].pkalgo;
     907           0 :           *oidlen = sig_algo_table[i].oidlen;
     908           0 :           return sig_algo_table[i].oid;
     909             :         }
     910             :     }
     911             : 
     912             :   /* Scan the standard table. */
     913           6 :   for (i=0; pk_algo_table[i].oid; i++)
     914             :     {
     915           6 :       if (!pk_algo_table[i].supported)
     916           0 :         continue;
     917           6 :       if (buflen == strlen (pk_algo_table[i].oidstring)
     918           0 :           && !memcmp (buf, pk_algo_table[i].oidstring, buflen))
     919           0 :         break;
     920           6 :       if (buflen == strlen (pk_algo_table[i].algo_string)
     921           6 :           && !memcmp (buf, pk_algo_table[i].algo_string, buflen))
     922           6 :         break;
     923             :     }
     924           6 :   if (!pk_algo_table[i].oid)
     925           0 :     return NULL;
     926             : 
     927           6 :   *r_pkalgo = pk_algo_table[i].pkalgo;
     928           6 :   *oidlen = pk_algo_table[i].oidlen;
     929           6 :   return pk_algo_table[i].oid;
     930             : }
     931             : 
     932             : 
     933             : /* Take a public-key S-Exp and convert it into a DER encoded
     934             :    publicKeyInfo */
     935             : gpg_error_t
     936           6 : _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
     937             :                          unsigned char **r_der, size_t *r_derlen)
     938             : {
     939             :   gpg_error_t err;
     940             :   const unsigned char *s;
     941             :   char *endp;
     942             :   unsigned long n, n1;
     943             :   const unsigned char *oid;
     944             :   int oidlen;
     945           6 :   unsigned char *curve_oid = NULL;
     946             :   size_t curve_oidlen;
     947             :   pkalgo_t pkalgo;
     948             :   int i;
     949             :   struct {
     950             :     const char *name;
     951             :     int namelen;
     952             :     const unsigned char *value;
     953             :     int valuelen;
     954             :   } parm[10];
     955             :   int parmidx;
     956             :   int idxtbl[10];
     957             :   int idxtbllen;
     958             :   const char *parmdesc, *algoparmdesc;
     959           6 :   ksba_writer_t writer = NULL;
     960           6 :   void *algoparmseq_value = NULL;
     961             :   size_t algoparmseq_len;
     962           6 :   void *bitstr_value = NULL;
     963             :   size_t bitstr_len;
     964             : 
     965           6 :   if (!sexp)
     966           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     967             : 
     968           6 :   s = sexp;
     969           6 :   if (*s != '(')
     970           0 :     return gpg_error (GPG_ERR_INV_SEXP);
     971           6 :   s++;
     972             : 
     973           6 :   n = strtoul (s, &endp, 10);
     974           6 :   s = endp;
     975           6 :   if (!n || *s != ':')
     976           0 :     return gpg_error (GPG_ERR_INV_SEXP); /* we don't allow empty lengths */
     977           6 :   s++;
     978           6 :   if (n != 10 || memcmp (s, "public-key", 10))
     979           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     980           6 :   s += 10;
     981           6 :   if (*s != '(')
     982           0 :     return gpg_error (digitp (s)? GPG_ERR_UNKNOWN_SEXP : GPG_ERR_INV_SEXP);
     983           6 :   s++;
     984             : 
     985             :   /* Break out the algorithm ID */
     986           6 :   n = strtoul (s, &endp, 10);
     987           6 :   s = endp;
     988           6 :   if (!n || *s != ':')
     989           0 :     return gpg_error (GPG_ERR_INV_SEXP); /* we don't allow empty lengths */
     990           6 :   s++;
     991           6 :   oid = oid_from_buffer (s, n, &oidlen, &pkalgo, 0);
     992           6 :   if (!oid)
     993           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     994           6 :   s += n;
     995             : 
     996             :   /* Collect all the values */
     997          18 :   for (parmidx = 0; *s != ')' ; parmidx++)
     998             :     {
     999          12 :       if (parmidx >= DIM(parm))
    1000           0 :         return gpg_error (GPG_ERR_GENERAL);
    1001          12 :       if (*s != '(')
    1002           0 :         return gpg_error (digitp(s)? GPG_ERR_UNKNOWN_SEXP:GPG_ERR_INV_SEXP);
    1003          12 :       s++;
    1004          12 :       n = strtoul (s, &endp, 10);
    1005          12 :       s = endp;
    1006          12 :       if (!n || *s != ':')
    1007           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1008          12 :       s++;
    1009          12 :       parm[parmidx].name = s;
    1010          12 :       parm[parmidx].namelen = n;
    1011          12 :       s += n;
    1012          12 :       if (!digitp(s))
    1013           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
    1014             : 
    1015          12 :       n = strtoul (s, &endp, 10);
    1016          12 :       s = endp;
    1017          12 :       if (!n || *s != ':')
    1018           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1019          12 :       s++;
    1020          12 :       parm[parmidx].value = s;
    1021          12 :       parm[parmidx].valuelen = n;
    1022          12 :       s += n;
    1023          12 :       if ( *s != ')')
    1024           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
    1025          12 :       s++;
    1026             :     }
    1027           6 :   s++;
    1028             :   /* We need another closing parenthesis. */
    1029           6 :   if ( *s != ')' )
    1030           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1031             : 
    1032             :   /* Describe the parameters in the order we want them and construct
    1033             :      IDXTBL to access them.  For DSA wie also set algoparmdesc so
    1034             :      that we can later build the parameters for the
    1035             :      algorithmIdentifier.  */
    1036           6 :   algoparmdesc = NULL;
    1037           6 :   switch (pkalgo)
    1038             :     {
    1039           6 :     case PKALGO_RSA: parmdesc = "ne"; break;
    1040           0 :     case PKALGO_DSA: parmdesc = "y" ; algoparmdesc = "pqg"; break;
    1041           0 :     case PKALGO_ECC: parmdesc = "Cq"; break;
    1042           0 :     default: return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
    1043             :     }
    1044             : 
    1045           6 :   idxtbllen = 0;
    1046          18 :   for (s = parmdesc; *s; s++)
    1047             :     {
    1048          30 :       for (i=0; i < parmidx; i++)
    1049             :         {
    1050          18 :           assert (idxtbllen < DIM (idxtbl));
    1051          18 :           switch (*s)
    1052             :             {
    1053             :             case 'C': /* Magic value for "curve".  */
    1054           0 :               if (parm[i].namelen == 5 && !memcmp (parm[i].name, "curve", 5))
    1055             :                 {
    1056           0 :                   idxtbl[idxtbllen++] = i;
    1057           0 :                   i = parmidx; /* Break inner loop.  */
    1058             :                 }
    1059           0 :               break;
    1060             :             default:
    1061          18 :               if (parm[i].namelen == 1 && parm[i].name[0] == *s)
    1062             :                 {
    1063          12 :                   idxtbl[idxtbllen++] = i;
    1064          12 :                   i = parmidx; /* Break inner loop.  */
    1065             :                 }
    1066          18 :               break;
    1067             :             }
    1068             :         }
    1069             :     }
    1070           6 :   if (idxtbllen != strlen (parmdesc))
    1071           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1072             : 
    1073           6 :   if (pkalgo == PKALGO_ECC)
    1074             :     {
    1075           0 :       curve_oid = get_ecc_curve_oid (parm[idxtbl[0]].value,
    1076           0 :                                      parm[idxtbl[0]].valuelen,
    1077             :                                      &curve_oidlen);
    1078           0 :       if (!curve_oid)
    1079           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1080             :     }
    1081             : 
    1082             : 
    1083             :   /* Create write object. */
    1084           6 :   err = ksba_writer_new (&writer);
    1085           6 :   if (err)
    1086           0 :     goto leave;
    1087           6 :   err = ksba_writer_set_mem (writer, 1024);
    1088           6 :   if (err)
    1089           0 :     goto leave;
    1090             : 
    1091             :   /* We create the keyinfo in 2 steps:
    1092             : 
    1093             :      1. We build the inner one and encapsulate it in a bit string.
    1094             : 
    1095             :      2. We create the outer sequence include the algorithm identifier
    1096             :         and the bit string from step 1.
    1097             :    */
    1098           6 :   if (pkalgo == PKALGO_ECC)
    1099             :     {
    1100             :       /* Write the bit string header and the number of unused bits. */
    1101           0 :       err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL,
    1102           0 :                                 0, parm[idxtbl[1]].valuelen + 1);
    1103           0 :       if (!err)
    1104           0 :         err = ksba_writer_write (writer, "", 1);
    1105             :       /* And the actual raw value.  */
    1106           0 :       if (!err)
    1107           0 :         err = ksba_writer_write (writer, parm[idxtbl[1]].value,
    1108           0 :                                  parm[idxtbl[1]].valuelen);
    1109           0 :       if (err)
    1110           0 :         goto leave;
    1111             : 
    1112             :     }
    1113             :   else /* RSA and DSA */
    1114             :     {
    1115             :       /* Calculate the size of the sequence value and the size of the
    1116             :          bit string value.  NOt ethat in case there is only one
    1117             :          integer to write, no sequence is used.  */
    1118          18 :       for (n=0, i=0; i < idxtbllen; i++ )
    1119             :         {
    1120          12 :           n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
    1121          12 :                                    parm[idxtbl[i]].valuelen);
    1122          12 :           n += parm[idxtbl[i]].valuelen;
    1123             :         }
    1124             : 
    1125           6 :       n1 = 1; /* # of unused bits.  */
    1126           6 :       if (idxtbllen > 1)
    1127           6 :         n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
    1128           6 :       n1 += n;
    1129             : 
    1130             :       /* Write the bit string header and the number of unused bits. */
    1131           6 :       err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL,
    1132             :                                 0, n1);
    1133           6 :       if (!err)
    1134           6 :         err = ksba_writer_write (writer, "", 1);
    1135           6 :       if (err)
    1136           0 :         goto leave;
    1137             : 
    1138             :       /* Write the sequence tag and the integers. */
    1139           6 :       if (idxtbllen > 1)
    1140           6 :         err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1,n);
    1141           6 :       if (err)
    1142           0 :         goto leave;
    1143          18 :       for (i=0; i < idxtbllen; i++)
    1144             :         {
    1145             :           /* fixme: we should make sure that the integer conforms to the
    1146             :              ASN.1 encoding rules. */
    1147          12 :           err  = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0,
    1148          12 :                                      parm[idxtbl[i]].valuelen);
    1149          12 :           if (!err)
    1150          12 :             err = ksba_writer_write (writer, parm[idxtbl[i]].value,
    1151          12 :                                      parm[idxtbl[i]].valuelen);
    1152          12 :           if (err)
    1153           0 :             goto leave;
    1154             :         }
    1155             :     }
    1156             : 
    1157             :   /* Get the encoded bit string. */
    1158           6 :   bitstr_value = ksba_writer_snatch_mem (writer, &bitstr_len);
    1159           6 :   if (!bitstr_value)
    1160             :     {
    1161           0 :       err = gpg_error (GPG_ERR_ENOMEM);
    1162           0 :       goto leave;
    1163             :     }
    1164             : 
    1165             :   /* If the algorithmIdentifier requires a sequence with parameters,
    1166             :      build them now.  We can reuse the IDXTBL for that.  */
    1167           6 :   if (algoparmdesc)
    1168             :     {
    1169           0 :       idxtbllen = 0;
    1170           0 :       for (s = algoparmdesc; *s; s++)
    1171             :         {
    1172           0 :           for (i=0; i < parmidx; i++)
    1173             :             {
    1174           0 :               assert (idxtbllen < DIM (idxtbl));
    1175           0 :               if (parm[i].namelen == 1 && parm[i].name[0] == *s)
    1176             :                 {
    1177           0 :                   idxtbl[idxtbllen++] = i;
    1178           0 :                   break;
    1179             :                 }
    1180             :             }
    1181             :         }
    1182           0 :       if (idxtbllen != strlen (algoparmdesc))
    1183           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1184             : 
    1185           0 :       err = ksba_writer_set_mem (writer, 1024);
    1186           0 :       if (err)
    1187           0 :         goto leave;
    1188             : 
    1189             :       /* Calculate the size of the sequence.  */
    1190           0 :       for (n=0, i=0; i < idxtbllen; i++ )
    1191             :         {
    1192           0 :           n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
    1193           0 :                                    parm[idxtbl[i]].valuelen);
    1194           0 :           n += parm[idxtbl[i]].valuelen;
    1195             :         }
    1196             :       /*  n += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n); */
    1197             : 
    1198             :       /* Write the sequence tag followed by the integers. */
    1199           0 :       err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
    1200           0 :       if (err)
    1201           0 :         goto leave;
    1202           0 :       for (i=0; i < idxtbllen; i++)
    1203             :         {
    1204           0 :           err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0,
    1205           0 :                                     parm[idxtbl[i]].valuelen);
    1206           0 :           if (!err)
    1207           0 :             err = ksba_writer_write (writer, parm[idxtbl[i]].value,
    1208           0 :                                      parm[idxtbl[i]].valuelen);
    1209           0 :           if (err)
    1210           0 :             goto leave;
    1211             :         }
    1212             : 
    1213             :       /* Get the encoded sequence.  */
    1214           0 :       algoparmseq_value = ksba_writer_snatch_mem (writer, &algoparmseq_len);
    1215           0 :       if (!algoparmseq_value)
    1216             :         {
    1217           0 :           err = gpg_error (GPG_ERR_ENOMEM);
    1218           0 :           goto leave;
    1219             :         }
    1220             :     }
    1221             :   else
    1222           6 :     algoparmseq_len = 0;
    1223             : 
    1224             :   /* Reinitialize the buffer to create the outer sequence. */
    1225           6 :   err = ksba_writer_set_mem (writer, 1024);
    1226           6 :   if (err)
    1227           0 :     goto leave;
    1228             : 
    1229             :   /* Calulate lengths. */
    1230           6 :   n  = _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, oidlen);
    1231           6 :   n += oidlen;
    1232           6 :   if (algoparmseq_len)
    1233             :     {
    1234           0 :       n += algoparmseq_len;
    1235             :     }
    1236           6 :   else if (pkalgo == PKALGO_ECC)
    1237             :     {
    1238           0 :       n += _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL,
    1239             :                                0, curve_oidlen);
    1240           0 :       n += curve_oidlen;
    1241             :     }
    1242           6 :   else if (pkalgo == PKALGO_RSA)
    1243             :     {
    1244           6 :       n += _ksba_ber_count_tl (TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
    1245             :     }
    1246             : 
    1247           6 :   n1 = n;
    1248           6 :   n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
    1249           6 :   n1 += bitstr_len;
    1250             : 
    1251             :   /* The outer sequence.  */
    1252           6 :   err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n1);
    1253           6 :   if (err)
    1254           0 :     goto leave;
    1255             : 
    1256             :   /* The sequence.  */
    1257           6 :   err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
    1258           6 :   if (err)
    1259           0 :     goto leave;
    1260             : 
    1261             :   /* The object id.  */
    1262           6 :   err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID,CLASS_UNIVERSAL, 0, oidlen);
    1263           6 :   if (!err)
    1264           6 :     err = ksba_writer_write (writer, oid, oidlen);
    1265           6 :   if (err)
    1266           0 :     goto leave;
    1267             : 
    1268             :   /* The parameter. */
    1269           6 :   if (algoparmseq_len)
    1270             :     {
    1271           0 :       err = ksba_writer_write (writer, algoparmseq_value, algoparmseq_len);
    1272             :     }
    1273           6 :   else if (pkalgo == PKALGO_ECC)
    1274             :     {
    1275           0 :       err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID, CLASS_UNIVERSAL,
    1276             :                                 0, curve_oidlen);
    1277           0 :       if (!err)
    1278           0 :         err = ksba_writer_write (writer, curve_oid, curve_oidlen);
    1279             :     }
    1280           6 :   else if (pkalgo == PKALGO_RSA)
    1281             :     {
    1282           6 :       err = _ksba_ber_write_tl (writer, TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
    1283             :     }
    1284           6 :   if (err)
    1285           0 :     goto leave;
    1286             : 
    1287             :   /* Append the pre-constructed bit string.  */
    1288           6 :   err = ksba_writer_write (writer, bitstr_value, bitstr_len);
    1289           6 :   if (err)
    1290           0 :     goto leave;
    1291             : 
    1292             :   /* Get the result. */
    1293           6 :   *r_der = ksba_writer_snatch_mem (writer, r_derlen);
    1294           6 :   if (!*r_der)
    1295           0 :     err = gpg_error (GPG_ERR_ENOMEM);
    1296             : 
    1297             :  leave:
    1298           6 :   ksba_writer_release (writer);
    1299           6 :   xfree (bitstr_value);
    1300           6 :   xfree (curve_oid);
    1301           6 :   return err;
    1302             : }
    1303             : 
    1304             : 
    1305             : /* Take a sig-val s-expression and convert it into a DER encoded
    1306             :    algorithmInfo.  Unfortunately this function clones a lot of code
    1307             :    from _ksba_keyinfo_from_sexp.  */
    1308             : gpg_error_t
    1309           0 : _ksba_algoinfo_from_sexp (ksba_const_sexp_t sexp,
    1310             :                           unsigned char **r_der, size_t *r_derlen)
    1311             : {
    1312             :   gpg_error_t err;
    1313             :   const unsigned char *s;
    1314             :   char *endp;
    1315             :   unsigned long n;
    1316             :   const unsigned char *oid;
    1317             :   int oidlen;
    1318           0 :   unsigned char *curve_oid = NULL;
    1319             :   size_t curve_oidlen;
    1320             :   pkalgo_t pkalgo;
    1321             :   int i;
    1322             :   struct {
    1323             :     const char *name;
    1324             :     int namelen;
    1325             :     const unsigned char *value;
    1326             :     int valuelen;
    1327             :   } parm[10];
    1328             :   int parmidx;
    1329             :   int idxtbl[10];
    1330             :   int idxtbllen;
    1331             :   const char *parmdesc, *algoparmdesc;
    1332           0 :   ksba_writer_t writer = NULL;
    1333           0 :   void *algoparmseq_value = NULL;
    1334             :   size_t algoparmseq_len;
    1335             : 
    1336           0 :   if (!sexp)
    1337           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1338             : 
    1339           0 :   s = sexp;
    1340           0 :   if (*s != '(')
    1341           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1342           0 :   s++;
    1343             : 
    1344           0 :   n = strtoul (s, &endp, 10);
    1345           0 :   s = endp;
    1346           0 :   if (!n || *s != ':')
    1347           0 :     return gpg_error (GPG_ERR_INV_SEXP); /* We don't allow empty lengths.  */
    1348           0 :   s++;
    1349           0 :   if (n == 7 && !memcmp (s, "sig-val", 7))
    1350           0 :     s += 7;
    1351           0 :   else if (n == 10 && !memcmp (s, "public-key", 10))
    1352           0 :     s += 10;
    1353             :   else
    1354           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1355             : 
    1356           0 :   if (*s != '(')
    1357           0 :     return gpg_error (digitp (s)? GPG_ERR_UNKNOWN_SEXP : GPG_ERR_INV_SEXP);
    1358           0 :   s++;
    1359             : 
    1360             :   /* Break out the algorithm ID */
    1361           0 :   n = strtoul (s, &endp, 10);
    1362           0 :   s = endp;
    1363           0 :   if (!n || *s != ':')
    1364           0 :     return gpg_error (GPG_ERR_INV_SEXP); /* We don't allow empty lengths.  */
    1365           0 :   s++;
    1366           0 :   oid = oid_from_buffer (s, n, &oidlen, &pkalgo, 1);
    1367           0 :   if (!oid)
    1368           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
    1369           0 :   s += n;
    1370             : 
    1371             :   /* Collect all the values */
    1372           0 :   for (parmidx = 0; *s != ')' ; parmidx++)
    1373             :     {
    1374           0 :       if (parmidx >= DIM(parm))
    1375           0 :         return gpg_error (GPG_ERR_GENERAL);
    1376           0 :       if (*s != '(')
    1377           0 :         return gpg_error (digitp(s)? GPG_ERR_UNKNOWN_SEXP:GPG_ERR_INV_SEXP);
    1378           0 :       s++;
    1379           0 :       n = strtoul (s, &endp, 10);
    1380           0 :       s = endp;
    1381           0 :       if (!n || *s != ':')
    1382           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1383           0 :       s++;
    1384           0 :       parm[parmidx].name = s;
    1385           0 :       parm[parmidx].namelen = n;
    1386           0 :       s += n;
    1387           0 :       if (!digitp(s))
    1388           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
    1389             : 
    1390           0 :       n = strtoul (s, &endp, 10);
    1391           0 :       s = endp;
    1392           0 :       if (!n || *s != ':')
    1393           0 :         return gpg_error (GPG_ERR_INV_SEXP);
    1394           0 :       s++;
    1395           0 :       parm[parmidx].value = s;
    1396           0 :       parm[parmidx].valuelen = n;
    1397           0 :       s += n;
    1398           0 :       if ( *s != ')')
    1399           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
    1400           0 :       s++;
    1401             :     }
    1402           0 :   s++;
    1403             :   /* We need another closing parenthesis. */
    1404           0 :   if ( *s != ')' )
    1405           0 :     return gpg_error (GPG_ERR_INV_SEXP);
    1406             : 
    1407             :   /* Describe the parameters in the order we want them and construct
    1408             :      IDXTBL to access them.  For DSA wie also set algoparmdesc so
    1409             :      that we can later build the parameters for the
    1410             :      algorithmIdentifier.  */
    1411           0 :   algoparmdesc = NULL;
    1412           0 :   switch (pkalgo)
    1413             :     {
    1414           0 :     case PKALGO_RSA: parmdesc = ""; break;
    1415           0 :     case PKALGO_DSA: parmdesc = "" ; algoparmdesc = "pqg"; break;
    1416           0 :     case PKALGO_ECC: parmdesc = "C"; break;
    1417           0 :     default: return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
    1418             :     }
    1419             : 
    1420           0 :   idxtbllen = 0;
    1421           0 :   for (s = parmdesc; *s; s++)
    1422             :     {
    1423           0 :       for (i=0; i < parmidx; i++)
    1424             :         {
    1425           0 :           assert (idxtbllen < DIM (idxtbl));
    1426           0 :           switch (*s)
    1427             :             {
    1428             :             case 'C': /* Magic value for "curve".  */
    1429           0 :               if (parm[i].namelen == 5 && !memcmp (parm[i].name, "curve", 5))
    1430             :                 {
    1431           0 :                   idxtbl[idxtbllen++] = i;
    1432           0 :                   i = parmidx; /* Break inner loop.  */
    1433             :                 }
    1434           0 :               break;
    1435             :             default:
    1436           0 :               if (parm[i].namelen == 1 && parm[i].name[0] == *s)
    1437             :                 {
    1438           0 :                   idxtbl[idxtbllen++] = i;
    1439           0 :                   i = parmidx; /* Break inner loop.  */
    1440             :                 }
    1441           0 :               break;
    1442             :             }
    1443             :         }
    1444             :     }
    1445           0 :   if (idxtbllen != strlen (parmdesc))
    1446           0 :     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1447             : 
    1448           0 :   if (pkalgo == PKALGO_ECC)
    1449             :     {
    1450           0 :       curve_oid = get_ecc_curve_oid (parm[idxtbl[0]].value,
    1451           0 :                                      parm[idxtbl[0]].valuelen,
    1452             :                                      &curve_oidlen);
    1453           0 :       if (!curve_oid)
    1454           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1455             :     }
    1456             : 
    1457             : 
    1458             :   /* Create write object. */
    1459           0 :   err = ksba_writer_new (&writer);
    1460           0 :   if (err)
    1461           0 :     goto leave;
    1462           0 :   err = ksba_writer_set_mem (writer, 1024);
    1463           0 :   if (err)
    1464           0 :     goto leave;
    1465             : 
    1466             :   /* Create the sequence of the algorithm identifier.  */
    1467             : 
    1468             :   /* If the algorithmIdentifier requires a sequence with parameters,
    1469             :      build them now.  We can reuse the IDXTBL for that.  */
    1470           0 :   if (algoparmdesc)
    1471             :     {
    1472           0 :       idxtbllen = 0;
    1473           0 :       for (s = algoparmdesc; *s; s++)
    1474             :         {
    1475           0 :           for (i=0; i < parmidx; i++)
    1476             :             {
    1477           0 :               assert (idxtbllen < DIM (idxtbl));
    1478           0 :               if (parm[i].namelen == 1 && parm[i].name[0] == *s)
    1479             :                 {
    1480           0 :                   idxtbl[idxtbllen++] = i;
    1481           0 :                   break;
    1482             :                 }
    1483             :             }
    1484             :         }
    1485           0 :       if (idxtbllen != strlen (algoparmdesc))
    1486           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    1487             : 
    1488           0 :       err = ksba_writer_set_mem (writer, 1024);
    1489           0 :       if (err)
    1490           0 :         goto leave;
    1491             : 
    1492             :       /* Calculate the size of the sequence.  */
    1493           0 :       for (n=0, i=0; i < idxtbllen; i++ )
    1494             :         {
    1495           0 :           n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
    1496           0 :                                    parm[idxtbl[i]].valuelen);
    1497           0 :           n += parm[idxtbl[i]].valuelen;
    1498             :         }
    1499             : 
    1500             :       /* Write the sequence tag followed by the integers. */
    1501           0 :       err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
    1502           0 :       if (err)
    1503           0 :         goto leave;
    1504           0 :       for (i=0; i < idxtbllen; i++)
    1505             :         {
    1506           0 :           err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0,
    1507           0 :                                     parm[idxtbl[i]].valuelen);
    1508           0 :           if (!err)
    1509           0 :             err = ksba_writer_write (writer, parm[idxtbl[i]].value,
    1510           0 :                                      parm[idxtbl[i]].valuelen);
    1511           0 :           if (err)
    1512           0 :             goto leave;
    1513             :         }
    1514             : 
    1515             :       /* Get the encoded sequence.  */
    1516           0 :       algoparmseq_value = ksba_writer_snatch_mem (writer, &algoparmseq_len);
    1517           0 :       if (!algoparmseq_value)
    1518             :         {
    1519           0 :           err = gpg_error (GPG_ERR_ENOMEM);
    1520           0 :           goto leave;
    1521             :         }
    1522             :     }
    1523             :   else
    1524           0 :     algoparmseq_len = 0;
    1525             : 
    1526             :   /* Reinitialize the buffer to create the sequence. */
    1527           0 :   err = ksba_writer_set_mem (writer, 1024);
    1528           0 :   if (err)
    1529           0 :     goto leave;
    1530             : 
    1531             :   /* Calulate lengths. */
    1532           0 :   n  = _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, oidlen);
    1533           0 :   n += oidlen;
    1534           0 :   if (algoparmseq_len)
    1535             :     {
    1536           0 :       n += algoparmseq_len;
    1537             :     }
    1538           0 :   else if (pkalgo == PKALGO_ECC)
    1539             :     {
    1540           0 :       n += _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL,
    1541             :                                0, curve_oidlen);
    1542           0 :       n += curve_oidlen;
    1543             :     }
    1544           0 :   else if (pkalgo == PKALGO_RSA)
    1545             :     {
    1546           0 :       n += _ksba_ber_count_tl (TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
    1547             :     }
    1548             : 
    1549             :   /* Write the sequence.  */
    1550           0 :   err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
    1551           0 :   if (err)
    1552           0 :     goto leave;
    1553             : 
    1554             :   /* Write the object id.  */
    1555           0 :   err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, oidlen);
    1556           0 :   if (!err)
    1557           0 :     err = ksba_writer_write (writer, oid, oidlen);
    1558           0 :   if (err)
    1559           0 :     goto leave;
    1560             : 
    1561             :   /* Write the parameters. */
    1562           0 :   if (algoparmseq_len)
    1563             :     {
    1564           0 :       err = ksba_writer_write (writer, algoparmseq_value, algoparmseq_len);
    1565             :     }
    1566           0 :   else if (pkalgo == PKALGO_ECC)
    1567             :     {
    1568             :       /* We only support the namedCuve choice for ECC parameters.  */
    1569           0 :       err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID, CLASS_UNIVERSAL,
    1570             :                                 0, curve_oidlen);
    1571           0 :       if (!err)
    1572           0 :         err = ksba_writer_write (writer, curve_oid, curve_oidlen);
    1573             :     }
    1574           0 :   else if (pkalgo == PKALGO_RSA)
    1575             :     {
    1576           0 :       err = _ksba_ber_write_tl (writer, TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
    1577             :     }
    1578           0 :   if (err)
    1579           0 :     goto leave;
    1580             : 
    1581             :   /* Get the result. */
    1582           0 :   *r_der = ksba_writer_snatch_mem (writer, r_derlen);
    1583           0 :   if (!*r_der)
    1584           0 :     err = gpg_error (GPG_ERR_ENOMEM);
    1585             : 
    1586             :  leave:
    1587           0 :   ksba_writer_release (writer);
    1588           0 :   xfree (curve_oid);
    1589           0 :   return err;
    1590             : }
    1591             : 
    1592             : 
    1593             : 
    1594             : /* Mode 0: work as described under _ksba_sigval_to_sexp
    1595             :    mode 1: work as described under _ksba_encval_to_sexp */
    1596             : static gpg_error_t
    1597           1 : cryptval_to_sexp (int mode, const unsigned char *der, size_t derlen,
    1598             :                   ksba_sexp_t *r_string)
    1599             : {
    1600             :   gpg_error_t err;
    1601             :   const struct algo_table_s *algo_table;
    1602             :   int c;
    1603             :   size_t nread, off, len;
    1604             :   int algoidx;
    1605             :   int is_bitstr;
    1606             :   const unsigned char *ctrl;
    1607             :   const char *elem;
    1608             :   struct stringbuf sb;
    1609             : 
    1610             :   /* FIXME: The entire function is very similar to keyinfo_to_sexp */
    1611           1 :   *r_string = NULL;
    1612             : 
    1613           1 :   if (!mode)
    1614           1 :     algo_table = sig_algo_table;
    1615             :   else
    1616           0 :     algo_table = enc_algo_table;
    1617             : 
    1618             : 
    1619           1 :   err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr,
    1620             :                        NULL, NULL, NULL);
    1621           1 :   if (err)
    1622           0 :     return err;
    1623             : 
    1624             :   /* look into our table of supported algorithms */
    1625           1 :   for (algoidx=0; algo_table[algoidx].oid; algoidx++)
    1626             :     {
    1627           1 :       if ( len == algo_table[algoidx].oidlen
    1628           1 :            && !memcmp (der+off, algo_table[algoidx].oid, len))
    1629           1 :         break;
    1630             :     }
    1631           1 :   if (!algo_table[algoidx].oid)
    1632           0 :     return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
    1633           1 :   if (!algo_table[algoidx].supported)
    1634           0 :     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
    1635             : 
    1636           1 :   der += nread;
    1637           1 :   derlen -= nread;
    1638             : 
    1639           1 :   if (is_bitstr)
    1640             :     { /* Funny: X.509 defines the signature value as a bit string but
    1641             :          CMS as an octet string - for ease of implementation we always
    1642             :          allow both */
    1643           1 :       if (!derlen)
    1644           0 :         return gpg_error (GPG_ERR_INV_KEYINFO);
    1645           1 :       c = *der++; derlen--;
    1646           1 :       if (c)
    1647           0 :         fprintf (stderr, "warning: number of unused bits is not zero\n");
    1648             :     }
    1649             : 
    1650             :   /* fixme: we should calculate the initial length form the size of the
    1651             :      sequence, so that we don't neen a realloc later */
    1652           1 :   init_stringbuf (&sb, 100);
    1653           1 :   put_stringbuf (&sb, mode? "(7:enc-val(":"(7:sig-val(");
    1654           1 :   put_stringbuf_sexp (&sb, algo_table[algoidx].algo_string);
    1655             : 
    1656             :   /* FIXME: We don't release the stringbuf in case of error
    1657             :      better let the macro jump to a label */
    1658           1 :   elem = algo_table[algoidx].elem_string;
    1659           1 :   ctrl = algo_table[algoidx].ctrl_string;
    1660           2 :   for (; *elem; ctrl++, elem++)
    1661             :     {
    1662             :       int is_int;
    1663             : 
    1664           1 :       if ( (*ctrl & 0x80) && !elem[1] )
    1665             :         {  /* Hack to allow a raw value */
    1666           1 :           is_int = 1;
    1667           1 :           len = derlen;
    1668             :         }
    1669             :       else
    1670             :         {
    1671           0 :           if (!derlen)
    1672           0 :             return gpg_error (GPG_ERR_INV_KEYINFO);
    1673           0 :           c = *der++; derlen--;
    1674           0 :           if ( c != *ctrl )
    1675           0 :             return gpg_error (GPG_ERR_UNEXPECTED_TAG);
    1676           0 :           is_int = c == 0x02;
    1677           0 :           TLV_LENGTH (der);
    1678             :         }
    1679           1 :       if (is_int && *elem != '-')
    1680             :         { /* take this integer */
    1681             :           char tmp[2];
    1682             : 
    1683           1 :           put_stringbuf (&sb, "(");
    1684           1 :           tmp[0] = *elem; tmp[1] = 0;
    1685           1 :           put_stringbuf_sexp (&sb, tmp);
    1686           1 :           put_stringbuf_mem_sexp (&sb, der, len);
    1687           1 :           der += len;
    1688           1 :           derlen -= len;
    1689           1 :           put_stringbuf (&sb, ")");
    1690             :         }
    1691             :     }
    1692           1 :   put_stringbuf (&sb, ")");
    1693           1 :   if (!mode && algo_table[algoidx].digest_string)
    1694             :     {
    1695             :       /* Insert the hash algorithm if included in the OID.  */
    1696           1 :       put_stringbuf (&sb, "(4:hash");
    1697           1 :       put_stringbuf_sexp (&sb, algo_table[algoidx].digest_string);
    1698           1 :       put_stringbuf (&sb, ")");
    1699             :     }
    1700           1 :   put_stringbuf (&sb, ")");
    1701             : 
    1702           1 :   *r_string = get_stringbuf (&sb);
    1703           1 :   if (!*r_string)
    1704           0 :     return gpg_error (GPG_ERR_ENOMEM);
    1705             : 
    1706           1 :   return 0;
    1707             : }
    1708             : 
    1709             : /* Assume that DER is a buffer of length DERLEN with a DER encoded
    1710             :    Asn.1 structure like this:
    1711             : 
    1712             :      SEQUENCE {
    1713             :         algorithm    OBJECT IDENTIFIER,
    1714             :         parameters   ANY DEFINED BY algorithm OPTIONAL }
    1715             :      signature  BIT STRING
    1716             : 
    1717             :   We only allow parameters == NULL.
    1718             : 
    1719             :   The function parses this structure and creates a S-Exp suitable to be
    1720             :   used as signature value in Libgcrypt:
    1721             : 
    1722             :   (sig-val
    1723             :     (<algo>
    1724             :       (<param_name1> <mpi>)
    1725             :       ...
    1726             :       (<param_namen> <mpi>))
    1727             :     (hash algo))
    1728             : 
    1729             :  The S-Exp will be returned in a string which the caller must free.
    1730             :  We don't pass an ASN.1 node here but a plain memory block.  */
    1731             : gpg_error_t
    1732           1 : _ksba_sigval_to_sexp (const unsigned char *der, size_t derlen,
    1733             :                       ksba_sexp_t *r_string)
    1734             : {
    1735           1 :   return cryptval_to_sexp (0, der, derlen, r_string);
    1736             : }
    1737             : 
    1738             : 
    1739             : /* Assume that der is a buffer of length DERLEN with a DER encoded
    1740             :  Asn.1 structure like this:
    1741             : 
    1742             :      SEQUENCE {
    1743             :         algorithm    OBJECT IDENTIFIER,
    1744             :         parameters   ANY DEFINED BY algorithm OPTIONAL }
    1745             :      encryptedKey  OCTET STRING
    1746             : 
    1747             :   We only allow parameters == NULL.
    1748             : 
    1749             :   The function parses this structure and creates a S-Exp suitable to be
    1750             :   used as encrypted value in Libgcrypt's public key functions:
    1751             : 
    1752             :   (enc-val
    1753             :     (<algo>
    1754             :       (<param_name1> <mpi>)
    1755             :       ...
    1756             :       (<param_namen> <mpi>)
    1757             :     ))
    1758             : 
    1759             :  The S-Exp will be returned in a string which the caller must free.
    1760             :  We don't pass an ASN.1 node here but a plain memory block.  */
    1761             : gpg_error_t
    1762           0 : _ksba_encval_to_sexp (const unsigned char *der, size_t derlen,
    1763             :                       ksba_sexp_t *r_string)
    1764             : {
    1765           0 :   return cryptval_to_sexp (1, der, derlen, r_string);
    1766             : }

Generated by: LCOV version 1.12