diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c index 50755c0fd..420dbb464 100644 --- a/agent/cvt-openpgp.c +++ b/agent/cvt-openpgp.c @@ -1384,6 +1384,17 @@ extract_private_key (gcry_sexp_t s_key, int req_private_key_data, err = gcry_sexp_extract_param (list, NULL, format, array+0, array+1, NULL); } + else if ( !strcmp (name, (algoname = "kyber512")) + || !strcmp (name, (algoname = "kyber768")) + || !strcmp (name, (algoname = "kyber1024"))) + { + format = "/ps?"; + elems = "ps?"; + npkey = 1; + nskey = 2; + err = gcry_sexp_extract_param (list, NULL, format, + array+0, array+1, NULL); + } else { err = gpg_error (GPG_ERR_PUBKEY_ALGO); diff --git a/agent/divert-scd.c b/agent/divert-scd.c index ed0173ea1..4a2bebffa 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -377,7 +377,7 @@ divert_pksign (ctrl_t ctrl, const unsigned char *grip, } -/* Decrypt the value given asn an S-expression in CIPHER using the +/* Decrypt the value given as an s-expression in CIPHER using the key identified by SHADOW_INFO and return the plaintext in an allocated buffer in R_BUF. The padding information is stored at R_PADDING with -1 for not known. */ diff --git a/common/openpgp-oid.c b/common/openpgp-oid.c index ceb211dd3..bc82cc6b0 100644 --- a/common/openpgp-oid.c +++ b/common/openpgp-oid.c @@ -623,6 +623,7 @@ map_gcry_pk_to_openpgp (enum gcry_pk_algos algo) case GCRY_PK_EDDSA: return PUBKEY_ALGO_EDDSA; case GCRY_PK_ECDSA: return PUBKEY_ALGO_ECDSA; case GCRY_PK_ECDH: return PUBKEY_ALGO_ECDH; + case GCRY_PK_KEM: return PUBKEY_ALGO_KYBER; default: return algo < 110 ? (pubkey_algo_t)algo : 0; } } diff --git a/common/sexputil.c b/common/sexputil.c index c7471be85..e6fc84da0 100644 --- a/common/sexputil.c +++ b/common/sexputil.c @@ -992,7 +992,7 @@ get_pk_algo_from_key (gcry_sexp_t key) gcry_sexp_t list; const char *s; size_t n; - char algoname[6]; + char algoname[10]; int algo = 0; list = gcry_sexp_nth (key, 1); diff --git a/g10/call-agent.c b/g10/call-agent.c index e7046f7b2..a49c987fa 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -2469,7 +2469,7 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, gpg_error_t err; char line[ASSUAN_LINELENGTH]; struct keyinfo_data_parm_s keyinfo; - char *s; + const char *s; memset (&keyinfo, 0,sizeof keyinfo); diff --git a/g10/keygen.c b/g10/keygen.c index 6426f7e4f..c2acf74c3 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1,7 +1,7 @@ /* keygen.c - Generate a key pair * Copyright (C) 1998-2007, 2009-2011 Free Software Foundation, Inc. * Copyright (C) 2014, 2015, 2016, 2017, 2018 Werner Koch - * Copyright (C) 2020 g10 Code GmbH + * Copyright (C) 2020, 2024 g10 Code GmbH * * This file is part of GnuPG. * @@ -1501,10 +1501,24 @@ do_create_from_keygrip (ctrl_t ctrl, int algo, PACKET *pkt; PKT_public_key *pk; gcry_sexp_t s_key; + gcry_sexp_t s_key2 = NULL; const char *algoelem; + char *hexkeygrip_buffer = NULL; + char *hexkeygrip2 = NULL; if (hexkeygrip[0] == '&') hexkeygrip++; + if (strchr (hexkeygrip, ',')) + { + hexkeygrip_buffer = xtrystrdup (hexkeygrip); + if (!hexkeygrip_buffer) + return gpg_error_from_syserror (); + hexkeygrip = hexkeygrip_buffer; + hexkeygrip2 = strchr (hexkeygrip_buffer, ','); + if (hexkeygrip2) + *hexkeygrip2++ = 0; + } + switch (algo) { @@ -1514,16 +1528,21 @@ do_create_from_keygrip (ctrl_t ctrl, int algo, case PUBKEY_ALGO_ECDH: case PUBKEY_ALGO_ECDSA: algoelem = ""; break; case PUBKEY_ALGO_EDDSA: algoelem = ""; break; - default: return gpg_error (GPG_ERR_INTERNAL); + case PUBKEY_ALGO_KYBER: algoelem = ""; break; + default: + xfree (hexkeygrip_buffer); + return gpg_error (GPG_ERR_INTERNAL); } - /* Ask the agent for the public key matching HEXKEYGRIP. */ if (cardkey) { err = agent_scd_readkey (ctrl, hexkeygrip, &s_key, NULL); if (err) - return err; + { + xfree (hexkeygrip_buffer); + return err; + } } else { @@ -1531,16 +1550,41 @@ do_create_from_keygrip (ctrl_t ctrl, int algo, err = agent_readkey (ctrl, 0, hexkeygrip, &public); if (err) - return err; + { + xfree (hexkeygrip_buffer); + return err; + } err = gcry_sexp_sscan (&s_key, NULL, public, gcry_sexp_canon_len (public, 0, NULL, NULL)); xfree (public); if (err) - return err; + { + xfree (hexkeygrip_buffer); + return err; + } + if (hexkeygrip2) + { + err = agent_readkey (ctrl, 0, hexkeygrip2, &public); + if (err) + { + gcry_sexp_release (s_key); + xfree (hexkeygrip_buffer); + return err; + } + err = gcry_sexp_sscan (&s_key2, NULL, public, + gcry_sexp_canon_len (public, 0, NULL, NULL)); + xfree (public); + if (err) + { + gcry_sexp_release (s_key); + xfree (hexkeygrip_buffer); + return err; + } + } } - /* For X448 we force the use of v5 packets. */ - if (curve_is_448 (s_key)) + /* For X448 and Kyber we force the use of v5 packets. */ + if (curve_is_448 (s_key) || algo == PUBKEY_ALGO_KYBER) *keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY; /* Build a public key packet. */ @@ -1549,6 +1593,8 @@ do_create_from_keygrip (ctrl_t ctrl, int algo, { err = gpg_error_from_syserror (); gcry_sexp_release (s_key); + gcry_sexp_release (s_key2); + xfree (hexkeygrip_buffer); return err; } @@ -1558,7 +1604,9 @@ do_create_from_keygrip (ctrl_t ctrl, int algo, pk->expiredate = pk->timestamp + expireval; pk->pubkey_algo = algo; - if (algo == PUBKEY_ALGO_ECDSA + if (algo == PUBKEY_ALGO_KYBER) + err = ecckey_from_sexp (pk->pkey, s_key, s_key2, algo); + else if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_EDDSA || algo == PUBKEY_ALGO_ECDH ) err = ecckey_from_sexp (pk->pkey, s_key, NULL, algo); @@ -1568,16 +1616,20 @@ do_create_from_keygrip (ctrl_t ctrl, int algo, { log_error ("key_from_sexp failed: %s\n", gpg_strerror (err) ); gcry_sexp_release (s_key); + gcry_sexp_release (s_key2); free_public_key (pk); + xfree (hexkeygrip_buffer); return err; } gcry_sexp_release (s_key); + gcry_sexp_release (s_key2); pkt = xtrycalloc (1, sizeof *pkt); if (!pkt) { err = gpg_error_from_syserror (); free_public_key (pk); + xfree (hexkeygrip_buffer); return err; } @@ -1585,6 +1637,7 @@ do_create_from_keygrip (ctrl_t ctrl, int algo, pkt->pkt.public_key = pk; add_kbnode (pub_root, new_kbnode (pkt)); + xfree (hexkeygrip_buffer); return 0; } @@ -2479,7 +2532,26 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage, continue; } - if (strlen (answer) != 40 && + if (strlen (answer) == 40+1+40 && answer[40]==',') + { + int algo1, algo2; + + answer[40] = 0; + algo1 = check_keygrip (ctrl, answer); + algo2 = check_keygrip (ctrl, answer+41); + answer[40] = ','; + if (algo1 == PUBKEY_ALGO_ECDH && algo2 == PUBKEY_ALGO_KYBER) + { + algo = PUBKEY_ALGO_KYBER; + break; + } + else if (!algo1 || !algo2) + tty_printf (_("No key with this keygrip\n")); + else + tty_printf ("Invalid combination for dual algo (%d,%d)\n", + algo1, algo2); + } + else if (strlen (answer) != 40 && !(answer[0] == '&' && strlen (answer+1) == 40)) tty_printf (_("Not a valid keygrip (expecting 40 hex digits)\n"));