mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Add arg session_algo to pk_decrypt.
* common/kem.c: Move constants to the top. Add some documentation. * g10/pkglue.c (pk_encrypt): Add arguments session_key and factor code out to ... (do_encrypt_rsa_elg): here, (do_encrypt_ecdh): and here, (do_encrypt_kem): and here. * g10/encrypt.c (write_pubkey_enc): Call with session key algorithm. -- This makes it easier to review the code.
This commit is contained in:
parent
35ef87d8d9
commit
4c20d2d273
32
common/kem.c
32
common/kem.c
@ -23,9 +23,10 @@
|
|||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copies of the GNU General Public License
|
* You should have received copies of the GNU General Public License
|
||||||
* and the GNU Lesser General Public License along with this program;
|
* and the GNU Lesser General Public License along with this program;
|
||||||
* if not, see <https://www.gnu.org/licenses/>.
|
* if not, see <https://www.gnu.org/licenses/>.
|
||||||
|
* SPDX-License-Identifier: (LGPL-3.0-or-later OR GPL-2.0-or-later)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -35,7 +36,18 @@
|
|||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
#include "mischelp.h"
|
#include "mischelp.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* domSeperation as per *PGP specs. */
|
||||||
|
#define KMAC_KEY "OpenPGPCompositeKeyDerivationFunction"
|
||||||
|
|
||||||
|
/* customizationString as per *PGP specs. */
|
||||||
|
#define KMAC_CUSTOM "KDF"
|
||||||
|
|
||||||
|
/* The blocksize used for Keccak by compute_kmac256. */
|
||||||
#define KECCAK512_BLOCKSIZE 136
|
#define KECCAK512_BLOCKSIZE 136
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
compute_kmac256 (void *digest, size_t digestlen,
|
compute_kmac256 (void *digest, size_t digestlen,
|
||||||
const void *key, size_t keylen,
|
const void *key, size_t keylen,
|
||||||
@ -163,14 +175,16 @@ gnupg_ecc_kem_kdf (void *kek, size_t kek_len,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compute KEK by combining two KEMs. The caller provides a buffer
|
||||||
/* domSeperation */
|
* KEK allocated with size KEK_LEN which will receive the computed
|
||||||
#define KMAC_KEY "OpenPGPCompositeKeyDerivationFunction"
|
* KEK. (ECC_SS, ECC_SS_LEN) is the shared secret of the first key.
|
||||||
|
* (ECC_CT, ECC_CT_LEN) is the ciphertext of the first key.
|
||||||
/* customizationString */
|
* (MLKEM_SS, ECC_SS_LEN) is the shared secret of the second key.
|
||||||
#define KMAC_CUSTOM "KDF"
|
* (MLKEM_CT, MLKEM_CT_LEN) is the ciphertext of the second key.
|
||||||
|
* (FIXEDINFO, FIXEDINFO_LEN) is an octet string used to bind the KEK
|
||||||
/* Compute KEK by combining two KEMs. */
|
* to a the key; for PGP we use the concatenation of the session key's
|
||||||
|
* algorithm id and the v5 fingerprint of the key.
|
||||||
|
*/
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
gnupg_kem_combiner (void *kek, size_t kek_len,
|
gnupg_kem_combiner (void *kek, size_t kek_len,
|
||||||
const void *ecc_ss, size_t ecc_ss_len,
|
const void *ecc_ss, size_t ecc_ss_len,
|
||||||
|
@ -1138,7 +1138,7 @@ write_pubkey_enc (ctrl_t ctrl,
|
|||||||
* build_packet(). */
|
* build_packet(). */
|
||||||
frame = encode_session_key (pk->pubkey_algo, dek,
|
frame = encode_session_key (pk->pubkey_algo, dek,
|
||||||
pubkey_nbits (pk->pubkey_algo, pk->pkey));
|
pubkey_nbits (pk->pubkey_algo, pk->pkey));
|
||||||
rc = pk_encrypt (pk, frame, enc->data);
|
rc = pk_encrypt (pk, frame, dek->algo, enc->data);
|
||||||
gcry_mpi_release (frame);
|
gcry_mpi_release (frame);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) );
|
log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) );
|
||||||
|
228
g10/pkglue.c
228
g10/pkglue.c
@ -1,6 +1,7 @@
|
|||||||
/* pkglue.c - public key operations glue code
|
/* pkglue.c - public key operations glue code
|
||||||
* Copyright (C) 2000, 2003, 2010 Free Software Foundation, Inc.
|
* Copyright (C) 2000, 2003, 2010 Free Software Foundation, Inc.
|
||||||
* Copyright (C) 2014 Werner Koch
|
* Copyright (C) 2014 Werner Koch
|
||||||
|
* Copyright (C) 2024 g10 Code GmbH.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -16,6 +17,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -415,60 +417,51 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Core of the encryption for KEM algorithms. See pk_decrypt for a
|
||||||
|
* description of the arguments. */
|
||||||
/*
|
static gpg_error_t
|
||||||
* Emulate our old PK interface here - sometime in the future we might
|
do_encrypt_kem (PKT_public_key *pk, gcry_mpi_t data, int seskey_algo,
|
||||||
* change the internal design to directly fit to libgcrypt. PK is is
|
gcry_mpi_t *resarr)
|
||||||
* the OpenPGP public key packet, DATA is an MPI with the to be
|
{
|
||||||
* encrypted data, and RESARR receives the encrypted data. RESARRAY
|
|
||||||
* is expected to be an two item array which will be filled with newly
|
log_debug ("Implement Kyber encryption\n");
|
||||||
* allocated MPIs.
|
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
*/
|
}
|
||||||
gpg_error_t
|
|
||||||
pk_encrypt (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|
||||||
|
/* Core of the encryption for the ECDH algorithms. See pk_decrypt for
|
||||||
|
* a description of the arguments. */
|
||||||
|
static gpg_error_t
|
||||||
|
do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
||||||
{
|
{
|
||||||
pubkey_algo_t algo = pk->pubkey_algo;
|
|
||||||
gcry_mpi_t *pkey = pk->pkey;
|
gcry_mpi_t *pkey = pk->pkey;
|
||||||
gcry_sexp_t s_ciph = NULL;
|
gcry_sexp_t s_ciph = NULL;
|
||||||
gcry_sexp_t s_data = NULL;
|
gcry_sexp_t s_data = NULL;
|
||||||
gcry_sexp_t s_pkey = NULL;
|
gcry_sexp_t s_pkey = NULL;
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
|
gcry_mpi_t k = NULL;
|
||||||
/* Make a sexp from pkey. */
|
char *curve = NULL;
|
||||||
if (algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E)
|
int with_djb_tweak_flag;
|
||||||
{
|
gcry_mpi_t public = NULL;
|
||||||
err = gcry_sexp_build (&s_pkey, NULL,
|
gcry_mpi_t result = NULL;
|
||||||
"(public-key(elg(p%m)(g%m)(y%m)))",
|
byte fp[MAX_FINGERPRINT_LEN];
|
||||||
pkey[0], pkey[1], pkey[2]);
|
byte *shared = NULL;
|
||||||
/* Put DATA into a simplified S-expression. */
|
byte *p;
|
||||||
if (!err)
|
size_t nshared;
|
||||||
err = gcry_sexp_build (&s_data, NULL, "%m", data);
|
unsigned int nbits;
|
||||||
}
|
|
||||||
else if (algo == PUBKEY_ALGO_RSA || algo == PUBKEY_ALGO_RSA_E)
|
|
||||||
{
|
|
||||||
err = gcry_sexp_build (&s_pkey, NULL,
|
|
||||||
"(public-key(rsa(n%m)(e%m)))",
|
|
||||||
pkey[0], pkey[1]);
|
|
||||||
/* Put DATA into a simplified S-expression. */
|
|
||||||
if (!err)
|
|
||||||
err = gcry_sexp_build (&s_data, NULL, "%m", data);
|
|
||||||
}
|
|
||||||
else if (algo == PUBKEY_ALGO_ECDH)
|
|
||||||
{
|
|
||||||
gcry_mpi_t k;
|
|
||||||
|
|
||||||
err = pk_ecdh_generate_ephemeral_key (pkey, &k);
|
err = pk_ecdh_generate_ephemeral_key (pkey, &k);
|
||||||
if (!err)
|
if (err)
|
||||||
{
|
goto leave;
|
||||||
char *curve;
|
|
||||||
|
|
||||||
curve = openpgp_oid_to_str (pkey[0]);
|
curve = openpgp_oid_to_str (pkey[0]);
|
||||||
if (!curve)
|
if (!curve)
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
int with_djb_tweak_flag = openpgp_oid_is_cv25519 (pkey[0]);
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
with_djb_tweak_flag = openpgp_oid_is_cv25519 (pkey[0]);
|
||||||
|
|
||||||
/* Now use the ephemeral secret to compute the shared point. */
|
/* Now use the ephemeral secret to compute the shared point. */
|
||||||
err = gcry_sexp_build (&s_pkey, NULL,
|
err = gcry_sexp_build (&s_pkey, NULL,
|
||||||
@ -476,37 +469,22 @@ pk_encrypt (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
"(public-key(ecdh(curve%s)(flags djb-tweak)(q%m)))"
|
"(public-key(ecdh(curve%s)(flags djb-tweak)(q%m)))"
|
||||||
: "(public-key(ecdh(curve%s)(q%m)))",
|
: "(public-key(ecdh(curve%s)(q%m)))",
|
||||||
curve, pkey[1]);
|
curve, pkey[1]);
|
||||||
xfree (curve);
|
|
||||||
/* Put K into a simplified S-expression. */
|
|
||||||
if (!err)
|
|
||||||
err = gcry_sexp_build (&s_data, NULL, "%m", k);
|
|
||||||
}
|
|
||||||
gcry_mpi_release (k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (algo == PUBKEY_ALGO_KYBER)
|
|
||||||
{
|
|
||||||
log_debug ("Implement Kyber encryption\n");
|
|
||||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
|
||||||
|
|
||||||
/* Pass it to libgcrypt. */
|
|
||||||
if (!err)
|
|
||||||
err = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
|
|
||||||
|
|
||||||
gcry_sexp_release (s_data);
|
|
||||||
gcry_sexp_release (s_pkey);
|
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
;
|
goto leave;
|
||||||
else if (algo == PUBKEY_ALGO_ECDH)
|
|
||||||
{
|
/* Put K into a simplified S-expression. */
|
||||||
gcry_mpi_t public, result;
|
err = gcry_sexp_build (&s_data, NULL, "%m", k);
|
||||||
byte fp[MAX_FINGERPRINT_LEN];
|
if (err)
|
||||||
byte *shared;
|
goto leave;
|
||||||
size_t nshared;
|
|
||||||
|
/* Run encryption. */
|
||||||
|
err = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
gcry_sexp_release (s_data); s_data = NULL;
|
||||||
|
gcry_sexp_release (s_pkey); s_pkey = NULL;
|
||||||
|
|
||||||
|
|
||||||
/* Get the shared point and the ephemeral public key. */
|
/* Get the shared point and the ephemeral public key. */
|
||||||
shared = get_data_from_sexp (s_ciph, "s", &nshared);
|
shared = get_data_from_sexp (s_ciph, "s", &nshared);
|
||||||
@ -516,8 +494,7 @@ pk_encrypt (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
err = sexp_extract_param_sos (s_ciph, "e", &public);
|
err = sexp_extract_param_sos (s_ciph, "e", &public);
|
||||||
gcry_sexp_release (s_ciph);
|
gcry_sexp_release (s_ciph); s_ciph = NULL;
|
||||||
s_ciph = NULL;
|
|
||||||
if (DBG_CRYPTO)
|
if (DBG_CRYPTO)
|
||||||
{
|
{
|
||||||
log_debug ("ECDH ephemeral key:");
|
log_debug ("ECDH ephemeral key:");
|
||||||
@ -525,42 +502,105 @@ pk_encrypt (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
log_printf ("\n");
|
log_printf ("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
result = NULL;
|
|
||||||
fingerprint_from_pk (pk, fp, NULL);
|
fingerprint_from_pk (pk, fp, NULL);
|
||||||
|
|
||||||
if (!err)
|
p = gcry_mpi_get_opaque (data, &nbits);
|
||||||
{
|
result = NULL;
|
||||||
unsigned int nbits;
|
|
||||||
byte *p = gcry_mpi_get_opaque (data, &nbits);
|
|
||||||
err = pk_ecdh_encrypt_with_shared_point (shared, nshared, fp, p,
|
err = pk_ecdh_encrypt_with_shared_point (shared, nshared, fp, p,
|
||||||
(nbits+7)/8, pkey, &result);
|
(nbits+7)/8, pkey, &result);
|
||||||
}
|
if (err)
|
||||||
xfree (shared);
|
goto leave;
|
||||||
if (!err)
|
|
||||||
{
|
resarr[0] = public; public = NULL;
|
||||||
resarr[0] = public;
|
resarr[1] = result; result = NULL;
|
||||||
resarr[1] = result;
|
|
||||||
}
|
leave:
|
||||||
else
|
|
||||||
{
|
|
||||||
gcry_mpi_release (public);
|
gcry_mpi_release (public);
|
||||||
gcry_mpi_release (result);
|
gcry_mpi_release (result);
|
||||||
}
|
xfree (shared);
|
||||||
}
|
gcry_sexp_release (s_ciph);
|
||||||
else /* Elgamal or RSA case. */
|
gcry_sexp_release (s_data);
|
||||||
{ /* Fixme: Add better error handling or make gnupg use
|
gcry_sexp_release (s_pkey);
|
||||||
S-expressions directly. */
|
xfree (curve);
|
||||||
|
gcry_mpi_release (k);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Core of the encryption for RSA and Elgamal algorithms. See
|
||||||
|
* pk_decrypt for a description of the arguments. */
|
||||||
|
static gpg_error_t
|
||||||
|
do_encrypt_rsa_elg (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
||||||
|
{
|
||||||
|
pubkey_algo_t algo = pk->pubkey_algo;
|
||||||
|
gcry_mpi_t *pkey = pk->pkey;
|
||||||
|
gcry_sexp_t s_ciph = NULL;
|
||||||
|
gcry_sexp_t s_data = NULL;
|
||||||
|
gcry_sexp_t s_pkey = NULL;
|
||||||
|
gpg_error_t err;
|
||||||
|
|
||||||
|
if (algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E)
|
||||||
|
err = gcry_sexp_build (&s_pkey, NULL,
|
||||||
|
"(public-key(elg(p%m)(g%m)(y%m)))",
|
||||||
|
pkey[0], pkey[1], pkey[2]);
|
||||||
|
else
|
||||||
|
err = gcry_sexp_build (&s_pkey, NULL,
|
||||||
|
"(public-key(rsa(n%m)(e%m)))",
|
||||||
|
pkey[0], pkey[1]);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = gcry_sexp_build (&s_data, NULL, "%m", data);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
gcry_sexp_release (s_data); s_data = NULL;
|
||||||
|
gcry_sexp_release (s_pkey); s_pkey = NULL;
|
||||||
|
|
||||||
resarr[0] = get_mpi_from_sexp (s_ciph, "a", GCRYMPI_FMT_USG);
|
resarr[0] = get_mpi_from_sexp (s_ciph, "a", GCRYMPI_FMT_USG);
|
||||||
if (!is_RSA (algo))
|
if (!is_RSA (algo))
|
||||||
resarr[1] = get_mpi_from_sexp (s_ciph, "b", GCRYMPI_FMT_USG);
|
resarr[1] = get_mpi_from_sexp (s_ciph, "b", GCRYMPI_FMT_USG);
|
||||||
}
|
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
gcry_sexp_release (s_data);
|
||||||
|
gcry_sexp_release (s_pkey);
|
||||||
gcry_sexp_release (s_ciph);
|
gcry_sexp_release (s_ciph);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emulate our old PK interface here - sometime in the future we might
|
||||||
|
* change the internal design to directly fit to libgcrypt. PK is is
|
||||||
|
* the OpenPGP public key packet, DATA is an MPI with the to be
|
||||||
|
* encrypted data, and RESARR receives the encrypted data. RESARRAY
|
||||||
|
* is expected to be an two item array which will be filled with newly
|
||||||
|
* allocated MPIs. SESKEY_ALGO is required for public key algorithms
|
||||||
|
* which do not encode it in DATA.
|
||||||
|
*/
|
||||||
|
gpg_error_t
|
||||||
|
pk_encrypt (PKT_public_key *pk, gcry_mpi_t data, int seskey_algo,
|
||||||
|
gcry_mpi_t *resarr)
|
||||||
|
{
|
||||||
|
pubkey_algo_t algo = pk->pubkey_algo;
|
||||||
|
|
||||||
|
if (algo == PUBKEY_ALGO_KYBER)
|
||||||
|
return do_encrypt_kem (pk, data, seskey_algo, resarr);
|
||||||
|
else if (algo == PUBKEY_ALGO_ECDH)
|
||||||
|
return do_encrypt_ecdh (pk, data, resarr);
|
||||||
|
else if (algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E)
|
||||||
|
return do_encrypt_rsa_elg (pk, data, resarr);
|
||||||
|
else if (algo == PUBKEY_ALGO_RSA || algo == PUBKEY_ALGO_RSA_E)
|
||||||
|
return do_encrypt_rsa_elg (pk, data, resarr);
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check whether SKEY is a suitable secret key. */
|
/* Check whether SKEY is a suitable secret key. */
|
||||||
int
|
int
|
||||||
pk_check_secret_key (pubkey_algo_t pkalgo, gcry_mpi_t *skey)
|
pk_check_secret_key (pubkey_algo_t pkalgo, gcry_mpi_t *skey)
|
||||||
|
@ -31,7 +31,7 @@ gpg_error_t sexp_extract_param_sos_nlz (gcry_sexp_t sexp, const char *param,
|
|||||||
|
|
||||||
int pk_verify (pubkey_algo_t algo, gcry_mpi_t hash, gcry_mpi_t *data,
|
int pk_verify (pubkey_algo_t algo, gcry_mpi_t hash, gcry_mpi_t *data,
|
||||||
gcry_mpi_t *pkey);
|
gcry_mpi_t *pkey);
|
||||||
gpg_error_t pk_encrypt (PKT_public_key *pk, gcry_mpi_t data,
|
gpg_error_t pk_encrypt (PKT_public_key *pk, gcry_mpi_t data, int seskey_algo,
|
||||||
gcry_mpi_t *resarr);
|
gcry_mpi_t *resarr);
|
||||||
int pk_check_secret_key (pubkey_algo_t algo, gcry_mpi_t *skey);
|
int pk_check_secret_key (pubkey_algo_t algo, gcry_mpi_t *skey);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user