aboutsummaryrefslogtreecommitdiffstats
path: root/cipher/pubkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'cipher/pubkey.c')
-rw-r--r--cipher/pubkey.c1552
1 files changed, 0 insertions, 1552 deletions
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
deleted file mode 100644
index 3dab336d7..000000000
--- a/cipher/pubkey.c
+++ /dev/null
@@ -1,1552 +0,0 @@
-/* pubkey.c - pubkey dispatcher
- * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "g10lib.h"
-#include "mpi.h"
-#include "cipher.h"
-#include "elgamal.h"
-#include "dsa.h"
-#include "rsa.h"
-#include "dynload.h"
-
-/* FIXME: use set_lasterr() */
-
-#define TABLE_SIZE 10
-
-struct pubkey_table_s {
- const char *name;
- int algo;
- int npkey;
- int nskey;
- int nenc;
- int nsig;
- int use;
- int (*generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
- int (*check_secret_key)( int algo, MPI *skey );
- int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey );
- int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey );
- int (*sign)( int algo, MPI *resarr, MPI data, MPI *skey );
- int (*verify)( int algo, MPI hash, MPI *data, MPI *pkey,
- int (*cmp)(void *, MPI), void *opaquev );
- unsigned (*get_nbits)( int algo, MPI *pkey );
-};
-
-static struct pubkey_table_s pubkey_table[TABLE_SIZE];
-static int disabled_algos[TABLE_SIZE];
-
-static struct { const char* name; int algo;
- const char* common_elements;
- const char* public_elements;
- const char* secret_elements;
-} algo_info_table[] = {
- { "dsa" , PUBKEY_ALGO_DSA , "pqgy", "", "x" },
- { "rsa" , PUBKEY_ALGO_RSA , "ne", "", "dpqu" },
- { "elg" , PUBKEY_ALGO_ELGAMAL , "pgy", "", "x" },
- { "openpgp-dsa" , PUBKEY_ALGO_DSA , "pqgy", "", "x" },
- { "openpgp-rsa" , PUBKEY_ALGO_RSA , "pqgy", "", "x" },
- { "openpgp-elg" , PUBKEY_ALGO_ELGAMAL_E , "pgy", "", "x" },
- { "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL , "pgy", "", "x" },
- { NULL }};
-
-static struct {
- const char* name; int algo;
- const char* elements;
-} sig_info_table[] = {
- { "dsa" , PUBKEY_ALGO_DSA , "rs" },
- { "rsa" , PUBKEY_ALGO_RSA , "s" },
- { "elg" , PUBKEY_ALGO_ELGAMAL , "rs" },
- { "openpgp-dsa" , PUBKEY_ALGO_DSA , "rs" },
- { "openpgp-rsa" , PUBKEY_ALGO_RSA , "s" },
- { "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL , "rs" },
- { NULL }};
-
-static struct {
- const char* name; int algo;
- const char* elements;
-} enc_info_table[] = {
- { "elg" , PUBKEY_ALGO_ELGAMAL , "ab" },
- { "rsa" , PUBKEY_ALGO_RSA , "a" },
- { "openpgp-rsa" , PUBKEY_ALGO_RSA , "a" },
- { "openpgp-elg" , PUBKEY_ALGO_ELGAMAL_E , "ab" },
- { "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL , "ab" },
- { NULL }};
-
-
-static int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey );
-static int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey );
-static int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
- int (*cmp)(void *, MPI), void *opaque );
-
-static int
-dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
-{ log_bug("no generate() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
-
-static int
-dummy_check_secret_key( int algo, MPI *skey )
-{ log_bug("no check_secret_key() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
-
-static int
-dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
-{ log_bug("no encrypt() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
-
-static int
-dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
-{ log_bug("no decrypt() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
-
-static int
-dummy_sign( int algo, MPI *resarr, MPI data, MPI *skey )
-{ log_bug("no sign() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
-
-static int
-dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey,
- int (*cmp)(void *, MPI), void *opaquev )
-{ log_bug("no verify() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
-
-static unsigned
-dummy_get_nbits( int algo, MPI *pkey )
-{ log_bug("no get_nbits() for %d\n", algo ); return 0; }
-
-
-/****************
- * Put the static entries into the table.
- * This is out constructor function which fill the table
- * of algorithms with the one we have statically linked.
- */
-static void
-setup_pubkey_table(void)
-{
- int i;
-
- i = 0;
- pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL;
- pubkey_table[i].name = elg_get_info( pubkey_table[i].algo,
- &pubkey_table[i].npkey,
- &pubkey_table[i].nskey,
- &pubkey_table[i].nenc,
- &pubkey_table[i].nsig,
- &pubkey_table[i].use );
- pubkey_table[i].generate = elg_generate;
- pubkey_table[i].check_secret_key = elg_check_secret_key;
- pubkey_table[i].encrypt = elg_encrypt;
- pubkey_table[i].decrypt = elg_decrypt;
- pubkey_table[i].sign = elg_sign;
- pubkey_table[i].verify = elg_verify;
- pubkey_table[i].get_nbits = elg_get_nbits;
- if( !pubkey_table[i].name )
- BUG();
- i++;
- pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL_E;
- pubkey_table[i].name = elg_get_info( pubkey_table[i].algo,
- &pubkey_table[i].npkey,
- &pubkey_table[i].nskey,
- &pubkey_table[i].nenc,
- &pubkey_table[i].nsig,
- &pubkey_table[i].use );
- pubkey_table[i].generate = elg_generate;
- pubkey_table[i].check_secret_key = elg_check_secret_key;
- pubkey_table[i].encrypt = elg_encrypt;
- pubkey_table[i].decrypt = elg_decrypt;
- pubkey_table[i].sign = elg_sign;
- pubkey_table[i].verify = elg_verify;
- pubkey_table[i].get_nbits = elg_get_nbits;
- if( !pubkey_table[i].name )
- BUG();
- i++;
- pubkey_table[i].algo = PUBKEY_ALGO_DSA;
- pubkey_table[i].name = dsa_get_info( pubkey_table[i].algo,
- &pubkey_table[i].npkey,
- &pubkey_table[i].nskey,
- &pubkey_table[i].nenc,
- &pubkey_table[i].nsig,
- &pubkey_table[i].use );
- pubkey_table[i].generate = dsa_generate;
- pubkey_table[i].check_secret_key = dsa_check_secret_key;
- pubkey_table[i].encrypt = dummy_encrypt;
- pubkey_table[i].decrypt = dummy_decrypt;
- pubkey_table[i].sign = dsa_sign;
- pubkey_table[i].verify = dsa_verify;
- pubkey_table[i].get_nbits = dsa_get_nbits;
- if( !pubkey_table[i].name )
- BUG();
- i++;
-
- pubkey_table[i].algo = PUBKEY_ALGO_RSA;
- pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
- &pubkey_table[i].npkey,
- &pubkey_table[i].nskey,
- &pubkey_table[i].nenc,
- &pubkey_table[i].nsig,
- &pubkey_table[i].use );
- pubkey_table[i].generate = rsa_generate;
- pubkey_table[i].check_secret_key = rsa_check_secret_key;
- pubkey_table[i].encrypt = rsa_encrypt;
- pubkey_table[i].decrypt = rsa_decrypt;
- pubkey_table[i].sign = rsa_sign;
- pubkey_table[i].verify = rsa_verify;
- pubkey_table[i].get_nbits = rsa_get_nbits;
- if( !pubkey_table[i].name )
- BUG();
- i++;
- pubkey_table[i].algo = PUBKEY_ALGO_RSA_E;
- pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
- &pubkey_table[i].npkey,
- &pubkey_table[i].nskey,
- &pubkey_table[i].nenc,
- &pubkey_table[i].nsig,
- &pubkey_table[i].use );
- pubkey_table[i].generate = rsa_generate;
- pubkey_table[i].check_secret_key = rsa_check_secret_key;
- pubkey_table[i].encrypt = rsa_encrypt;
- pubkey_table[i].decrypt = rsa_decrypt;
- pubkey_table[i].sign = dummy_sign;
- pubkey_table[i].verify = dummy_verify;
- pubkey_table[i].get_nbits = rsa_get_nbits;
- if( !pubkey_table[i].name )
- BUG();
- i++;
- pubkey_table[i].algo = PUBKEY_ALGO_RSA_S;
- pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
- &pubkey_table[i].npkey,
- &pubkey_table[i].nskey,
- &pubkey_table[i].nenc,
- &pubkey_table[i].nsig,
- &pubkey_table[i].use );
- pubkey_table[i].generate = rsa_generate;
- pubkey_table[i].check_secret_key = rsa_check_secret_key;
- pubkey_table[i].encrypt = dummy_encrypt;
- pubkey_table[i].decrypt = dummy_decrypt;
- pubkey_table[i].sign = rsa_sign;
- pubkey_table[i].verify = rsa_verify;
- pubkey_table[i].get_nbits = rsa_get_nbits;
- if( !pubkey_table[i].name )
- BUG();
- i++;
-
- for( ; i < TABLE_SIZE; i++ )
- pubkey_table[i].name = NULL;
-}
-
-static void
-release_mpi_array( MPI *array )
-{
- for( ; *array; array++ ) {
- mpi_free(*array);
- *array = NULL;
- }
-}
-
-/****************
- * Try to load all modules and return true if new modules are available
- */
-static int
-load_pubkey_modules(void)
-{
- static int initialized = 0;
- static int done = 0;
- void *context = NULL;
- struct pubkey_table_s *ct;
- int ct_idx;
- int i;
- const char *name;
- int any = 0;
-
-
- if( !initialized ) {
- cipher_modules_constructor();
- setup_pubkey_table();
- initialized = 1;
- return 1;
- }
- if( done )
- return 0;
- done = 1;
- for(ct_idx=0, ct = pubkey_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) {
- if( !ct->name )
- break;
- }
- if( ct_idx >= TABLE_SIZE-1 )
- BUG(); /* table already full */
- /* now load all extensions */
- while( (name = enum_gnupgext_pubkeys( &context, &ct->algo,
- &ct->npkey, &ct->nskey, &ct->nenc,
- &ct->nsig, &ct->use,
- &ct->generate,
- &ct->check_secret_key,
- &ct->encrypt,
- &ct->decrypt,
- &ct->sign,
- &ct->verify,
- &ct->get_nbits )) ) {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == ct->algo )
- break;
- if( pubkey_table[i].name ) {
- log_info("skipping pubkey %d: already loaded\n", ct->algo );
- continue;
- }
-
- if( !ct->generate ) ct->generate = dummy_generate;
- if( !ct->check_secret_key ) ct->check_secret_key =
- dummy_check_secret_key;
- if( !ct->encrypt ) ct->encrypt = dummy_encrypt;
- if( !ct->decrypt ) ct->decrypt = dummy_decrypt;
- if( !ct->sign ) ct->sign = dummy_sign;
- if( !ct->verify ) ct->verify = dummy_verify;
- if( !ct->get_nbits ) ct->get_nbits= dummy_get_nbits;
- /* put it into the table */
- if( g10_log_verbosity( 2 ) )
- log_info("loaded pubkey %d (%s)\n", ct->algo, name);
- ct->name = name;
- ct_idx++;
- ct++;
- any = 1;
- /* check whether there are more available table slots */
- if( ct_idx >= TABLE_SIZE-1 ) {
- log_info("pubkey table full; ignoring other extensions\n");
- break;
- }
- }
- enum_gnupgext_pubkeys( &context, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL );
- return any;
-}
-
-
-/****************
- * Map a string to the pubkey algo
- */
-int
-gcry_pk_map_name( const char *string )
-{
- int i;
- const char *s;
-
- do {
- for(i=0; (s=pubkey_table[i].name); i++ )
- if( !stricmp( s, string ) )
- return pubkey_table[i].algo;
- } while( load_pubkey_modules() );
- return 0;
-}
-
-
-/****************
- * Map a pubkey algo to a string
- */
-const char *
-gcry_pk_algo_name( int algo )
-{
- int i;
-
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo )
- return pubkey_table[i].name;
- } while( load_pubkey_modules() );
- return NULL;
-}
-
-
-static void
-disable_pubkey_algo( int algo )
-{
- int i;
-
- for(i=0; i < DIM(disabled_algos); i++ ) {
- if( !disabled_algos[i] || disabled_algos[i] == algo ) {
- disabled_algos[i] = algo;
- return;
- }
- }
- log_fatal("can't disable pubkey algo %d: table full\n", algo );
-}
-
-
-/****************
- * a use of 0 means: don't care
- */
-static int
-check_pubkey_algo( int algo, unsigned use )
-{
- int i;
-
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo ) {
- if( (use & GCRY_PK_USAGE_SIGN)
- && !(pubkey_table[i].use & GCRY_PK_USAGE_SIGN) )
- return GCRYERR_WRONG_PK_ALGO;
- if( (use & GCRY_PK_USAGE_ENCR)
- && !(pubkey_table[i].use & GCRY_PK_USAGE_ENCR) )
- return GCRYERR_WRONG_PK_ALGO;
-
- for(i=0; i < DIM(disabled_algos); i++ ) {
- if( disabled_algos[i] == algo )
- return GCRYERR_INV_PK_ALGO;
- }
- return 0; /* okay */
- }
- } while( load_pubkey_modules() );
- return GCRYERR_INV_PK_ALGO;
-}
-
-
-
-
-/****************
- * Return the number of public key material numbers
- */
-static int
-pubkey_get_npkey( int algo )
-{
- int i;
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo )
- return pubkey_table[i].npkey;
- } while( load_pubkey_modules() );
- return 0;
-}
-
-/****************
- * Return the number of secret key material numbers
- */
-static int
-pubkey_get_nskey( int algo )
-{
- int i;
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo )
- return pubkey_table[i].nskey;
- } while( load_pubkey_modules() );
- return 0;
-}
-
-/****************
- * Return the number of signature material numbers
- */
-static int
-pubkey_get_nsig( int algo )
-{
- int i;
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo )
- return pubkey_table[i].nsig;
- } while( load_pubkey_modules() );
- return 0;
-}
-
-/****************
- * Return the number of encryption material numbers
- */
-static int
-pubkey_get_nenc( int algo )
-{
- int i;
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo )
- return pubkey_table[i].nenc;
- } while( load_pubkey_modules() );
- return 0;
-}
-
-
-static int
-pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
-{
- int i;
-
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo )
- return (*pubkey_table[i].generate)( algo, nbits,
- skey, retfactors );
- } while( load_pubkey_modules() );
- return GCRYERR_INV_PK_ALGO;
-}
-
-
-static int
-pubkey_check_secret_key( int algo, MPI *skey )
-{
- int i;
-
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo )
- return (*pubkey_table[i].check_secret_key)( algo, skey );
- } while( load_pubkey_modules() );
- return GCRYERR_INV_PK_ALGO;
-}
-
-
-/****************
- * This is the interface to the public key encryption.
- * Encrypt DATA with PKEY and put it into RESARR which
- * should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the
- * algorithm allows this - check with pubkey_get_nenc() )
- */
-static int
-pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
-{
- int i, rc;
-
- if( DBG_CIPHER ) {
- log_debug("pubkey_encrypt: algo=%d\n", algo );
- for(i=0; i < pubkey_get_npkey(algo); i++ )
- log_mpidump(" pkey:", pkey[i] );
- log_mpidump(" data:", data );
- }
-
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo ) {
- rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey );
- goto ready;
- }
- } while( load_pubkey_modules() );
- rc = GCRYERR_INV_PK_ALGO;
- ready:
- if( !rc && DBG_CIPHER ) {
- for(i=0; i < pubkey_get_nenc(algo); i++ )
- log_mpidump(" encr:", resarr[i] );
- }
- return rc;
-}
-
-
-
-/****************
- * This is the interface to the public key decryption.
- * ALGO gives the algorithm to use and this implicitly determines
- * the size of the arrays.
- * result is a pointer to a mpi variable which will receive a
- * newly allocated mpi or NULL in case of an error.
- */
-static int
-pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
-{
- int i, rc;
-
- *result = NULL; /* so the caller can always do a mpi_free */
- if( DBG_CIPHER ) {
- log_debug("pubkey_decrypt: algo=%d\n", algo );
- for(i=0; i < pubkey_get_nskey(algo); i++ )
- log_mpidump(" skey:", skey[i] );
- for(i=0; i < pubkey_get_nenc(algo); i++ )
- log_mpidump(" data:", data[i] );
- }
-
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo ) {
- rc = (*pubkey_table[i].decrypt)( algo, result, data, skey );
- goto ready;
- }
- } while( load_pubkey_modules() );
- rc = GCRYERR_INV_PK_ALGO;
- ready:
- if( !rc && DBG_CIPHER ) {
- log_mpidump(" plain:", *result );
- }
- return rc;
-}
-
-
-/****************
- * This is the interface to the public key signing.
- * Sign data with skey and put the result into resarr which
- * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
- * algorithm allows this - check with pubkey_get_nsig() )
- */
-static int
-pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey )
-{
- int i, rc;
-
- if( DBG_CIPHER ) {
- log_debug("pubkey_sign: algo=%d\n", algo );
- for(i=0; i < pubkey_get_nskey(algo); i++ )
- log_mpidump(" skey:", skey[i] );
- log_mpidump(" data:", data );
- }
-
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo ) {
- rc = (*pubkey_table[i].sign)( algo, resarr, data, skey );
- goto ready;
- }
- } while( load_pubkey_modules() );
- rc = GCRYERR_INV_PK_ALGO;
- ready:
- if( !rc && DBG_CIPHER ) {
- for(i=0; i < pubkey_get_nsig(algo); i++ )
- log_mpidump(" sig:", resarr[i] );
- }
- return rc;
-}
-
-/****************
- * Verify a public key signature.
- * Return 0 if the signature is good
- */
-static int
-pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
- int (*cmp)(void *, MPI), void *opaquev )
-{
- int i, rc;
-
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo ) {
- rc = (*pubkey_table[i].verify)( algo, hash, data, pkey,
- cmp, opaquev );
- goto ready;
- }
- } while( load_pubkey_modules() );
- rc = GCRYERR_INV_PK_ALGO;
- ready:
- return rc;
-}
-
-
-
-/****************
- * Convert a S-Exp with either a private or a public key to our
- * internal format. Currently we do only support the following
- * algorithms:
- * dsa
- * rsa
- * openpgp-dsa
- * openpgp-rsa
- * openpgp-elg
- * openpgp-elg-sig
- * Provide a SE with the first element be either "private-key" or
- * or "public-key". the followed by a list with its first element
- * be one of the above algorithm identifiers and the following
- * elements are pairs with parameter-id and value.
- * NOTE: we look through the list to find a list beginning with
- * "private-key" or "public-key" - the first one found is used.
- *
- * FIXME: Allow for encrypted secret keys here.
- *
- * Returns: A pointer to an allocated array of MPIs if the return value is
- * zero; the caller has to release this array.
- *
- * Example of a DSA public key:
- * (private-key
- * (dsa
- * (p <mpi>)
- * (g <mpi>)
- * (y <mpi>)
- * (x <mpi>)
- * )
- * )
- * The <mpi> are expected to be in GCRYMPI_FMT_USG
- */
-static int
-sexp_to_key( GCRY_SEXP sexp, int want_private, MPI **retarray, int *retalgo)
-{
- GCRY_SEXP list, l2;
- const char *name;
- const char *s;
- size_t n;
- int i, idx;
- int algo;
- const char *elems1, *elems2;
- GCRY_MPI *array;
-
- /* check that the first element is valid */
- list = gcry_sexp_find_token( sexp, want_private? "private-key"
- :"public-key", 0 );
- if( !list )
- return GCRYERR_INV_OBJ; /* Does not contain a public- or private-key object */
- l2 = gcry_sexp_cadr( list );
- gcry_sexp_release ( list );
- list = l2;
- name = gcry_sexp_nth_data( list, 0, &n );
- if( !name ) {
- gcry_sexp_release ( list );
- return GCRYERR_INV_OBJ; /* invalid structure of object */
- }
- for(i=0; (s=algo_info_table[i].name); i++ ) {
- if( strlen(s) == n && !memcmp( s, name, n ) )
- break;
- }
- if( !s ) {
- gcry_sexp_release ( list );
- return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
- }
- algo = algo_info_table[i].algo;
- elems1 = algo_info_table[i].common_elements;
- elems2 = want_private? algo_info_table[i].secret_elements
- : algo_info_table[i].public_elements;
- array = g10_calloc( strlen(elems1)+strlen(elems2)+1, sizeof *array );
- if( !array ) {
- gcry_sexp_release ( list );
- return GCRYERR_NO_MEM;
- }
-
- idx = 0;
- for(s=elems1; *s; s++, idx++ ) {
- l2 = gcry_sexp_find_token( list, s, 1 );
- if( !l2 ) {
- for(i=0; i<idx; i++)
- g10_free( array[i] );
- g10_free( array );
- gcry_sexp_release ( list );
- return GCRYERR_NO_OBJ; /* required parameter not found */
- }
- array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
- gcry_sexp_release ( l2 );
- if( !array[idx] ) {
- for(i=0; i<idx; i++)
- g10_free( array[i] );
- g10_free( array );
- gcry_sexp_release ( list );
- return GCRYERR_INV_OBJ; /* required parameter is invalid */
- }
- }
- for(s=elems2; *s; s++, idx++ ) {
- l2 = gcry_sexp_find_token( list, s, 1 );
- if( !l2 ) {
- for(i=0; i<idx; i++)
- g10_free( array[i] );
- g10_free( array );
- gcry_sexp_release ( list );
- return GCRYERR_NO_OBJ; /* required parameter not found */
- }
- array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
- gcry_sexp_release ( l2 );
- if( !array[idx] ) {
- for(i=0; i<idx; i++)
- g10_free( array[i] );
- g10_free( array );
- gcry_sexp_release ( list );
- return GCRYERR_INV_OBJ; /* required parameter is invalid */
- }
- }
-
- gcry_sexp_release ( list );
- *retarray = array;
- *retalgo = algo;
-
- return 0;
-}
-
-static int
-sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
-{
- GCRY_SEXP list, l2;
- const char *name;
- const char *s;
- size_t n;
- int i, idx;
- int algo;
- const char *elems;
- GCRY_MPI *array;
-
- /* check that the first element is valid */
- list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
- if( !list )
- return GCRYERR_INV_OBJ; /* Does not contain a signature value object */
- l2 = gcry_sexp_cadr( list );
- gcry_sexp_release ( list );
- list = l2;
- if( !list )
- return GCRYERR_NO_OBJ; /* no cadr for the sig object */
- name = gcry_sexp_nth_data( list, 0, &n );
- if( !name ) {
- gcry_sexp_release ( list );
- return GCRYERR_INV_OBJ; /* invalid structure of object */
- }
- for(i=0; (s=sig_info_table[i].name); i++ ) {
- if( strlen(s) == n && !memcmp( s, name, n ) )
- break;
- }
- if( !s ) {
- gcry_sexp_release ( list );
- return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
- }
- algo = sig_info_table[i].algo;
- elems = sig_info_table[i].elements;
- array = g10_calloc( (strlen(elems)+1) , sizeof *array );
- if( !array ) {
- gcry_sexp_release ( list );
- return GCRYERR_NO_MEM;
- }
-
- idx = 0;
- for(s=elems; *s; s++, idx++ ) {
- l2 = gcry_sexp_find_token( list, s, 1 );
- if( !l2 ) {
- g10_free( array );
- gcry_sexp_release ( list );
- return GCRYERR_NO_OBJ; /* required parameter not found */
- }
- array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
- gcry_sexp_release ( l2 );
- if( !array[idx] ) {
- g10_free( array );
- gcry_sexp_release ( list );
- return GCRYERR_INV_OBJ; /* required parameter is invalid */
- }
- }
-
- gcry_sexp_release ( list );
- *retarray = array;
- *retalgo = algo;
-
- return 0;
-}
-
-
-/****************
- * Take sexp and return an array of MPI as used for our internal decrypt
- * function.
- */
-static int
-sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
-{
- GCRY_SEXP list, l2;
- const char *name;
- const char *s;
- size_t n;
- int i, idx;
- int algo;
- const char *elems;
- GCRY_MPI *array;
-
- /* check that the first element is valid */
- list = gcry_sexp_find_token( sexp, "enc-val" , 0 );
- if( !list )
- return GCRYERR_INV_OBJ; /* Does not contain a encrypted value object */
- l2 = gcry_sexp_cadr( list );
- gcry_sexp_release ( list );
- list = l2;
- if( !list ) {
- gcry_sexp_release ( list );
- return GCRYERR_NO_OBJ; /* no cdr for the data object */
- }
- name = gcry_sexp_nth_data( list, 0, &n );
- if( !name ) {
- gcry_sexp_release ( list );
- return GCRYERR_INV_OBJ; /* invalid structure of object */
- }
- for(i=0; (s=enc_info_table[i].name); i++ ) {
- if( strlen(s) == n && !memcmp( s, name, n ) )
- break;
- }
- if( !s ) {
- gcry_sexp_release ( list );
- return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
- }
-
- algo = enc_info_table[i].algo;
- elems = enc_info_table[i].elements;
- array = g10_calloc( (strlen(elems)+1) , sizeof *array );
- if( !array ) {
- gcry_sexp_release ( list );
- return GCRYERR_NO_MEM;
- }
-
- idx = 0;
- for(s=elems; *s; s++, idx++ ) {
- l2 = gcry_sexp_find_token( list, s, 1 );
- if( !l2 ) {
- g10_free( array );
- gcry_sexp_release ( list );
- return GCRYERR_NO_OBJ; /* required parameter not found */
- }
- array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
- gcry_sexp_release ( l2 );
- if( !array[idx] ) {
- g10_free( array );
- gcry_sexp_release ( list );
- return GCRYERR_INV_OBJ; /* required parameter is invalid */
- }
- }
-
- gcry_sexp_release ( list );
- *retarray = array;
- *retalgo = algo;
-
- return 0;
-}
-
-
-/****************
- * Do a PK encrypt operation
- *
- * Caller has to provide a public key as the SEXP pkey and data as a SEXP
- * with just one MPI in it. The function returns a a sexp which may
- * be passed tp to pk_decrypt.
- * Later versions of this functions may take more complex input data.
- *
- * Returns: 0 or an errorcode.
- *
- * s_data = (<mpi>)
- * s_pkey = <key-as-defined-in-sexp_to_key>
- * r_ciph = (enc-val
- * (<algo>
- * (<param_name1> <mpi>)
- * ...
- * (<param_namen> <mpi>)
- * ))
- */
-int
-gcry_pk_encrypt( GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey )
-{
- MPI *pkey, data, *ciph;
- const char *algo_name, *algo_elems;
- int i, rc, algo;
-
- /* get the key */
- rc = sexp_to_key( s_pkey, 0, &pkey, &algo );
- if( rc ) {
- return rc;
- }
-
- /* get the name and the required size of the return value */
- for(i=0; (algo_name = enc_info_table[i].name); i++ ) {
- if( enc_info_table[i].algo == algo )
- break;
- }
- if( !algo_name ) {
- release_mpi_array( pkey );
- return GCRYERR_INV_PK_ALGO;
- }
- algo_elems = enc_info_table[i].elements;
-
- /* get the stuff we want to encrypt */
- data = gcry_sexp_nth_mpi( s_data, 0, 0 );
- if( !data ) {
- release_mpi_array( pkey );
- return GCRYERR_INV_OBJ;
- }
-
- /* Now we can encrypt data to ciph */
- ciph = g10_xcalloc( (strlen(algo_elems)+1) , sizeof *ciph );
- rc = pubkey_encrypt( algo, ciph, data, pkey );
- release_mpi_array( pkey );
- mpi_free( data );
- if( rc ) {
- release_mpi_array( ciph );
- g10_free( ciph );
- return rc;
- }
-
- /* We did it. Now build the return list */
- {
- char *string, *p;
- size_t nelem, needed= strlen(algo_name) + 20;
-
- /* count elements, so that we can allocate enough space */
- for(nelem=0; algo_elems[nelem]; nelem++ )
- needed += 10; /* 6 + a safety margin */
- /* build the string */
- string = p = g10_xmalloc ( needed );
- p = stpcpy ( p, "(enc-val(" );
- p = stpcpy ( p, algo_name );
- for(i=0; algo_elems[i]; i++ ) {
- *p++ = '(';
- *p++ = algo_elems[i];
- p = stpcpy ( p, "%m)" );
- }
- strcpy ( p, "))" );
- /* and now the ugly part: we don't have a function to
- * pass an array to a format string, so we have to do it this way :-(
- */
- switch ( nelem ) {
- case 1: rc = gcry_sexp_build ( r_ciph, NULL, string,
- ciph[0]
- ); break;
- case 2: rc = gcry_sexp_build ( r_ciph, NULL, string,
- ciph[0], ciph[1]
- ); break;
- case 3: rc = gcry_sexp_build ( r_ciph, NULL, string,
- ciph[0], ciph[1], ciph[2]
- ); break;
- case 4: rc = gcry_sexp_build ( r_ciph, NULL, string,
- ciph[0], ciph[1], ciph[2], ciph[3]
- ); break;
- case 5: rc = gcry_sexp_build ( r_ciph, NULL, string,
- ciph[0], ciph[1], ciph[2], ciph[3], ciph[4]
- ); break;
- case 6: rc = gcry_sexp_build ( r_ciph, NULL, string,
- ciph[0], ciph[1], ciph[2], ciph[3], ciph[4], ciph[5]
- ); break;
- default: BUG ();
- }
- if ( rc )
- BUG ();
- g10_free ( string );
- }
- release_mpi_array( ciph );
- g10_free( ciph );
-
-
- return 0;
-}
-
-/****************
- * Do a PK decrypt operation
- *
- * Caller has to provide a secret key as the SEXP skey and data in a format
- * as created by gcry_pk_encrypt. Currently the function returns
- * simply a MPI. Later versions of this functions may return a more
- * complex data structure.
- *
- * Returns: 0 or an errorcode.
- *
- * s_data = (enc-val
- * (<algo>
- * (<param_name1> <mpi>)
- * ...
- * (<param_namen> <mpi>)
- * ))
- * s_skey = <key-as-defined-in-sexp_to_key>
- * r_plain= (<mpi>) FIXME: Return a more structered value
- */
-int
-gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey )
-{
- MPI *skey, *data, plain;
- int rc, algo, dataalgo;
-
- rc = sexp_to_key( s_skey, 1, &skey, &algo );
- if( rc ) {
- return rc;
- }
- rc = sexp_to_enc( s_data, &data, &dataalgo );
- if( rc ) {
- release_mpi_array( skey );
- return rc;
- }
- if( algo != dataalgo ) {
- release_mpi_array( skey );
- release_mpi_array( data );
- return -1; /* fixme: add real errornumber - algo does not match */
- }
-
- rc = pubkey_decrypt( algo, &plain, data, skey );
- if( rc ) {
- release_mpi_array( skey );
- release_mpi_array( data );
- return -1; /* fixme: add real errornumber - decryption failed */
- }
-
- if ( gcry_sexp_build( r_plain, NULL, "%m", plain ) )
- BUG ();
-
- mpi_free( plain );
- release_mpi_array( data );
- release_mpi_array( skey );
- return 0;
-}
-
-
-
-/****************
- * Create a signature.
- *
- * Caller has to provide a secret key as the SEXP skey and data expressed
- * as a SEXP list hash with only one element which should instantly be
- * available as a MPI. Later versions of this functions may provide padding
- * and other things depending on data.
- *
- * Returns: 0 or an errorcode.
- * In case of 0 the function returns a new SEXP with the
- * signature value; the structure of this signature depends on the
- * other arguments but is always suitable to be passed to
- * gcry_pk_verify
- *
- * s_hash = (<mpi>)
- * s_skey = <key-as-defined-in-sexp_to_key>
- * r_sig = (sig-val
- * (<algo>
- * (<param_name1> <mpi>)
- * ...
- * (<param_namen> <mpi>)
- * ))
- */
-int
-gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey )
-{
- MPI *skey, hash;
- MPI *result;
- int i, algo, rc;
- const char *algo_name, *algo_elems;
-
- rc = sexp_to_key( s_skey, 1, &skey, &algo );
- if( rc )
- return rc;
-
- /* get the name and the required size of the result array */
- for(i=0; (algo_name = sig_info_table[i].name); i++ ) {
- if( sig_info_table[i].algo == algo )
- break;
- }
- if( !algo_name ) {
- release_mpi_array( skey );
- return -4; /* oops: unknown algorithm */
- }
- algo_elems = sig_info_table[i].elements;
-
- /* get the stuff we want to sign */
- hash = gcry_sexp_nth_mpi( s_hash, 0, 0 );
- if( !hash ) {
- release_mpi_array( skey );
- return -1; /* fixme: get a real errorcode for this */
- }
- result = g10_xcalloc( (strlen(algo_elems)+1) , sizeof *result );
- rc = pubkey_sign( algo, result, hash, skey );
- release_mpi_array( skey );
- mpi_free( hash );
- if( rc ) {
- g10_free( result );
- return rc;
- }
-
- {
- char *string, *p;
- size_t nelem, needed= strlen(algo_name) + 20;
-
- /* count elements, so that we can allocate enough space */
- for(nelem=0; algo_elems[nelem]; nelem++ )
- needed += 10; /* 6 + a safety margin */
- /* build the string */
- string = p = g10_xmalloc ( needed );
- p = stpcpy ( p, "(sig-val(" );
- p = stpcpy ( p, algo_name );
- for(i=0; algo_elems[i]; i++ ) {
- *p++ = '(';
- *p++ = algo_elems[i];
- p = stpcpy ( p, "%m)" );
- }
- strcpy ( p, "))" );
- /* and now the ugly part: we don't have a function to
- * pass an array to a format string, so we have to do it this way :-(
- */
- switch ( nelem ) {
- case 1: rc = gcry_sexp_build ( r_sig, NULL, string,
- result[0]
- ); break;
- case 2: rc = gcry_sexp_build ( r_sig, NULL, string,
- result[0], result[1]
- ); break;
- case 3: rc = gcry_sexp_build ( r_sig, NULL, string,
- result[0], result[1], result[2]
- ); break;
- case 4: rc = gcry_sexp_build ( r_sig, NULL, string,
- result[0], result[1], result[2], result[3]
- ); break;
- case 5: rc = gcry_sexp_build ( r_sig, NULL, string,
- result[0], result[1], result[2], result[3], result[4]
- ); break;
- case 6: rc = gcry_sexp_build ( r_sig, NULL, string,
- result[0], result[1], result[2], result[3], result[4], result[5]
- ); break;
- default: BUG ();
- }
- if ( rc )
- BUG ();
- g10_free ( string );
- }
- release_mpi_array( result );
- g10_free( result );
-
- return 0;
-}
-
-
-/****************
- * Verify a sgnature. Caller has to supply the public key pkey,
- * the signature sig and his hashvalue data. Public key has to be
- * a standard public key given as an S-Exp, sig is a S-Exp as returned
- * from gcry_pk_sign and data must be an S-Exp like the one in sign too.
- */
-int
-gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey )
-{
- MPI *pkey, hash, *sig;
- int algo, sigalgo;
- int rc;
-
- rc = sexp_to_key( s_pkey, 0, &pkey, &algo );
- if( rc )
- return rc;
- rc = sexp_to_sig( s_sig, &sig, &sigalgo );
- if( rc ) {
- release_mpi_array( pkey );
- return rc;
- }
- if( algo != sigalgo ) {
- release_mpi_array( pkey );
- release_mpi_array( sig );
- return -1; /* fixme: add real errornumber - algo does not match */
- }
-
- hash = gcry_sexp_nth_mpi( s_hash, 0, 0 );
- if( !hash ) {
- release_mpi_array( pkey );
- release_mpi_array( sig );
- return -1; /* fixme: get a real errorcode for this */
- }
-
- rc = pubkey_verify( algo, hash, sig, pkey, NULL, NULL );
- release_mpi_array( pkey );
- release_mpi_array( sig );
- mpi_free(hash);
-
- return rc;
-}
-
-
-/****************
- * Test a key. This may be used either for a public or a secret key
- * to see whether internal structre is valid.
- *
- * Returns: 0 or an errorcode.
- *
- * s_key = <key-as-defined-in-sexp_to_key>
- */
-int
-gcry_pk_testkey( GCRY_SEXP s_key )
-{
- MPI *key;
- int rc, algo;
-
- /* Note we currently support only secret key checking */
- rc = sexp_to_key( s_key, 1, &key, &algo );
- if( rc ) {
- return rc;
- }
-
- rc = pubkey_check_secret_key( algo, key );
- release_mpi_array( key );
- return rc;
-}
-
-
-/****************
- * Create a public key pair and return it in r_key.
- * How the key is created depends on s_parms:
- * (genkey
- * (algo
- * (parameter_name_1 ....)
- * ....
- * (parameter_name_n ....)
- * ))
- * The key is returned in a format depending on the
- * algorithm. Both, private and secret keys are returned
- * and optionally some additional informatin.
- * For elgamal we return this structure:
- * (key-data
- * (public-key
- * (elg
- * (p <mpi>)
- * (g <mpi>)
- * (y <mpi>)
- * )
- * )
- * (private-key
- * (elg
- * (p <mpi>)
- * (g <mpi>)
- * (y <mpi>)
- * (x <mpi>)
- * )
- * )
- * (misc-key-info
- * (pm1-factors n1 n2 ... nn)
- * )
- * )
- */
-int
-gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms )
-{
- GCRY_SEXP list, l2;
- const char *name;
- const char *s;
- size_t n;
- int rc, i;
- const char *algo_name;
- int algo;
- char sec_elems[20], pub_elems[20]; /* fixme: check bounds */
- GCRY_MPI skey[10], *factors;
- unsigned int nbits;
-
- list = gcry_sexp_find_token( s_parms, "genkey", 0 );
- if( !list )
- return GCRYERR_INV_OBJ; /* Does not contain genkey data */
- l2 = gcry_sexp_cadr( list );
- gcry_sexp_release ( list );
- list = l2;
- if( !list )
- return GCRYERR_NO_OBJ; /* no cdr for the genkey */
- name = gcry_sexp_nth_data( list, 0, &n );
- if( !name ) {
- gcry_sexp_release ( list );
- return GCRYERR_INV_OBJ; /* algo string missing */
- }
- for(i=0; (s=algo_info_table[i].name); i++ ) {
- if( strlen(s) == n && !memcmp( s, name, n ) )
- break;
- }
- if( !s ) {
- gcry_sexp_release ( list );
- return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
- }
-
- algo = algo_info_table[i].algo;
- algo_name = algo_info_table[i].name;
- strcpy( pub_elems, algo_info_table[i].common_elements );
- strcat( pub_elems, algo_info_table[i].public_elements );
- strcpy( sec_elems, algo_info_table[i].common_elements );
- strcat( sec_elems, algo_info_table[i].secret_elements );
-
- l2 = gcry_sexp_find_token( list, "nbits", 0 );
- gcry_sexp_release ( list );
- list = l2;
- if( !list )
- return GCRYERR_NO_OBJ; /* no nbits parameter */
- name = gcry_sexp_nth_data( list, 1, &n );
- if( !name ) {
- gcry_sexp_release ( list );
- return GCRYERR_INV_OBJ; /* nbits without a cdr */
- }
- {
- char *p = g10_xmalloc(n+1);
- memcpy(p, name, n );
- p[n] = 0;
- nbits = (unsigned int)strtol( p, NULL, 0 );
- g10_free( p );
- }
- gcry_sexp_release ( list );
-
- rc = pubkey_generate( algo, nbits, skey, &factors );
- if( rc ) {
- return rc;
- }
-
- {
- char *string, *p;
- size_t nelem=0, needed=0;
- GCRY_MPI mpis[30];
-
-
- /* count elements, so that we can allocate enough space */
- for(i=0; pub_elems[i]; i++, nelem++ )
- needed += 10; /* 6 + a safety margin */
- for(i=0; sec_elems[i]; i++, nelem++ )
- needed += 10; /* 6 + a safety margin */
- for(i=0; factors[i]; i++, nelem++ )
- needed += 10; /* 6 + a safety margin */
- needed += 2* strlen(algo_name) + 300;
- if ( nelem > DIM(mpis) )
- BUG ();
-
- /* build the string */
- nelem = 0;
- string = p = g10_xmalloc ( needed );
- p = stpcpy ( p, "(key-data" );
-
- p = stpcpy ( p, "(public-key(" );
- p = stpcpy ( p, algo_name );
- for(i=0; pub_elems[i]; i++ ) {
- *p++ = '(';
- *p++ = pub_elems[i];
- p = stpcpy ( p, "%m)" );
- mpis[nelem++] = skey[i];
- }
- p = stpcpy ( p, "))" );
-
- p = stpcpy ( p, "(private-key(" );
- p = stpcpy ( p, algo_name );
- for(i=0; sec_elems[i]; i++ ) {
- *p++ = '(';
- *p++ = sec_elems[i];
- p = stpcpy ( p, "%m)" );
- mpis[nelem++] = skey[i];
- }
- p = stpcpy ( p, "))" );
- /* Very ugly hack to make release_mpi_array() work FIXME */
- skey[i] = NULL;
-
- p = stpcpy ( p, "(misc-key-info(pm1-factors" );
- for(i=0; factors[i]; i++ ) {
- p = stpcpy ( p, "%m" );
- mpis[nelem++] = factors[i];
- }
- strcpy ( p, ")))" );
-
- while ( nelem < DIM(mpis) )
- mpis[nelem++] = NULL;
-
- /* and now the ugly part: we don't have a function to
- * pass an array to a format string, so we have just pass everything
- * we have. which normally should be no problem as only those
- * with a corresponding %m are used
- */
- if ( gcry_sexp_build ( r_key, NULL, string,
- mpis[0], mpis[1], mpis[2], mpis[3], mpis[4], mpis[5],
- mpis[6], mpis[7], mpis[8], mpis[9], mpis[10], mpis[11],
- mpis[12], mpis[13], mpis[14], mpis[15], mpis[16], mpis[17],
- mpis[18], mpis[19], mpis[20], mpis[21], mpis[22], mpis[23],
- mpis[24], mpis[25], mpis[26], mpis[27], mpis[28], mpis[29]
- ) )
- BUG ();
- assert ( DIM(mpis) == 30 );
- g10_free ( string );
- }
- release_mpi_array ( skey );
- release_mpi_array ( factors );
-
- return 0;
-}
-
-/****************
- * Get the number of nbits from the public key
- * Hmmm: Should we have really this function or is it
- * better to have a more general function to retrieve
- * different propoerties of the key?
- */
-unsigned int
-gcry_pk_get_nbits( GCRY_SEXP key )
-{
- int rc, i, algo;
- MPI *keyarr;
- unsigned int nbits = 0;
-
- rc = sexp_to_key( key, 0, &keyarr, &algo );
- if( rc == GCRYERR_INV_OBJ )
- rc = sexp_to_key( key, 0, &keyarr, &algo );
- if( rc )
- return 0;
-
- do {
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo ) {
- nbits = (*pubkey_table[i].get_nbits)( algo, keyarr );
- goto leave;
- }
- } while( load_pubkey_modules() );
- if( is_RSA(algo) ) /* we always wanna see the length of a key :-) */
- nbits = mpi_get_nbits( keyarr[0] );
- leave:
- release_mpi_array( keyarr );
- return nbits;
-}
-
-
-
-int
-gcry_pk_ctl( int cmd, void *buffer, size_t buflen)
-{
- switch( cmd ) {
- case GCRYCTL_DISABLE_ALGO:
- /* this one expects a buffer pointing to an
- * integer with the algo number.
- */
- if( !buffer || buflen != sizeof(int) )
- return set_lasterr( GCRYERR_INV_CIPHER_ALGO );
- disable_pubkey_algo( *(int*)buffer );
- break;
-
- default:
- return set_lasterr( GCRYERR_INV_OP );
- }
- return 0;
-}
-
-
-/****************
- * Return information about the given algorithm
- * WHAT select the kind of information returned:
- * GCRYCTL_TEST_ALGO:
- * Returns 0 when the specified algorithm is available for use.
- * Buffer must be NULL, nbytes may have the address of a variable
- * with the required usage of the algorithm. It may be 0 for don't
- * care or a combination of the GCRY_PK_USAGE_xxx flags;
- * GCRYCTL_GET_ALGO_USAGE:
- * Return the usage glafs for the give algo. An invalid alog
- * does return 0. Disabled algos are ignored here becuase we
- * only want to know whether the algo is at all capable of
- * the usage.
- *
- * On error the value -1 is returned and the error reason may be
- * retrieved by gcry_errno().
- * Note: Because this function is in most caes used to return an
- * integer value, we can make it easier for the caller to just look at
- * the return value. The caller will in all cases consult the value
- * and thereby detecting whether a error occured or not (i.e. while checking
- * the block size)
- */
-int
-gcry_pk_algo_info( int algo, int what, void *buffer, size_t *nbytes)
-{
- switch( what ) {
- case GCRYCTL_TEST_ALGO: {
- int use = nbytes? *nbytes: 0;
- if( buffer ) {
- set_lasterr( GCRYERR_INV_ARG );
- return -1;
- }
- if( check_pubkey_algo( algo, use ) ) {
- set_lasterr( GCRYERR_INV_PK_ALGO );
- return -1;
- }
- }
- break;
-
- case GCRYCTL_GET_ALGO_USAGE:
- do {
- int i;
- for(i=0; pubkey_table[i].name; i++ )
- if( pubkey_table[i].algo == algo )
- return pubkey_table[i].use;
- } while( load_pubkey_modules() );
- return 0;
-
- case GCRYCTL_GET_ALGO_NPKEY: return pubkey_get_npkey( algo );
- case GCRYCTL_GET_ALGO_NSKEY: return pubkey_get_nskey( algo );
- case GCRYCTL_GET_ALGO_NSIGN: return pubkey_get_nsig( algo );
- case GCRYCTL_GET_ALGO_NENCR: return pubkey_get_nenc( algo );
-
- default:
- set_lasterr( GCRYERR_INV_OP );
- return -1;
- }
- return 0;
-}
-
-