Extending DKEK and key storage to key domains.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
135
src/hsm/dkek.c
135
src/hsm/dkek.c
@@ -29,114 +29,121 @@
|
|||||||
#include "mbedtls/ecdsa.h"
|
#include "mbedtls/ecdsa.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
|
||||||
static uint8_t dkek[IV_SIZE+32];
|
|
||||||
static uint8_t tmp_dkek[32];
|
|
||||||
extern bool has_session_pin;
|
extern bool has_session_pin;
|
||||||
extern uint8_t session_pin[32];
|
extern uint8_t session_pin[32];
|
||||||
|
|
||||||
int load_dkek() {
|
int load_dkek(uint8_t id, uint8_t *dkek) {
|
||||||
if (has_session_pin == false)
|
if (has_session_pin == false)
|
||||||
return CCID_NO_LOGIN;
|
return CCID_NO_LOGIN;
|
||||||
file_t *tf = search_dynamic_file(EF_DKEK);
|
file_t *tf = search_dynamic_file(EF_DKEK+id);
|
||||||
if (!tf)
|
if (!tf)
|
||||||
return CCID_ERR_FILE_NOT_FOUND;
|
return CCID_ERR_FILE_NOT_FOUND;
|
||||||
memcpy(dkek, file_read(tf->data+sizeof(uint16_t)), IV_SIZE+32);
|
memcpy(dkek, file_read(tf->data+sizeof(uint16_t)), DKEK_SIZE);
|
||||||
int ret = aes_decrypt_cfb_256(session_pin, dkek, dkek+IV_SIZE, 32);
|
int ret = aes_decrypt_cfb_256(session_pin, DKEK_IV(dkek), DKEK_KEY(dkek), DKEK_KEY_SIZE);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return CCID_EXEC_ERROR;
|
return CCID_EXEC_ERROR;
|
||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void release_dkek() {
|
void release_dkek(uint8_t *dkek) {
|
||||||
memset(dkek, 0, sizeof(dkek));
|
memset(dkek, 0, DKEK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_dkek() {
|
int store_dkek_key(uint8_t id, uint8_t *dkek) {
|
||||||
release_dkek();
|
file_t *tf = search_dynamic_file(EF_DKEK+id);
|
||||||
memset(tmp_dkek, 0, sizeof(tmp_dkek));
|
|
||||||
}
|
|
||||||
|
|
||||||
int store_dkek_key() {
|
|
||||||
aes_encrypt_cfb_256(session_pin, dkek, dkek+IV_SIZE, 32);
|
|
||||||
file_t *tf = search_dynamic_file(EF_DKEK);
|
|
||||||
if (!tf)
|
if (!tf)
|
||||||
return CCID_ERR_FILE_NOT_FOUND;
|
return CCID_ERR_FILE_NOT_FOUND;
|
||||||
flash_write_data_to_file(tf, dkek, sizeof(dkek));
|
aes_encrypt_cfb_256(session_pin, DKEK_IV(dkek), DKEK_KEY(dkek), DKEK_KEY_SIZE);
|
||||||
|
flash_write_data_to_file(tf, dkek, DKEK_SIZE);
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
release_dkek();
|
release_dkek(dkek);
|
||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int save_dkek_key(const uint8_t *key) {
|
int save_dkek_key(uint8_t id, const uint8_t *key) {
|
||||||
|
uint8_t dkek[DKEK_SIZE];
|
||||||
const uint8_t *iv = random_bytes_get(32);
|
const uint8_t *iv = random_bytes_get(32);
|
||||||
memcpy(dkek, iv, IV_SIZE);
|
memcpy(dkek, iv, DKEK_IV_SIZE);
|
||||||
if (!key)
|
if (!key) {
|
||||||
key = tmp_dkek;
|
file_t *tf = search_dynamic_file(EF_DKEK+id);
|
||||||
memcpy(dkek+IV_SIZE, key, 32);
|
if (!tf)
|
||||||
return store_dkek_key();
|
return CCID_ERR_FILE_NOT_FOUND;
|
||||||
|
memcpy(DKEK_KEY(dkek), file_read(tf->data+sizeof(uint16_t)), DKEK_KEY_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memcpy(DKEK_KEY(dkek), key, DKEK_KEY_SIZE);
|
||||||
|
return store_dkek_key(id, dkek);
|
||||||
}
|
}
|
||||||
|
|
||||||
void import_dkek_share(const uint8_t *share) {
|
int import_dkek_share(uint8_t id, const uint8_t *share) {
|
||||||
for (int i = 0; i < 32; i++)
|
uint8_t tmp_dkek[DKEK_KEY_SIZE];
|
||||||
|
file_t *tf = search_dynamic_file(EF_DKEK+id);
|
||||||
|
if (!tf)
|
||||||
|
return CCID_ERR_FILE_NOT_FOUND;
|
||||||
|
memset(tmp_dkek, 0, sizeof(tmp_dkek));
|
||||||
|
if (tf->data && file_read_uint16(tf->data) == DKEK_KEY_SIZE)
|
||||||
|
memcpy(tmp_dkek, file_read(tf->data+sizeof(uint16_t)),DKEK_KEY_SIZE);
|
||||||
|
for (int i = 0; i < DKEK_KEY_SIZE; i++)
|
||||||
tmp_dkek[i] ^= share[i];
|
tmp_dkek[i] ^= share[i];
|
||||||
|
flash_write_data_to_file(tf, tmp_dkek, DKEK_KEY_SIZE);
|
||||||
|
low_flash_available();
|
||||||
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dkek_kcv(uint8_t *kcv) { //kcv 8 bytes
|
int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes
|
||||||
uint8_t hsh[32];
|
uint8_t hsh[32], dkek[DKEK_SIZE];
|
||||||
int r = load_dkek();
|
int r = load_dkek(id, dkek);
|
||||||
if (r != CCID_OK)
|
if (r != CCID_OK)
|
||||||
return r;
|
return r;
|
||||||
hash256(dkek+IV_SIZE, 32, hsh);
|
hash256(DKEK_KEY(dkek), DKEK_KEY_SIZE, hsh);
|
||||||
release_dkek();
|
release_dkek(dkek);
|
||||||
memcpy(kcv, hsh, 8);
|
memcpy(kcv, hsh, 8);
|
||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dkek_kenc(uint8_t *kenc) { //kenc 32 bytes
|
int dkek_kenc(uint8_t id, uint8_t *kenc) { //kenc 32 bytes
|
||||||
uint8_t buf[32+4];
|
uint8_t dkek[DKEK_SIZE+4];
|
||||||
int r = load_dkek();
|
int r = load_dkek(id, dkek);
|
||||||
if (r != CCID_OK)
|
if (r != CCID_OK)
|
||||||
return r;
|
return r;
|
||||||
memcpy(buf, dkek+IV_SIZE, 32);
|
memcpy(DKEK_KEY(dkek)+DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4);
|
||||||
release_dkek();
|
hash256(DKEK_KEY(dkek), DKEK_KEY_SIZE+4, kenc);
|
||||||
memcpy(buf+32, "\x0\x0\x0\x1", 4);
|
release_dkek(dkek);
|
||||||
hash256(buf, sizeof(buf), kenc);
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dkek_kmac(uint8_t *kmac) { //kmac 32 bytes
|
int dkek_kmac(uint8_t id, uint8_t *kmac) { //kmac 32 bytes
|
||||||
uint8_t buf[32+4];
|
uint8_t dkek[DKEK_SIZE+4];
|
||||||
int r = load_dkek();
|
int r = load_dkek(id, dkek);
|
||||||
if (r != CCID_OK)
|
if (r != CCID_OK)
|
||||||
return r;
|
return r;
|
||||||
memcpy(buf, dkek+IV_SIZE, 32);
|
memcpy(DKEK_KEY(dkek)+DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4);
|
||||||
release_dkek();
|
hash256(DKEK_KEY(dkek), DKEK_KEY_SIZE+4, kmac);
|
||||||
memcpy(buf+32, "\x0\x0\x0\x2", 4);
|
release_dkek(dkek);
|
||||||
hash256(buf, sizeof(buf), kmac);
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dkek_encrypt(uint8_t *data, size_t len) {
|
int dkek_encrypt(uint8_t id, uint8_t *data, size_t len) {
|
||||||
int r;
|
int r;
|
||||||
if ((r = load_dkek()) != CCID_OK)
|
uint8_t dkek[DKEK_SIZE+4];
|
||||||
|
if ((r = load_dkek(id, dkek)) != CCID_OK)
|
||||||
return r;
|
return r;
|
||||||
r = aes_encrypt_cfb_256(dkek+IV_SIZE, dkek, data, len);
|
r = aes_encrypt_cfb_256(DKEK_KEY(dkek), DKEK_IV(dkek), data, len);
|
||||||
release_dkek();
|
release_dkek(dkek);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dkek_decrypt(uint8_t *data, size_t len) {
|
int dkek_decrypt(uint8_t id, uint8_t *data, size_t len) {
|
||||||
int r;
|
int r;
|
||||||
if ((r = load_dkek()) != CCID_OK)
|
uint8_t dkek[DKEK_SIZE+4];
|
||||||
|
if ((r = load_dkek(id, dkek)) != CCID_OK)
|
||||||
return r;
|
return r;
|
||||||
r = aes_decrypt_cfb_256(dkek+IV_SIZE, dkek, data, len);
|
r = aes_decrypt_cfb_256(DKEK_KEY(dkek), DKEK_IV(dkek), data, len);
|
||||||
release_dkek();
|
release_dkek(dkek);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) {
|
int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, size_t *out_len) {
|
||||||
if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES))
|
if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES))
|
||||||
return CCID_WRONG_DATA;
|
return CCID_WRONG_DATA;
|
||||||
|
|
||||||
@@ -149,15 +156,15 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len)
|
|||||||
uint8_t allowed_len = 0;
|
uint8_t allowed_len = 0;
|
||||||
uint8_t kenc[32];
|
uint8_t kenc[32];
|
||||||
memset(kenc, 0, sizeof(kenc));
|
memset(kenc, 0, sizeof(kenc));
|
||||||
dkek_kenc(kenc);
|
dkek_kenc(id, kenc);
|
||||||
|
|
||||||
uint8_t kcv[8];
|
uint8_t kcv[8];
|
||||||
memset(kcv, 0, sizeof(kcv));
|
memset(kcv, 0, sizeof(kcv));
|
||||||
dkek_kcv(kcv);
|
dkek_kcv(id, kcv);
|
||||||
|
|
||||||
uint8_t kmac[32];
|
uint8_t kmac[32];
|
||||||
memset(kmac, 0, sizeof(kmac));
|
memset(kmac, 0, sizeof(kmac));
|
||||||
dkek_kmac(kmac);
|
dkek_kmac(id, kmac);
|
||||||
|
|
||||||
if (key_type & HSM_KEY_AES) {
|
if (key_type & HSM_KEY_AES) {
|
||||||
if (key_type & HSM_KEY_AES_128)
|
if (key_type & HSM_KEY_AES_128)
|
||||||
@@ -290,18 +297,18 @@ int dkek_type_key(const uint8_t *in) {
|
|||||||
return 0x0;
|
return 0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out) {
|
int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out) {
|
||||||
uint8_t kcv[8];
|
uint8_t kcv[8];
|
||||||
memset(kcv, 0, sizeof(kcv));
|
memset(kcv, 0, sizeof(kcv));
|
||||||
dkek_kcv(kcv);
|
dkek_kcv(id, kcv);
|
||||||
|
|
||||||
uint8_t kmac[32];
|
uint8_t kmac[32];
|
||||||
memset(kmac, 0, sizeof(kmac));
|
memset(kmac, 0, sizeof(kmac));
|
||||||
dkek_kmac(kmac);
|
dkek_kmac(id, kmac);
|
||||||
|
|
||||||
uint8_t kenc[32];
|
uint8_t kenc[32];
|
||||||
memset(kenc, 0, sizeof(kenc));
|
memset(kenc, 0, sizeof(kenc));
|
||||||
dkek_kenc(kenc);
|
dkek_kenc(id, kenc);
|
||||||
|
|
||||||
if (memcmp(kcv, in, 8) != 0)
|
if (memcmp(kcv, in, 8) != 0)
|
||||||
return CCID_WRONG_DKEK;
|
return CCID_WRONG_DKEK;
|
||||||
@@ -472,4 +479,4 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si
|
|||||||
memcpy(key_ctx, kb+ofs, key_size);
|
memcpy(key_ctx, kb+ofs, key_size);
|
||||||
}
|
}
|
||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,19 +18,27 @@
|
|||||||
#ifndef _DKEK_H_
|
#ifndef _DKEK_H_
|
||||||
#define _DKEK_H_
|
#define _DKEK_H_
|
||||||
|
|
||||||
extern int load_dkek();
|
extern int load_dkek(uint8_t, uint8_t *);
|
||||||
extern int save_dkek_key(const uint8_t *key);
|
extern int save_dkek_key(uint8_t, const uint8_t *key);
|
||||||
extern int store_dkek_key();
|
extern int store_dkek_key(uint8_t, uint8_t *);
|
||||||
extern void init_dkek();
|
extern void init_dkek();
|
||||||
extern void release_dkek();
|
extern void release_dkek(uint8_t *);
|
||||||
extern void import_dkek_share(const uint8_t *share);
|
extern int import_dkek_share(uint8_t, const uint8_t *share);
|
||||||
extern int dkek_kcv(uint8_t *kcv);
|
extern int dkek_kcv(uint8_t, uint8_t *kcv);
|
||||||
extern int dkek_encrypt(uint8_t *data, size_t len);
|
extern int dkek_encrypt(uint8_t, uint8_t *data, size_t len);
|
||||||
extern int dkek_decrypt(uint8_t *data, size_t len);
|
extern int dkek_decrypt(uint8_t, uint8_t *data, size_t len);
|
||||||
extern int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len);
|
extern int dkek_encode_key(uint8_t, void *key_ctx, int key_type, uint8_t *out, size_t *out_len);
|
||||||
extern int dkek_type_key(const uint8_t *in);
|
extern int dkek_type_key(const uint8_t *in);
|
||||||
extern int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out);
|
extern int dkek_decode_key(uint8_t, void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out);
|
||||||
|
|
||||||
#define MAX_DKEK_ENCODE_KEY_BUFFER (8+1+12+6+(8+2*4+2*4096/8+3+13)+16)
|
#define MAX_DKEK_ENCODE_KEY_BUFFER (8+1+12+6+(8+2*4+2*4096/8+3+13)+16)
|
||||||
|
|
||||||
|
#define MAX_KEY_DOMAINS 16
|
||||||
|
|
||||||
|
#define DKEK_IV_SIZE (IV_SIZE)
|
||||||
|
#define DKEK_KEY_SIZE (32)
|
||||||
|
#define DKEK_SIZE (DKEK_IV_SIZE+DKEK_KEY_SIZE)
|
||||||
|
#define DKEK_KEY(p) (p+DKEK_IV_SIZE)
|
||||||
|
#define DKEK_IV(p) (p)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -682,7 +682,7 @@ static int cmd_initialize() {
|
|||||||
initialize_flash(true);
|
initialize_flash(true);
|
||||||
scan_all();
|
scan_all();
|
||||||
dkeks = current_dkeks = 0;
|
dkeks = current_dkeks = 0;
|
||||||
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL;
|
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL, kds = 1;
|
||||||
size_t tag_len = 0;
|
size_t tag_len = 0;
|
||||||
while (walk_tlv(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, &p, &tag, &tag_len, &tag_data)) {
|
while (walk_tlv(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, &p, &tag, &tag_len, &tag_data)) {
|
||||||
if (tag == 0x80) { //options
|
if (tag == 0x80) { //options
|
||||||
@@ -723,10 +723,12 @@ static int cmd_initialize() {
|
|||||||
file_t *tf = file_new(EF_DKEK);
|
file_t *tf = file_new(EF_DKEK);
|
||||||
if (!tf)
|
if (!tf)
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
|
flash_write_data_to_file(tf, NULL, 0);
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
}
|
}
|
||||||
else if (tag == 0x97) {
|
else if (tag == 0x97) {
|
||||||
for (int i = 0; i < MIN(*tag_data,16); i++) {
|
kds = MIN(*tag_data,16);
|
||||||
|
for (int i = 0; i < kds; i++) {
|
||||||
file_t *tf = file_new(EF_DKEK+i);
|
file_t *tf = file_new(EF_DKEK+i);
|
||||||
if (!tf)
|
if (!tf)
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
@@ -736,12 +738,22 @@ static int cmd_initialize() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dkeks == 0) {
|
if (dkeks == 0) {
|
||||||
int r = save_dkek_key(random_bytes_get(32));
|
//At least, the first DKEK shall exist
|
||||||
if (r != CCID_OK)
|
file_t *tf = search_dynamic_file(EF_DKEK);
|
||||||
return SW_EXEC_ERROR();
|
if (!tf) {
|
||||||
|
file_t *tf = file_new(EF_DKEK);
|
||||||
|
if (!tf)
|
||||||
|
return SW_MEMORY_FAILURE();
|
||||||
|
flash_write_data_to_file(tf, NULL, 0);
|
||||||
|
low_flash_available();
|
||||||
|
}
|
||||||
|
for (int kd = 0; kd < kds; kd++) {
|
||||||
|
int r = save_dkek_key(kd, random_bytes_get(32));
|
||||||
|
printf("r %d\r\n",r);
|
||||||
|
if (r != CCID_OK)
|
||||||
|
return SW_EXEC_ERROR();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
init_dkek();
|
|
||||||
}
|
}
|
||||||
else { //free memory bytes request
|
else { //free memory bytes request
|
||||||
int heap_left = heapLeft();
|
int heap_left = heapLeft();
|
||||||
@@ -764,7 +776,7 @@ static int cmd_key_domain() {
|
|||||||
if (has_session_pin == false && apdu.cmd_apdu_data_len > 0)
|
if (has_session_pin == false && apdu.cmd_apdu_data_len > 0)
|
||||||
return SW_CONDITIONS_NOT_SATISFIED();
|
return SW_CONDITIONS_NOT_SATISFIED();
|
||||||
if (p1 == 0x0) { //dkek import
|
if (p1 == 0x0) { //dkek import
|
||||||
if (p2 > 0xF)
|
if (p2 > MAX_KEY_DOMAINS)
|
||||||
return SW_WRONG_P1P2();
|
return SW_WRONG_P1P2();
|
||||||
if (apdu.cmd_apdu_data_len > 0) {
|
if (apdu.cmd_apdu_data_len > 0) {
|
||||||
file_t *tf = file_new(EF_DKEK+p2);
|
file_t *tf = file_new(EF_DKEK+p2);
|
||||||
@@ -772,9 +784,9 @@ static int cmd_key_domain() {
|
|||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
if (apdu.cmd_apdu_data_len < 32)
|
if (apdu.cmd_apdu_data_len < 32)
|
||||||
return SW_WRONG_LENGTH();
|
return SW_WRONG_LENGTH();
|
||||||
import_dkek_share(apdu.cmd_apdu_data);
|
import_dkek_share(p2, apdu.cmd_apdu_data);
|
||||||
if (++current_dkeks == dkeks) {
|
if (++current_dkeks >= dkeks) {
|
||||||
if (save_dkek_key(NULL) != CCID_OK)
|
if (save_dkek_key(p2, NULL) != CCID_OK)
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
@@ -786,8 +798,8 @@ static int cmd_key_domain() {
|
|||||||
}
|
}
|
||||||
memset(res_APDU,0,10);
|
memset(res_APDU,0,10);
|
||||||
res_APDU[0] = dkeks;
|
res_APDU[0] = dkeks;
|
||||||
res_APDU[1] = dkeks-current_dkeks;
|
res_APDU[1] = dkeks > current_dkeks ? dkeks-current_dkeks : 0;
|
||||||
dkek_kcv(res_APDU+2);
|
dkek_kcv(p2, res_APDU+2);
|
||||||
res_APDU_size = 2+8;
|
res_APDU_size = 2+8;
|
||||||
}
|
}
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
@@ -821,7 +833,7 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) {
|
|||||||
key_size = 32;
|
key_size = 32;
|
||||||
memcpy(kdata, key_ctx, key_size);
|
memcpy(kdata, key_ctx, key_size);
|
||||||
}
|
}
|
||||||
r = dkek_encrypt(kdata, key_size);
|
r = dkek_encrypt(0, kdata, key_size);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -1260,14 +1272,17 @@ static int cmd_change_pin() {
|
|||||||
}
|
}
|
||||||
uint8_t pin_len = file_read_uint8(file_pin1->data+2);
|
uint8_t pin_len = file_read_uint8(file_pin1->data+2);
|
||||||
uint16_t r = check_pin(file_pin1, apdu.cmd_apdu_data, pin_len);
|
uint16_t r = check_pin(file_pin1, apdu.cmd_apdu_data, pin_len);
|
||||||
|
uint8_t dkek[DKEK_SIZE];
|
||||||
if (r != 0x9000)
|
if (r != 0x9000)
|
||||||
return r;
|
return r;
|
||||||
if (load_dkek() != CCID_OK) //loads the DKEK with old pin
|
if (load_dkek(0, dkek) != CCID_OK) //loads the DKEK with old pin
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
//encrypt DKEK with new pin
|
//encrypt DKEK with new pin
|
||||||
hash_multi(apdu.cmd_apdu_data+pin_len, apdu.cmd_apdu_data_len-pin_len, session_pin);
|
hash_multi(apdu.cmd_apdu_data+pin_len, apdu.cmd_apdu_data_len-pin_len, session_pin);
|
||||||
has_session_pin = true;
|
has_session_pin = true;
|
||||||
if (store_dkek_key() != CCID_OK)
|
r = store_dkek_key(0, dkek);
|
||||||
|
release_dkek(dkek);
|
||||||
|
if (r != CCID_OK)
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
uint8_t dhash[33];
|
uint8_t dhash[33];
|
||||||
dhash[0] = apdu.cmd_apdu_data_len-pin_len;
|
dhash[0] = apdu.cmd_apdu_data_len-pin_len;
|
||||||
@@ -1318,7 +1333,7 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
|
|||||||
int key_size = file_read_uint16(fkey->data);
|
int key_size = file_read_uint16(fkey->data);
|
||||||
uint8_t kdata[4096/8];
|
uint8_t kdata[4096/8];
|
||||||
memcpy(kdata, file_read(fkey->data+2), key_size);
|
memcpy(kdata, file_read(fkey->data+2), key_size);
|
||||||
if (dkek_decrypt(kdata, key_size) != 0) {
|
if (dkek_decrypt(0, kdata, key_size) != 0) {
|
||||||
return CCID_EXEC_ERROR;
|
return CCID_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size/2) != 0) {
|
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size/2) != 0) {
|
||||||
@@ -1355,7 +1370,7 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) {
|
|||||||
int key_size = file_read_uint16(fkey->data);
|
int key_size = file_read_uint16(fkey->data);
|
||||||
uint8_t kdata[67]; //Worst case, 521 bit + 1byte
|
uint8_t kdata[67]; //Worst case, 521 bit + 1byte
|
||||||
memcpy(kdata, file_read(fkey->data+2), key_size);
|
memcpy(kdata, file_read(fkey->data+2), key_size);
|
||||||
if (dkek_decrypt(kdata, key_size) != 0) {
|
if (dkek_decrypt(0, kdata, key_size) != 0) {
|
||||||
return CCID_EXEC_ERROR;
|
return CCID_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
mbedtls_ecp_group_id gid = kdata[0];
|
mbedtls_ecp_group_id gid = kdata[0];
|
||||||
@@ -1538,7 +1553,7 @@ static int cmd_key_wrap() {
|
|||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = dkek_encode_key(&ctx, HSM_KEY_RSA, res_APDU, &wrap_len);
|
r = dkek_encode_key(0, &ctx, HSM_KEY_RSA, res_APDU, &wrap_len);
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
}
|
}
|
||||||
else if (*dprkd == P15_KEYTYPE_ECC) {
|
else if (*dprkd == P15_KEYTYPE_ECC) {
|
||||||
@@ -1551,7 +1566,7 @@ static int cmd_key_wrap() {
|
|||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = dkek_encode_key(&ctx, HSM_KEY_EC, res_APDU, &wrap_len);
|
r = dkek_encode_key(0, &ctx, HSM_KEY_EC, res_APDU, &wrap_len);
|
||||||
mbedtls_ecdsa_free(&ctx);
|
mbedtls_ecdsa_free(&ctx);
|
||||||
}
|
}
|
||||||
else if (*dprkd == P15_KEYTYPE_AES) {
|
else if (*dprkd == P15_KEYTYPE_AES) {
|
||||||
@@ -1561,7 +1576,7 @@ static int cmd_key_wrap() {
|
|||||||
|
|
||||||
int key_size = file_read_uint16(ef->data), aes_type = HSM_KEY_AES;
|
int key_size = file_read_uint16(ef->data), aes_type = HSM_KEY_AES;
|
||||||
memcpy(kdata, file_read(ef->data+2), key_size);
|
memcpy(kdata, file_read(ef->data+2), key_size);
|
||||||
if (dkek_decrypt(kdata, key_size) != 0) {
|
if (dkek_decrypt(0, kdata, key_size) != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
if (key_size == 32)
|
if (key_size == 32)
|
||||||
@@ -1570,7 +1585,7 @@ static int cmd_key_wrap() {
|
|||||||
aes_type = HSM_KEY_AES_192;
|
aes_type = HSM_KEY_AES_192;
|
||||||
else if (key_size == 16)
|
else if (key_size == 16)
|
||||||
aes_type = HSM_KEY_AES_128;
|
aes_type = HSM_KEY_AES_128;
|
||||||
r = dkek_encode_key(kdata, aes_type, res_APDU, &wrap_len);
|
r = dkek_encode_key(0, kdata, aes_type, res_APDU, &wrap_len);
|
||||||
}
|
}
|
||||||
if (r != CCID_OK)
|
if (r != CCID_OK)
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -1590,7 +1605,7 @@ static int cmd_key_unwrap() {
|
|||||||
if (key_type == HSM_KEY_RSA) {
|
if (key_type == HSM_KEY_RSA) {
|
||||||
mbedtls_rsa_context ctx;
|
mbedtls_rsa_context ctx;
|
||||||
mbedtls_rsa_init(&ctx);
|
mbedtls_rsa_init(&ctx);
|
||||||
r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, NULL);
|
r = dkek_decode_key(0, &ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, NULL);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -1606,7 +1621,7 @@ static int cmd_key_unwrap() {
|
|||||||
else if (key_type == HSM_KEY_EC) {
|
else if (key_type == HSM_KEY_EC) {
|
||||||
mbedtls_ecdsa_context ctx;
|
mbedtls_ecdsa_context ctx;
|
||||||
mbedtls_ecdsa_init(&ctx);
|
mbedtls_ecdsa_init(&ctx);
|
||||||
r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, NULL);
|
r = dkek_decode_key(0, &ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, NULL);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
mbedtls_ecdsa_free(&ctx);
|
mbedtls_ecdsa_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -1622,7 +1637,7 @@ static int cmd_key_unwrap() {
|
|||||||
else if (key_type == HSM_KEY_AES) {
|
else if (key_type == HSM_KEY_AES) {
|
||||||
uint8_t aes_key[32];
|
uint8_t aes_key[32];
|
||||||
int key_size = 0, aes_type;
|
int key_size = 0, aes_type;
|
||||||
r = dkek_decode_key(aes_key, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, &key_size);
|
r = dkek_decode_key(0, aes_key, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, &key_size);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
@@ -1677,7 +1692,7 @@ static int cmd_decrypt_asym() {
|
|||||||
int key_size = file_read_uint16(ef->data);
|
int key_size = file_read_uint16(ef->data);
|
||||||
uint8_t *kdata = (uint8_t *)calloc(1,key_size);
|
uint8_t *kdata = (uint8_t *)calloc(1,key_size);
|
||||||
memcpy(kdata, file_read(ef->data+2), key_size);
|
memcpy(kdata, file_read(ef->data+2), key_size);
|
||||||
if (dkek_decrypt(kdata, key_size) != 0) {
|
if (dkek_decrypt(0, kdata, key_size) != 0) {
|
||||||
free(kdata);
|
free(kdata);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
@@ -1733,7 +1748,7 @@ static int cmd_cipher_sym() {
|
|||||||
int key_size = file_read_uint16(ef->data);
|
int key_size = file_read_uint16(ef->data);
|
||||||
uint8_t kdata[32]; //maximum AES key size
|
uint8_t kdata[32]; //maximum AES key size
|
||||||
memcpy(kdata, file_read(ef->data+2), key_size);
|
memcpy(kdata, file_read(ef->data+2), key_size);
|
||||||
if (dkek_decrypt(kdata, key_size) != 0) {
|
if (dkek_decrypt(0, kdata, key_size) != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
if (algo == ALGO_AES_CBC_ENCRYPT || algo == ALGO_AES_CBC_DECRYPT) {
|
if (algo == ALGO_AES_CBC_ENCRYPT || algo == ALGO_AES_CBC_DECRYPT) {
|
||||||
@@ -2109,4 +2124,4 @@ int sc_hsm_process_apdu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SW_INS_NOT_SUPPORTED();
|
return SW_INS_NOT_SUPPORTED();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user