Skip to content

Commit 85b6c90

Browse files
committed
Added support for key import.
Signed-off-by: Pol Henarejos <[email protected]>
1 parent 9fe59a5 commit 85b6c90

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

src/openpgp/piv.c

+93
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#define PIV_ALGO_AES256 0x0c
3939
#define PIV_ALGO_RSA1024 0x06
4040
#define PIV_ALGO_RSA2048 0x07
41+
#define PIV_ALGO_RSA3072 0x05
42+
#define PIV_ALGO_RSA4096 0x16
4143
#define PIV_ALGO_ECCP256 0x11
4244
#define PIV_ALGO_ECCP384 0x14
4345
#define PIV_ALGO_X25519 0xE1
@@ -1111,6 +1113,95 @@ static int cmd_attestation() {
11111113
return SW_OK();
11121114
}
11131115

1116+
static int cmd_import_asym() {
1117+
uint8_t algo = P1(apdu), key_ref = P2(apdu);
1118+
if (key_ref != EF_PIV_KEY_AUTHENTICATION && key_ref != EF_PIV_KEY_SIGNATURE && key_ref != EF_PIV_KEY_KEYMGM && key_ref != EF_PIV_KEY_CARDAUTH && !(key_ref >= EF_PIV_KEY_RETIRED1 && key_ref <= EF_PIV_KEY_RETIRED20)) {
1119+
return SW_INCORRECT_P1P2();
1120+
}
1121+
asn1_ctx_t ctxi, aaa = {0}, aab = {0};
1122+
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
1123+
asn1_find_tag(&ctxi, 0xAA, &aaa);
1124+
asn1_find_tag(&ctxi, 0xAB, &aab);
1125+
if (algo == PIV_ALGO_RSA1024 || algo == PIV_ALGO_RSA2048 || algo == PIV_ALGO_RSA3072 || algo == PIV_ALGO_RSA4096) {
1126+
asn1_ctx_t a1 = { 0 }, a2 = { 0 };
1127+
asn1_find_tag(&ctxi, 0x01, &a1);
1128+
asn1_find_tag(&ctxi, 0x02, &a2);
1129+
if (asn1_len(&a1) <= 0 || asn1_len(&a2) <= 0) {
1130+
return SW_WRONG_DATA();
1131+
}
1132+
mbedtls_rsa_context rsa;
1133+
mbedtls_rsa_init(&rsa);
1134+
int r = mbedtls_mpi_read_binary(&rsa.P, a1.data, a1.len);
1135+
if (r != 0) {
1136+
mbedtls_rsa_free(&rsa);
1137+
return SW_WRONG_DATA();
1138+
}
1139+
r = mbedtls_mpi_read_binary(&rsa.Q, a2.data, a2.len);
1140+
if (r != 0) {
1141+
mbedtls_rsa_free(&rsa);
1142+
return SW_WRONG_DATA();
1143+
}
1144+
int exponent = 65537;
1145+
mbedtls_mpi_lset(&rsa.E, exponent);
1146+
r = mbedtls_rsa_import(&rsa, NULL, &rsa.P, &rsa.Q, NULL, &rsa.E);
1147+
if (r != 0) {
1148+
mbedtls_rsa_free(&rsa);
1149+
return SW_EXEC_ERROR();
1150+
}
1151+
r = mbedtls_rsa_complete(&rsa);
1152+
if (r != 0) {
1153+
mbedtls_rsa_free(&rsa);
1154+
return SW_EXEC_ERROR();
1155+
}
1156+
r = mbedtls_rsa_check_privkey(&rsa);
1157+
if (r != 0) {
1158+
mbedtls_rsa_free(&rsa);
1159+
return SW_EXEC_ERROR();
1160+
}
1161+
r = store_keys(&rsa, ALGO_RSA, key_ref, false);
1162+
mbedtls_rsa_free(&rsa);
1163+
if (r != 0) {
1164+
return SW_EXEC_ERROR();
1165+
}
1166+
}
1167+
else if (algo == PIV_ALGO_ECCP256 || algo == PIV_ALGO_ECCP384) {
1168+
asn1_ctx_t a6 = {0};
1169+
asn1_find_tag(&ctxi, 0x06, &a6);
1170+
if (asn1_len(&a6) <= 0) {
1171+
return SW_WRONG_DATA();
1172+
}
1173+
mbedtls_ecp_group_id gid = algo == PIV_ALGO_ECCP256 ? MBEDTLS_ECP_DP_SECP256R1 : MBEDTLS_ECP_DP_SECP384R1;
1174+
mbedtls_ecdsa_context ecdsa;
1175+
mbedtls_ecdsa_init(&ecdsa);
1176+
int r = mbedtls_ecp_read_key(gid, &ecdsa, a6.data, a6.len);
1177+
if (r != 0) {
1178+
mbedtls_ecdsa_free(&ecdsa);
1179+
return SW_EXEC_ERROR();
1180+
}
1181+
r = mbedtls_ecp_mul(&ecdsa.grp, &ecdsa.Q, &ecdsa.d, &ecdsa.grp.G, random_gen, NULL);
1182+
if (r != 0) {
1183+
mbedtls_ecdsa_free(&ecdsa);
1184+
return SW_EXEC_ERROR();
1185+
}
1186+
r = mbedtls_ecp_check_pub_priv(&ecdsa, &ecdsa, random_gen, NULL);
1187+
if (r != 0) {
1188+
mbedtls_ecdsa_free(&ecdsa);
1189+
return SW_EXEC_ERROR();
1190+
}
1191+
r = store_keys(&ecdsa, ALGO_ECDSA, key_ref, false);
1192+
mbedtls_ecdsa_free(&ecdsa);
1193+
if (r != 0) {
1194+
return SW_EXEC_ERROR();
1195+
}
1196+
}
1197+
else {
1198+
return SW_WRONG_DATA();
1199+
}
1200+
uint8_t meta[] = { algo, asn1_len(&aaa) ? aaa.data[0] : PINPOLICY_ALWAYS, asn1_len(&aab) ? aab.data[0] : TOUCHPOLICY_ALWAYS, ORIGIN_IMPORTED };
1201+
meta_add(key_ref, meta, sizeof(meta));
1202+
return SW_OK();
1203+
}
1204+
11141205
#define INS_VERIFY 0x20
11151206
#define INS_VERSION 0xFD
11161207
#define INS_SELECT 0xA4
@@ -1128,6 +1219,7 @@ static int cmd_attestation() {
11281219
#define INS_SET_RETRIES 0xFA
11291220
#define INS_RESET 0xFB
11301221
#define INS_ATTESTATION 0xF9
1222+
#define INS_IMPORT_ASYM 0xFE
11311223

11321224
static const cmd_t cmds[] = {
11331225
{ INS_VERSION, cmd_version },
@@ -1146,6 +1238,7 @@ static const cmd_t cmds[] = {
11461238
{ INS_SET_RETRIES, cmd_set_retries },
11471239
{ INS_RESET, cmd_reset },
11481240
{ INS_ATTESTATION, cmd_attestation },
1241+
{ INS_IMPORT_ASYM, cmd_import_asym },
11491242
{ 0x00, 0x0 }
11501243
};
11511244

0 commit comments

Comments
 (0)