Merge pull request #97 from LedgerHQ/cev/clean_supported_algo
Handle supported algorithms and curves
6
Makefile
@ -29,8 +29,8 @@ APPNAME = OpenPGP
|
|||||||
|
|
||||||
# Application version
|
# Application version
|
||||||
APPVERSION_M = 2
|
APPVERSION_M = 2
|
||||||
APPVERSION_N = 0
|
APPVERSION_N = 1
|
||||||
APPVERSION_P = 1
|
APPVERSION_P = 0
|
||||||
APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)"
|
APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)"
|
||||||
|
|
||||||
SPECVERSION:="3.3.1"
|
SPECVERSION:="3.3.1"
|
||||||
@ -122,6 +122,8 @@ DISABLE_STANDARD_WEBUSB = 1
|
|||||||
DEFINES += CUSTOM_IO_APDU_BUFFER_SIZE=\(255+5+64\)
|
DEFINES += CUSTOM_IO_APDU_BUFFER_SIZE=\(255+5+64\)
|
||||||
DEFINES += HAVE_USB_CLASS_CCID
|
DEFINES += HAVE_USB_CLASS_CCID
|
||||||
DEFINES += HAVE_RSA
|
DEFINES += HAVE_RSA
|
||||||
|
# Watchdog issue causing the device reset with long prime number computation
|
||||||
|
# DEFINES += WITH_SUPPORT_RSA4096
|
||||||
|
|
||||||
ifeq ($(TARGET_NAME),TARGET_NANOS)
|
ifeq ($(TARGET_NAME),TARGET_NANOS)
|
||||||
DEFINES += HAVE_UX_LEGACY
|
DEFINES += HAVE_UX_LEGACY
|
||||||
|
10
README.md
@ -11,7 +11,7 @@ This specification is available in *doc* directory and at <https://g10code.com/p
|
|||||||
|
|
||||||
The application supports:
|
The application supports:
|
||||||
|
|
||||||
- RSA with key up to 4096 bits
|
- RSA with key up to 3072 bits
|
||||||
- ECDSA with secp256k1
|
- ECDSA with secp256k1
|
||||||
- EDDSA with Ed25519 curve
|
- EDDSA with Ed25519 curve
|
||||||
- ECDH with secp256k1 and curve25519 curves
|
- ECDH with secp256k1 and curve25519 curves
|
||||||
@ -321,3 +321,11 @@ It outputs 3 artifacts:
|
|||||||
|
|
||||||
- `compiled_app_binaries` within binary files of the build process for each device
|
- `compiled_app_binaries` within binary files of the build process for each device
|
||||||
- `code-coverage` within HTML details of code coverage
|
- `code-coverage` within HTML details of code coverage
|
||||||
|
|
||||||
|
## Known limitations
|
||||||
|
|
||||||
|
Today, the current App has some known limitations.
|
||||||
|
|
||||||
|
- RSA4096 is disabled, because of an issue with the watchdog, resetting the device
|
||||||
|
during long prime number operation.
|
||||||
|
- Using Ed25519 template, the decrypt doesn't output a correct result.
|
||||||
|
@ -50,10 +50,10 @@ This specification is available in doc directory at [G10CODE]_.
|
|||||||
|
|
||||||
The application supports:
|
The application supports:
|
||||||
|
|
||||||
- RSA with key up to 4096 bits
|
- RSA with key up to 3072 bits
|
||||||
- ECDSA with secp256k1, secp256r1, brainpool 256r1 and brainpool 256t1 curves
|
- ECDSA with secp256R1
|
||||||
- EDDSA with Ed25519 curve
|
- EDDSA with Ed25519 curve
|
||||||
- ECDH with secp256k1, secp256r1, brainpool 256r1, brainpool 256t1 and curve25519 curves
|
- ECDH with secp256R1 and curve25519 curves
|
||||||
|
|
||||||
This release has known missing parts (see also [GPGADD]_):
|
This release has known missing parts (see also [GPGADD]_):
|
||||||
|
|
||||||
@ -154,8 +154,7 @@ The full menu layout is:
|
|||||||
| Choose Type...
|
| Choose Type...
|
||||||
| RSA 2048
|
| RSA 2048
|
||||||
| RSA 3072
|
| RSA 3072
|
||||||
| RSA 4096
|
| SECP 256R1
|
||||||
| NIST P256
|
|
||||||
| ED25519
|
| ED25519
|
||||||
| Set Template
|
| Set Template
|
||||||
| Seed mode *ON/OFF*
|
| Seed mode *ON/OFF*
|
||||||
@ -1100,7 +1099,7 @@ The *usage* field tells you each key purpose:
|
|||||||
The *card-no* field provides you with the serial number of the card on which the key are stored.
|
The *card-no* field provides you with the serial number of the card on which the key are stored.
|
||||||
You should have 3 or less keys with the same serial. These are the keys we want to restore.
|
You should have 3 or less keys with the same serial. These are the keys we want to restore.
|
||||||
|
|
||||||
For each key you also have the key template (*rsa2048*, *rsa3072*, *rsa4096*, *ed2559*, *cv25519*) followed by the
|
For each key you also have the key template (*rsa2048*, *rsa3072*, *ed2559*, *cv25519*) followed by the
|
||||||
short fingerprint, e.g. ``ed25519/8451AAF7D43D1095``
|
short fingerprint, e.g. ``ed25519/8451AAF7D43D1095``
|
||||||
|
|
||||||
Please note the serial and the 3 key template names: ``FD6C11BE`` , ``ed25519:cv25519:ed25519``.
|
Please note the serial and the 3 key template names: ``FD6C11BE`` , ``ed25519:cv25519:ed25519``.
|
||||||
@ -1465,7 +1464,7 @@ Its usage is:
|
|||||||
| ``--set-templates SIG:DEC:AUT``
|
| ``--set-templates SIG:DEC:AUT``
|
||||||
| ``Set template identifier for selected 'key-type'``
|
| ``Set template identifier for selected 'key-type'``
|
||||||
| ``If 'key-type' is not specified, set for all keys (SIG:DEC:AUT)``
|
| ``If 'key-type' is not specified, set for all keys (SIG:DEC:AUT)``
|
||||||
| ``Valid values are rsa2048, rsa3072, rsa4096, nistp256, ed25519, cv25519``
|
| ``Valid values are rsa2048, rsa3072, nistp256, ed25519, cv25519``
|
||||||
| ``--seed-key Regenerate all keys, based on seed mode``
|
| ``--seed-key Regenerate all keys, based on seed mode``
|
||||||
| ``--file FILE Public Key export file (default is 'pubkey')``
|
| ``--file FILE Public Key export file (default is 'pubkey')``
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ dirName=$(dirname "${exeName}")
|
|||||||
gnupg_home_dir="$(realpath "${dirName}/gnupg")"
|
gnupg_home_dir="$(realpath "${dirName}/gnupg")"
|
||||||
|
|
||||||
VERBOSE=false
|
VERBOSE=false
|
||||||
|
EXPERT=false
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
#
|
#
|
||||||
@ -23,7 +24,8 @@ help() {
|
|||||||
echo
|
echo
|
||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo
|
echo
|
||||||
echo " -c <init|card|encrypt|decryptsign|verify> : Requested command"
|
echo " -c <init|reset|card|encrypt|decryptsign|verify> : Requested command"
|
||||||
|
echo " -e : Expert mode mode"
|
||||||
echo " -v : Verbose mode"
|
echo " -v : Verbose mode"
|
||||||
echo " -h : Displays this help"
|
echo " -h : Displays this help"
|
||||||
echo
|
echo
|
||||||
@ -32,10 +34,10 @@ help() {
|
|||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
#
|
#
|
||||||
# kill_process - Kill running process, ensure clear next operation
|
# reset - Kill running process, ensure clear next operation
|
||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
kill_process() {
|
reset() {
|
||||||
# Kill running process
|
# Kill running process
|
||||||
killall scdaemon gpg-agent 2>/dev/null
|
killall scdaemon gpg-agent 2>/dev/null
|
||||||
}
|
}
|
||||||
@ -46,7 +48,7 @@ kill_process() {
|
|||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
init() {
|
init() {
|
||||||
kill_process
|
reset
|
||||||
|
|
||||||
# Cleanup old gnupg home directory
|
# Cleanup old gnupg home directory
|
||||||
dir=$(basename "${gnupg_home_dir}")
|
dir=$(basename "${gnupg_home_dir}")
|
||||||
@ -68,8 +70,11 @@ init() {
|
|||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
card() {
|
card() {
|
||||||
|
local expert_mode=""
|
||||||
|
|
||||||
gpg --homedir "${gnupg_home_dir}" --card-edit
|
[[ ${EXPERT} == true ]] && expert_mode="--expert"
|
||||||
|
|
||||||
|
gpg --homedir "${gnupg_home_dir}" ${expert_mode} --card-edit
|
||||||
}
|
}
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
@ -79,7 +84,8 @@ card() {
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
encrypt() {
|
encrypt() {
|
||||||
local recipient=""
|
local recipient=""
|
||||||
kill_process
|
local verbose_mode=""
|
||||||
|
reset
|
||||||
rm -fr foo*
|
rm -fr foo*
|
||||||
echo CLEAR > foo.txt
|
echo CLEAR > foo.txt
|
||||||
|
|
||||||
@ -98,8 +104,9 @@ encrypt() {
|
|||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
decrypt() {
|
decrypt() {
|
||||||
|
local verbose_mode=""
|
||||||
|
|
||||||
kill_process
|
reset
|
||||||
|
|
||||||
[[ ${VERBOSE} == true ]] && verbose_mode="--verbose"
|
[[ ${VERBOSE} == true ]] && verbose_mode="--verbose"
|
||||||
|
|
||||||
@ -121,8 +128,9 @@ decrypt() {
|
|||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
sign() {
|
sign() {
|
||||||
|
local verbose_mode=""
|
||||||
|
|
||||||
kill_process
|
reset
|
||||||
rm -fr foo*
|
rm -fr foo*
|
||||||
echo CLEAR > foo.txt
|
echo CLEAR > foo.txt
|
||||||
|
|
||||||
@ -137,8 +145,9 @@ sign() {
|
|||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
verify() {
|
verify() {
|
||||||
|
local verbose_mode=""
|
||||||
|
|
||||||
kill_process
|
reset
|
||||||
|
|
||||||
[[ ${VERBOSE} == true ]] && verbose_mode="--verbose"
|
[[ ${VERBOSE} == true ]] && verbose_mode="--verbose"
|
||||||
|
|
||||||
@ -156,12 +165,12 @@ if (($# < 1)); then
|
|||||||
help
|
help
|
||||||
fi
|
fi
|
||||||
|
|
||||||
while getopts ":c:vh" opt; do
|
while getopts ":c:evh" opt; do
|
||||||
case $opt in
|
case $opt in
|
||||||
|
|
||||||
c)
|
c)
|
||||||
case ${OPTARG} in
|
case ${OPTARG} in
|
||||||
init|card|encrypt|decrypt|sign|verify)
|
init|reset|card|encrypt|decrypt|sign|verify)
|
||||||
CMD=${OPTARG}
|
CMD=${OPTARG}
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@ -171,6 +180,7 @@ while getopts ":c:vh" opt; do
|
|||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
e) EXPERT=true ;;
|
||||||
v) VERBOSE=true ;;
|
v) VERBOSE=true ;;
|
||||||
h) help ;;
|
h) help ;;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ from enum import Enum, IntEnum
|
|||||||
KEY_TEMPLATES = {
|
KEY_TEMPLATES = {
|
||||||
"rsa2048" : "010800002001",
|
"rsa2048" : "010800002001",
|
||||||
"rsa3072" : "010C00002001",
|
"rsa3072" : "010C00002001",
|
||||||
"rsa4096" : "011000002001",
|
# "rsa4096" : "011000002001", not supported yet
|
||||||
"nistp256": "132A8648CE3D030107",
|
"nistp256": "132A8648CE3D030107",
|
||||||
"ed25519" : "162B06010401DA470F01",
|
"ed25519" : "162B06010401DA470F01",
|
||||||
"cv25519" : "122B060104019755010501"
|
"cv25519" : "122B060104019755010501"
|
||||||
|
141
src/gpg_data.c
@ -231,6 +231,8 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||||||
void *pkey = NULL;
|
void *pkey = NULL;
|
||||||
cx_aes_key_t aes_key = {0};
|
cx_aes_key_t aes_key = {0};
|
||||||
cx_err_t error = CX_INTERNAL_ERROR;
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
|
unsigned int pkey_size = 0;
|
||||||
|
unsigned int ksz, curve;
|
||||||
|
|
||||||
G_gpg_vstate.DO_current = ref;
|
G_gpg_vstate.DO_current = ref;
|
||||||
|
|
||||||
@ -326,7 +328,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||||||
/* ----------------- Extended Header list -----------------*/
|
/* ----------------- Extended Header list -----------------*/
|
||||||
case 0x3FFF: {
|
case 0x3FFF: {
|
||||||
unsigned int len_e, len_p, len_q;
|
unsigned int len_e, len_p, len_q;
|
||||||
unsigned int endof, ksz, reset_cnt;
|
unsigned int endof, reset_cnt;
|
||||||
gpg_key_t *keygpg = NULL;
|
gpg_key_t *keygpg = NULL;
|
||||||
// fecth 4D
|
// fecth 4D
|
||||||
gpg_io_fetch_tl(&t, &l);
|
gpg_io_fetch_tl(&t, &l);
|
||||||
@ -395,13 +397,11 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- RSA KEY ---
|
|
||||||
if (keygpg->attributes.value[0] == KEY_ID_RSA) {
|
if (keygpg->attributes.value[0] == KEY_ID_RSA) {
|
||||||
unsigned int e = 0;
|
unsigned int e = 0;
|
||||||
unsigned char *p, *q, *pq;
|
unsigned char *p, *q, *pq;
|
||||||
cx_rsa_public_key_t *rsa_pub;
|
cx_rsa_public_key_t *rsa_pub;
|
||||||
cx_rsa_private_key_t *rsa_priv;
|
cx_rsa_private_key_t *rsa_priv;
|
||||||
unsigned int pkey_size = 0;
|
|
||||||
// check length
|
// check length
|
||||||
ksz = U2BE(keygpg->attributes.value, 1) >> 3;
|
ksz = U2BE(keygpg->attributes.value, 1) >> 3;
|
||||||
rsa_pub = (cx_rsa_public_key_t *) &G_gpg_vstate.work.rsa.public;
|
rsa_pub = (cx_rsa_public_key_t *) &G_gpg_vstate.work.rsa.public;
|
||||||
@ -415,10 +415,12 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||||||
pkey_size = sizeof(cx_rsa_3072_private_key_t);
|
pkey_size = sizeof(cx_rsa_3072_private_key_t);
|
||||||
pq = G_gpg_vstate.work.rsa.public3072.n;
|
pq = G_gpg_vstate.work.rsa.public3072.n;
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case 4096 / 8:
|
case 4096 / 8:
|
||||||
pkey_size = sizeof(cx_rsa_4096_private_key_t);
|
pkey_size = sizeof(cx_rsa_4096_private_key_t);
|
||||||
pq = G_gpg_vstate.work.rsa.public4096.n;
|
pq = G_gpg_vstate.work.rsa.public4096.n;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -475,15 +477,11 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||||||
nvm_write(&G_gpg_vstate.kslot->sig_count, &reset_cnt, sizeof(unsigned int));
|
nvm_write(&G_gpg_vstate.kslot->sig_count, &reset_cnt, sizeof(unsigned int));
|
||||||
}
|
}
|
||||||
sw = SW_OK;
|
sw = SW_OK;
|
||||||
}
|
} else if ((keygpg->attributes.value[0] == KEY_ID_ECDH) ||
|
||||||
// --- ECC KEY ---
|
(keygpg->attributes.value[0] == KEY_ID_ECDSA) ||
|
||||||
else if ((keygpg->attributes.value[0] == KEY_ID_ECDH) ||
|
(keygpg->attributes.value[0] == KEY_ID_EDDSA)) {
|
||||||
(keygpg->attributes.value[0] == KEY_ID_ECDSA) ||
|
|
||||||
(keygpg->attributes.value[0] == KEY_ID_EDDSA)) {
|
|
||||||
unsigned int curve;
|
|
||||||
|
|
||||||
curve = gpg_oid2curve(&keygpg->attributes.value[1], keygpg->attributes.length - 1);
|
curve = gpg_oid2curve(&keygpg->attributes.value[1], keygpg->attributes.length - 1);
|
||||||
if (curve == 0) {
|
if (curve == CX_CURVE_NONE) {
|
||||||
sw = SW_WRONG_DATA;
|
sw = SW_WRONG_DATA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -637,9 +635,35 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||||||
sw = SW_WRONG_LENGTH;
|
sw = SW_WRONG_LENGTH;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
switch (G_gpg_vstate.work.io_buffer[0]) {
|
||||||
nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
case KEY_ID_RSA:
|
||||||
sw = SW_OK;
|
ksz = U2BE(G_gpg_vstate.work.io_buffer, 1);
|
||||||
|
if ((ksz != 2048) && (ksz != 3072)) {
|
||||||
|
sw = SW_WRONG_DATA;
|
||||||
|
} else {
|
||||||
|
sw = SW_OK;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_ID_ECDH:
|
||||||
|
case KEY_ID_ECDSA:
|
||||||
|
case KEY_ID_EDDSA:
|
||||||
|
curve =
|
||||||
|
gpg_oid2curve(G_gpg_vstate.work.io_buffer + 1, G_gpg_vstate.io_length - 1);
|
||||||
|
if (curve == CX_CURVE_NONE) {
|
||||||
|
sw = SW_WRONG_DATA;
|
||||||
|
} else {
|
||||||
|
sw = SW_OK;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sw = SW_WRONG_DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sw == SW_OK) {
|
||||||
|
nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
||||||
|
nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* ----------------- PWS status ----------------- */
|
/* ----------------- PWS status ----------------- */
|
||||||
@ -801,11 +825,13 @@ end:
|
|||||||
// cmd
|
// cmd
|
||||||
// resp TID API COMPAT len_pub len_priv priv
|
// resp TID API COMPAT len_pub len_priv priv
|
||||||
int gpg_apdu_get_key_data(unsigned int ref) {
|
int gpg_apdu_get_key_data(unsigned int ref) {
|
||||||
cx_aes_key_t keyenc;
|
cx_aes_key_t keyenc = {0};
|
||||||
gpg_key_t *keygpg;
|
gpg_key_t *keygpg = NULL;
|
||||||
|
cx_rsa_private_key_t *key = NULL;
|
||||||
unsigned int len = 0;
|
unsigned int len = 0;
|
||||||
cx_err_t error = CX_INTERNAL_ERROR;
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
int sw = SW_UNKNOWN;
|
int sw = SW_UNKNOWN;
|
||||||
|
unsigned int ksz = 0;
|
||||||
|
|
||||||
sw = gpg_init_keyenc(&keyenc);
|
sw = gpg_init_keyenc(&keyenc);
|
||||||
if (sw != SW_OK) {
|
if (sw != SW_OK) {
|
||||||
@ -832,18 +858,39 @@ int gpg_apdu_get_key_data(unsigned int ref) {
|
|||||||
|
|
||||||
// encrypted part
|
// encrypted part
|
||||||
switch (keygpg->attributes.value[0]) {
|
switch (keygpg->attributes.value[0]) {
|
||||||
case KEY_ID_RSA: // RSA
|
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
|
// insert pubkey
|
||||||
gpg_io_insert_u32(4);
|
gpg_io_insert_u32(4);
|
||||||
gpg_io_insert(keygpg->pub_key.rsa, 4);
|
gpg_io_insert(keygpg->pub_key.rsa, 4);
|
||||||
|
|
||||||
// insert privkey
|
// insert privkey
|
||||||
gpg_io_mark();
|
gpg_io_mark();
|
||||||
len = GPG_IO_BUFFER_LENGTH - G_gpg_vstate.io_offset;
|
|
||||||
CX_CHECK(cx_aes_no_throw(&keyenc,
|
CX_CHECK(cx_aes_no_throw(&keyenc,
|
||||||
CX_ENCRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST,
|
CX_ENCRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST,
|
||||||
(unsigned char *) &keygpg->priv_key.rsa4096,
|
(unsigned char *) key,
|
||||||
sizeof(cx_rsa_4096_private_key_t),
|
len,
|
||||||
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
||||||
&len));
|
&len));
|
||||||
gpg_io_inserted(len);
|
gpg_io_inserted(len);
|
||||||
@ -853,7 +900,7 @@ int gpg_apdu_get_key_data(unsigned int ref) {
|
|||||||
sw = SW_OK;
|
sw = SW_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEY_ID_ECDH: // ECC
|
case KEY_ID_ECDH:
|
||||||
case KEY_ID_ECDSA:
|
case KEY_ID_ECDSA:
|
||||||
case KEY_ID_EDDSA:
|
case KEY_ID_EDDSA:
|
||||||
// insert pubkey
|
// insert pubkey
|
||||||
@ -889,12 +936,14 @@ end:
|
|||||||
// cmd TID API COMPAT len_pub len_priv priv
|
// cmd TID API COMPAT len_pub len_priv priv
|
||||||
// resp -
|
// resp -
|
||||||
int gpg_apdu_put_key_data(unsigned int ref) {
|
int gpg_apdu_put_key_data(unsigned int ref) {
|
||||||
cx_aes_key_t keyenc;
|
cx_aes_key_t keyenc = {0};
|
||||||
gpg_key_t *keygpg;
|
gpg_key_t *keygpg = NULL;
|
||||||
unsigned int len;
|
unsigned int len = 0;
|
||||||
unsigned int offset;
|
cx_rsa_private_key_t *key = NULL;
|
||||||
|
unsigned int offset = 0;
|
||||||
cx_err_t error = CX_INTERNAL_ERROR;
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
int sw = SW_UNKNOWN;
|
int sw = SW_UNKNOWN;
|
||||||
|
unsigned int ksz = 0;
|
||||||
|
|
||||||
sw = gpg_init_keyenc(&keyenc);
|
sw = gpg_init_keyenc(&keyenc);
|
||||||
if (sw != SW_OK) {
|
if (sw != SW_OK) {
|
||||||
@ -920,7 +969,6 @@ int gpg_apdu_put_key_data(unsigned int ref) {
|
|||||||
gpg_io_fetch_u32();
|
gpg_io_fetch_u32();
|
||||||
|
|
||||||
switch (keygpg->attributes.value[0]) {
|
switch (keygpg->attributes.value[0]) {
|
||||||
// RSA
|
|
||||||
case KEY_ID_RSA:
|
case KEY_ID_RSA:
|
||||||
// insert pubkey
|
// insert pubkey
|
||||||
len = gpg_io_fetch_u32();
|
len = gpg_io_fetch_u32();
|
||||||
@ -937,26 +985,51 @@ int gpg_apdu_put_key_data(unsigned int ref) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
offset = G_gpg_vstate.io_offset;
|
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)) {
|
||||||
|
sw = SW_CONDITIONS_NOT_SATISFIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (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);
|
gpg_io_discard(0);
|
||||||
len = GPG_IO_BUFFER_LENGTH;
|
|
||||||
CX_CHECK(cx_aes_no_throw(&keyenc,
|
CX_CHECK(cx_aes_no_throw(&keyenc,
|
||||||
CX_DECRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST,
|
CX_DECRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST,
|
||||||
G_gpg_vstate.work.io_buffer + offset,
|
G_gpg_vstate.work.io_buffer + offset,
|
||||||
len,
|
len,
|
||||||
G_gpg_vstate.work.io_buffer,
|
G_gpg_vstate.work.io_buffer,
|
||||||
&len));
|
&ksz));
|
||||||
if (len != sizeof(cx_rsa_4096_private_key_t)) {
|
if (len != ksz) {
|
||||||
|
PRINTF("[DATA] - put_key_data: Wrong aes output len: %d / %d\n", len, ksz);
|
||||||
sw = SW_WRONG_DATA;
|
sw = SW_WRONG_DATA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nvm_write((unsigned char *) &keygpg->priv_key.rsa4096,
|
nvm_write((unsigned char *) key, G_gpg_vstate.work.io_buffer, len);
|
||||||
G_gpg_vstate.work.io_buffer,
|
|
||||||
len);
|
|
||||||
sw = SW_OK;
|
sw = SW_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// ECC
|
case KEY_ID_ECDH:
|
||||||
case KEY_ID_ECDH: // ECC
|
|
||||||
case KEY_ID_ECDSA:
|
case KEY_ID_ECDSA:
|
||||||
case KEY_ID_EDDSA:
|
case KEY_ID_EDDSA:
|
||||||
// insert pubkey
|
// insert pubkey
|
||||||
|
@ -93,9 +93,11 @@ static int gpg_gen_rsa_kyey(gpg_key_t *keygpg, uint8_t *name) {
|
|||||||
case 3072 / 8:
|
case 3072 / 8:
|
||||||
pkey_size = sizeof(cx_rsa_3072_private_key_t);
|
pkey_size = sizeof(cx_rsa_3072_private_key_t);
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case 4096 / 8:
|
case 4096 / 8:
|
||||||
pkey_size = sizeof(cx_rsa_4096_private_key_t);
|
pkey_size = sizeof(cx_rsa_4096_private_key_t);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
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);
|
gpg_io_insert_tlv(0x81, ksz, (unsigned char *) &keygpg->priv_key.rsa3072.n);
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case 4096 / 8:
|
case 4096 / 8:
|
||||||
if (keygpg->priv_key.rsa4096.size == 0) {
|
if (keygpg->priv_key.rsa4096.size == 0) {
|
||||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
gpg_io_insert_tlv(0x81, ksz, (unsigned char *) &keygpg->priv_key.rsa4096.n);
|
gpg_io_insert_tlv(0x81, ksz, (unsigned char *) &keygpg->priv_key.rsa4096.n);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
gpg_io_insert_tlv(0x82, 4, keygpg->pub_key.rsa);
|
gpg_io_insert_tlv(0x82, 4, keygpg->pub_key.rsa);
|
||||||
|
|
||||||
@ -224,7 +230,7 @@ static int gpg_read_ecc_kyey(gpg_key_t *keygpg) {
|
|||||||
uint32_t i, len;
|
uint32_t i, len;
|
||||||
cx_err_t error = CX_INTERNAL_ERROR;
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
|
|
||||||
if (keygpg->pub_key.ecfp256.W_len == 0) {
|
if (keygpg->pub_key.ecfp.W_len == 0) {
|
||||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
gpg_io_discard(1);
|
gpg_io_discard(1);
|
||||||
@ -232,23 +238,23 @@ static int gpg_read_ecc_kyey(gpg_key_t *keygpg) {
|
|||||||
curve = gpg_oid2curve(keygpg->attributes.value + 1, keygpg->attributes.length - 1);
|
curve = gpg_oid2curve(keygpg->attributes.value + 1, keygpg->attributes.length - 1);
|
||||||
if (curve == CX_CURVE_Ed25519) {
|
if (curve == CX_CURVE_Ed25519) {
|
||||||
memmove(G_gpg_vstate.work.io_buffer + 128,
|
memmove(G_gpg_vstate.work.io_buffer + 128,
|
||||||
keygpg->pub_key.ecfp256.W,
|
keygpg->pub_key.ecfp.W,
|
||||||
keygpg->pub_key.ecfp256.W_len);
|
keygpg->pub_key.ecfp.W_len);
|
||||||
CX_CHECK(cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519,
|
CX_CHECK(cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519,
|
||||||
G_gpg_vstate.work.io_buffer + 128,
|
G_gpg_vstate.work.io_buffer + 128,
|
||||||
65));
|
65));
|
||||||
gpg_io_insert_tlv(0x86, 32,
|
gpg_io_insert_tlv(0x86, 32,
|
||||||
G_gpg_vstate.work.io_buffer + 129); // 129: discard 02
|
G_gpg_vstate.work.io_buffer + 129); // 129: discard 02
|
||||||
} else if (curve == CX_CURVE_Curve25519) {
|
} else if (curve == CX_CURVE_Curve25519) {
|
||||||
len = keygpg->pub_key.ecfp256.W_len - 1;
|
len = keygpg->pub_key.ecfp.W_len - 1;
|
||||||
for (i = 0; i <= len; i++) {
|
for (i = 0; i <= len; i++) {
|
||||||
G_gpg_vstate.work.io_buffer[128 + i] = keygpg->pub_key.ecfp256.W[len - i];
|
G_gpg_vstate.work.io_buffer[128 + i] = keygpg->pub_key.ecfp.W[len - i];
|
||||||
}
|
}
|
||||||
gpg_io_insert_tlv(0x86, 32, G_gpg_vstate.work.io_buffer + 128);
|
gpg_io_insert_tlv(0x86, 32, G_gpg_vstate.work.io_buffer + 128);
|
||||||
} else {
|
} else {
|
||||||
gpg_io_insert_tlv(0x86,
|
gpg_io_insert_tlv(0x86,
|
||||||
keygpg->pub_key.ecfp256.W_len,
|
keygpg->pub_key.ecfp.W_len,
|
||||||
(unsigned char *) &keygpg->pub_key.ecfp256.W);
|
(unsigned char *) &keygpg->pub_key.ecfp.W);
|
||||||
}
|
}
|
||||||
return SW_OK;
|
return SW_OK;
|
||||||
|
|
||||||
@ -304,7 +310,6 @@ int gpg_apdu_gen() {
|
|||||||
case GEN_ASYM_KEY_SEED:
|
case GEN_ASYM_KEY_SEED:
|
||||||
|
|
||||||
if (keygpg->attributes.value[0] == KEY_ID_RSA) {
|
if (keygpg->attributes.value[0] == KEY_ID_RSA) {
|
||||||
// RSA
|
|
||||||
sw = gpg_gen_rsa_kyey(keygpg, name);
|
sw = gpg_gen_rsa_kyey(keygpg, name);
|
||||||
if (sw != SW_OK) {
|
if (sw != SW_OK) {
|
||||||
break;
|
break;
|
||||||
@ -312,7 +317,6 @@ int gpg_apdu_gen() {
|
|||||||
} else if ((keygpg->attributes.value[0] == KEY_ID_ECDH) ||
|
} else if ((keygpg->attributes.value[0] == KEY_ID_ECDH) ||
|
||||||
(keygpg->attributes.value[0] == KEY_ID_ECDSA) ||
|
(keygpg->attributes.value[0] == KEY_ID_ECDSA) ||
|
||||||
(keygpg->attributes.value[0] == KEY_ID_EDDSA)) {
|
(keygpg->attributes.value[0] == KEY_ID_EDDSA)) {
|
||||||
// ECC
|
|
||||||
sw = gpg_gen_ecc_kyey(keygpg, name);
|
sw = gpg_gen_ecc_kyey(keygpg, name);
|
||||||
if (sw != SW_OK) {
|
if (sw != SW_OK) {
|
||||||
break;
|
break;
|
||||||
@ -323,12 +327,10 @@ int gpg_apdu_gen() {
|
|||||||
// --- read pubkey ---
|
// --- read pubkey ---
|
||||||
case READ_ASYM_KEY:
|
case READ_ASYM_KEY:
|
||||||
if (keygpg->attributes.value[0] == KEY_ID_RSA) {
|
if (keygpg->attributes.value[0] == KEY_ID_RSA) {
|
||||||
// read RSA
|
|
||||||
sw = gpg_read_rsa_kyey(keygpg);
|
sw = gpg_read_rsa_kyey(keygpg);
|
||||||
} else if ((keygpg->attributes.value[0] == KEY_ID_ECDH) ||
|
} else if ((keygpg->attributes.value[0] == KEY_ID_ECDH) ||
|
||||||
(keygpg->attributes.value[0] == KEY_ID_ECDSA) ||
|
(keygpg->attributes.value[0] == KEY_ID_ECDSA) ||
|
||||||
(keygpg->attributes.value[0] == KEY_ID_EDDSA)) {
|
(keygpg->attributes.value[0] == KEY_ID_EDDSA)) {
|
||||||
// read ECC
|
|
||||||
sw = gpg_read_ecc_kyey(keygpg);
|
sw = gpg_read_ecc_kyey(keygpg);
|
||||||
}
|
}
|
||||||
l = G_gpg_vstate.io_length;
|
l = G_gpg_vstate.io_length;
|
||||||
|
@ -56,7 +56,7 @@ const unsigned char C_OID_BRAINPOOL256T1[9] = {
|
|||||||
const unsigned char C_OID_BRAINPOOL256R1[9] = {
|
const unsigned char C_OID_BRAINPOOL256R1[9] = {
|
||||||
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x08
|
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x08
|
||||||
};
|
};
|
||||||
//brainpool 284r1: 1.3.36.3.3.2.8.1.1.11
|
//brainpool 384r1: 1.3.36.3.3.2.8.1.1.11
|
||||||
const unsigned char C_OID_BRAINPOOL384R1[9] = {
|
const unsigned char C_OID_BRAINPOOL384R1[9] = {
|
||||||
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B
|
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B
|
||||||
};
|
};
|
||||||
@ -66,7 +66,7 @@ const unsigned char C_OID_BRAINPOOL512R1[9] = {
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Ed25519/curve25519: 1.3.6.1.4.1.11591.15.1
|
// "twisted" curve25519 for Ed25519: 1.3.6.1.4.1.11591.15.1
|
||||||
const unsigned char C_OID_Ed25519[9] = {
|
const unsigned char C_OID_Ed25519[9] = {
|
||||||
0x2B,
|
0x2B,
|
||||||
0x06,
|
0x06,
|
||||||
@ -79,7 +79,7 @@ const unsigned char C_OID_Ed25519[9] = {
|
|||||||
0x01,
|
0x01,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ed25519/curve25519: 1.3.6.1.4.1.11591.15.1
|
// "Montgomery" curve25519 for X25519: 1.3.6.1.4.1.11591.1.5.1
|
||||||
const unsigned char C_OID_cv25519[10] = {
|
const unsigned char C_OID_cv25519[10] = {
|
||||||
0x2B,
|
0x2B,
|
||||||
0x06,
|
0x06,
|
||||||
|
@ -65,7 +65,6 @@ static void gpg_pso_reset_PW1() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int gpg_sign(gpg_key_t *sigkey) {
|
static int gpg_sign(gpg_key_t *sigkey) {
|
||||||
// --- RSA
|
|
||||||
cx_err_t error = CX_INTERNAL_ERROR;
|
cx_err_t error = CX_INTERNAL_ERROR;
|
||||||
if (sigkey->attributes.value[0] == KEY_ID_RSA) {
|
if (sigkey->attributes.value[0] == KEY_ID_RSA) {
|
||||||
cx_rsa_private_key_t *key = NULL;
|
cx_rsa_private_key_t *key = NULL;
|
||||||
@ -78,9 +77,11 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
|||||||
case 3072 / 8:
|
case 3072 / 8:
|
||||||
key = (cx_rsa_private_key_t *) &sigkey->priv_key.rsa3072;
|
key = (cx_rsa_private_key_t *) &sigkey->priv_key.rsa3072;
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case 4096 / 8:
|
case 4096 / 8:
|
||||||
key = (cx_rsa_private_key_t *) &sigkey->priv_key.rsa4096;
|
key = (cx_rsa_private_key_t *) &sigkey->priv_key.rsa4096;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -113,7 +114,6 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
|||||||
gpg_pso_reset_PW1();
|
gpg_pso_reset_PW1();
|
||||||
return SW_OK;
|
return SW_OK;
|
||||||
}
|
}
|
||||||
// --- ECDSA/EdDSA
|
|
||||||
if ((sigkey->attributes.value[0] == KEY_ID_ECDSA) ||
|
if ((sigkey->attributes.value[0] == KEY_ID_ECDSA) ||
|
||||||
(sigkey->attributes.value[0] == KEY_ID_EDDSA)) {
|
(sigkey->attributes.value[0] == KEY_ID_EDDSA)) {
|
||||||
cx_ecfp_private_key_t *key;
|
cx_ecfp_private_key_t *key;
|
||||||
@ -223,7 +223,7 @@ int gpg_apdu_pso() {
|
|||||||
// --- PSO:ENC ---
|
// --- PSO:ENC ---
|
||||||
case PSO_ENC: {
|
case PSO_ENC: {
|
||||||
unsigned int msg_len;
|
unsigned int msg_len;
|
||||||
cx_aes_key_t *key;
|
cx_aes_key_t *key = NULL;
|
||||||
key = &G_gpg_vstate.kslot->AES_dec;
|
key = &G_gpg_vstate.kslot->AES_dec;
|
||||||
if (!(key->size != 16)) {
|
if (!(key->size != 16)) {
|
||||||
return SW_CONDITIONS_NOT_SATISFIED;
|
return SW_CONDITIONS_NOT_SATISFIED;
|
||||||
@ -252,7 +252,7 @@ int gpg_apdu_pso() {
|
|||||||
switch (pad_byte) {
|
switch (pad_byte) {
|
||||||
// --- PSO:DEC:RSA
|
// --- PSO:DEC:RSA
|
||||||
case 0x00: {
|
case 0x00: {
|
||||||
cx_rsa_private_key_t *key;
|
cx_rsa_private_key_t *key = NULL;
|
||||||
if (G_gpg_vstate.mse_dec->attributes.value[0] != KEY_ID_RSA) {
|
if (G_gpg_vstate.mse_dec->attributes.value[0] != KEY_ID_RSA) {
|
||||||
return SW_CONDITIONS_NOT_SATISFIED;
|
return SW_CONDITIONS_NOT_SATISFIED;
|
||||||
}
|
}
|
||||||
@ -265,9 +265,11 @@ int gpg_apdu_pso() {
|
|||||||
case 3072 / 8:
|
case 3072 / 8:
|
||||||
key = (cx_rsa_private_key_t *) &G_gpg_vstate.mse_dec->priv_key.rsa3072;
|
key = (cx_rsa_private_key_t *) &G_gpg_vstate.mse_dec->priv_key.rsa3072;
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case 4096 / 8:
|
case 4096 / 8:
|
||||||
key = (cx_rsa_private_key_t *) &G_gpg_vstate.mse_dec->priv_key.rsa4096;
|
key = (cx_rsa_private_key_t *) &G_gpg_vstate.mse_dec->priv_key.rsa4096;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((key == NULL) || (key->size != ksz)) {
|
if ((key == NULL) || (key->size != ksz)) {
|
||||||
|
@ -84,8 +84,9 @@ typedef struct gpg_key_s {
|
|||||||
cx_rsa_private_key_t rsa;
|
cx_rsa_private_key_t rsa;
|
||||||
cx_rsa_2048_private_key_t rsa2048;
|
cx_rsa_2048_private_key_t rsa2048;
|
||||||
cx_rsa_3072_private_key_t rsa3072;
|
cx_rsa_3072_private_key_t rsa3072;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
cx_rsa_4096_private_key_t rsa4096;
|
cx_rsa_4096_private_key_t rsa4096;
|
||||||
|
#endif
|
||||||
cx_ecfp_private_key_t ecfp;
|
cx_ecfp_private_key_t ecfp;
|
||||||
cx_ecfp_256_private_key_t ecfp256;
|
cx_ecfp_256_private_key_t ecfp256;
|
||||||
cx_ecfp_384_private_key_t ecfp384;
|
cx_ecfp_384_private_key_t ecfp384;
|
||||||
@ -215,13 +216,17 @@ struct gpg_v_state_s {
|
|||||||
cx_rsa_public_key_t public;
|
cx_rsa_public_key_t public;
|
||||||
cx_rsa_2048_public_key_t public2048;
|
cx_rsa_2048_public_key_t public2048;
|
||||||
cx_rsa_3072_public_key_t public3072;
|
cx_rsa_3072_public_key_t public3072;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
cx_rsa_4096_public_key_t public4096;
|
cx_rsa_4096_public_key_t public4096;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
union {
|
union {
|
||||||
cx_rsa_private_key_t private;
|
cx_rsa_private_key_t private;
|
||||||
cx_rsa_2048_private_key_t private2048;
|
cx_rsa_2048_private_key_t private2048;
|
||||||
cx_rsa_3072_private_key_t private3072;
|
cx_rsa_3072_private_key_t private3072;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
cx_rsa_4096_private_key_t private4096;
|
cx_rsa_4096_private_key_t private4096;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
} rsa;
|
} rsa;
|
||||||
|
|
||||||
|
@ -29,8 +29,7 @@
|
|||||||
#define LABEL_RSA2048 "RSA 2048"
|
#define LABEL_RSA2048 "RSA 2048"
|
||||||
#define LABEL_RSA3072 "RSA 3072"
|
#define LABEL_RSA3072 "RSA 3072"
|
||||||
#define LABEL_RSA4096 "RSA 4096"
|
#define LABEL_RSA4096 "RSA 4096"
|
||||||
#define LABEL_NISTP256 "NIST P256"
|
#define LABEL_SECP256R1 "SECP 256R1"
|
||||||
#define LABEL_SECP256K1 "SECP 256K1"
|
|
||||||
#define LABEL_Ed25519 "Ed25519"
|
#define LABEL_Ed25519 "Ed25519"
|
||||||
|
|
||||||
void ui_CCID_reset(void);
|
void ui_CCID_reset(void);
|
||||||
|
@ -536,8 +536,10 @@ const ux_menu_entry_t ui_menu_tmpl_key[] = {
|
|||||||
const ux_menu_entry_t ui_menu_tmpl_type[] = {
|
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, 2048, NULL, LABEL_RSA2048, NULL, 0, 0},
|
||||||
{NULL, ui_menu_tmpl_type_action, 3072, NULL, LABEL_RSA3072, 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},
|
{NULL, ui_menu_tmpl_type_action, 4096, NULL, LABEL_RSA4096, NULL, 0, 0},
|
||||||
{NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256R1, NULL, LABEL_NISTP256, NULL, 0, 0},
|
#endif
|
||||||
|
{NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256R1, NULL, LABEL_SECP256R1, NULL, 0, 0},
|
||||||
{NULL, ui_menu_tmpl_type_action, CX_CURVE_Ed25519, NULL, LABEL_Ed25519, 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},
|
{ui_menu_template, NULL, 0, &C_icon_back, "Back", NULL, 61, 40},
|
||||||
UX_MENU_END};
|
UX_MENU_END};
|
||||||
@ -570,12 +572,13 @@ const bagl_element_t *ui_menu_template_predisplay(const ux_menu_entry_t *entry,
|
|||||||
case 3072:
|
case 3072:
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_RSA3072);
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_RSA3072);
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case 4096:
|
case 4096:
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_RSA4096);
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_RSA4096);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case CX_CURVE_SECP256R1:
|
case CX_CURVE_SECP256R1:
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_NISTP256);
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_SECP256R1);
|
||||||
break;
|
break;
|
||||||
case CX_CURVE_Ed25519:
|
case CX_CURVE_Ed25519:
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_Ed25519);
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_Ed25519);
|
||||||
@ -605,7 +608,9 @@ void ui_menu_tmpl_set_action(unsigned int value) {
|
|||||||
switch (G_gpg_vstate.ux_type) {
|
switch (G_gpg_vstate.ux_type) {
|
||||||
case 2048:
|
case 2048:
|
||||||
case 3072:
|
case 3072:
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case 4096:
|
case 4096:
|
||||||
|
#endif
|
||||||
attributes.value[0] = KEY_ID_RSA;
|
attributes.value[0] = KEY_ID_RSA;
|
||||||
U2BE_ENCODE(attributes.value, 1, G_gpg_vstate.ux_type);
|
U2BE_ENCODE(attributes.value, 1, G_gpg_vstate.ux_type);
|
||||||
attributes.value[3] = 0x00;
|
attributes.value[3] = 0x00;
|
||||||
@ -621,7 +626,7 @@ void ui_menu_tmpl_set_action(unsigned int value) {
|
|||||||
attributes.value[0] = KEY_ID_ECDSA;
|
attributes.value[0] = KEY_ID_ECDSA;
|
||||||
}
|
}
|
||||||
oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len);
|
oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len);
|
||||||
memmove(attributes.value + 1, oid, sizeof(oid_len));
|
memmove(attributes.value + 1, oid, oid_len);
|
||||||
attributes.length = 1 + oid_len;
|
attributes.length = 1 + oid_len;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -474,13 +474,17 @@ void tmpl_key_selector(unsigned int idx) {
|
|||||||
|
|
||||||
const char *const tmpl_type_getter_values[] = {LABEL_RSA2048,
|
const char *const tmpl_type_getter_values[] = {LABEL_RSA2048,
|
||||||
LABEL_RSA3072,
|
LABEL_RSA3072,
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
LABEL_RSA4096,
|
LABEL_RSA4096,
|
||||||
LABEL_SECP256K1,
|
#endif
|
||||||
|
LABEL_SECP256R1,
|
||||||
LABEL_Ed25519};
|
LABEL_Ed25519};
|
||||||
|
|
||||||
const unsigned int tmpl_type_getter_values_map[] = {2048,
|
const unsigned int tmpl_type_getter_values_map[] = {2048,
|
||||||
3072,
|
3072,
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
4096,
|
4096,
|
||||||
|
#endif
|
||||||
CX_CURVE_SECP256R1,
|
CX_CURVE_SECP256R1,
|
||||||
CX_CURVE_Ed25519};
|
CX_CURVE_Ed25519};
|
||||||
|
|
||||||
@ -567,11 +571,13 @@ void ui_menu_template_predisplay() {
|
|||||||
case 3072:
|
case 3072:
|
||||||
snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_RSA3072);
|
snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_RSA3072);
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case 4096:
|
case 4096:
|
||||||
snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_RSA4096);
|
snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_RSA4096);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case CX_CURVE_SECP256R1:
|
case CX_CURVE_SECP256R1:
|
||||||
snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_SECP256K1);
|
snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_SECP256R1);
|
||||||
break;
|
break;
|
||||||
case CX_CURVE_Ed25519:
|
case CX_CURVE_Ed25519:
|
||||||
snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_Ed25519);
|
snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_Ed25519);
|
||||||
@ -590,14 +596,16 @@ void ui_menu_tmpl_set_action(unsigned int value) {
|
|||||||
UNUSED(value);
|
UNUSED(value);
|
||||||
LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH);
|
LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH);
|
||||||
gpg_key_t *dest = NULL;
|
gpg_key_t *dest = NULL;
|
||||||
const unsigned char *oid;
|
const unsigned char *oid = NULL;
|
||||||
unsigned int oid_len;
|
unsigned int oid_len;
|
||||||
|
|
||||||
memset(&attributes, 0, sizeof(attributes));
|
memset(&attributes, 0, sizeof(attributes));
|
||||||
switch (G_gpg_vstate.ux_type) {
|
switch (G_gpg_vstate.ux_type) {
|
||||||
case 2048:
|
case 2048:
|
||||||
case 3072:
|
case 3072:
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case 4096:
|
case 4096:
|
||||||
|
#endif
|
||||||
attributes.value[0] = KEY_ID_RSA;
|
attributes.value[0] = KEY_ID_RSA;
|
||||||
U2BE_ENCODE(attributes.value, 1, G_gpg_vstate.ux_type);
|
U2BE_ENCODE(attributes.value, 1, G_gpg_vstate.ux_type);
|
||||||
attributes.value[3] = 0x00;
|
attributes.value[3] = 0x00;
|
||||||
@ -607,13 +615,16 @@ void ui_menu_tmpl_set_action(unsigned int value) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CX_CURVE_SECP256R1:
|
case CX_CURVE_SECP256R1:
|
||||||
|
oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len);
|
||||||
|
if (oid == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (G_gpg_vstate.ux_key == 2) {
|
if (G_gpg_vstate.ux_key == 2) {
|
||||||
attributes.value[0] = KEY_ID_ECDH;
|
attributes.value[0] = KEY_ID_ECDH;
|
||||||
} else {
|
} else {
|
||||||
attributes.value[0] = KEY_ID_ECDSA;
|
attributes.value[0] = KEY_ID_ECDSA;
|
||||||
}
|
}
|
||||||
oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len);
|
memmove(attributes.value + 1, oid, oid_len);
|
||||||
memmove(attributes.value + 1, oid, sizeof(oid_len));
|
|
||||||
attributes.length = 1 + oid_len;
|
attributes.length = 1 + oid_len;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -204,16 +204,20 @@ static const char* const keyNameTexts[] = {LABEL_SIG, LABEL_DEC, LABEL_AUT};
|
|||||||
enum {
|
enum {
|
||||||
TOKEN_TYPE_RSA2048 = FIRST_USER_TOKEN,
|
TOKEN_TYPE_RSA2048 = FIRST_USER_TOKEN,
|
||||||
TOKEN_TYPE_RSA3072,
|
TOKEN_TYPE_RSA3072,
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
TOKEN_TYPE_RSA4096,
|
TOKEN_TYPE_RSA4096,
|
||||||
TOKEN_TYPE_SECP256K1,
|
#endif
|
||||||
|
TOKEN_TYPE_SECP256R1,
|
||||||
TOKEN_TYPE_Ed25519,
|
TOKEN_TYPE_Ed25519,
|
||||||
TOKEN_TYPE_BACK
|
TOKEN_TYPE_BACK
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* const keyTypeTexts[] = {LABEL_RSA2048,
|
static const char* const keyTypeTexts[] = {LABEL_RSA2048,
|
||||||
LABEL_RSA3072,
|
LABEL_RSA3072,
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
LABEL_RSA4096,
|
LABEL_RSA4096,
|
||||||
LABEL_SECP256K1,
|
#endif
|
||||||
|
LABEL_SECP256R1,
|
||||||
LABEL_Ed25519};
|
LABEL_Ed25519};
|
||||||
|
|
||||||
static uint32_t _getKeyType(const uint8_t key) {
|
static uint32_t _getKeyType(const uint8_t key) {
|
||||||
@ -237,7 +241,6 @@ static uint32_t _getKeyType(const uint8_t key) {
|
|||||||
}
|
}
|
||||||
switch (attributes[0]) {
|
switch (attributes[0]) {
|
||||||
case KEY_ID_RSA:
|
case KEY_ID_RSA:
|
||||||
// RSA
|
|
||||||
tag = U2BE(attributes, 1);
|
tag = U2BE(attributes, 1);
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case 2048:
|
case 2048:
|
||||||
@ -246,16 +249,18 @@ static uint32_t _getKeyType(const uint8_t key) {
|
|||||||
case 3072:
|
case 3072:
|
||||||
token = TOKEN_TYPE_RSA3072;
|
token = TOKEN_TYPE_RSA3072;
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case 4096:
|
case 4096:
|
||||||
token = TOKEN_TYPE_RSA4096;
|
token = TOKEN_TYPE_RSA4096;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_ID_ECDH:
|
case KEY_ID_ECDH:
|
||||||
tag = attributes[1];
|
tag = attributes[1];
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case 0x2A:
|
case 0x2A:
|
||||||
token = TOKEN_TYPE_SECP256K1;
|
token = TOKEN_TYPE_SECP256R1;
|
||||||
break;
|
break;
|
||||||
case 0x2B:
|
case 0x2B:
|
||||||
token = TOKEN_TYPE_Ed25519;
|
token = TOKEN_TYPE_Ed25519;
|
||||||
@ -263,7 +268,7 @@ static uint32_t _getKeyType(const uint8_t key) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_ID_ECDSA:
|
case KEY_ID_ECDSA:
|
||||||
token = TOKEN_TYPE_SECP256K1;
|
token = TOKEN_TYPE_SECP256R1;
|
||||||
break;
|
break;
|
||||||
case KEY_ID_EDDSA:
|
case KEY_ID_EDDSA:
|
||||||
token = TOKEN_TYPE_Ed25519;
|
token = TOKEN_TYPE_Ed25519;
|
||||||
@ -285,7 +290,9 @@ static void template_key_cb(int token, uint8_t index) {
|
|||||||
switch (key_type) {
|
switch (key_type) {
|
||||||
case TOKEN_TYPE_RSA2048:
|
case TOKEN_TYPE_RSA2048:
|
||||||
case TOKEN_TYPE_RSA3072:
|
case TOKEN_TYPE_RSA3072:
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case TOKEN_TYPE_RSA4096:
|
case TOKEN_TYPE_RSA4096:
|
||||||
|
#endif
|
||||||
switch (key_type) {
|
switch (key_type) {
|
||||||
case TOKEN_TYPE_RSA2048:
|
case TOKEN_TYPE_RSA2048:
|
||||||
size = 2048;
|
size = 2048;
|
||||||
@ -293,9 +300,11 @@ static void template_key_cb(int token, uint8_t index) {
|
|||||||
case TOKEN_TYPE_RSA3072:
|
case TOKEN_TYPE_RSA3072:
|
||||||
size = 3072;
|
size = 3072;
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case TOKEN_TYPE_RSA4096:
|
case TOKEN_TYPE_RSA4096:
|
||||||
size = 4096;
|
size = 4096;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
attributes.value[0] = KEY_ID_RSA;
|
attributes.value[0] = KEY_ID_RSA;
|
||||||
U2BE_ENCODE(attributes.value, 1, size);
|
U2BE_ENCODE(attributes.value, 1, size);
|
||||||
@ -306,7 +315,7 @@ static void template_key_cb(int token, uint8_t index) {
|
|||||||
oid_len = 6;
|
oid_len = 6;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_TYPE_SECP256K1:
|
case TOKEN_TYPE_SECP256R1:
|
||||||
if (G_gpg_vstate.ux_key == TOKEN_TEMPLATE_DEC) {
|
if (G_gpg_vstate.ux_key == TOKEN_TEMPLATE_DEC) {
|
||||||
attributes.value[0] = KEY_ID_ECDH;
|
attributes.value[0] = KEY_ID_ECDH;
|
||||||
} else {
|
} else {
|
||||||
@ -395,11 +404,13 @@ static void ui_settings_template(void) {
|
|||||||
case TOKEN_TYPE_RSA3072:
|
case TOKEN_TYPE_RSA3072:
|
||||||
bar.subText = PIC(LABEL_RSA3072);
|
bar.subText = PIC(LABEL_RSA3072);
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_SUPPORT_RSA4096
|
||||||
case TOKEN_TYPE_RSA4096:
|
case TOKEN_TYPE_RSA4096:
|
||||||
bar.subText = PIC(LABEL_RSA4096);
|
bar.subText = PIC(LABEL_RSA4096);
|
||||||
break;
|
break;
|
||||||
case TOKEN_TYPE_SECP256K1:
|
#endif
|
||||||
bar.subText = PIC(LABEL_SECP256K1);
|
case TOKEN_TYPE_SECP256R1:
|
||||||
|
bar.subText = PIC(LABEL_SECP256R1);
|
||||||
break;
|
break;
|
||||||
case TOKEN_TYPE_Ed25519:
|
case TOKEN_TYPE_Ed25519:
|
||||||
bar.subText = PIC(LABEL_Ed25519);
|
bar.subText = PIC(LABEL_Ed25519);
|
||||||
|
Before Width: | Height: | Size: 400 B After Width: | Height: | Size: 401 B |
Before Width: | Height: | Size: 421 B After Width: | Height: | Size: 417 B |
Before Width: | Height: | Size: 405 B After Width: | Height: | Size: 321 B |
Before Width: | Height: | Size: 426 B After Width: | Height: | Size: 415 B |
Before Width: | Height: | Size: 426 B After Width: | Height: | Size: 415 B |
Before Width: | Height: | Size: 465 B After Width: | Height: | Size: 475 B |
Before Width: | Height: | Size: 588 B After Width: | Height: | Size: 604 B |
Before Width: | Height: | Size: 666 B After Width: | Height: | Size: 601 B |
Before Width: | Height: | Size: 613 B After Width: | Height: | Size: 484 B |
Before Width: | Height: | Size: 418 B After Width: | Height: | Size: 376 B |
Before Width: | Height: | Size: 418 B After Width: | Height: | Size: 376 B |
Before Width: | Height: | Size: 465 B After Width: | Height: | Size: 475 B |
Before Width: | Height: | Size: 588 B After Width: | Height: | Size: 604 B |
Before Width: | Height: | Size: 666 B After Width: | Height: | Size: 601 B |
Before Width: | Height: | Size: 613 B After Width: | Height: | Size: 484 B |
Before Width: | Height: | Size: 418 B After Width: | Height: | Size: 376 B |
Before Width: | Height: | Size: 418 B After Width: | Height: | Size: 376 B |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
@ -44,7 +44,7 @@ def _gen_key(client: CommandSender, template: str):
|
|||||||
[
|
[
|
||||||
"rsa2048",
|
"rsa2048",
|
||||||
pytest.param("rsa3072", marks=pytest.mark.skipif("--full" not in sys.argv, reason="skipping long test")),
|
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
|
"nistp256", # ECDSA
|
||||||
"ed25519", # EdDSA
|
"ed25519", # EdDSA
|
||||||
# "cv25519", # ECDH, SDK returns CX_EC_INVALID_CURVE
|
# "cv25519", # ECDH, SDK returns CX_EC_INVALID_CURVE
|
||||||
|
@ -22,7 +22,7 @@ ROOT_SCREENSHOT_PATH = Path(__file__).parent.resolve()
|
|||||||
KEY_TEMPLATES = {
|
KEY_TEMPLATES = {
|
||||||
"rsa2048" : "010800002001",
|
"rsa2048" : "010800002001",
|
||||||
"rsa3072" : "010C00002001",
|
"rsa3072" : "010C00002001",
|
||||||
"rsa4096" : "011000002001",
|
# "rsa4096" : "011000002001", Not supported yet
|
||||||
"nistp256": "132A8648CE3D030107",
|
"nistp256": "132A8648CE3D030107",
|
||||||
"ed25519" : "162B06010401DA470F01",
|
"ed25519" : "162B06010401DA470F01",
|
||||||
"cv25519" : "122B060104019755010501"
|
"cv25519" : "122B060104019755010501"
|
||||||
|