summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cipher/ChangeLog11
-rw-r--r--cipher/pubkey.c256
-rw-r--r--mpi/ChangeLog4
-rw-r--r--mpi/mpicoder.c2
-rw-r--r--src/ChangeLog4
-rw-r--r--src/gcrypt.h6
-rw-r--r--src/sexp.c43
7 files changed, 309 insertions, 17 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 33b04e4f..5925a041 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,14 @@
+Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * pubkey.c (gcry_pk_decrypt): Implemented.
+ (gcry_pk_encrypt): Implemented.
+ (gcry_pk_testkey): New.
+ (gcry_pk_genkey): New.
+ (pubkey_decrypt): Made static.
+ (pubkey_encrypt): Ditto.
+ (pubkey_check_secret_key): Ditto.
+ (pubkey_generate): Ditto.
+
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* pubkey.c (pubkey_nbits): Removed and replaced by ...
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 949e3b9c..4def6f69 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -95,6 +95,7 @@ static struct {
{ 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 );
@@ -432,7 +433,7 @@ pubkey_get_nenc( int algo )
}
-int
+static int
pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
{
int i;
@@ -447,7 +448,7 @@ pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
}
-int
+static int
pubkey_check_secret_key( int algo, MPI *skey )
{
int i;
@@ -467,7 +468,7 @@ pubkey_check_secret_key( int algo, MPI *skey )
* should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the
* algorithm allows this - check with pubkey_get_nenc() )
*/
-int
+static int
pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
{
int i, rc;
@@ -504,12 +505,12 @@ pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
* result is a pointer to a mpi variable which will receive a
* newly allocated mpi or NULL in case of an error.
*/
-int
+static int
pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
{
int i, rc;
- *result = NULL; /* so the caller can always do an mpi_free */
+ *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++ )
@@ -751,20 +752,196 @@ sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
}
+/****************
+ * 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 */
+ list = gcry_sexp_cdr( list );
+ if( !list )
+ return GCRYERR_NO_OBJ; /* no cdr for the data object */
+ name = gcry_sexp_car_data( list, &n );
+ if( !name )
+ 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 )
+ 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 )
+ 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 );
+ return GCRYERR_NO_OBJ; /* required parameter not found */
+ }
+ array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
+ if( !array[idx] ) {
+ g10_free( array );
+ return GCRYERR_INV_OBJ; /* required parameter is invalid */
+ }
+ }
+
+ *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 *result, GCRY_SEXP data, GCRY_SEXP pkey )
+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;
+ GCRY_SEXP *s_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_car_mpi( s_data, 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 ) {
+ g10_free( ciph );
+ return rc;
+ }
+
+ /* We did it. Now build the return list */
+ s_elems = g10_xcalloc( (strlen(algo_elems)+2), sizeof *s_elems );
+ s_elems[0] = SEXP_NEW( algo_name, 0 );
+ for(i=0; algo_elems[i]; i++ ) {
+ char tmp[2];
+ tmp[0] = algo_elems[i];
+ tmp[1] = 0;
+ s_elems[i+1] = gcry_sexp_new_name_mpi( tmp, ciph[i] );
+ }
+ release_mpi_array( ciph );
+ g10_free( ciph );
+
+ *r_ciph = SEXP_CONS( SEXP_NEW( "enc-val", 0 ),
+ gcry_sexp_alist( s_elems ) );
+
+ g10_free( s_elems );
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 *result, GCRY_SEXP data, GCRY_SEXP skey )
+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 */
+ }
+
+ *r_plain = gcry_sexp_new_mpi( plain );
+ mpi_free( plain );
+ release_mpi_array( data );
+ release_mpi_array( skey );
return 0;
}
@@ -800,7 +977,7 @@ gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey )
MPI *result;
int i, algo, rc;
const char *algo_name, *algo_elems;
- GCRY_SEXP s;
+ GCRY_SEXP *s_elems;
rc = sexp_to_key( s_skey, 1, &skey, &algo );
if( rc )
@@ -832,16 +1009,21 @@ gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey )
return rc;
}
- s = SEXP_NEW( algo_name, 0 );
+ s_elems = g10_xcalloc( (strlen(algo_elems)+2), sizeof *s_elems );
+ s_elems[0] = SEXP_NEW( algo_name, 0 );
for(i=0; algo_elems[i]; i++ ) {
char tmp[2];
tmp[0] = algo_elems[i];
tmp[1] = 0;
- s = gcry_sexp_append( s, gcry_sexp_new_name_mpi( tmp, result[i] ) );
+ s_elems[i+1] = gcry_sexp_new_name_mpi( tmp, result[i] );
}
+ release_mpi_array( result );
g10_free( result );
- *r_sig = SEXP_CONS( SEXP_NEW( "sig-val", 0 ), s );
- gcry_sexp_dump( *r_sig );
+
+ *r_sig = SEXP_CONS( SEXP_NEW( "sig-val", 0 ),
+ gcry_sexp_alist( s_elems ) );
+
+ g10_free( s_elems );
return 0;
}
@@ -890,6 +1072,52 @@ gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey )
/****************
+ * 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:
+ * (GNU
+ * (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
+ * and optionally some additional informatin.
+ */
+int
+gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms )
+{
+ return GCRYERR_NOT_IMPL;
+}
+
+/****************
* 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
diff --git a/mpi/ChangeLog b/mpi/ChangeLog
index 2d2ec8bd..9465aa51 100644
--- a/mpi/ChangeLog
+++ b/mpi/ChangeLog
@@ -1,3 +1,7 @@
+Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * mpicoder.c (gcry_mpi_aprint): Now really returns the length.
+
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* mpiutil.c: Removed all memory debugging code.
diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c
index ca805f28..bd79aca5 100644
--- a/mpi/mpicoder.c
+++ b/mpi/mpicoder.c
@@ -608,6 +608,8 @@ gcry_mpi_aprint( enum gcry_mpi_format format, void **buffer, size_t *nbytes,
g10_free(*buffer);
*buffer = NULL;
}
+ else if( nbytes )
+ *nbytes = n;
return rc;
}
diff --git a/src/ChangeLog b/src/ChangeLog
index 4c2a5b2f..30e508fb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
+Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * sexp.c (gcry_sexp_alist): New.
+
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* secmem.c: Moved from ../util to here.
diff --git a/src/gcrypt.h b/src/gcrypt.h
index 63715d49..c21e6b38 100644
--- a/src/gcrypt.h
+++ b/src/gcrypt.h
@@ -87,7 +87,8 @@ enum {
GCRYERR_INV_OBJ = 65, /* an object is not valid */
GCRYERR_TOO_SHORT = 66, /* provided buffer too short */
GCRYERR_TOO_LARGE = 67, /* object is too large */
- GCRYERR_NO_OBJ = 68, /* Missign item in an object */
+ GCRYERR_NO_OBJ = 68, /* Missing item in an object */
+ GCRYERR_NOT_IMPL = 69, /* Not implemented */
};
const char *gcry_check_version( const char *req_version );
@@ -156,6 +157,7 @@ GCRY_SEXP gcry_sexp_new_name_mpi( const char *name, GCRY_MPI mpi );
void gcry_sexp_release( GCRY_SEXP sexp );
void gcry_sexp_dump( GCRY_SEXP a );
GCRY_SEXP gcry_sexp_cons( GCRY_SEXP a, GCRY_SEXP b );
+GCRY_SEXP gcry_sexp_alist( GCRY_SEXP *array );
GCRY_SEXP gcry_sexp_vlist( GCRY_SEXP a, ... );
GCRY_SEXP gcry_sexp_append( GCRY_SEXP a, GCRY_SEXP n );
GCRY_SEXP gcry_sexp_prepend( GCRY_SEXP a, GCRY_SEXP n );
@@ -329,6 +331,8 @@ int gcry_pk_encrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP pkey );
int gcry_pk_decrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP skey );
int gcry_pk_sign( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP skey );
int gcry_pk_verify( GCRY_SEXP sigval, GCRY_SEXP data, GCRY_SEXP pkey );
+int gcry_pk_testkey( GCRY_SEXP key );
+int gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms );
int gcry_pk_ctl( int cmd, void *buffer, size_t buflen);
int gcry_pk_algo_info( int algo, int what, void *buffer, size_t *nbytes);
diff --git a/src/sexp.c b/src/sexp.c
index 915c633d..e56e6c19 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -268,6 +268,46 @@ gcry_sexp_cons( GCRY_SEXP a, GCRY_SEXP b )
/****************
+ * Make a list from all items in the array the end of the array is marked
+ * with a NULL. y a NULL
+ * Don't use the passed lists later on, they are void.
+ */
+GCRY_SEXP
+gcry_sexp_alist( GCRY_SEXP *array )
+{
+ NODE head, tail = NULL, node;
+ va_list arg_ptr ;
+ int i;
+
+ if( !*array )
+ return NULL;
+
+ head = g10_xcalloc( 1, sizeof *node );
+ head->type = ntLIST;
+
+ for( i=0; (node = array[i]); i++ ) {
+ if( node->type != ntLIST ) {
+ fputs("sexp_alist: an arg is not a list\n", stderr );
+ return NULL; /* fixme: we should release already allocated nodes */
+ }
+ if( !node->u.list->next ) { /* node has only one item */
+ NODE tmp = node;
+ node = node->u.list;
+ /* fixme: release tmp here */
+ }
+ if( !tail ) {
+ head->u.list = node;
+ }
+ else
+ tail->next = node;
+ node->up = head;
+ tail = node;
+ }
+
+ return head;
+}
+
+/****************
* Make a list from all items, the end of list is indicated by a NULL
* don't use the passed lists later on, they are void.
*/
@@ -296,7 +336,7 @@ gcry_sexp_vlist( GCRY_SEXP a, ... )
while( (node = va_arg( arg_ptr, NODE )) ) {
if( node->type != ntLIST ) {
fputs("sexp_vlist: an arg is not a list\n", stderr );
- return NULL; /* fixme: we should release alread allocated nodes */
+ return NULL; /* fixme: we should release already allocated nodes */
}
if( !node->u.list->next ) { /* node has only one item */
NODE tmp = node;
@@ -321,7 +361,6 @@ gcry_sexp_vlist( GCRY_SEXP a, ... )
GCRY_SEXP
gcry_sexp_append( GCRY_SEXP a, GCRY_SEXP n )
{
-
GCRY_SEXP node;
if( a->type != ntLIST ) {