1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-06-13 18:21:03 +02:00

scd:piv: Support rsa3072

* scd/app-piv.c (PIV_ALGORITHM_RSA): Rename to PIV_ALGORITHM_RSA_2048.
(PIV_ALGORITHM_RSA_3072): New.
(get_key_algorithm_by_dobj): Decide whether to use 3072 or 2048.
(do_sign): Support rsa3072.
(do_decipher): Ditto.
(do_genkey): Ditto.
--

Take care: Due to a lack of a PIV token capable of 3072, this has
not been tested at all.
This commit is contained in:
Werner Koch 2025-05-28 11:06:23 +02:00
parent 15a71f108d
commit e2732b8e19
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B

View File

@ -70,7 +70,9 @@
#define PIV_ALGORITHM_2DES_CBC 0x02 #define PIV_ALGORITHM_2DES_CBC 0x02
#define PIV_ALGORITHM_3DES_ECB 0x03 #define PIV_ALGORITHM_3DES_ECB 0x03
#define PIV_ALGORITHM_3DES_CBC 0x04 #define PIV_ALGORITHM_3DES_CBC 0x04
#define PIV_ALGORITHM_RSA 0x07 #define PIV_ALGORITHM_RSA_3072 0x05
/*#define PIV_ALGORITHM_RSA_1024 0x06*/
#define PIV_ALGORITHM_RSA_2048 0x07
#define PIV_ALGORITHM_AES128_ECB 0x08 #define PIV_ALGORITHM_AES128_ECB 0x08
#define PIV_ALGORITHM_AES128_CBC 0x09 #define PIV_ALGORITHM_AES128_CBC 0x09
#define PIV_ALGORITHM_AES192_ECB 0x0A #define PIV_ALGORITHM_AES192_ECB 0x0A
@ -1271,7 +1273,7 @@ get_keygrip_by_tag (app_t app, unsigned int tag,
goto leave; goto leave;
if (mechanism) /* Compute keygrip from public key. */ if (mechanism) /* Compute keygrip from public key. */
{ {
if (mechanism == PIV_ALGORITHM_RSA) if (mechanism == PIV_ALGORITHM_RSA_2048)
err = genkey_parse_rsa (certbuf, certbuflen, &s_pkey); err = genkey_parse_rsa (certbuf, certbuflen, &s_pkey);
else if (mechanism == PIV_ALGORITHM_ECC_P256 else if (mechanism == PIV_ALGORITHM_ECC_P256
|| mechanism == PIV_ALGORITHM_ECC_P384) || mechanism == PIV_ALGORITHM_ECC_P384)
@ -1486,7 +1488,7 @@ do_readkey (app_t app, ctrl_t ctrl, const char *keyrefstr, unsigned int flags,
else else
{ {
/* Convert the public key into the expected s-expression. */ /* Convert the public key into the expected s-expression. */
if (mechanism == PIV_ALGORITHM_RSA) if (mechanism == PIV_ALGORITHM_RSA_2048)
err = genkey_parse_rsa (cert, certlen, &s_pkey); err = genkey_parse_rsa (cert, certlen, &s_pkey);
else if (mechanism == PIV_ALGORITHM_ECC_P256 else if (mechanism == PIV_ALGORITHM_ECC_P256
|| mechanism == PIV_ALGORITHM_ECC_P384) || mechanism == PIV_ALGORITHM_ECC_P384)
@ -1573,7 +1575,8 @@ get_key_algorithm_by_dobj (app_t app, data_object_t dobj, int *r_mechanism)
/* A public key was found. That makes it easy. */ /* A public key was found. That makes it easy. */
switch (mechanism) switch (mechanism)
{ {
case PIV_ALGORITHM_RSA: case PIV_ALGORITHM_RSA_2048:
case PIV_ALGORITHM_RSA_3072:
case PIV_ALGORITHM_ECC_P256: case PIV_ALGORITHM_ECC_P256:
case PIV_ALGORITHM_ECC_P384: case PIV_ALGORITHM_ECC_P384:
*r_mechanism = mechanism; *r_mechanism = mechanism;
@ -1636,7 +1639,10 @@ get_key_algorithm_by_dobj (app_t app, data_object_t dobj, int *r_mechanism)
switch (algo) switch (algo)
{ {
case GCRY_PK_RSA: case GCRY_PK_RSA:
algo = PIV_ALGORITHM_RSA; if (gcry_pk_get_nbits (s_pkey) > 3000)
algo = PIV_ALGORITHM_RSA_3072;
else
algo = PIV_ALGORITHM_RSA_2048;
break; break;
case GCRY_PK_ECC: case GCRY_PK_ECC:
@ -2260,7 +2266,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
indatalen -= oidbuflen; indatalen -= oidbuflen;
} }
} }
else if (mechanism == PIV_ALGORITHM_RSA else if (mechanism == PIV_ALGORITHM_RSA_2048
&& indatalen == 2048/8 && indata[indatalen-1] == 0xBC) && indatalen == 2048/8 && indata[indatalen-1] == 0xBC)
{ {
/* If the provided data length matches the supported RSA /* If the provided data length matches the supported RSA
@ -2268,13 +2274,27 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
* this is PSS formatted data and we use it verbatim; PIV cards * this is PSS formatted data and we use it verbatim; PIV cards
* accept PSS as well as PKCS#1. */ * accept PSS as well as PKCS#1. */
} }
else if (mechanism == PIV_ALGORITHM_RSA) else if (mechanism == PIV_ALGORITHM_RSA_3072
&& indatalen == 3072/8 && indata[indatalen-1] == 0xBC)
{ {
/* PIV requires 2048 bit RSA. */ /* If the provided data length matches the supported RSA
unsigned int framelen = 2048 / 8; * framelen and the last octet of the data is 0xBC, we assume
* this is PSS formatted data and we use it verbatim; PIV cards
* accept PSS as well as PKCS#1. */
}
else if (mechanism == PIV_ALGORITHM_RSA_2048
|| mechanism == PIV_ALGORITHM_RSA_3072)
{
/* PIV requires 2048 bit or 3072 bit RSA. */
unsigned int framelen;
unsigned char *frame; unsigned char *frame;
int i; int i;
if (mechanism == PIV_ALGORITHM_RSA_2048)
framelen = 2048 / 8;
else
framelen = 3072 / 8;
oidbuflen = sizeof oidbuf; oidbuflen = sizeof oidbuf;
if (!hashalgo) if (!hashalgo)
{ {
@ -2380,7 +2400,12 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
if (outdatalen && *outdata == 0x7c if (outdatalen && *outdata == 0x7c
&& (s = find_tlv (outdata, outdatalen, 0x82, &n))) && (s = find_tlv (outdata, outdatalen, 0x82, &n)))
{ {
if (mechanism == PIV_ALGORITHM_RSA) if (mechanism == PIV_ALGORITHM_RSA_2048)
{
memmove (outdata, outdata + (s - outdata), n);
outdatalen = n;
}
else if (mechanism == PIV_ALGORITHM_RSA_3072)
{ {
memmove (outdata, outdata + (s - outdata), n); memmove (outdata, outdata + (s - outdata), n);
outdatalen = n; outdatalen = n;
@ -2526,9 +2551,12 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
case PIV_ALGORITHM_ECC_P384: case PIV_ALGORITHM_ECC_P384:
framelen = 1+48+48; framelen = 1+48+48;
break; break;
case PIV_ALGORITHM_RSA: case PIV_ALGORITHM_RSA_2048:
framelen = 2048 / 8; framelen = 2048 / 8;
break; break;
case PIV_ALGORITHM_RSA_3072:
framelen = 3072 / 8;
break;
default: default:
err = gpg_error (GPG_ERR_INTERNAL); err = gpg_error (GPG_ERR_INTERNAL);
log_debug ("piv: unknown PIV mechanism %d while decrypting\n", mechanism); log_debug ("piv: unknown PIV mechanism %d while decrypting\n", mechanism);
@ -2545,7 +2573,8 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
* uncompressed point. */ * uncompressed point. */
if (indatalen > framelen) if (indatalen > framelen)
{ {
if (mechanism == PIV_ALGORITHM_RSA if ((mechanism == PIV_ALGORITHM_RSA_2048
|| mechanism == PIV_ALGORITHM_RSA_3072)
&& indatalen == framelen + 1 && !*indata) && indatalen == framelen + 1 && !*indata)
{ {
indata_buffer = xtrycalloc (1, framelen); indata_buffer = xtrycalloc (1, framelen);
@ -2588,7 +2617,8 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
err = concat_tlv_list (0, &apdudata, &apdudatalen, err = concat_tlv_list (0, &apdudata, &apdudatalen,
(int)0x7c, (size_t)0, NULL, /* Constructed. */ (int)0x7c, (size_t)0, NULL, /* Constructed. */
(int)0x82, (size_t)0, "", (int)0x82, (size_t)0, "",
mechanism == PIV_ALGORITHM_RSA? (mechanism == PIV_ALGORITHM_RSA_2048
|| mechanism == PIV_ALGORITHM_RSA_3072)?
(int)0x81 : (int)0x85, (size_t)indatalen, indata, (int)0x81 : (int)0x85, (size_t)indatalen, indata,
(int)0, (size_t)0, NULL); (int)0, (size_t)0, NULL);
if (err) if (err)
@ -2678,6 +2708,7 @@ writekey_rsa (app_t app, data_object_t dobj, int keyref,
const unsigned char *tok; const unsigned char *tok;
size_t toklen; size_t toklen;
int last_depth1, last_depth2; int last_depth1, last_depth2;
int mechanism;
const unsigned char *rsa_n = NULL; const unsigned char *rsa_n = NULL;
const unsigned char *rsa_e = NULL; const unsigned char *rsa_e = NULL;
const unsigned char *rsa_p = NULL; const unsigned char *rsa_p = NULL;
@ -2796,11 +2827,16 @@ writekey_rsa (app_t app, data_object_t dobj, int keyref,
if (err) if (err)
goto leave; goto leave;
if (rsa_n_len > 3000/8)
mechanism = PIV_ALGORITHM_RSA_3072;
else
mechanism = PIV_ALGORITHM_RSA_2048;
err = iso7816_send_apdu (app_get_slot (app), err = iso7816_send_apdu (app_get_slot (app),
-1, /* Use command chaining. */ -1, /* Use command chaining. */
0, /* Class */ 0, /* Class */
0xfe, /* Ins: Yubikey Import Asym. Key. */ 0xfe, /* Ins: Yubikey Import Asym. Key. */
PIV_ALGORITHM_RSA, /* P1 */ mechanism, /* P1 */
keyref, /* P2 */ keyref, /* P2 */
apdudatalen,/* Lc */ apdudatalen,/* Lc */
apdudata, /* data */ apdudata, /* data */
@ -2817,7 +2853,7 @@ writekey_rsa (app_t app, data_object_t dobj, int keyref,
if (err) if (err)
goto leave; goto leave;
tmpl[0] = PIV_ALGORITHM_RSA; tmpl[0] = mechanism;
err = put_data (app_get_slot (app), dobj->tag, err = put_data (app_get_slot (app), dobj->tag,
(int)0x80, (size_t)1, tmpl, (int)0x80, (size_t)1, tmpl,
(int)0x7f49, (size_t)apdudatalen, apdudata, (int)0x7f49, (size_t)apdudatalen, apdudata,
@ -3208,7 +3244,7 @@ genkey_parse_ecc (const unsigned char *data, size_t datalen, int mechanism,
/* Create a new keypair for KEYREF. If KEYTYPE is NULL a default /* Create a new keypair for KEYREF. If KEYTYPE is NULL a default
* keytype is selected, else it may be one of the strings: * keytype is selected, else it may be one of the strings:
* "rsa2048", "nistp256, or "nistp384". * "rsa2048", "rsa3072", "nistp256, or "nistp384".
* *
* Supported FLAGS are: * Supported FLAGS are:
* APP_GENKEY_FLAG_FORCE Overwrite existing key. * APP_GENKEY_FLAG_FORCE Overwrite existing key.
@ -3249,7 +3285,9 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keyrefstr, const char *keytype,
keytype = "rsa2048"; keytype = "rsa2048";
if (!strcmp (keytype, "rsa2048")) if (!strcmp (keytype, "rsa2048"))
mechanism = PIV_ALGORITHM_RSA; mechanism = PIV_ALGORITHM_RSA_2048;
else if (!strcmp (keytype, "rsa3072"))
mechanism = PIV_ALGORITHM_RSA_3072;
else if (!strcmp (keytype, "nistp256")) else if (!strcmp (keytype, "nistp256"))
mechanism = PIV_ALGORITHM_ECC_P256; mechanism = PIV_ALGORITHM_ECC_P256;
else if (!strcmp (keytype, "nistp384")) else if (!strcmp (keytype, "nistp384"))