From e0972d3d962548972872d889b362560e499340d1 Mon Sep 17 00:00:00 2001 From: Andrey Jivsov Date: Wed, 5 Jan 2011 17:33:17 -0800 Subject: Integrating http://code.google.com/p/gnupg-ecc/source/detail?r=15 . The following works: gpg2 --gen-key (ECC) gpg2 --list-keys gpg2 --list-packets ~/.gnupg/pubring.gpg gpg2 --list-packets ECDH doesn't work yet as the code must be re-written to adjust for gpg-agent refactoring. --- g10/keyid.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'g10/keyid.c') diff --git a/g10/keyid.c b/g10/keyid.c index 62ce03685..2a9bd1988 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -57,6 +57,8 @@ pubkey_letter( int algo ) case PUBKEY_ALGO_ELGAMAL_E: return 'g'; case PUBKEY_ALGO_ELGAMAL: return 'G' ; case PUBKEY_ALGO_DSA: return 'D' ; + case PUBKEY_ALGO_ECDSA: return 'E' ; // ECC DSA (sign only) + case PUBKEY_ALGO_ECDH: return 'e' ; // ECC DH (encrypt only) default: return '?'; } } @@ -74,6 +76,8 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) unsigned int nbits; size_t nbytes; int npkey = pubkey_get_npkey (pk->pubkey_algo); + /* name OID, MPI of public point, [for ECDH only: KEK params] */ + enum gcry_mpi_format ecc_pub_format[3] = {GCRYMPI_FMT_USG, GCRYMPI_FMT_PGP, GCRYMPI_FMT_USG}; /* Two extra bytes for the expiration date in v3 */ if(pk->version<4) @@ -90,11 +94,13 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) { for(i=0; i < npkey; i++ ) { - if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i])) + const enum gcry_mpi_format fmt = + ((pk->pubkey_algo==PUBKEY_ALGO_ECDSA || pk->pubkey_algo==PUBKEY_ALGO_ECDH) ? ecc_pub_format[i] : GCRYMPI_FMT_PGP); + + if (gcry_mpi_print (fmt, NULL, 0, &nbytes, pk->pkey[i])) BUG (); pp[i] = xmalloc (nbytes); - if (gcry_mpi_print (GCRYMPI_FMT_PGP, pp[i], nbytes, - &nbytes, pk->pkey[i])) + if (gcry_mpi_print (fmt, pp[i], nbytes, &nbytes, pk->pkey[i])) BUG (); nn[i] = nbytes; n += nn[i]; @@ -712,6 +718,20 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array) pk->pkey[0], pk->pkey[1]); break; + case PUBKEY_ALGO_ECDSA: + case PUBKEY_ALGO_ECDH: + err = gcry_sexp_build (&s_pkey, NULL, + "(public-key(ecc(c%m)(q%m)))", + pk->pkey[0], pk->pkey[1]); + break; +/* + case PUBKEY_ALGO_ECDH: + err = gcry_sexp_build (&s_pkey, NULL, + "(public-key(ecdh(c%m)(q%m)(p%m)))", + pk->pkey[0], pk->pkey[1], pk->pkey[2]); + break; +*/ + default: err = gpg_error (GPG_ERR_PUBKEY_ALGO); break; -- cgit v1.2.3 From 90b0ff23b7e51332592668e4034967c1aac1c593 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 21 Jan 2011 12:00:57 +0100 Subject: Editorial changes and allow building with old libgcrypts. Changed order of some conditional to make to put the special case into the true branch. Indentation changes. Minor other changes to make the ECC code more similar to the rest of our code. It builds but many sefltests still fail. Need to fix that before using it with an ECDH enabled libgcrypt. [/] 2011-01-21 Werner Koch * configure.ac: Need Libgcrypt 1.4.6 due to AESWRAP. (HAVE_GCRY_PK_ECDH): Add new test. [agent/] 2011-01-21 Werner Koch * cvt-openpgp.c (GCRY_PK_ECDH) [!HAVE_GCRY_PK_ECDH]: New. [include/] 2011-01-21 Werner Koch * cipher.h (GCRY_PK_USAGE_CERT): Remove compatibility macros because we now require libgcrypt 1.4.6. (GCRY_PK_ECDH): Add replacement. --- g10/keyid.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'g10/keyid.c') diff --git a/g10/keyid.c b/g10/keyid.c index 2a9bd1988..0405b8b2f 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -54,11 +54,11 @@ pubkey_letter( int algo ) case PUBKEY_ALGO_RSA: return 'R' ; case PUBKEY_ALGO_RSA_E: return 'r' ; case PUBKEY_ALGO_RSA_S: return 's' ; - case PUBKEY_ALGO_ELGAMAL_E: return 'g'; + case PUBKEY_ALGO_ELGAMAL_E: return 'g' ; case PUBKEY_ALGO_ELGAMAL: return 'G' ; case PUBKEY_ALGO_DSA: return 'D' ; - case PUBKEY_ALGO_ECDSA: return 'E' ; // ECC DSA (sign only) - case PUBKEY_ALGO_ECDH: return 'e' ; // ECC DH (encrypt only) + case PUBKEY_ALGO_ECDSA: return 'E' ; /* ECC DSA (sign only) */ + case PUBKEY_ALGO_ECDH: return 'e' ; /* ECC DH (encrypt only) */ default: return '?'; } } @@ -76,8 +76,6 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) unsigned int nbits; size_t nbytes; int npkey = pubkey_get_npkey (pk->pubkey_algo); - /* name OID, MPI of public point, [for ECDH only: KEK params] */ - enum gcry_mpi_format ecc_pub_format[3] = {GCRYMPI_FMT_USG, GCRYMPI_FMT_PGP, GCRYMPI_FMT_USG}; /* Two extra bytes for the expiration date in v3 */ if(pk->version<4) @@ -92,11 +90,17 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) } else { - for(i=0; i < npkey; i++ ) + for (i=0; i < npkey; i++ ) { - const enum gcry_mpi_format fmt = - ((pk->pubkey_algo==PUBKEY_ALGO_ECDSA || pk->pubkey_algo==PUBKEY_ALGO_ECDH) ? ecc_pub_format[i] : GCRYMPI_FMT_PGP); - + enum gcry_mpi_format fmt; + + if ((pk->pubkey_algo == PUBKEY_ALGO_ECDSA + || pk->pubkey_algo == PUBKEY_ALGO_ECDH) + && (i == 0 || i == 2)) + fmt = GCRYMPI_FMT_USG; /* Name of OID or KEK parms. */ + else + fmt = GCRYMPI_FMT_PGP; + if (gcry_mpi_print (fmt, NULL, 0, &nbytes, pk->pkey[i])) BUG (); pp[i] = xmalloc (nbytes); @@ -106,7 +110,7 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) n += nn[i]; } } - + gcry_md_putc ( md, 0x99 ); /* ctb */ /* What does it mean if n is greater than than 0xFFFF ? */ gcry_md_putc ( md, n >> 8 ); /* 2 byte length header */ @@ -724,13 +728,12 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array) "(public-key(ecc(c%m)(q%m)))", pk->pkey[0], pk->pkey[1]); break; -/* - case PUBKEY_ALGO_ECDH: - err = gcry_sexp_build (&s_pkey, NULL, - "(public-key(ecdh(c%m)(q%m)(p%m)))", - pk->pkey[0], pk->pkey[1], pk->pkey[2]); - break; -*/ + + /* case PUBKEY_ALGO_ECDH: */ + /* err = gcry_sexp_build (&s_pkey, NULL, */ + /* "(public-key(ecdh(c%m)(q%m)(p%m)))", */ + /* pk->pkey[0], pk->pkey[1], pk->pkey[2]); */ + /* break; */ default: err = gpg_error (GPG_ERR_PUBKEY_ALGO); -- cgit v1.2.3 From 0fb0bb8d9a960a2473ab70a021d20639a43227e0 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 31 Jan 2011 09:27:06 +0100 Subject: Reworked the ECC changes to better fit into the Libgcrypt API. See ChangeLog for details. Key generation, signing and verification works. Encryption does not yet work. Requires latest Libgcrypt changes. --- g10/keyid.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'g10/keyid.c') diff --git a/g10/keyid.c b/g10/keyid.c index 0405b8b2f..6571a51c0 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -724,17 +724,20 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array) case PUBKEY_ALGO_ECDSA: case PUBKEY_ALGO_ECDH: - err = gcry_sexp_build (&s_pkey, NULL, - "(public-key(ecc(c%m)(q%m)))", - pk->pkey[0], pk->pkey[1]); + { + char *curve = openpgp_oid_to_str (pk->pkey[0]); + if (!curve) + err = gpg_error_from_syserror (); + else + { + err = gcry_sexp_build (&s_pkey, NULL, + "(public-key(ecc(curve%s)(q%m)))", + curve, pk->pkey[1]); + xfree (curve); + } + } break; - /* case PUBKEY_ALGO_ECDH: */ - /* err = gcry_sexp_build (&s_pkey, NULL, */ - /* "(public-key(ecdh(c%m)(q%m)(p%m)))", */ - /* pk->pkey[0], pk->pkey[1], pk->pkey[2]); */ - /* break; */ - default: err = gpg_error (GPG_ERR_PUBKEY_ALGO); break; -- cgit v1.2.3 From 4659c923a08002a72cb4bb5b3c4e6a02d7484767 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 2 Feb 2011 15:48:54 +0100 Subject: Sample ECC keys and message do now work. Import and export of secret keys does now work. Encryption has been fixed to be compatible with the sample messages. This version tests for new Libgcrypt function and thus needs to be build with a new Libgcrypt installed. --- g10/keyid.c | 97 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 43 deletions(-) (limited to 'g10/keyid.c') diff --git a/g10/keyid.c b/g10/keyid.c index 6571a51c0..cbcc971c3 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -39,7 +39,7 @@ #ifdef HAVE_UNSIGNED_TIME_T # define IS_INVALID_TIME_T(a) ((a) == (time_t)(-1)) -#else +#else /* Error or 32 bit time_t and value after 2038-01-19. */ # define IS_INVALID_TIME_T(a) ((a) < 0) #endif @@ -81,6 +81,11 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) if(pk->version<4) n+=2; + /* FIXME: We can avoid the extra malloc by calling only the first + mpi_print here which computes the required length and calling the + real mpi_print only at the end. The speed advantage would only be + for ECC (opaque MPIs) or if we could implement an mpi_print + variant with a callback handler to do the hashing. */ if (npkey==0 && pk->pkey[0] && gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE)) { @@ -92,25 +97,32 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) { for (i=0; i < npkey; i++ ) { - enum gcry_mpi_format fmt; - - if ((pk->pubkey_algo == PUBKEY_ALGO_ECDSA - || pk->pubkey_algo == PUBKEY_ALGO_ECDH) - && (i == 0 || i == 2)) - fmt = GCRYMPI_FMT_USG; /* Name of OID or KEK parms. */ + if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE)) + { + size_t nbits; + const void *p; + + p = gcry_mpi_get_opaque (pk->pkey[i], &nbits); + pp[i] = xmalloc ((nbits+7)/8); + memcpy (pp[i], p, (nbits+7)/8); + nn[i] = (nbits+7)/8; + n += nn[i]; + } else - fmt = GCRYMPI_FMT_PGP; - - if (gcry_mpi_print (fmt, NULL, 0, &nbytes, pk->pkey[i])) - BUG (); - pp[i] = xmalloc (nbytes); - if (gcry_mpi_print (fmt, pp[i], nbytes, &nbytes, pk->pkey[i])) - BUG (); - nn[i] = nbytes; - n += nn[i]; + { + if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, + &nbytes, pk->pkey[i])) + BUG (); + pp[i] = xmalloc (nbytes); + if (gcry_mpi_print (GCRYMPI_FMT_PGP, pp[i], nbytes, + &nbytes, pk->pkey[i])) + BUG (); + nn[i] = nbytes; + n += nn[i]; + } } } - + gcry_md_putc ( md, 0x99 ); /* ctb */ /* What does it mean if n is greater than than 0xFFFF ? */ gcry_md_putc ( md, n >> 8 ); /* 2 byte length header */ @@ -127,7 +139,7 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) u16 days=0; if(pk->expiredate) days=(u16)((pk->expiredate - pk->timestamp) / 86400L); - + gcry_md_putc ( md, days >> 8 ); gcry_md_putc ( md, days ); } @@ -178,7 +190,7 @@ v3_keyid (gcry_mpi_t a, u32 *ki) BUG (); if (nbytes < 8) /* oops */ ki[0] = ki[1] = 0; - else + else { p = buffer + nbytes - 8; ki[0] = (p[0] << 24) | (p[1] <<16) | (p[2] << 8) | p[3]; @@ -215,7 +227,7 @@ keystrlen(void) const char * keystr (u32 *keyid) -{ +{ static char keyid_str[KEYID_STR_SIZE]; switch (opt.keyid_format) @@ -226,7 +238,7 @@ keystr (u32 *keyid) case KF_LONG: if (keyid[0]) - snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX", + snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX", (ulong)keyid[0], (ulong)keyid[1]); else snprintf (keyid_str, sizeof keyid_str, "%08lX", (ulong)keyid[1]); @@ -238,12 +250,12 @@ keystr (u32 *keyid) case KF_0xLONG: if(keyid[0]) - snprintf (keyid_str, sizeof keyid_str, "0x%08lX%08lX", + snprintf (keyid_str, sizeof keyid_str, "0x%08lX%08lX", (ulong)keyid[0],(ulong)keyid[1]); else snprintf (keyid_str, sizeof keyid_str, "0x%08lX", (ulong)keyid[1]); break; - + default: BUG(); } @@ -254,7 +266,7 @@ keystr (u32 *keyid) const char * keystr_with_sub (u32 *main_kid, u32 *sub_kid) -{ +{ static char buffer[KEYID_STR_SIZE+1+KEYID_STR_SIZE]; char *p; @@ -408,7 +420,7 @@ keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid ) else keyid_from_pk (&pk, keyid); } - else + else { const byte *dp = fprint; keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ; @@ -422,7 +434,7 @@ keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid ) u32 keyid_from_sig (PKT_signature *sig, u32 *keyid) { - if( keyid ) + if( keyid ) { keyid[0] = sig->keyid[0]; keyid[1] = sig->keyid[1]; @@ -437,13 +449,13 @@ namehash_from_uid (PKT_user_id *uid) if (!uid->namehash) { uid->namehash = xmalloc (20); - + if (uid->attrib_data) rmd160_hash_buffer (uid->namehash, uid->attrib_data, uid->attrib_len); else rmd160_hash_buffer (uid->namehash, uid->name, uid->len); } - + return uid->namehash; } @@ -465,7 +477,7 @@ mk_datestr (char *buffer, time_t atime) if (IS_INVALID_TIME_T (atime)) strcpy (buffer, "????" "-??" "-??"); /* Mark this as invalid. */ - else + else { tp = gmtime (&atime); sprintf (buffer,"%04d-%02d-%02d", @@ -485,7 +497,7 @@ datestr_from_pk (PKT_public_key *pk) { static char buffer[11+5]; time_t atime = pk->timestamp; - + return mk_datestr (buffer, atime); } @@ -518,7 +530,7 @@ expirestr_from_sig (PKT_signature *sig) { static char buffer[11+5]; time_t atime; - + if (!sig->expiredate) return _("never "); atime=sig->expiredate; @@ -591,7 +603,7 @@ const char * colon_datestr_from_sig (PKT_signature *sig) { static char buf[20]; - + snprintf (buf, sizeof buf, "%lu", (ulong)sig->timestamp); return buf; } @@ -621,21 +633,21 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len) const byte *dp; size_t len, nbytes; int i; - + if ( pk->version < 4 ) { if ( is_RSA(pk->pubkey_algo) ) { /* RSA in version 3 packets is special. */ gcry_md_hd_t md; - + if (gcry_md_open (&md, DIGEST_ALGO_MD5, 0)) BUG (); - if ( pubkey_get_npkey (pk->pubkey_algo) > 1 ) + if ( pubkey_get_npkey (pk->pubkey_algo) > 1 ) { for (i=0; i < 2; i++) { - if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, + if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nbytes, pk->pkey[i])) BUG (); /* fixme: Better allocate BUF on the stack */ @@ -662,10 +674,10 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len) memset (array,0,16); } } - else + else { gcry_md_hd_t md; - + md = do_fingerprint_md(pk); dp = gcry_md_read( md, 0 ); len = gcry_md_get_algo_dlen (gcry_md_get_algo (md)); @@ -677,7 +689,7 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len) pk->keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ; gcry_md_close( md); } - + *ret_len = len; return array; } @@ -694,7 +706,7 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array) { gpg_error_t err; gcry_sexp_t s_pkey; - + if (DBG_PACKET) log_debug ("get_keygrip for public key\n"); @@ -742,7 +754,7 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array) err = gpg_error (GPG_ERR_PUBKEY_ALGO); break; } - + if (err) return err; @@ -758,7 +770,7 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array) /* FIXME: Save the keygrip in PK. */ } gcry_sexp_release (s_pkey); - + return 0; } @@ -786,4 +798,3 @@ hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip) } return err; } - -- cgit v1.2.3