aboutsummaryrefslogtreecommitdiffstats
path: root/cipher/pubkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'cipher/pubkey.c')
-rw-r--r--cipher/pubkey.c143
1 files changed, 134 insertions, 9 deletions
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 4def6f699..3ace1d83c 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -668,11 +668,15 @@ sexp_to_key( GCRY_SEXP sexp, int want_private, MPI **retarray, int *retalgo)
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 );
return GCRYERR_NO_OBJ; /* required parameter not found */
}
array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
if( !array[idx] ) {
+ for(i=0; i<idx; i++)
+ g10_free( array[i] );
g10_free( array );
return GCRYERR_INV_OBJ; /* required parameter is invalid */
}
@@ -680,12 +684,16 @@ sexp_to_key( GCRY_SEXP sexp, int want_private, MPI **retarray, int *retalgo)
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 );
return GCRYERR_NO_OBJ; /* required parameter not found */
}
/* FIXME: put the MPI in secure memory when needed */
array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
if( !array[idx] ) {
+ for(i=0; i<idx; i++)
+ g10_free( array[i] );
g10_free( array );
return GCRYERR_INV_OBJ; /* required parameter is invalid */
}
@@ -1100,21 +1108,138 @@ gcry_pk_testkey( GCRY_SEXP s_key )
/****************
* Create a public key pair and return it in r_key.
* How the key is created depends on s_parms:
- * (GNU
- * (genkey
- * (algo
- * (parameter_name_1 ....)
- * ....
- * (parameter_name_n ....)
- * )))
+ * (genkey
+ * (algo
+ * (parameter_name_1 ....)
+ * ....
+ * (parameter_name_n ....)
+ * ))
* The key is returned in a format depending on the
- * algorithm. Both, private and secret key are returned
+ * 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 )
{
- return GCRYERR_NOT_IMPL;
+ GCRY_SEXP list, l2, *s_elems, pub_list, sec_list, misc_list;
+ 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 */
+ list = gcry_sexp_cdr( list );
+ if( !list )
+ return GCRYERR_NO_OBJ; /* no cdr for the genkey */
+ name = gcry_sexp_car_data( list, &n );
+ if( !name )
+ 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 )
+ 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 );
+ if( !l2 )
+ return GCRYERR_NO_OBJ; /* no nbits aparemter */
+ name = gcry_sexp_cdr_data( l2, &n );
+ if( !name )
+ 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 );
+ }
+
+ rc = pubkey_generate( algo, nbits, skey, &factors );
+ if( rc ) {
+ return rc;
+ }
+
+ /* build the public key list */
+ s_elems = g10_xcalloc( (strlen(pub_elems)+2), sizeof *s_elems );
+ s_elems[0] = SEXP_NEW( algo_name, 0 );
+ for(i=0; pub_elems[i]; i++ ) {
+ char tmp[2];
+ tmp[0] = pub_elems[i];
+ tmp[1] = 0;
+ s_elems[i+1] = gcry_sexp_new_name_mpi( tmp, skey[i] );
+ }
+ pub_list = SEXP_CONS( SEXP_NEW( "public-key", 0 ),
+ gcry_sexp_alist( s_elems ) );
+ g10_free( s_elems );
+
+ /* build the secret key list */
+ s_elems = g10_xcalloc( (strlen(sec_elems)+2), sizeof *s_elems );
+ s_elems[0] = SEXP_NEW( algo_name, 0 );
+ for(i=0; sec_elems[i]; i++ ) {
+ char tmp[2];
+ tmp[0] = sec_elems[i];
+ tmp[1] = 0;
+ s_elems[i+1] = gcry_sexp_new_name_mpi( tmp, skey[i] );
+ }
+ sec_list = SEXP_CONS( SEXP_NEW( "private-key", 0 ),
+ gcry_sexp_alist( s_elems ) );
+ g10_free( s_elems );
+
+ /* build the list of factors */
+ for(n=0; factors[n]; n++ )
+ ;
+ s_elems = g10_xcalloc( n+2, sizeof *s_elems );
+ s_elems[0] = SEXP_NEW( "pm1-factors", 0 );
+ for(i=0; factors[i]; i++ ) {
+ s_elems[i+1] = gcry_sexp_new_mpi( factors[i] );
+ }
+ misc_list = SEXP_CONS( SEXP_NEW( "misc-key-info", 0 ),
+ gcry_sexp_alist( s_elems ) );
+ g10_free( s_elems );
+
+ /* and put all together */
+ *r_key = gcry_sexp_vlist( SEXP_NEW( "key-data", 0 ),
+ pub_list, sec_list, misc_list, NULL );
+ gcry_sexp_release( pub_list );
+ gcry_sexp_release( sec_list );
+ gcry_sexp_release( misc_list );
+ return 0;
}
/****************