Adding RSA keypair generation.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2022-04-21 19:20:45 +02:00
parent 55afbd7fd6
commit 54eb4838dd
3 changed files with 175 additions and 12 deletions

View File

@@ -123,18 +123,24 @@ file_t file_entries[] = {
/* 37 */ { .fid = EF_APP_DATA, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_app_data, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 38 */ { .fid = EF_DISCRETE_DO, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_discrete_do, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 39 */ { .fid = EF_PW1, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 40 */ { .fid = EF_RC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 39 */ { .fid = EF_PW1, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 40 */ { .fid = EF_RC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 41 */ { .fid = EF_PW3, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 42 */ { .fid = EF_PW1_RETRIES, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 43 */ { .fid = EF_RC_RETRIES, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 43 */ { .fid = EF_RC_RETRIES, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 44 */ { .fid = EF_PW3_RETRIES, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 45 */ { .fid = EF_ALGO_PRIV1, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 46 */ { .fid = EF_ALGO_PRIV2, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 46 */ { .fid = EF_ALGO_PRIV2, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 47 */ { .fid = EF_ALGO_PRIV3, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 48 */ { .fid = EF_PK_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 49 */ { .fid = EF_PK_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 50 */ { .fid = EF_PK_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 51 */ { .fid = EF_PB_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 52 */ { .fid = EF_PB_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 53 */ { .fid = EF_PB_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 48 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 49 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = ACL_NONE } //end
/* 54 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 55 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = ACL_NONE } //end
};
const file_t *MF = &file_entries[0];

View File

@@ -30,6 +30,12 @@
#define EF_ALGO_PRIV1 0x10c1
#define EF_ALGO_PRIV2 0x10c2
#define EF_ALGO_PRIV3 0x10c3
#define EF_PK_SIG 0x10d1
#define EF_PK_DEC 0x10d2
#define EF_PK_AUT 0x10d3
#define EF_PB_SIG 0x10d4
#define EF_PB_DEC 0x10d5
#define EF_PB_AUT 0x10d6
#define EF_EXT_HEADER 0x004d //C
#define EF_FULL_AID 0x004f //S

View File

@@ -15,14 +15,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "openpgp.h"
#include "version.h"
#include "files.h"
#include "random.h"
#include "eac.h"
#include "crypto_utils.h"
#include "mbedtls/rsa.h"
#include "mbedtls/ecdsa.h"
bool has_pw1 = false;
bool has_pw3 = false;
uint8_t session_pw3[32];
uint8_t openpgp_aid[] = {
6,
@@ -374,9 +379,13 @@ int parse_pw_status(const file_t *f, int mode) {
return res_APDU_size-init_len;
}
#define ALGO_RSA 0x01
#define ALGO_ECDH 0x12
#define ALGO_ECDSA 0x13
#define ALGO_RSA 0x01
#define ALGO_ECDH 0x12
#define ALGO_ECDSA 0x13
#define ALGO_AES 0x70
#define ALGO_AES_128 0x71
#define ALGO_AES_192 0x72
#define ALGO_AES_256 0x74
static const uint8_t algorithm_attr_x448[] = {
4,
@@ -628,11 +637,12 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
if (r != CCID_OK)
return SW_MEMORY_FAILURE();
isUserAuthenticated = true;
//hash_multi(data, len, session_pin);
if (pin->fid == EF_PW1)
has_pw1 = true;
else if (pin->fid == EF_PW3)
else if (pin->fid == EF_PW3) {
has_pw3 = true;
hash_multi(data, len, session_pw3);
}
return SW_OK();
}
@@ -736,9 +746,150 @@ static int cmd_reset_retry() {
return SW_INCORRECT_P1P2();
}
int store_keys(void *key_ctx, int type, uint16_t key_id) {
int r, key_size;
uint8_t kdata[4096/8]; //worst
if (!has_pw3)
return CCID_NO_LOGIN;
file_t *pw3 = search_by_fid(EF_PW3, NULL, SPECIFY_EF);
if (!pw3)
return CCID_ERR_FILE_NOT_FOUND;
file_t *ef = search_by_fid(key_id, NULL, SPECIFY_EF);
if (!ef)
return CCID_ERR_FILE_NOT_FOUND;
if (type == ALGO_RSA) {
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx;
key_size = mbedtls_mpi_size(&rsa->P)+mbedtls_mpi_size(&rsa->Q);
mbedtls_mpi_write_binary(&rsa->P, kdata, key_size/2);
mbedtls_mpi_write_binary(&rsa->Q, kdata+key_size/2, key_size/2);
}
else if (type == ALGO_ECDSA || type == ALGO_ECDH) {
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx;
key_size = mbedtls_mpi_size(&ecdsa->d);
kdata[0] = ecdsa->grp.id & 0xff;
mbedtls_mpi_write_binary(&ecdsa->d, kdata+1, key_size);
key_size++;
}
else if (type & ALGO_AES) {
if (type == ALGO_AES_128)
key_size = 16;
else if (type == ALGO_AES_192)
key_size = 24;
else if (type == ALGO_AES_256)
key_size = 32;
memcpy(kdata, key_ctx, key_size);
}
r = aes_decrypt_cfb_256(file_read(pw3->data+2), session_pw3, kdata, key_size);
if (r != CCID_OK)
return r;
r = flash_write_data_to_file(ef, kdata, key_size);
if (r != CCID_OK)
return r;
low_flash_available();
return CCID_OK;
}
mbedtls_ecp_group_id get_ec_group_id_from_attr(const uint8_t *algo, size_t algo_len) {
if (memcmp(algorithm_attr_p256k1, algo, algo_len) == 0)
return MBEDTLS_ECP_DP_SECP256K1;
else if (memcmp(algorithm_attr_p256r1, algo, algo_len) == 0)
return MBEDTLS_ECP_DP_SECP256R1;
else if (memcmp(algorithm_attr_p384r1, algo, algo_len) == 0)
return MBEDTLS_ECP_DP_SECP384R1;
else if (memcmp(algorithm_attr_p521r1, algo, algo_len) == 0)
return MBEDTLS_ECP_DP_SECP521R1;
else if (memcmp(algorithm_attr_bp256r1, algo, algo_len) == 0)
return MBEDTLS_ECP_DP_BP256R1;
else if (memcmp(algorithm_attr_bp384r1, algo, algo_len) == 0)
return MBEDTLS_ECP_DP_BP384R1;
else if (memcmp(algorithm_attr_bp512r1, algo, algo_len) == 0)
return MBEDTLS_ECP_DP_BP512R1;
else if (memcmp(algorithm_attr_cv25519, algo, algo_len) == 0)
return MBEDTLS_ECP_DP_CURVE25519;
else if (memcmp(algorithm_attr_x448, algo, algo_len) == 0)
return MBEDTLS_ECP_DP_CURVE448;
return MBEDTLS_ECP_DP_NONE;
}
static int cmd_keypair_gen() {
if (P2(apdu) != 0x0)
return SW_INCORRECT_P1P2();
if (apdu.cmd_apdu_data_len != 2 && apdu.cmd_apdu_data_len != 5)
return SW_WRONG_LENGTH();
uint16_t fid = 0x0;
int r = CCID_OK;
if (apdu.cmd_apdu_data[0] == 0xB6)
fid = EF_PK_SIG;
else if (apdu.cmd_apdu_data[0] == 0xB8)
fid = EF_PK_DEC;
else if (apdu.cmd_apdu_data[0] == 0xA4)
fid = EF_PK_AUT;
else
return SW_WRONG_DATA();
if (P1(apdu) == 0x80) { //generate
file_t *algo_ef = search_by_fid(fid-0x0010, NULL, SPECIFY_EF);
const uint8_t *algo = algorithm_attr_rsa2k+1;
uint16_t algo_len = algorithm_attr_rsa2k[0];
if (algo_ef && algo_ef->data) {
algo_len = file_read_uint16(algo_ef->data);
algo = file_read(algo_ef->data+2);
}
if (algo[0] == ALGO_RSA) {
int exponent = 65537, nlen = (algo[1] << 8) | algo[2];
printf("KEYPAIR RSA %d\r\n",nlen);
//if (nlen != 2048 && nlen != 4096)
// return SW_FUNC_NOT_SUPPORTED();
mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa);
uint8_t index = 0;
r = mbedtls_rsa_gen_key(&rsa, random_gen, &index, nlen, exponent);
printf("r %d\r\n",r);
if (r != 0) {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = store_keys(&rsa, ALGO_RSA, fid);
printf("r %d\r\n",r);
memcpy(res_APDU, "\x7f\x49\x82\x00\x00", 5);
uint8_t *lp = res_APDU+3;
res_APDU_size = 5;
res_APDU[res_APDU_size++] = 0x81;
res_APDU[res_APDU_size++] = 0x82;
put_uint16_t(mbedtls_mpi_size(&rsa.N), res_APDU+res_APDU_size); res_APDU_size += 2;
mbedtls_mpi_write_binary(&rsa.N, res_APDU+res_APDU_size, mbedtls_mpi_size(&rsa.N)); res_APDU_size += mbedtls_mpi_size(&rsa.N);
res_APDU[res_APDU_size++] = 0x82;
res_APDU[res_APDU_size++] = mbedtls_mpi_size(&rsa.E) & 0xff;
mbedtls_mpi_write_binary(&rsa.E, res_APDU+res_APDU_size, mbedtls_mpi_size(&rsa.E)); res_APDU_size += mbedtls_mpi_size(&rsa.E);
put_uint16_t(res_APDU_size-5, res_APDU+3);
mbedtls_rsa_free(&rsa);
if (r != CCID_OK)
return SW_EXEC_ERROR();
}
else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA) {
printf("KEYPAIR ECDSA\r\n");
mbedtls_ecp_group_id gid = get_ec_group_id_from_attr(algo, algo_len);
if (gid == MBEDTLS_ECP_DP_NONE)
return SW_FUNC_NOT_SUPPORTED();
if ((gid == MBEDTLS_ECP_DP_CURVE25519 || gid == MBEDTLS_ECP_DP_CURVE448) && (fid == EF_PK_SIG || fid == EF_PK_AUT))
return SW_FUNC_NOT_SUPPORTED();
mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init(&ecdsa);
uint8_t index = 0;
r = mbedtls_ecdsa_genkey(&ecdsa, gid, random_gen, &index);
if (r != 0) {
mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR();
}
r = store_keys(&ecdsa, algo[0], fid);
mbedtls_ecdsa_free(&ecdsa);
if (r != CCID_OK)
return SW_EXEC_ERROR();
}
else
return SW_FUNC_NOT_SUPPORTED();
return SW_OK();
}
else if (P1(apdu) == 0x81) { //read