diff --git a/Makefile b/Makefile index 8a1e45c..0373f13 100644 --- a/Makefile +++ b/Makefile @@ -122,6 +122,7 @@ DISABLE_STANDARD_WEBUSB = 1 DEFINES += CUSTOM_IO_APDU_BUFFER_SIZE=\(255+5+64\) DEFINES += HAVE_USB_CLASS_CCID DEFINES += HAVE_RSA +# DEFINES += WITH_SUPPORT_RSA4096 ifeq ($(TARGET_NAME),TARGET_NANOS) DEFINES += HAVE_UX_LEGACY diff --git a/README.md b/README.md index cee34ea..afa9dfc 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This specification is available in *doc* directory and at attributes.value[0]) { case KEY_ID_RSA: + ksz = U2BE(G_gpg_vstate.mse_dec->attributes.value, 1) >> 3; + switch (ksz) { + case 2048 / 8: + key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa2048; + len = sizeof(cx_rsa_2048_private_key_t); + break; + case 3072 / 8: + key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa3072; + len = sizeof(cx_rsa_3072_private_key_t); + break; +#ifdef WITH_SUPPORT_RSA4096 + case 4096 / 8: + key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa4096; + len = sizeof(cx_rsa_4096_private_key_t); + break; +#endif + } + + if ((key == NULL) || (key->size != ksz)) { + return SW_CONDITIONS_NOT_SATISFIED; + } + // insert pubkey gpg_io_insert_u32(4); gpg_io_insert(keygpg->pub_key.rsa, 4); // insert privkey gpg_io_mark(); - len = GPG_IO_BUFFER_LENGTH - G_gpg_vstate.io_offset; CX_CHECK(cx_aes_no_throw(&keyenc, CX_ENCRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST, - (unsigned char *) &keygpg->priv_key.rsa4096, - sizeof(cx_rsa_4096_private_key_t), + (unsigned char *) key, + len, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, &len)); gpg_io_inserted(len); @@ -890,8 +915,11 @@ int gpg_apdu_put_key_data(unsigned int ref) { cx_aes_key_t keyenc = {0}; gpg_key_t *keygpg = NULL; unsigned int len = 0; + cx_rsa_private_key_t *key = NULL; + unsigned int offset = 0; cx_err_t error = CX_INTERNAL_ERROR; int sw = SW_UNKNOWN; + unsigned int ksz = 0; sw = gpg_init_keyenc(&keyenc); if (sw != SW_OK) { @@ -933,19 +961,50 @@ int gpg_apdu_put_key_data(unsigned int ref) { break; } offset = G_gpg_vstate.io_offset; + + ksz = U2BE(G_gpg_vstate.mse_dec->attributes.value, 1) >> 3; + switch (ksz) { + case 2048 / 8: + key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa2048; + len = sizeof(cx_rsa_2048_private_key_t); + break; + case 3072 / 8: + key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa3072; + len = sizeof(cx_rsa_3072_private_key_t); + break; +#ifdef WITH_SUPPORT_RSA4096 + case 4096 / 8: + key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa4096; + len = sizeof(cx_rsa_4096_private_key_t); + break; +#endif + } + + if ((key == NULL) || (key->size != ksz)) { + PRINTF("[DATA] - put_key_data: Wrong key len: %d / %d\n", ksz, key->size); + sw = SW_CONDITIONS_NOT_SATISFIED; + break; + } + if (len != GPG_IO_BUFFER_LENGTH) { + PRINTF("[DATA] - put_key_data: Wrong buffer len: %d / %d\n", len, GPG_IO_BUFFER_LENGTH); + sw = SW_CONDITIONS_NOT_SATISFIED; + break; + } + + PRINTF("[DATA] - put_key_data: key len: %d\n", len); gpg_io_discard(0); - len = GPG_IO_BUFFER_LENGTH; CX_CHECK(cx_aes_no_throw(&keyenc, CX_DECRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST, G_gpg_vstate.work.io_buffer + offset, len, G_gpg_vstate.work.io_buffer, - &len)); - if (len != sizeof(cx_rsa_4096_private_key_t)) { + &ksz)); + if (len != ksz) { + PRINTF("[DATA] - put_key_data: Wrong aes output len: %d / %d\n", len, ksz); sw = SW_WRONG_DATA; break; } - nvm_write((unsigned char *) &keygpg->priv_key.rsa4096, + nvm_write((unsigned char *) key, G_gpg_vstate.work.io_buffer, len); sw = SW_OK; diff --git a/src/gpg_gen.c b/src/gpg_gen.c index 5327cc3..c3b8986 100644 --- a/src/gpg_gen.c +++ b/src/gpg_gen.c @@ -93,9 +93,11 @@ static int gpg_gen_rsa_kyey(gpg_key_t *keygpg, uint8_t *name) { case 3072 / 8: pkey_size = sizeof(cx_rsa_3072_private_key_t); break; +#ifdef WITH_SUPPORT_RSA4096 case 4096 / 8: pkey_size = sizeof(cx_rsa_4096_private_key_t); break; +#endif default: break; } @@ -164,12 +166,16 @@ static int gpg_read_rsa_kyey(gpg_key_t *keygpg) { } gpg_io_insert_tlv(0x81, ksz, (unsigned char *) &keygpg->priv_key.rsa3072.n); break; +#ifdef WITH_SUPPORT_RSA4096 case 4096 / 8: if (keygpg->priv_key.rsa4096.size == 0) { return SW_REFERENCED_DATA_NOT_FOUND; } gpg_io_insert_tlv(0x81, ksz, (unsigned char *) &keygpg->priv_key.rsa4096.n); break; +#endif + default: + return SW_REFERENCED_DATA_NOT_FOUND; } gpg_io_insert_tlv(0x82, 4, keygpg->pub_key.rsa); diff --git a/src/gpg_pso.c b/src/gpg_pso.c index 7977b27..ed4fea5 100644 --- a/src/gpg_pso.c +++ b/src/gpg_pso.c @@ -77,9 +77,11 @@ static int gpg_sign(gpg_key_t *sigkey) { case 3072 / 8: key = (cx_rsa_private_key_t *) &sigkey->priv_key.rsa3072; break; +#ifdef WITH_SUPPORT_RSA4096 case 4096 / 8: key = (cx_rsa_private_key_t *) &sigkey->priv_key.rsa4096; break; +#endif default: break; } @@ -263,9 +265,11 @@ int gpg_apdu_pso() { case 3072 / 8: key = (cx_rsa_private_key_t *) &G_gpg_vstate.mse_dec->priv_key.rsa3072; break; +#ifdef WITH_SUPPORT_RSA4096 case 4096 / 8: key = (cx_rsa_private_key_t *) &G_gpg_vstate.mse_dec->priv_key.rsa4096; break; +#endif } if ((key == NULL) || (key->size != ksz)) { diff --git a/src/gpg_types.h b/src/gpg_types.h index 34a4ba4..41e0dd8 100644 --- a/src/gpg_types.h +++ b/src/gpg_types.h @@ -84,8 +84,9 @@ typedef struct gpg_key_s { cx_rsa_private_key_t rsa; cx_rsa_2048_private_key_t rsa2048; cx_rsa_3072_private_key_t rsa3072; +#ifdef WITH_SUPPORT_RSA4096 cx_rsa_4096_private_key_t rsa4096; - +#endif cx_ecfp_private_key_t ecfp; cx_ecfp_256_private_key_t ecfp256; cx_ecfp_384_private_key_t ecfp384; @@ -215,13 +216,17 @@ struct gpg_v_state_s { cx_rsa_public_key_t public; cx_rsa_2048_public_key_t public2048; cx_rsa_3072_public_key_t public3072; +#ifdef WITH_SUPPORT_RSA4096 cx_rsa_4096_public_key_t public4096; +#endif }; union { cx_rsa_private_key_t private; cx_rsa_2048_private_key_t private2048; cx_rsa_3072_private_key_t private3072; +#ifdef WITH_SUPPORT_RSA4096 cx_rsa_4096_private_key_t private4096; +#endif }; } rsa; diff --git a/src/gpg_ux_nanos.c b/src/gpg_ux_nanos.c index 55870f9..a5391b7 100644 --- a/src/gpg_ux_nanos.c +++ b/src/gpg_ux_nanos.c @@ -536,7 +536,9 @@ const ux_menu_entry_t ui_menu_tmpl_key[] = { const ux_menu_entry_t ui_menu_tmpl_type[] = { {NULL, ui_menu_tmpl_type_action, 2048, NULL, LABEL_RSA2048, NULL, 0, 0}, {NULL, ui_menu_tmpl_type_action, 3072, NULL, LABEL_RSA3072, NULL, 0, 0}, +#ifdef WITH_SUPPORT_RSA4096 {NULL, ui_menu_tmpl_type_action, 4096, NULL, LABEL_RSA4096, NULL, 0, 0}, +#endif {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256R1, NULL, LABEL_NISTP256, NULL, 0, 0}, {NULL, ui_menu_tmpl_type_action, CX_CURVE_Ed25519, NULL, LABEL_Ed25519, NULL, 0, 0}, {ui_menu_template, NULL, 0, &C_icon_back, "Back", NULL, 61, 40}, @@ -570,10 +572,11 @@ const bagl_element_t *ui_menu_template_predisplay(const ux_menu_entry_t *entry, case 3072: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_RSA3072); break; +#ifdef WITH_SUPPORT_RSA4096 case 4096: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_RSA4096); break; - +#endif case CX_CURVE_SECP256R1: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_NISTP256); break; @@ -605,7 +608,9 @@ void ui_menu_tmpl_set_action(unsigned int value) { switch (G_gpg_vstate.ux_type) { case 2048: case 3072: +#ifdef WITH_SUPPORT_RSA4096 case 4096: +#endif attributes.value[0] = KEY_ID_RSA; U2BE_ENCODE(attributes.value, 1, G_gpg_vstate.ux_type); attributes.value[3] = 0x00; diff --git a/src/gpg_ux_nanox.c b/src/gpg_ux_nanox.c index e2b9342..bb9dd71 100644 --- a/src/gpg_ux_nanox.c +++ b/src/gpg_ux_nanox.c @@ -474,13 +474,17 @@ void tmpl_key_selector(unsigned int idx) { const char *const tmpl_type_getter_values[] = {LABEL_RSA2048, LABEL_RSA3072, +#ifdef WITH_SUPPORT_RSA4096 LABEL_RSA4096, +#endif LABEL_SECP256K1, LABEL_Ed25519}; const unsigned int tmpl_type_getter_values_map[] = {2048, 3072, +#ifdef WITH_SUPPORT_RSA4096 4096, +#endif CX_CURVE_SECP256R1, CX_CURVE_Ed25519}; @@ -567,9 +571,11 @@ void ui_menu_template_predisplay() { case 3072: snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_RSA3072); break; +#ifdef WITH_SUPPORT_RSA4096 case 4096: snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_RSA4096); break; +#endif case CX_CURVE_SECP256R1: snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_SECP256K1); break; @@ -597,7 +603,9 @@ void ui_menu_tmpl_set_action(unsigned int value) { switch (G_gpg_vstate.ux_type) { case 2048: case 3072: +#ifdef WITH_SUPPORT_RSA4096 case 4096: +#endif attributes.value[0] = KEY_ID_RSA; U2BE_ENCODE(attributes.value, 1, G_gpg_vstate.ux_type); attributes.value[3] = 0x00; diff --git a/src/gpg_ux_nbgl.c b/src/gpg_ux_nbgl.c index d0acb70..a587fee 100644 --- a/src/gpg_ux_nbgl.c +++ b/src/gpg_ux_nbgl.c @@ -204,7 +204,9 @@ static const char* const keyNameTexts[] = {LABEL_SIG, LABEL_DEC, LABEL_AUT}; enum { TOKEN_TYPE_RSA2048 = FIRST_USER_TOKEN, TOKEN_TYPE_RSA3072, +#ifdef WITH_SUPPORT_RSA4096 TOKEN_TYPE_RSA4096, +#endif TOKEN_TYPE_SECP256K1, TOKEN_TYPE_Ed25519, TOKEN_TYPE_BACK @@ -212,7 +214,9 @@ enum { static const char* const keyTypeTexts[] = {LABEL_RSA2048, LABEL_RSA3072, +#ifdef WITH_SUPPORT_RSA4096 LABEL_RSA4096, +#endif LABEL_SECP256K1, LABEL_Ed25519}; @@ -245,9 +249,11 @@ static uint32_t _getKeyType(const uint8_t key) { case 3072: token = TOKEN_TYPE_RSA3072; break; +#ifdef WITH_SUPPORT_RSA4096 case 4096: token = TOKEN_TYPE_RSA4096; break; +#endif } break; case KEY_ID_ECDH: @@ -284,7 +290,9 @@ static void template_key_cb(int token, uint8_t index) { switch (key_type) { case TOKEN_TYPE_RSA2048: case TOKEN_TYPE_RSA3072: +#ifdef WITH_SUPPORT_RSA4096 case TOKEN_TYPE_RSA4096: +#endif switch (key_type) { case TOKEN_TYPE_RSA2048: size = 2048; @@ -292,9 +300,11 @@ static void template_key_cb(int token, uint8_t index) { case TOKEN_TYPE_RSA3072: size = 3072; break; +#ifdef WITH_SUPPORT_RSA4096 case TOKEN_TYPE_RSA4096: size = 4096; break; +#endif } attributes.value[0] = KEY_ID_RSA; U2BE_ENCODE(attributes.value, 1, size); @@ -394,9 +404,11 @@ static void ui_settings_template(void) { case TOKEN_TYPE_RSA3072: bar.subText = PIC(LABEL_RSA3072); break; +#ifdef WITH_SUPPORT_RSA4096 case TOKEN_TYPE_RSA4096: bar.subText = PIC(LABEL_RSA4096); break; +#endif case TOKEN_TYPE_SECP256K1: bar.subText = PIC(LABEL_SECP256K1); break; diff --git a/tests/test_seed.py b/tests/test_seed.py index cf15194..987bf67 100644 --- a/tests/test_seed.py +++ b/tests/test_seed.py @@ -44,7 +44,7 @@ def _gen_key(client: CommandSender, template: str): [ "rsa2048", pytest.param("rsa3072", marks=pytest.mark.skipif("--full" not in sys.argv, reason="skipping long test")), - pytest.param("rsa4096", marks=pytest.mark.skipif("--full" not in sys.argv, reason="skipping long test")), + # pytest.param("rsa4096", marks=pytest.mark.skipif("--full" not in sys.argv, reason="skipping long test")), "nistp256", # ECDSA "ed25519", # EdDSA # "cv25519", # ECDH, SDK returns CX_EC_INVALID_CURVE diff --git a/tests/utils.py b/tests/utils.py index b89303e..5d5e770 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -22,7 +22,7 @@ ROOT_SCREENSHOT_PATH = Path(__file__).parent.resolve() KEY_TEMPLATES = { "rsa2048" : "010800002001", "rsa3072" : "010C00002001", - "rsa4096" : "011000002001", + # "rsa4096" : "011000002001", Not supported yet "nistp256": "132A8648CE3D030107", "ed25519" : "162B06010401DA470F01", "cv25519" : "122B060104019755010501"