mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02:00
agent: For ECC, use opaque MPI for key representation.
* agent/cvt-openpgp.c (scan_pgp_format): New with SOS support. (do_unprotect): Use scan_pgp_format, handle opaque MPI for ECC. (convert_from_openpgp_main): Use opaque MPI for ECC. (apply_protection): Set GCRYMPI_FLAG_USER1 flag for encrypted secret. (extract_private_key): Use "/qd" for ECC, opaque MPI. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
a7d46c78e2
commit
2b11851624
@ -374,6 +374,38 @@ prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Scan octet string in the PGP format (length-in-two-octet octets) */
|
||||||
|
static int
|
||||||
|
scan_pgp_format (gcry_mpi_t *r_mpi, int pubkey_algo,
|
||||||
|
const unsigned char *buffer,
|
||||||
|
size_t buflen, size_t *r_nbytes)
|
||||||
|
{
|
||||||
|
/* Using gcry_mpi_scan with GCRYMPI_FLAG_PGP can be used if it is
|
||||||
|
MPI, but it will be "normalized" removing leading zeros. */
|
||||||
|
unsigned int nbits, nbytes;
|
||||||
|
|
||||||
|
if (pubkey_algo != GCRY_PK_ECC)
|
||||||
|
return gcry_mpi_scan (r_mpi, GCRYMPI_FMT_PGP, buffer, buflen, r_nbytes);
|
||||||
|
|
||||||
|
/* It's ECC, where we use SOS. */
|
||||||
|
|
||||||
|
if (buflen < 2)
|
||||||
|
return GPG_ERR_INV_OBJ;
|
||||||
|
|
||||||
|
nbits = (buffer[0] << 8) | buffer[1];
|
||||||
|
if (nbits >= 16384)
|
||||||
|
return GPG_ERR_INV_OBJ;
|
||||||
|
|
||||||
|
nbytes = (nbits + 7) / 8;
|
||||||
|
if (buflen < nbytes + 2)
|
||||||
|
return GPG_ERR_INV_OBJ;
|
||||||
|
|
||||||
|
*r_nbytes = nbytes + 2;
|
||||||
|
*r_mpi = gcry_mpi_set_opaque_copy (NULL, buffer+2, nbits);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Note that this function modifies SKEY. SKEYSIZE is the allocated
|
/* Note that this function modifies SKEY. SKEYSIZE is the allocated
|
||||||
size of the array including the NULL item; this is used for a
|
size of the array including the NULL item; this is used for a
|
||||||
bounds check. On success a converted key is stored at R_KEY. */
|
bounds check. On success a converted key is stored at R_KEY. */
|
||||||
@ -407,29 +439,43 @@ do_unprotect (const char *passphrase,
|
|||||||
actual_csum = 0;
|
actual_csum = 0;
|
||||||
for (i=npkey; i < nskey; i++)
|
for (i=npkey; i < nskey; i++)
|
||||||
{
|
{
|
||||||
|
unsigned char *buffer;
|
||||||
|
|
||||||
if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
|
if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
|
||||||
return gpg_error (GPG_ERR_BAD_SECKEY);
|
return gpg_error (GPG_ERR_BAD_SECKEY);
|
||||||
|
|
||||||
if (gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
|
if (gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
|
||||||
{
|
{
|
||||||
unsigned int nbits;
|
unsigned int nbits;
|
||||||
const unsigned char *buffer;
|
|
||||||
buffer = gcry_mpi_get_opaque (skey[i], &nbits);
|
buffer = gcry_mpi_get_opaque (skey[i], &nbits);
|
||||||
nbytes = (nbits+7)/8;
|
nbytes = (nbits+7)/8;
|
||||||
|
|
||||||
|
nbits = nbytes * 8;
|
||||||
|
if (*buffer)
|
||||||
|
if (nbits >= 8 && !(*buffer & 0x80))
|
||||||
|
if (--nbits >= 7 && !(*buffer & 0x40))
|
||||||
|
if (--nbits >= 6 && !(*buffer & 0x20))
|
||||||
|
if (--nbits >= 5 && !(*buffer & 0x10))
|
||||||
|
if (--nbits >= 4 && !(*buffer & 0x08))
|
||||||
|
if (--nbits >= 3 && !(*buffer & 0x04))
|
||||||
|
if (--nbits >= 2 && !(*buffer & 0x02))
|
||||||
|
if (--nbits >= 1 && !(*buffer & 0x01))
|
||||||
|
--nbits;
|
||||||
|
|
||||||
|
actual_csum += (nbits >> 8);
|
||||||
|
actual_csum += (nbits & 0xff);
|
||||||
actual_csum += checksum (buffer, nbytes);
|
actual_csum += checksum (buffer, nbytes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned char *buffer;
|
|
||||||
|
|
||||||
err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, &buffer, &nbytes,
|
err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, &buffer, &nbytes,
|
||||||
skey[i]);
|
skey[i]);
|
||||||
if (!err)
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
actual_csum += checksum (buffer, nbytes);
|
actual_csum += checksum (buffer, nbytes);
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
}
|
}
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actual_csum != desired_csum)
|
if (actual_csum != desired_csum)
|
||||||
@ -487,7 +533,7 @@ do_unprotect (const char *passphrase,
|
|||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
u16 csum_pgp7 = 0;
|
u16 csum_pgp7 = 0;
|
||||||
|
|
||||||
if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_OPAQUE ))
|
if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_USER1))
|
||||||
{
|
{
|
||||||
gcry_cipher_close (cipher_hd);
|
gcry_cipher_close (cipher_hd);
|
||||||
return gpg_error (GPG_ERR_BAD_SECKEY);
|
return gpg_error (GPG_ERR_BAD_SECKEY);
|
||||||
@ -556,7 +602,7 @@ do_unprotect (const char *passphrase,
|
|||||||
{
|
{
|
||||||
for (i=npkey; i < nskey; i++ )
|
for (i=npkey; i < nskey; i++ )
|
||||||
{
|
{
|
||||||
if (gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_PGP, p, ndata, &nbytes))
|
if (scan_pgp_format (&tmpmpi, pubkey_algo, p, ndata, &nbytes))
|
||||||
{
|
{
|
||||||
/* Checksum was okay, but not correctly decrypted. */
|
/* Checksum was okay, but not correctly decrypted. */
|
||||||
desired_csum = 0;
|
desired_csum = 0;
|
||||||
@ -587,7 +633,7 @@ do_unprotect (const char *passphrase,
|
|||||||
size_t ndata;
|
size_t ndata;
|
||||||
unsigned int ndatabits;
|
unsigned int ndatabits;
|
||||||
|
|
||||||
if (!skey[i] || !gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
|
if (!skey[i] || !gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
|
||||||
{
|
{
|
||||||
gcry_cipher_close (cipher_hd);
|
gcry_cipher_close (cipher_hd);
|
||||||
return gpg_error (GPG_ERR_BAD_SECKEY);
|
return gpg_error (GPG_ERR_BAD_SECKEY);
|
||||||
@ -614,7 +660,7 @@ do_unprotect (const char *passphrase,
|
|||||||
buffer[1] = p[1];
|
buffer[1] = p[1];
|
||||||
gcry_cipher_decrypt (cipher_hd, buffer+2, ndata-2, p+2, ndata-2);
|
gcry_cipher_decrypt (cipher_hd, buffer+2, ndata-2, p+2, ndata-2);
|
||||||
actual_csum += checksum (buffer, ndata);
|
actual_csum += checksum (buffer, ndata);
|
||||||
err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_PGP, buffer, ndata, &ndata);
|
err = scan_pgp_format (&tmpmpi, pubkey_algo, buffer, ndata, &nbytes);
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -837,12 +883,13 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, int dontcare_exist,
|
|||||||
value = gcry_sexp_nth_data (list, ++idx, &valuelen);
|
value = gcry_sexp_nth_data (list, ++idx, &valuelen);
|
||||||
if (!value || !valuelen)
|
if (!value || !valuelen)
|
||||||
goto bad_seckey;
|
goto bad_seckey;
|
||||||
if (is_enc)
|
if (is_enc || npkey == 1 /* This is ECC */)
|
||||||
{
|
{
|
||||||
/* Encrypted parameters need to be stored as opaque. */
|
|
||||||
skey[skeyidx] = gcry_mpi_set_opaque_copy (NULL, value, valuelen*8);
|
skey[skeyidx] = gcry_mpi_set_opaque_copy (NULL, value, valuelen*8);
|
||||||
if (!skey[skeyidx])
|
if (!skey[skeyidx])
|
||||||
goto outofmem;
|
goto outofmem;
|
||||||
|
if (is_enc)
|
||||||
|
/* Encrypted parameters need to have a USER1 flag. */
|
||||||
gcry_mpi_set_flag (skey[skeyidx], GCRYMPI_FLAG_USER1);
|
gcry_mpi_set_flag (skey[skeyidx], GCRYMPI_FLAG_USER1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1171,6 +1218,7 @@ apply_protection (gcry_mpi_t *array, int npkey, int nskey,
|
|||||||
array[i] = NULL;
|
array[i] = NULL;
|
||||||
}
|
}
|
||||||
array[npkey] = gcry_mpi_set_opaque (NULL, data, ndata*8);
|
array[npkey] = gcry_mpi_set_opaque (NULL, data, ndata*8);
|
||||||
|
gcry_mpi_set_flag (array[npkey], GCRYMPI_FLAG_USER1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1199,7 +1247,7 @@ extract_private_key (gcry_sexp_t s_key, int req_private_key_data,
|
|||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
gcry_sexp_t list, l2;
|
gcry_sexp_t list, l2;
|
||||||
char *name;
|
char *name;
|
||||||
const char *algoname, *format;
|
const char *algoname, *format, *elems;
|
||||||
int npkey, nskey;
|
int npkey, nskey;
|
||||||
gcry_sexp_t curve = NULL;
|
gcry_sexp_t curve = NULL;
|
||||||
gcry_sexp_t flags = NULL;
|
gcry_sexp_t flags = NULL;
|
||||||
@ -1244,7 +1292,7 @@ extract_private_key (gcry_sexp_t s_key, int req_private_key_data,
|
|||||||
if (!strcmp (name, "rsa"))
|
if (!strcmp (name, "rsa"))
|
||||||
{
|
{
|
||||||
algoname = "rsa";
|
algoname = "rsa";
|
||||||
format = "ned?p?q?u?";
|
format = elems = "ned?p?q?u?";
|
||||||
npkey = 2;
|
npkey = 2;
|
||||||
nskey = 6;
|
nskey = 6;
|
||||||
err = gcry_sexp_extract_param (list, NULL, format,
|
err = gcry_sexp_extract_param (list, NULL, format,
|
||||||
@ -1254,7 +1302,7 @@ extract_private_key (gcry_sexp_t s_key, int req_private_key_data,
|
|||||||
else if (!strcmp (name, "elg"))
|
else if (!strcmp (name, "elg"))
|
||||||
{
|
{
|
||||||
algoname = "elg";
|
algoname = "elg";
|
||||||
format = "pgyx?";
|
format = elems = "pgyx?";
|
||||||
npkey = 3;
|
npkey = 3;
|
||||||
nskey = 4;
|
nskey = 4;
|
||||||
err = gcry_sexp_extract_param (list, NULL, format,
|
err = gcry_sexp_extract_param (list, NULL, format,
|
||||||
@ -1264,7 +1312,7 @@ extract_private_key (gcry_sexp_t s_key, int req_private_key_data,
|
|||||||
else if (!strcmp (name, "dsa"))
|
else if (!strcmp (name, "dsa"))
|
||||||
{
|
{
|
||||||
algoname = "dsa";
|
algoname = "dsa";
|
||||||
format = "pqgyx?";
|
format = elems = "pqgyx?";
|
||||||
npkey = 4;
|
npkey = 4;
|
||||||
nskey = 5;
|
nskey = 5;
|
||||||
err = gcry_sexp_extract_param (list, NULL, format,
|
err = gcry_sexp_extract_param (list, NULL, format,
|
||||||
@ -1274,7 +1322,8 @@ extract_private_key (gcry_sexp_t s_key, int req_private_key_data,
|
|||||||
else if (!strcmp (name, "ecc") || !strcmp (name, "ecdsa"))
|
else if (!strcmp (name, "ecc") || !strcmp (name, "ecdsa"))
|
||||||
{
|
{
|
||||||
algoname = "ecc";
|
algoname = "ecc";
|
||||||
format = "qd?";
|
format = "/qd?";
|
||||||
|
elems = "qd?";
|
||||||
npkey = 1;
|
npkey = 1;
|
||||||
nskey = 2;
|
nskey = 2;
|
||||||
curve = gcry_sexp_find_token (list, "curve", 0);
|
curve = gcry_sexp_find_token (list, "curve", 0);
|
||||||
@ -1298,7 +1347,7 @@ extract_private_key (gcry_sexp_t s_key, int req_private_key_data,
|
|||||||
{
|
{
|
||||||
*r_algoname = algoname;
|
*r_algoname = algoname;
|
||||||
if (r_elems)
|
if (r_elems)
|
||||||
*r_elems = format;
|
*r_elems = elems;
|
||||||
*r_npkey = npkey;
|
*r_npkey = npkey;
|
||||||
if (r_nskey)
|
if (r_nskey)
|
||||||
*r_nskey = nskey;
|
*r_nskey = nskey;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user