LCOV - code coverage report
Current view: top level - cipher - pubkey.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 206 328 62.8 %
Date: 2017-03-02 16:44:37 Functions: 19 27 70.4 %

          Line data    Source code
       1             : /* pubkey.c  -  pubkey dispatcher
       2             :  * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005,
       3             :  *               2007, 2008, 2011 Free Software Foundation, Inc.
       4             :  * Copyright (C) 2013 g10 Code GmbH
       5             :  *
       6             :  * This file is part of Libgcrypt.
       7             :  *
       8             :  * Libgcrypt is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU Lesser general Public License as
      10             :  * published by the Free Software Foundation; either version 2.1 of
      11             :  * the License, or (at your option) any later version.
      12             :  *
      13             :  * Libgcrypt is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #include <errno.h>
      27             : 
      28             : #include "g10lib.h"
      29             : #include "mpi.h"
      30             : #include "cipher.h"
      31             : #include "context.h"
      32             : #include "pubkey-internal.h"
      33             : 
      34             : 
      35             : /* This is the list of the public-key algorithms included in
      36             :    Libgcrypt.  */
      37             : static gcry_pk_spec_t *pubkey_list[] =
      38             :   {
      39             : #if USE_ECC
      40             :     &_gcry_pubkey_spec_ecc,
      41             : #endif
      42             : #if USE_RSA
      43             :     &_gcry_pubkey_spec_rsa,
      44             : #endif
      45             : #if USE_DSA
      46             :     &_gcry_pubkey_spec_dsa,
      47             : #endif
      48             : #if USE_ELGAMAL
      49             :     &_gcry_pubkey_spec_elg,
      50             : #endif
      51             :     NULL
      52             :   };
      53             : 
      54             : 
      55             : static int
      56          70 : map_algo (int algo)
      57             : {
      58          70 :  switch (algo)
      59             :    {
      60           0 :    case GCRY_PK_RSA_E: return GCRY_PK_RSA;
      61           0 :    case GCRY_PK_RSA_S: return GCRY_PK_RSA;
      62           0 :    case GCRY_PK_ELG_E: return GCRY_PK_ELG;
      63          38 :    case GCRY_PK_ECDSA: return GCRY_PK_ECC;
      64           0 :    case GCRY_PK_ECDH:  return GCRY_PK_ECC;
      65          32 :    default:            return algo;
      66             :    }
      67             : }
      68             : 
      69             : 
      70             : /* Return the spec structure for the public key algorithm ALGO.  For
      71             :    an unknown algorithm NULL is returned.  */
      72             : static gcry_pk_spec_t *
      73          62 : spec_from_algo (int algo)
      74             : {
      75             :   int idx;
      76             :   gcry_pk_spec_t *spec;
      77             : 
      78          62 :   algo = map_algo (algo);
      79             : 
      80          97 :   for (idx = 0; (spec = pubkey_list[idx]); idx++)
      81          97 :     if (algo == spec->algo)
      82          62 :       return spec;
      83           0 :   return NULL;
      84             : }
      85             : 
      86             : 
      87             : /* Return the spec structure for the public key algorithm with NAME.
      88             :    For an unknown name NULL is returned.  */
      89             : static gcry_pk_spec_t *
      90        5750 : spec_from_name (const char *name)
      91             : {
      92             :   gcry_pk_spec_t *spec;
      93             :   int idx;
      94             :   const char **aliases;
      95             : 
      96        9393 :   for (idx=0; (spec = pubkey_list[idx]); idx++)
      97             :     {
      98        9393 :       if (!stricmp (name, spec->name))
      99        5594 :         return spec;
     100       21220 :       for (aliases = spec->aliases; *aliases; aliases++)
     101       17577 :         if (!stricmp (name, *aliases))
     102         156 :           return spec;
     103             :     }
     104             : 
     105           0 :   return NULL;
     106             : }
     107             : 
     108             : 
     109             : 
     110             : /* Given the s-expression SEXP with the first element be either
     111             :  * "private-key" or "public-key" return the spec structure for it.  We
     112             :  * look through the list to find a list beginning with "private-key"
     113             :  * or "public-key" - the first one found is used.  If WANT_PRIVATE is
     114             :  * set the function will only succeed if a private key has been given.
     115             :  * On success the spec is stored at R_SPEC.  On error NULL is stored
     116             :  * at R_SPEC and an error code returned.  If R_PARMS is not NULL and
     117             :  * the function returns success, the parameter list below
     118             :  * "private-key" or "public-key" is stored there and the caller must
     119             :  * call gcry_sexp_release on it.
     120             :  */
     121             : static gcry_err_code_t
     122        5621 : spec_from_sexp (gcry_sexp_t sexp, int want_private,
     123             :                 gcry_pk_spec_t **r_spec, gcry_sexp_t *r_parms)
     124             : {
     125             :   gcry_sexp_t list, l2;
     126             :   char *name;
     127             :   gcry_pk_spec_t *spec;
     128             : 
     129        5621 :   *r_spec = NULL;
     130        5621 :   if (r_parms)
     131        5621 :     *r_parms = NULL;
     132             : 
     133             :   /* Check that the first element is valid.  If we are looking for a
     134             :      public key but a private key was supplied, we allow the use of
     135             :      the private key anyway.  The rationale for this is that the
     136             :      private key is a superset of the public key.  */
     137        5621 :   list = sexp_find_token (sexp, want_private? "private-key":"public-key", 0);
     138        5621 :   if (!list && !want_private)
     139          86 :     list = sexp_find_token (sexp, "private-key", 0);
     140        5621 :   if (!list)
     141           0 :     return GPG_ERR_INV_OBJ; /* Does not contain a key object.  */
     142             : 
     143        5621 :   l2 = sexp_cadr (list);
     144        5621 :   sexp_release (list);
     145        5621 :   list = l2;
     146        5621 :   name = sexp_nth_string (list, 0);
     147        5621 :   if (!name)
     148             :     {
     149           0 :       sexp_release ( list );
     150           0 :       return GPG_ERR_INV_OBJ;      /* Invalid structure of object. */
     151             :     }
     152        5621 :   spec = spec_from_name (name);
     153        5621 :   xfree (name);
     154        5621 :   if (!spec)
     155             :     {
     156           0 :       sexp_release (list);
     157           0 :       return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
     158             :     }
     159        5621 :   *r_spec = spec;
     160        5621 :   if (r_parms)
     161        5621 :     *r_parms = list;
     162             :   else
     163           0 :     sexp_release (list);
     164        5621 :   return 0;
     165             : }
     166             : 
     167             : 
     168             : 
     169             : /* Disable the use of the algorithm ALGO.  This is not thread safe and
     170             :    should thus be called early.  */
     171             : static void
     172           0 : disable_pubkey_algo (int algo)
     173             : {
     174           0 :   gcry_pk_spec_t *spec = spec_from_algo (algo);
     175             : 
     176           0 :   if (spec)
     177           0 :     spec->flags.disabled = 1;
     178           0 : }
     179             : 
     180             : 
     181             : 
     182             : /*
     183             :  * Map a string to the pubkey algo
     184             :  */
     185             : int
     186           0 : _gcry_pk_map_name (const char *string)
     187             : {
     188             :   gcry_pk_spec_t *spec;
     189             : 
     190           0 :   if (!string)
     191           0 :     return 0;
     192           0 :   spec = spec_from_name (string);
     193           0 :   if (!spec)
     194           0 :     return 0;
     195           0 :   if (spec->flags.disabled)
     196           0 :     return 0;
     197           0 :   return spec->algo;
     198             : }
     199             : 
     200             : 
     201             : /* Map the public key algorithm whose ID is contained in ALGORITHM to
     202             :    a string representation of the algorithm name.  For unknown
     203             :    algorithm IDs this functions returns "?". */
     204             : const char *
     205           0 : _gcry_pk_algo_name (int algo)
     206             : {
     207             :   gcry_pk_spec_t *spec;
     208             : 
     209           0 :   spec = spec_from_algo (algo);
     210           0 :   if (spec)
     211           0 :     return spec->name;
     212           0 :   return "?";
     213             : }
     214             : 
     215             : 
     216             : /****************
     217             :  * A USE of 0 means: don't care.
     218             :  */
     219             : static gcry_err_code_t
     220          56 : check_pubkey_algo (int algo, unsigned use)
     221             : {
     222          56 :   gcry_err_code_t err = 0;
     223             :   gcry_pk_spec_t *spec;
     224             : 
     225          56 :   spec = spec_from_algo (algo);
     226          56 :   if (spec)
     227             :     {
     228          56 :       if (((use & GCRY_PK_USAGE_SIGN)
     229           0 :            && (! (spec->use & GCRY_PK_USAGE_SIGN)))
     230          56 :           || ((use & GCRY_PK_USAGE_ENCR)
     231           0 :               && (! (spec->use & GCRY_PK_USAGE_ENCR))))
     232           0 :         err = GPG_ERR_WRONG_PUBKEY_ALGO;
     233             :     }
     234             :   else
     235           0 :     err = GPG_ERR_PUBKEY_ALGO;
     236             : 
     237          56 :   return err;
     238             : }
     239             : 
     240             : 
     241             : /****************
     242             :  * Return the number of public key material numbers
     243             :  */
     244             : static int
     245           0 : pubkey_get_npkey (int algo)
     246             : {
     247           0 :   gcry_pk_spec_t *spec = spec_from_algo (algo);
     248             : 
     249           0 :   return spec? strlen (spec->elements_pkey) : 0;
     250             : }
     251             : 
     252             : 
     253             : /****************
     254             :  * Return the number of secret key material numbers
     255             :  */
     256             : static int
     257           0 : pubkey_get_nskey (int algo)
     258             : {
     259           0 :   gcry_pk_spec_t *spec = spec_from_algo (algo);
     260             : 
     261           0 :   return spec? strlen (spec->elements_skey) : 0;
     262             : }
     263             : 
     264             : 
     265             : /****************
     266             :  * Return the number of signature material numbers
     267             :  */
     268             : static int
     269           0 : pubkey_get_nsig (int algo)
     270             : {
     271           0 :   gcry_pk_spec_t *spec = spec_from_algo (algo);
     272             : 
     273           0 :   return spec? strlen (spec->elements_sig) : 0;
     274             : }
     275             : 
     276             : /****************
     277             :  * Return the number of encryption material numbers
     278             :  */
     279             : static int
     280           0 : pubkey_get_nenc (int algo)
     281             : {
     282           0 :   gcry_pk_spec_t *spec = spec_from_algo (algo);
     283             : 
     284           0 :   return spec? strlen (spec->elements_enc) : 0;
     285             : }
     286             : 
     287             : 
     288             : 
     289             : /*
     290             :    Do a PK encrypt operation
     291             : 
     292             :    Caller has to provide a public key as the SEXP pkey and data as a
     293             :    SEXP with just one MPI in it. Alternatively S_DATA might be a
     294             :    complex S-Expression, similar to the one used for signature
     295             :    verification.  This provides a flag which allows to handle PKCS#1
     296             :    block type 2 padding.  The function returns a sexp which may be
     297             :    passed to to pk_decrypt.
     298             : 
     299             :    Returns: 0 or an errorcode.
     300             : 
     301             :    s_data = See comment for _gcry_pk_util_data_to_mpi
     302             :    s_pkey = <key-as-defined-in-sexp_to_key>
     303             :    r_ciph = (enc-val
     304             :                (<algo>
     305             :                  (<param_name1> <mpi>)
     306             :                  ...
     307             :                  (<param_namen> <mpi>)
     308             :                ))
     309             : 
     310             : */
     311             : gcry_err_code_t
     312         787 : _gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
     313             : {
     314             :   gcry_err_code_t rc;
     315             :   gcry_pk_spec_t *spec;
     316             :   gcry_sexp_t keyparms;
     317             : 
     318         787 :   *r_ciph = NULL;
     319             : 
     320         787 :   rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms);
     321         787 :   if (rc)
     322           0 :     goto leave;
     323             : 
     324         787 :   if (spec->encrypt)
     325         787 :     rc = spec->encrypt (r_ciph, s_data, keyparms);
     326             :   else
     327           0 :     rc = GPG_ERR_NOT_IMPLEMENTED;
     328             : 
     329             :  leave:
     330         787 :   sexp_release (keyparms);
     331         787 :   return rc;
     332             : }
     333             : 
     334             : 
     335             : /*
     336             :    Do a PK decrypt operation
     337             : 
     338             :    Caller has to provide a secret key as the SEXP skey and data in a
     339             :    format as created by gcry_pk_encrypt.  For historic reasons the
     340             :    function returns simply an MPI as an S-expression part; this is
     341             :    deprecated and the new method should be used which returns a real
     342             :    S-expressionl this is selected by adding at least an empty flags
     343             :    list to S_DATA.
     344             : 
     345             :    Returns: 0 or an errorcode.
     346             : 
     347             :    s_data = (enc-val
     348             :               [(flags [raw, pkcs1, oaep])]
     349             :               (<algo>
     350             :                 (<param_name1> <mpi>)
     351             :                 ...
     352             :                 (<param_namen> <mpi>)
     353             :               ))
     354             :    s_skey = <key-as-defined-in-sexp_to_key>
     355             :    r_plain= Either an incomplete S-expression without the parentheses
     356             :             or if the flags list is used (even if empty) a real S-expression:
     357             :             (value PLAIN).  In raw mode (or no flags given) the returned value
     358             :             is to be interpreted as a signed MPI, thus it may have an extra
     359             :             leading zero octet even if not included in the original data.
     360             :             With pkcs1 or oaep decoding enabled the returned value is a
     361             :             verbatim octet string.
     362             :  */
     363             : gcry_err_code_t
     364         692 : _gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
     365             : {
     366             :   gcry_err_code_t rc;
     367             :   gcry_pk_spec_t *spec;
     368             :   gcry_sexp_t keyparms;
     369             : 
     370         692 :   *r_plain = NULL;
     371             : 
     372         692 :   rc = spec_from_sexp (s_skey, 1, &spec, &keyparms);
     373         692 :   if (rc)
     374           0 :     goto leave;
     375             : 
     376         692 :   if (spec->decrypt)
     377         692 :     rc = spec->decrypt (r_plain, s_data, keyparms);
     378             :   else
     379           0 :     rc = GPG_ERR_NOT_IMPLEMENTED;
     380             : 
     381             :  leave:
     382         692 :   sexp_release (keyparms);
     383         692 :   return rc;
     384             : }
     385             : 
     386             : 
     387             : 
     388             : /*
     389             :    Create a signature.
     390             : 
     391             :    Caller has to provide a secret key as the SEXP skey and data
     392             :    expressed as a SEXP list hash with only one element which should
     393             :    instantly be available as a MPI. Alternatively the structure given
     394             :    below may be used for S_HASH, it provides the abiliy to pass flags
     395             :    to the operation; the flags defined by now are "pkcs1" which does
     396             :    PKCS#1 block type 1 style padding and "pss" for PSS encoding.
     397             : 
     398             :    Returns: 0 or an errorcode.
     399             :             In case of 0 the function returns a new SEXP with the
     400             :             signature value; the structure of this signature depends on the
     401             :             other arguments but is always suitable to be passed to
     402             :             gcry_pk_verify
     403             : 
     404             :    s_hash = See comment for _gcry-pk_util_data_to_mpi
     405             : 
     406             :    s_skey = <key-as-defined-in-sexp_to_key>
     407             :    r_sig  = (sig-val
     408             :               (<algo>
     409             :                 (<param_name1> <mpi>)
     410             :                 ...
     411             :                 (<param_namen> <mpi>))
     412             :              [(hash algo)])
     413             : 
     414             :   Note that (hash algo) in R_SIG is not used.
     415             : */
     416             : gcry_err_code_t
     417        2004 : _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
     418             : {
     419             :   gcry_err_code_t rc;
     420             :   gcry_pk_spec_t *spec;
     421             :   gcry_sexp_t keyparms;
     422             : 
     423        2004 :   *r_sig = NULL;
     424             : 
     425        2004 :   rc = spec_from_sexp (s_skey, 1, &spec, &keyparms);
     426        2004 :   if (rc)
     427           0 :     goto leave;
     428             : 
     429        2004 :   if (spec->sign)
     430        2004 :     rc = spec->sign (r_sig, s_hash, keyparms);
     431             :   else
     432           0 :     rc = GPG_ERR_NOT_IMPLEMENTED;
     433             : 
     434             :  leave:
     435        2004 :   sexp_release (keyparms);
     436        2004 :   return rc;
     437             : }
     438             : 
     439             : 
     440             : /*
     441             :    Verify a signature.
     442             : 
     443             :    Caller has to supply the public key pkey, the signature sig and his
     444             :    hashvalue data.  Public key has to be a standard public key given
     445             :    as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data
     446             :    must be an S-Exp like the one in sign too.  */
     447             : gcry_err_code_t
     448        2086 : _gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
     449             : {
     450             :   gcry_err_code_t rc;
     451             :   gcry_pk_spec_t *spec;
     452             :   gcry_sexp_t keyparms;
     453             : 
     454        2086 :   rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms);
     455        2086 :   if (rc)
     456           0 :     goto leave;
     457             : 
     458        2086 :   if (spec->verify)
     459        2086 :     rc = spec->verify (s_sig, s_hash, keyparms);
     460             :   else
     461           0 :     rc = GPG_ERR_NOT_IMPLEMENTED;
     462             : 
     463             :  leave:
     464        2086 :   sexp_release (keyparms);
     465        2086 :   return rc;
     466             : }
     467             : 
     468             : 
     469             : /*
     470             :    Test a key.
     471             : 
     472             :    This may be used either for a public or a secret key to see whether
     473             :    the internal structure is okay.
     474             : 
     475             :    Returns: 0 or an errorcode.
     476             : 
     477             :    NOTE: We currently support only secret key checking. */
     478             : gcry_err_code_t
     479          32 : _gcry_pk_testkey (gcry_sexp_t s_key)
     480             : {
     481             :   gcry_err_code_t rc;
     482             :   gcry_pk_spec_t *spec;
     483             :   gcry_sexp_t keyparms;
     484             : 
     485          32 :   rc = spec_from_sexp (s_key, 1, &spec, &keyparms);
     486          32 :   if (rc)
     487           0 :     goto leave;
     488             : 
     489          32 :   if (spec->check_secret_key)
     490          32 :     rc = spec->check_secret_key (keyparms);
     491             :   else
     492           0 :     rc = GPG_ERR_NOT_IMPLEMENTED;
     493             : 
     494             :  leave:
     495          32 :   sexp_release (keyparms);
     496          32 :   return rc;
     497             : }
     498             : 
     499             : 
     500             : /*
     501             :   Create a public key pair and return it in r_key.
     502             :   How the key is created depends on s_parms:
     503             :   (genkey
     504             :    (algo
     505             :      (parameter_name_1 ....)
     506             :       ....
     507             :      (parameter_name_n ....)
     508             :   ))
     509             :   The key is returned in a format depending on the
     510             :   algorithm. Both, private and secret keys are returned
     511             :   and optionally some additional informatin.
     512             :   For elgamal we return this structure:
     513             :   (key-data
     514             :    (public-key
     515             :      (elg
     516             :         (p <mpi>)
     517             :         (g <mpi>)
     518             :         (y <mpi>)
     519             :      )
     520             :    )
     521             :    (private-key
     522             :      (elg
     523             :         (p <mpi>)
     524             :         (g <mpi>)
     525             :         (y <mpi>)
     526             :         (x <mpi>)
     527             :      )
     528             :    )
     529             :    (misc-key-info
     530             :       (pm1-factors n1 n2 ... nn)
     531             :    ))
     532             :  */
     533             : gcry_err_code_t
     534          91 : _gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
     535             : {
     536          91 :   gcry_pk_spec_t *spec = NULL;
     537          91 :   gcry_sexp_t list = NULL;
     538          91 :   gcry_sexp_t l2 = NULL;
     539          91 :   char *name = NULL;
     540             :   gcry_err_code_t rc;
     541             : 
     542          91 :   *r_key = NULL;
     543             : 
     544          91 :   list = sexp_find_token (s_parms, "genkey", 0);
     545          91 :   if (!list)
     546             :     {
     547           0 :       rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */
     548           0 :       goto leave;
     549             :     }
     550             : 
     551          91 :   l2 = sexp_cadr (list);
     552          91 :   sexp_release (list);
     553          91 :   list = l2;
     554          91 :   l2 = NULL;
     555          91 :   if (! list)
     556             :     {
     557           0 :       rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */
     558           0 :       goto leave;
     559             :     }
     560             : 
     561          91 :   name = _gcry_sexp_nth_string (list, 0);
     562          91 :   if (!name)
     563             :     {
     564           0 :       rc = GPG_ERR_INV_OBJ; /* Algo string missing.  */
     565           0 :       goto leave;
     566             :     }
     567             : 
     568          91 :   spec = spec_from_name (name);
     569          91 :   xfree (name);
     570          91 :   name = NULL;
     571          91 :   if (!spec)
     572             :     {
     573           0 :       rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm.  */
     574           0 :       goto leave;
     575             :     }
     576             : 
     577          91 :   if (spec->generate)
     578          91 :     rc = spec->generate (list, r_key);
     579             :   else
     580           0 :     rc = GPG_ERR_NOT_IMPLEMENTED;
     581             : 
     582             :  leave:
     583          91 :   sexp_release (list);
     584          91 :   xfree (name);
     585          91 :   sexp_release (l2);
     586             : 
     587          91 :   return rc;
     588             : }
     589             : 
     590             : 
     591             : /*
     592             :    Get the number of nbits from the public key.
     593             : 
     594             :    Hmmm: Should we have really this function or is it better to have a
     595             :    more general function to retrieve different properties of the key?  */
     596             : unsigned int
     597          16 : _gcry_pk_get_nbits (gcry_sexp_t key)
     598             : {
     599             :   gcry_pk_spec_t *spec;
     600             :   gcry_sexp_t parms;
     601             :   unsigned int nbits;
     602             : 
     603             :   /* Parsing KEY might be considered too much overhead.  For example
     604             :      for RSA we would only need to look at P and stop parsing right
     605             :      away.  However, with ECC things are more complicate in that only
     606             :      a curve name might be specified.  Thus we need to tear the sexp
     607             :      apart. */
     608             : 
     609          16 :   if (spec_from_sexp (key, 0, &spec, &parms))
     610           0 :     return 0; /* Error - 0 is a suitable indication for that.  */
     611             : 
     612          16 :   nbits = spec->get_nbits (parms);
     613          16 :   sexp_release (parms);
     614          16 :   return nbits;
     615             : }
     616             : 
     617             : 
     618             : /* Return the so called KEYGRIP which is the SHA-1 hash of the public
     619             :    key parameters expressed in a way depending on the algorithm.
     620             : 
     621             :    ARRAY must either be 20 bytes long or NULL; in the latter case a
     622             :    newly allocated array of that size is returned, otherwise ARRAY or
     623             :    NULL is returned to indicate an error which is most likely an
     624             :    unknown algorithm.  The function accepts public or secret keys. */
     625             : unsigned char *
     626          12 : _gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
     627             : {
     628          12 :   gcry_sexp_t list = NULL;
     629          12 :   gcry_sexp_t l2 = NULL;
     630          12 :   gcry_pk_spec_t *spec = NULL;
     631             :   const char *s;
     632          12 :   char *name = NULL;
     633             :   int idx;
     634             :   const char *elems;
     635          12 :   gcry_md_hd_t md = NULL;
     636          12 :   int okay = 0;
     637             : 
     638             :   /* Check that the first element is valid. */
     639          12 :   list = sexp_find_token (key, "public-key", 0);
     640          12 :   if (! list)
     641           2 :     list = sexp_find_token (key, "private-key", 0);
     642          12 :   if (! list)
     643           0 :     list = sexp_find_token (key, "protected-private-key", 0);
     644          12 :   if (! list)
     645           0 :     list = sexp_find_token (key, "shadowed-private-key", 0);
     646          12 :   if (! list)
     647           0 :     return NULL; /* No public- or private-key object. */
     648             : 
     649          12 :   l2 = sexp_cadr (list);
     650          12 :   sexp_release (list);
     651          12 :   list = l2;
     652          12 :   l2 = NULL;
     653             : 
     654          12 :   name = _gcry_sexp_nth_string (list, 0);
     655          12 :   if (!name)
     656           0 :     goto fail; /* Invalid structure of object. */
     657             : 
     658          12 :   spec = spec_from_name (name);
     659          12 :   if (!spec)
     660           0 :     goto fail; /* Unknown algorithm.  */
     661             : 
     662          12 :   elems = spec->elements_grip;
     663          12 :   if (!elems)
     664           0 :     goto fail; /* No grip parameter.  */
     665             : 
     666          12 :   if (_gcry_md_open (&md, GCRY_MD_SHA1, 0))
     667           0 :     goto fail;
     668             : 
     669          12 :   if (spec->comp_keygrip)
     670             :     {
     671             :       /* Module specific method to compute a keygrip.  */
     672          10 :       if (spec->comp_keygrip (md, list))
     673           0 :         goto fail;
     674             :     }
     675             :   else
     676             :     {
     677             :       /* Generic method to compute a keygrip.  */
     678          20 :       for (idx = 0, s = elems; *s; s++, idx++)
     679             :         {
     680             :           const char *data;
     681             :           size_t datalen;
     682             :           char buf[30];
     683             : 
     684           8 :           l2 = sexp_find_token (list, s, 1);
     685           8 :           if (! l2)
     686           0 :             goto fail;
     687           8 :           data = sexp_nth_data (l2, 1, &datalen);
     688           8 :           if (! data)
     689           0 :             goto fail;
     690             : 
     691           8 :           snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen);
     692           8 :           _gcry_md_write (md, buf, strlen (buf));
     693           8 :           _gcry_md_write (md, data, datalen);
     694           8 :           sexp_release (l2);
     695           8 :           l2 = NULL;
     696           8 :           _gcry_md_write (md, ")", 1);
     697             :         }
     698             :     }
     699             : 
     700          12 :   if (!array)
     701             :     {
     702           0 :       array = xtrymalloc (20);
     703           0 :       if (! array)
     704           0 :         goto fail;
     705             :     }
     706             : 
     707          12 :   memcpy (array, _gcry_md_read (md, GCRY_MD_SHA1), 20);
     708          12 :   okay = 1;
     709             : 
     710             :  fail:
     711          12 :   xfree (name);
     712          12 :   sexp_release (l2);
     713          12 :   _gcry_md_close (md);
     714          12 :   sexp_release (list);
     715          12 :   return okay? array : NULL;
     716             : }
     717             : 
     718             : 
     719             : 
     720             : const char *
     721          28 : _gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
     722             : {
     723          28 :   const char *result = NULL;
     724             :   gcry_pk_spec_t *spec;
     725          28 :   gcry_sexp_t keyparms = NULL;
     726             : 
     727          28 :   if (r_nbits)
     728          25 :     *r_nbits = 0;
     729             : 
     730          28 :   if (key)
     731             :     {
     732           4 :       iterator = 0;
     733             : 
     734           4 :       if (spec_from_sexp (key, 0, &spec, &keyparms))
     735           0 :         return NULL;
     736             :     }
     737             :   else
     738             :     {
     739          24 :       spec = spec_from_name ("ecc");
     740          24 :       if (!spec)
     741           0 :         return NULL;
     742             :     }
     743             : 
     744          28 :   if (spec->get_curve)
     745          28 :     result = spec->get_curve (keyparms, iterator, r_nbits);
     746             : 
     747          28 :   sexp_release (keyparms);
     748          28 :   return result;
     749             : }
     750             : 
     751             : 
     752             : 
     753             : gcry_sexp_t
     754           2 : _gcry_pk_get_param (int algo, const char *name)
     755             : {
     756           2 :   gcry_sexp_t result = NULL;
     757           2 :   gcry_pk_spec_t *spec = NULL;
     758             : 
     759           2 :   algo = map_algo (algo);
     760             : 
     761           2 :   if (algo != GCRY_PK_ECC)
     762           0 :     return NULL;
     763             : 
     764           2 :   spec = spec_from_name ("ecc");
     765           2 :   if (spec)
     766             :     {
     767           2 :       if (spec && spec->get_curve_param)
     768           2 :         result = spec->get_curve_param (name);
     769             :     }
     770           2 :   return result;
     771             : }
     772             : 
     773             : 
     774             : 
     775             : gcry_err_code_t
     776           0 : _gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
     777             : {
     778           0 :   gcry_err_code_t rc = 0;
     779             : 
     780           0 :   switch (cmd)
     781             :     {
     782             :     case GCRYCTL_DISABLE_ALGO:
     783             :       /* This one expects a buffer pointing to an integer with the
     784             :          algo number.  */
     785           0 :       if ((! buffer) || (buflen != sizeof (int)))
     786           0 :         rc = GPG_ERR_INV_ARG;
     787             :       else
     788           0 :         disable_pubkey_algo (*((int *) buffer));
     789           0 :       break;
     790             : 
     791             :     default:
     792           0 :       rc = GPG_ERR_INV_OP;
     793             :     }
     794             : 
     795           0 :   return rc;
     796             : }
     797             : 
     798             : 
     799             : /* Return information about the given algorithm
     800             : 
     801             :    WHAT selects the kind of information returned:
     802             : 
     803             :     GCRYCTL_TEST_ALGO:
     804             :         Returns 0 when the specified algorithm is available for use.
     805             :         Buffer must be NULL, nbytes  may have the address of a variable
     806             :         with the required usage of the algorithm. It may be 0 for don't
     807             :         care or a combination of the GCRY_PK_USAGE_xxx flags;
     808             : 
     809             :     GCRYCTL_GET_ALGO_USAGE:
     810             :         Return the usage flags for the given algo.  An invalid algo
     811             :         returns 0.  Disabled algos are ignored here because we
     812             :         only want to know whether the algo is at all capable of
     813             :         the usage.
     814             : 
     815             :    Note: Because this function is in most cases used to return an
     816             :    integer value, we can make it easier for the caller to just look at
     817             :    the return value.  The caller will in all cases consult the value
     818             :    and thereby detecting whether a error occurred or not (i.e. while
     819             :    checking the block size) */
     820             : gcry_err_code_t
     821          56 : _gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes)
     822             : {
     823          56 :   gcry_err_code_t rc = 0;
     824             : 
     825          56 :   switch (what)
     826             :     {
     827             :     case GCRYCTL_TEST_ALGO:
     828             :       {
     829          56 :         int use = nbytes ? *nbytes : 0;
     830          56 :         if (buffer)
     831           0 :           rc = GPG_ERR_INV_ARG;
     832          56 :         else if (check_pubkey_algo (algorithm, use))
     833           0 :           rc = GPG_ERR_PUBKEY_ALGO;
     834          56 :         break;
     835             :       }
     836             : 
     837             :     case GCRYCTL_GET_ALGO_USAGE:
     838             :       {
     839             :         gcry_pk_spec_t *spec;
     840             : 
     841           0 :         spec = spec_from_algo (algorithm);
     842           0 :         *nbytes = spec? spec->use : 0;
     843           0 :         break;
     844             :       }
     845             : 
     846             :     case GCRYCTL_GET_ALGO_NPKEY:
     847             :       {
     848             :         /* FIXME?  */
     849           0 :         int npkey = pubkey_get_npkey (algorithm);
     850           0 :         *nbytes = npkey;
     851           0 :         break;
     852             :       }
     853             :     case GCRYCTL_GET_ALGO_NSKEY:
     854             :       {
     855             :         /* FIXME?  */
     856           0 :         int nskey = pubkey_get_nskey (algorithm);
     857           0 :         *nbytes = nskey;
     858           0 :         break;
     859             :       }
     860             :     case GCRYCTL_GET_ALGO_NSIGN:
     861             :       {
     862             :         /* FIXME?  */
     863           0 :         int nsign = pubkey_get_nsig (algorithm);
     864           0 :         *nbytes = nsign;
     865           0 :         break;
     866             :       }
     867             :     case GCRYCTL_GET_ALGO_NENCR:
     868             :       {
     869             :         /* FIXME?  */
     870           0 :         int nencr = pubkey_get_nenc (algorithm);
     871           0 :         *nbytes = nencr;
     872           0 :         break;
     873             :       }
     874             : 
     875             :     default:
     876           0 :       rc = GPG_ERR_INV_OP;
     877             :     }
     878             : 
     879          56 :   return rc;
     880             : }
     881             : 
     882             : 
     883             : /* Return an S-expression representing the context CTX.  Depending on
     884             :    the state of that context, the S-expression may either be a public
     885             :    key, a private key or any other object used with public key
     886             :    operations.  On success a new S-expression is stored at R_SEXP and
     887             :    0 is returned, on error NULL is store there and an error code is
     888             :    returned.  MODE is either 0 or one of the GCRY_PK_GET_xxx values.
     889             : 
     890             :    As of now it only support certain ECC operations because a context
     891             :    object is right now only defined for ECC.  Over time this function
     892             :    will be extended to cover more algorithms.  Note also that the name
     893             :    of the function is gcry_pubkey_xxx and not gcry_pk_xxx.  The idea
     894             :    is that we will eventually provide variants of the existing
     895             :    gcry_pk_xxx functions which will take a context parameter.   */
     896             : gcry_err_code_t
     897          11 : _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
     898             : {
     899             :   mpi_ec_t ec;
     900             : 
     901          11 :   if (!r_sexp)
     902           0 :     return GPG_ERR_INV_VALUE;
     903          11 :   *r_sexp = NULL;
     904          11 :   switch (mode)
     905             :     {
     906             :     case 0:
     907             :     case GCRY_PK_GET_PUBKEY:
     908             :     case GCRY_PK_GET_SECKEY:
     909          11 :       break;
     910             :     default:
     911           0 :       return GPG_ERR_INV_VALUE;
     912             :     }
     913          11 :   if (!ctx)
     914           0 :     return GPG_ERR_NO_CRYPT_CTX;
     915             : 
     916          11 :   ec = _gcry_ctx_find_pointer (ctx, CONTEXT_TYPE_EC);
     917          11 :   if (ec)
     918          11 :     return _gcry_pk_ecc_get_sexp (r_sexp, mode, ec);
     919             : 
     920           0 :   return GPG_ERR_WRONG_CRYPT_CTX;
     921             : }
     922             : 
     923             : 
     924             : 
     925             : /* Explicitly initialize this module.  */
     926             : gcry_err_code_t
     927          34 : _gcry_pk_init (void)
     928             : {
     929          34 :   if (fips_mode())
     930             :     {
     931             :       /* disable algorithms that are disallowed in fips */
     932             :       int idx;
     933             :       gcry_pk_spec_t *spec;
     934             : 
     935           0 :       for (idx = 0; (spec = pubkey_list[idx]); idx++)
     936           0 :         if (!spec->flags.fips)
     937           0 :           spec->flags.disabled = 1;
     938             :     }
     939             : 
     940          34 :   return 0;
     941             : }
     942             : 
     943             : 
     944             : /* Run the selftests for pubkey algorithm ALGO with optional reporting
     945             :    function REPORT.  */
     946             : gpg_error_t
     947           6 : _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report)
     948             : {
     949             :   gcry_err_code_t ec;
     950             :   gcry_pk_spec_t *spec;
     951             : 
     952           6 :   algo = map_algo (algo);
     953           6 :   spec = spec_from_algo (algo);
     954           6 :   if (spec && !spec->flags.disabled && spec->selftest)
     955           6 :     ec = spec->selftest (algo, extended, report);
     956             :   else
     957             :     {
     958           0 :       ec = GPG_ERR_PUBKEY_ALGO;
     959             :       /* Fixme: We need to change the report function to allow passing
     960             :          of an encryption mode (e.g. pkcs1, ecdsa, or ecdh).  */
     961           0 :       if (report)
     962           0 :         report ("pubkey", algo, "module",
     963           0 :                 spec && !spec->flags.disabled?
     964             :                 "no selftest available" :
     965           0 :                 spec? "algorithm disabled" :
     966             :                 "algorithm not found");
     967             :     }
     968             : 
     969           6 :   return gpg_error (ec);
     970             : }

Generated by: LCOV version 1.13