summaryrefslogtreecommitdiffstats
path: root/agent/cvt-openpgp.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2011-02-02 15:48:54 +0100
committerWerner Koch <wk@gnupg.org>2011-02-02 15:48:54 +0100
commit4659c923a08002a72cb4bb5b3c4e6a02d7484767 (patch)
tree7763258d394316b479245bc69d67fb49dbba37df /agent/cvt-openpgp.c
parentMove OpenPGP OID helpers to common/. (diff)
downloadgnupg2-4659c923a08002a72cb4bb5b3c4e6a02d7484767.tar.xz
gnupg2-4659c923a08002a72cb4bb5b3c4e6a02d7484767.zip
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.
Diffstat (limited to 'agent/cvt-openpgp.c')
-rw-r--r--agent/cvt-openpgp.c86
1 files changed, 42 insertions, 44 deletions
diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c
index 02c2bc841..690459330 100644
--- a/agent/cvt-openpgp.c
+++ b/agent/cvt-openpgp.c
@@ -37,7 +37,7 @@
/* Helper to pass data via the callback to do_unprotect. */
-struct try_do_unprotect_arg_s
+struct try_do_unprotect_arg_s
{
int is_v4;
int is_protected;
@@ -87,10 +87,12 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip)
"(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
break;
- case GCRY_PK_ECDSA:
- case GCRY_PK_ECDH:
+ case GCRY_PK_ECDSA:
+ case GCRY_PK_ECDH:
err = gcry_sexp_build (&s_pkey, NULL,
- "(public-key(ecc(c%m)(q%m)))", pkey[0], pkey[1]);
+ "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))",
+ pkey[0], pkey[1], pkey[2], pkey[3], pkey[4],
+ pkey[5]);
break;
default:
@@ -108,8 +110,7 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip)
/* Convert a secret key given as algorithm id and an array of key
parameters into our s-expression based format. Note that
- PUBKEY_ALGO is a standard id and not an OpenPGP id.
- */
+ PUBKEY_ALGO has an gcrypt algorithm number. */
static gpg_error_t
convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
{
@@ -118,9 +119,6 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
*r_key = NULL;
- /* FIXME: This is not consistent with the above comment. */
- pubkey_algo = map_pk_openpgp_to_gcry (pubkey_algo);
-
switch (pubkey_algo)
{
case GCRY_PK_DSA:
@@ -147,15 +145,15 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
break;
case GCRY_PK_ECDSA:
- err = gcry_sexp_build (&s_skey, NULL,
- "(private-key(ecdsa(c%m)(q%m)(d%m)))",
- skey[0], skey[1], skey[2]);
- break;
-
case GCRY_PK_ECDH:
+ /* Although our code would work with "ecc" we explicitly use
+ "ecdh" or "ecdsa" to implicitly set the key capabilities. */
err = gcry_sexp_build (&s_skey, NULL,
- "(private-key(ecdh(c%m)(q%m)(p%m)(d%m)))",
- skey[0], skey[1], skey[2], skey[3]);
+ "(private-key(%s(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)"
+ "(d%m)))",
+ pubkey_algo == GCRY_PK_ECDSA?"ecdsa":"ecdh",
+ skey[0], skey[1], skey[2], skey[3], skey[4],
+ skey[5], skey[6]);
break;
default:
@@ -184,7 +182,7 @@ hash_passphrase_and_set_key (const char *passphrase,
keylen = gcry_cipher_get_algo_keylen (protect_algo);
if (!keylen)
return gpg_error (GPG_ERR_INTERNAL);
-
+
key = xtrymalloc_secure (keylen);
if (!key)
return gpg_error_from_syserror ();
@@ -204,7 +202,7 @@ static u16
checksum (const unsigned char *p, unsigned int n)
{
u16 a;
-
+
for (a=0; n; n-- )
a += *p++;
return a;
@@ -272,7 +270,7 @@ do_unprotect (const char *passphrase,
return gpg_error (GPG_ERR_MISSING_VALUE);
if (nskey+1 >= skeysize)
return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
-
+
/* Check whether SKEY is at all protected. If it is not protected
merely verify the checksum. */
if (!is_protected)
@@ -284,7 +282,7 @@ do_unprotect (const char *passphrase,
{
if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
return gpg_error (GPG_ERR_BAD_SECKEY);
-
+
err = gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, skey[i]);
if (!err)
{
@@ -301,7 +299,7 @@ do_unprotect (const char *passphrase,
if (err)
return err;
}
-
+
if (actual_csum != desired_csum)
return gpg_error (GPG_ERR_CHECKSUM);
return 0;
@@ -324,7 +322,7 @@ do_unprotect (const char *passphrase,
s2k_algo, gcry_md_algo_name (s2k_algo));
return gpg_error (GPG_ERR_DIGEST_ALGO);
}
-
+
err = gcry_cipher_open (&cipher_hd, protect_algo,
GCRY_CIPHER_MODE_CFB,
(GCRY_CIPHER_SECURE
@@ -343,10 +341,10 @@ do_unprotect (const char *passphrase,
{
gcry_cipher_close (cipher_hd);
return err;
- }
+ }
gcry_cipher_setiv (cipher_hd, protect_iv, protect_ivlen);
-
+
actual_csum = 0;
if (pkt_version >= 4)
{
@@ -379,15 +377,15 @@ do_unprotect (const char *passphrase,
{
/* This is the new SHA1 checksum method to detect tampering
with the key as used by the Klima/Rosa attack. */
- desired_csum = 0;
+ desired_csum = 0;
actual_csum = 1; /* Default to bad checksum. */
- if (ndata < 20)
+ if (ndata < 20)
log_error ("not enough bytes for SHA-1 checksum\n");
- else
+ else
{
gcry_md_hd_t h;
-
+
if (gcry_md_open (&h, GCRY_MD_SHA1, 1))
BUG(); /* Algo not available. */
gcry_md_write (h, data, ndata - 20);
@@ -397,13 +395,13 @@ do_unprotect (const char *passphrase,
gcry_md_close (h);
}
}
- else
+ else
{
/* Old 16 bit checksum method. */
if (ndata < 2)
{
log_error ("not enough bytes for checksum\n");
- desired_csum = 0;
+ desired_csum = 0;
actual_csum = 1; /* Mark checksum bad. */
}
else
@@ -417,7 +415,7 @@ do_unprotect (const char *passphrase,
}
}
}
-
+
/* Better check it here. Otherwise the gcry_mpi_scan would fail
because the length may have an arbitrary value. */
if (desired_csum == actual_csum)
@@ -468,7 +466,7 @@ do_unprotect (const char *passphrase,
gcry_cipher_close (cipher_hd);
return gpg_error (GPG_ERR_BAD_SECKEY);
}
-
+
buffer = xtrymalloc_secure (ndata);
if (!buffer)
{
@@ -476,7 +474,7 @@ do_unprotect (const char *passphrase,
gcry_cipher_close (cipher_hd);
return err;
}
-
+
gcry_cipher_sync (cipher_hd);
buffer[0] = p[0];
buffer[1] = p[1];
@@ -557,7 +555,7 @@ try_do_unprotect_cb (struct pin_entry_info_s *pi)
pointed to by GRIP. On error NULL is stored at all return
arguments. */
gpg_error_t
-convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
+convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
unsigned char *grip, const char *prompt,
const char *cache_nonce,
unsigned char **r_key, char **r_passphrase)
@@ -625,7 +623,7 @@ convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
if (!protect_algo && !!strcmp (string, "IDEA"))
protect_algo = GCRY_CIPHER_IDEA;
xfree (string);
-
+
value = gcry_sexp_nth_data (list, 3, &valuelen);
if (!value || !valuelen || valuelen > sizeof iv)
goto bad_seckey;
@@ -848,7 +846,7 @@ convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
bad_seckey:
err = gpg_error (GPG_ERR_BAD_SECKEY);
goto leave;
-
+
outofmem:
err = gpg_error (GPG_ERR_ENOMEM);
goto leave;
@@ -874,13 +872,13 @@ key_from_sexp (gcry_sexp_t sexp, const char *elems, gcry_mpi_t *array)
}
array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l2);
- if (!array[idx])
+ if (!array[idx])
{
err = gpg_error (GPG_ERR_INV_OBJ); /* Required parameter invalid. */
goto leave;
}
}
-
+
leave:
if (err)
{
@@ -1028,7 +1026,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
gcry_sexp_release (list);
return gpg_error (GPG_ERR_INV_OBJ); /* Invalid structure of object. */
}
-
+
algo = gcry_pk_map_name (name);
xfree (name);
@@ -1038,8 +1036,8 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
case GCRY_PK_ELG: algoname = "elg"; npkey = 3; elems = "pgyx"; break;
case GCRY_PK_ELG_E: algoname = "elg"; npkey = 3; elems = "pgyx"; break;
case GCRY_PK_DSA: algoname = "dsa"; npkey = 4; elems = "pqgyx"; break;
- case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 2; elems = "cqd"; break;
- case GCRY_PK_ECDH: algoname = "ecdh"; npkey = 3; elems = "cqpd"; break;
+ case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 6; elems = "pabgnqd"; break;
+ case GCRY_PK_ECDH: algoname = "ecdh"; npkey = 6; elems = "pabgnqd"; break;
default: algoname = ""; npkey = 0; elems = NULL; break;
}
assert (!elems || strlen (elems) < DIM (array) );
@@ -1070,9 +1068,9 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
void *format_args[10+2];
size_t n;
gcry_sexp_t tmpkey, tmpsexp = NULL;
-
+
snprintf (countbuf, sizeof countbuf, "%lu", s2k_count);
-
+
init_membuf (&mbuf, 50);
put_membuf_str (&mbuf, "(skey");
for (i=j=0; i < npkey; i++)
@@ -1105,7 +1103,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
" %S\n"
" (protection sha1 aes %b 1:3 sha1 %b %s))\n",
algoname,
- tmpkey,
+ tmpkey,
(int)sizeof protect_iv, protect_iv,
(int)sizeof salt, salt,
countbuf);