mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
sm: Support decryption of ECDH data.
* sm/decrypt.c: Include tlv.h. (string_from_gcry_buffer): New. (hash_ecc_cms_shared_info): New. (ecdh_decrypt): New. (prepare_decryption): Support ECDH. Add arg pk_algo. (gpgsm_decrypt): Lift some variables from an inner code block. -- Note: This has only been tested with a single messages created by OpenSSL and taken from the Mozilla bug tracker. In particular the code to included UserKeyingMaterial (ukm) has not been tested. GnuPG-bug-id: 4098 Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
5d015b38eb
commit
95d83cf906
396
sm/decrypt.c
396
sm/decrypt.c
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
|
#include "../common/tlv.h"
|
||||||
#include "../common/compliance.h"
|
#include "../common/compliance.h"
|
||||||
|
|
||||||
struct decrypt_filter_parm_s
|
struct decrypt_filter_parm_s
|
||||||
@ -51,11 +52,319 @@ struct decrypt_filter_parm_s
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the hash algorithm's algo id from its name given in the
|
||||||
|
* non-null termnated string in (buffer,buflen). Returns 0 on failure
|
||||||
|
* or if the algo is not known. */
|
||||||
|
static char *
|
||||||
|
string_from_gcry_buffer (gcry_buffer_t *buffer)
|
||||||
|
{
|
||||||
|
char *string;
|
||||||
|
|
||||||
|
string = xtrymalloc (buffer->len + 1);
|
||||||
|
if (!string)
|
||||||
|
return NULL;
|
||||||
|
memcpy (string, buffer->data, buffer->len);
|
||||||
|
string[buffer->len] = 0;
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper to construct and hash the
|
||||||
|
* ECC-CMS-SharedInfo ::= SEQUENCE {
|
||||||
|
* keyInfo AlgorithmIdentifier,
|
||||||
|
* entityUInfo [0] EXPLICIT OCTET STRING OPTIONAL,
|
||||||
|
* suppPubInfo [2] EXPLICIT OCTET STRING }
|
||||||
|
* as described in RFC-5753, 7.2. */
|
||||||
|
static gpg_error_t
|
||||||
|
hash_ecc_cms_shared_info (gcry_md_hd_t hash_hd, const char *wrap_algo_str,
|
||||||
|
unsigned int keylen,
|
||||||
|
const void *ukm, unsigned int ukmlen)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
void *p;
|
||||||
|
unsigned char *oid;
|
||||||
|
size_t n, oidlen, toidlen, tkeyinfo, tukmlen, tsupppubinfo;
|
||||||
|
unsigned char keylenbuf[6];
|
||||||
|
membuf_t mb = MEMBUF_ZERO;
|
||||||
|
|
||||||
|
err = ksba_oid_from_str (wrap_algo_str, &oid, &oidlen);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
toidlen = get_tlv_length (CLASS_UNIVERSAL, TAG_OBJECT_ID, 0, oidlen);
|
||||||
|
tkeyinfo = get_tlv_length (CLASS_UNIVERSAL, TAG_SEQUENCE, 1, toidlen);
|
||||||
|
|
||||||
|
tukmlen = ukm? get_tlv_length (CLASS_CONTEXT, 0, 1, ukmlen) : 0;
|
||||||
|
|
||||||
|
keylen *= 8;
|
||||||
|
keylenbuf[0] = TAG_OCTET_STRING;
|
||||||
|
keylenbuf[1] = 4;
|
||||||
|
keylenbuf[2] = (keylen >> 24);
|
||||||
|
keylenbuf[3] = (keylen >> 16);
|
||||||
|
keylenbuf[4] = (keylen >> 8);
|
||||||
|
keylenbuf[5] = keylen;
|
||||||
|
|
||||||
|
tsupppubinfo = get_tlv_length (CLASS_CONTEXT, 2, 1, sizeof keylenbuf);
|
||||||
|
|
||||||
|
put_tlv_to_membuf (&mb, CLASS_UNIVERSAL, TAG_SEQUENCE, 1,
|
||||||
|
tkeyinfo + tukmlen + tsupppubinfo);
|
||||||
|
put_tlv_to_membuf (&mb, CLASS_UNIVERSAL, TAG_SEQUENCE, 1,
|
||||||
|
toidlen);
|
||||||
|
put_tlv_to_membuf (&mb, CLASS_UNIVERSAL, TAG_OBJECT_ID, 0, oidlen);
|
||||||
|
put_membuf (&mb, oid, oidlen);
|
||||||
|
ksba_free (oid);
|
||||||
|
|
||||||
|
if (ukm)
|
||||||
|
{
|
||||||
|
put_tlv_to_membuf (&mb, CLASS_CONTEXT, 0, 1, ukmlen);
|
||||||
|
put_membuf (&mb, ukm, ukmlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
put_tlv_to_membuf (&mb, CLASS_CONTEXT, 2, 1, sizeof keylenbuf);
|
||||||
|
put_membuf (&mb, keylenbuf, sizeof keylenbuf);
|
||||||
|
|
||||||
|
p = get_membuf (&mb, &n);
|
||||||
|
if (!p)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
gcry_md_write (hash_hd, p, n);
|
||||||
|
xfree (p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function will modify SECRET. */
|
||||||
|
static gpg_error_t
|
||||||
|
ecdh_decrypt (unsigned char *secret, size_t secretlen,
|
||||||
|
gcry_sexp_t enc_val,
|
||||||
|
unsigned char **r_result, unsigned int *r_resultlen)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
gcry_buffer_t ioarray[4] = { {0}, {0}, {0}, {0} };
|
||||||
|
char *encr_algo_str = NULL;
|
||||||
|
char *wrap_algo_str = NULL;
|
||||||
|
int hash_algo, cipher_algo;
|
||||||
|
const unsigned char *ukm; /* Alias for ioarray[2]. */
|
||||||
|
unsigned int ukmlen;
|
||||||
|
const unsigned char *data; /* Alias for ioarray[3]. */
|
||||||
|
unsigned int datalen;
|
||||||
|
unsigned int keylen, hashlen;
|
||||||
|
unsigned char key[32];
|
||||||
|
gcry_cipher_hd_t cipher_hd = NULL;
|
||||||
|
unsigned char *result = NULL;
|
||||||
|
unsigned int resultlen;
|
||||||
|
|
||||||
|
*r_resultlen = 0;
|
||||||
|
*r_result = NULL;
|
||||||
|
|
||||||
|
/* Extract X from SECRET; this is the actual secret. It must be in
|
||||||
|
* the format of:
|
||||||
|
*
|
||||||
|
* 04 || X || Y
|
||||||
|
* 40 || X
|
||||||
|
* 41 || X
|
||||||
|
*/
|
||||||
|
if (secretlen < 2)
|
||||||
|
return gpg_error (GPG_ERR_BAD_DATA);
|
||||||
|
if (*secret == 0x04)
|
||||||
|
{
|
||||||
|
secretlen--;
|
||||||
|
memmove (secret, secret+1, secretlen);
|
||||||
|
if ((secretlen & 1))
|
||||||
|
return gpg_error (GPG_ERR_BAD_DATA);
|
||||||
|
secretlen /= 2;
|
||||||
|
}
|
||||||
|
else if (*secret == 0x40 || *secret == 0x41)
|
||||||
|
{
|
||||||
|
secretlen--;
|
||||||
|
memmove (secret, secret+1, secretlen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_BAD_DATA);
|
||||||
|
if (!secretlen)
|
||||||
|
return gpg_error (GPG_ERR_BAD_DATA);
|
||||||
|
|
||||||
|
if (DBG_CRYPTO)
|
||||||
|
log_printhex (secret, secretlen, "ECDH X ..:");
|
||||||
|
|
||||||
|
/* We have now the shared secret bytes in (SECRET,SECRETLEN). Now
|
||||||
|
* we will compute the KEK using a value dervied from the secret
|
||||||
|
* bytes. */
|
||||||
|
err = gcry_sexp_extract_param (enc_val, "enc-val",
|
||||||
|
"&'encr-algo''wrap-algo''ukm'?s",
|
||||||
|
ioarray+0, ioarray+1,
|
||||||
|
ioarray+2, ioarray+3, NULL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("extracting ECDH parameter failed: %s\n", gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
encr_algo_str = string_from_gcry_buffer (ioarray);
|
||||||
|
if (!encr_algo_str)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
wrap_algo_str = string_from_gcry_buffer (ioarray+1);
|
||||||
|
if (!wrap_algo_str)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
ukm = ioarray[2].data;
|
||||||
|
ukmlen = ioarray[2].len;
|
||||||
|
data = ioarray[3].data;
|
||||||
|
datalen = ioarray[3].len;
|
||||||
|
|
||||||
|
/* Check parameters. */
|
||||||
|
if (DBG_CRYPTO)
|
||||||
|
{
|
||||||
|
log_debug ("encr_algo: %s\n", encr_algo_str);
|
||||||
|
log_debug ("wrap_algo: %s\n", wrap_algo_str);
|
||||||
|
log_printhex (ukm, ukmlen, "ukm .....:");
|
||||||
|
log_printhex (data, datalen, "data ....:");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp (encr_algo_str, "1.3.132.1.11.1"))
|
||||||
|
{
|
||||||
|
/* dhSinglePass-stdDH-sha256kdf-scheme */
|
||||||
|
hash_algo = GCRY_MD_SHA256;
|
||||||
|
hashlen = 32;
|
||||||
|
}
|
||||||
|
else if (!strcmp (encr_algo_str, "1.3.132.1.11.2"))
|
||||||
|
{
|
||||||
|
/* dhSinglePass-stdDH-sha384kdf-scheme */
|
||||||
|
hash_algo = GCRY_MD_SHA384;
|
||||||
|
hashlen = 48;
|
||||||
|
}
|
||||||
|
else if (!strcmp (encr_algo_str, "1.3.132.1.11.3"))
|
||||||
|
{
|
||||||
|
/* dhSinglePass-stdDH-sha512kdf-scheme */
|
||||||
|
hash_algo = GCRY_MD_SHA512;
|
||||||
|
hashlen = 64;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp (wrap_algo_str, "2.16.840.1.101.3.4.1.5"))
|
||||||
|
{
|
||||||
|
cipher_algo = GCRY_CIPHER_AES128;
|
||||||
|
keylen = 16;
|
||||||
|
}
|
||||||
|
else if (!strcmp (wrap_algo_str, "2.16.840.1.101.3.4.1.25"))
|
||||||
|
{
|
||||||
|
cipher_algo = GCRY_CIPHER_AES192;
|
||||||
|
keylen = 24;
|
||||||
|
}
|
||||||
|
else if (!strcmp (wrap_algo_str, "2.16.840.1.101.3.4.1.45"))
|
||||||
|
{
|
||||||
|
cipher_algo = GCRY_CIPHER_AES256;
|
||||||
|
keylen = 32;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Derive a KEK (key wrapping key) using MESSAGE and SECRET_X.
|
||||||
|
* According to SEC1 3.6.1 we should check that
|
||||||
|
* SECRETLEN + UKMLEN + 4 < maxhashlen
|
||||||
|
* However, we have no practical limit on the hash length and thus
|
||||||
|
* there is no point in checking this. The second check that
|
||||||
|
* KEYLEN < hashlen*(2^32-1)
|
||||||
|
* is obviously also not needed. Because with our allowed
|
||||||
|
* parameters KEYLEN is always less or equal to HASHLEN so that we
|
||||||
|
* do not need to iterate at all.
|
||||||
|
*/
|
||||||
|
log_assert (gcry_md_get_algo_dlen (hash_algo) == hashlen);
|
||||||
|
{
|
||||||
|
gcry_md_hd_t hash_hd;
|
||||||
|
err = gcry_md_open (&hash_hd, hash_algo, 0);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
gcry_md_write(hash_hd, secret, secretlen);
|
||||||
|
gcry_md_write(hash_hd, "\x00\x00\x00\x01", 4); /* counter */
|
||||||
|
err = hash_ecc_cms_shared_info (hash_hd, wrap_algo_str, keylen,
|
||||||
|
ukm, ukmlen);
|
||||||
|
gcry_md_final (hash_hd);
|
||||||
|
log_assert (keylen <= sizeof key && keylen <= hashlen);
|
||||||
|
memcpy (key, gcry_md_read (hash_hd, 0), keylen);
|
||||||
|
gcry_md_close (hash_hd);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DBG_CRYPTO)
|
||||||
|
log_printhex (key, keylen, "KEK .....:");
|
||||||
|
|
||||||
|
/* Unwrap the key. */
|
||||||
|
if ((datalen % 8) || datalen < 16)
|
||||||
|
{
|
||||||
|
log_error ("can't use a shared secret of %u bytes for ecdh\n", datalen);
|
||||||
|
err = gpg_error (GPG_ERR_BAD_DATA);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
resultlen = datalen - 8;
|
||||||
|
result = xtrymalloc_secure (resultlen);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gcry_cipher_open (&cipher_hd, cipher_algo, GCRY_CIPHER_MODE_AESWRAP, 0);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("ecdh failed to initialize AESWRAP: %s\n", gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gcry_cipher_setkey (cipher_hd, key, keylen);
|
||||||
|
wipememory (key, sizeof key);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("ecdh failed in gcry_cipher_setkey: %s\n", gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gcry_cipher_decrypt (cipher_hd, result, resultlen, data, datalen);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("ecdh failed in gcry_cipher_decrypt: %s\n",gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
*r_resultlen = resultlen;
|
||||||
|
*r_result = result;
|
||||||
|
result = NULL;
|
||||||
|
|
||||||
|
leave:
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
wipememory (result, resultlen);
|
||||||
|
xfree (result);
|
||||||
|
}
|
||||||
|
gcry_cipher_close (cipher_hd);
|
||||||
|
xfree (encr_algo_str);
|
||||||
|
xfree (wrap_algo_str);
|
||||||
|
xfree (ioarray[0].data);
|
||||||
|
xfree (ioarray[1].data);
|
||||||
|
xfree (ioarray[2].data);
|
||||||
|
xfree (ioarray[3].data);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Decrypt the session key and fill in the parm structure. The
|
/* Decrypt the session key and fill in the parm structure. The
|
||||||
algo and the IV is expected to be already in PARM. */
|
algo and the IV is expected to be already in PARM. */
|
||||||
static int
|
static int
|
||||||
prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
prepare_decryption (ctrl_t ctrl, const char *hexkeygrip,
|
||||||
|
int pk_algo, const char *desc,
|
||||||
ksba_const_sexp_t enc_val,
|
ksba_const_sexp_t enc_val,
|
||||||
struct decrypt_filter_parm_s *parm)
|
struct decrypt_filter_parm_s *parm)
|
||||||
{
|
{
|
||||||
@ -63,6 +372,8 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
|||||||
size_t n, seskeylen;
|
size_t n, seskeylen;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (DBG_CRYPTO)
|
||||||
|
log_printcanon ("decrypting:", enc_val, 0);
|
||||||
rc = gpgsm_agent_pkdecrypt (ctrl, hexkeygrip, desc, enc_val,
|
rc = gpgsm_agent_pkdecrypt (ctrl, hexkeygrip, desc, enc_val,
|
||||||
&seskey, &seskeylen);
|
&seskey, &seskeylen);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -72,10 +383,31 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (DBG_CRYPTO)
|
if (DBG_CRYPTO)
|
||||||
log_printhex (seskey, seskeylen, "pkcs1 encoded session key:");
|
log_printhex (seskey, seskeylen, "DEK frame:");
|
||||||
|
|
||||||
n=0;
|
n=0;
|
||||||
if (seskeylen == 32 || seskeylen == 24 || seskeylen == 16)
|
if (pk_algo == GCRY_PK_ECC)
|
||||||
|
{
|
||||||
|
gcry_sexp_t s_enc_val;
|
||||||
|
unsigned char *decrypted;
|
||||||
|
unsigned int decryptedlen;
|
||||||
|
|
||||||
|
rc = gcry_sexp_sscan (&s_enc_val, NULL, enc_val,
|
||||||
|
gcry_sexp_canon_len (enc_val, 0, NULL, NULL));
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
rc = ecdh_decrypt (seskey, seskeylen, s_enc_val,
|
||||||
|
&decrypted, &decryptedlen);
|
||||||
|
gcry_sexp_release (s_enc_val);
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
xfree (seskey);
|
||||||
|
seskey = decrypted;
|
||||||
|
seskeylen = decryptedlen;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (seskeylen == 32 || seskeylen == 24 || seskeylen == 16)
|
||||||
{
|
{
|
||||||
/* Smells like an AES-128, 3-DES, or AES-256 key. This might
|
/* Smells like an AES-128, 3-DES, or AES-256 key. This might
|
||||||
* happen because a SC has already done the unpacking. A better
|
* happen because a SC has already done the unpacking. A better
|
||||||
@ -115,7 +447,7 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (DBG_CRYPTO)
|
if (DBG_CRYPTO)
|
||||||
log_printhex (seskey+n, seskeylen-n, "session key:");
|
log_printhex (seskey+n, seskeylen-n, "CEK .....:");
|
||||||
|
|
||||||
rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0);
|
rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -398,6 +730,9 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
|||||||
char *desc = NULL;
|
char *desc = NULL;
|
||||||
char kidbuf[16+1];
|
char kidbuf[16+1];
|
||||||
int tmp_rc;
|
int tmp_rc;
|
||||||
|
ksba_cert_t cert = NULL;
|
||||||
|
unsigned int nbits;
|
||||||
|
int pk_algo = 0;
|
||||||
|
|
||||||
*kidbuf = 0;
|
*kidbuf = 0;
|
||||||
|
|
||||||
@ -410,8 +745,6 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
|||||||
recp, gpg_strerror (tmp_rc));
|
recp, gpg_strerror (tmp_rc));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ksba_cert_t cert = NULL;
|
|
||||||
|
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
{
|
{
|
||||||
log_info ("recp %d - issuer: '%s'\n",
|
log_info ("recp %d - issuer: '%s'\n",
|
||||||
@ -480,34 +813,29 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
|||||||
hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
|
hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
|
||||||
desc = gpgsm_format_keydesc (cert);
|
desc = gpgsm_format_keydesc (cert);
|
||||||
|
|
||||||
{
|
pk_algo = gpgsm_get_key_algo_info (cert, &nbits);
|
||||||
unsigned int nbits;
|
|
||||||
int pk_algo = gpgsm_get_key_algo_info (cert, &nbits);
|
|
||||||
|
|
||||||
/* Check compliance. */
|
/* Check compliance. */
|
||||||
if (!gnupg_pk_is_allowed (opt.compliance,
|
if (!gnupg_pk_is_allowed (opt.compliance,
|
||||||
PK_USE_DECRYPTION,
|
PK_USE_DECRYPTION,
|
||||||
pk_algo, NULL, nbits, NULL))
|
pk_algo, NULL, nbits, NULL))
|
||||||
{
|
{
|
||||||
char kidstr[10+1];
|
char kidstr[10+1];
|
||||||
|
|
||||||
snprintf (kidstr, sizeof kidstr, "0x%08lX",
|
snprintf (kidstr, sizeof kidstr, "0x%08lX",
|
||||||
gpgsm_get_short_fingerprint (cert, NULL));
|
gpgsm_get_short_fingerprint (cert, NULL));
|
||||||
log_info
|
log_info (_("key %s is not suitable for decryption"
|
||||||
(_("key %s is not suitable for decryption"
|
" in %s mode\n"),
|
||||||
" in %s mode\n"),
|
kidstr,
|
||||||
kidstr,
|
gnupg_compliance_option_string(opt.compliance));
|
||||||
gnupg_compliance_option_string (opt.compliance));
|
rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||||
rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
goto oops;
|
||||||
goto oops;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that all certs are compliant with CO_DE_VS. */
|
/* Check that all certs are compliant with CO_DE_VS. */
|
||||||
is_de_vs =
|
is_de_vs = (is_de_vs
|
||||||
(is_de_vs
|
&& gnupg_pk_is_compliant (CO_DE_VS, pk_algo,
|
||||||
&& gnupg_pk_is_compliant (CO_DE_VS, pk_algo, NULL,
|
NULL, nbits, NULL));
|
||||||
nbits, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -521,15 +849,15 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
|||||||
ksba_cert_release (cert);
|
ksba_cert_release (cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hexkeygrip)
|
if (!hexkeygrip || !pk_algo)
|
||||||
;
|
;
|
||||||
else if (!(enc_val = ksba_cms_get_enc_val (cms, recp)))
|
else if (!(enc_val = ksba_cms_get_enc_val (cms, recp)))
|
||||||
log_error ("recp %d - error getting encrypted session key\n",
|
log_error ("recp %d - error getting encrypted session key\n",
|
||||||
recp);
|
recp);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rc = prepare_decryption (ctrl,
|
rc = prepare_decryption (ctrl, hexkeygrip, pk_algo,
|
||||||
hexkeygrip, desc, enc_val, &dfparm);
|
desc, enc_val, &dfparm);
|
||||||
xfree (enc_val);
|
xfree (enc_val);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user