mirror of
https://github.com/polhenarejos/pico-hsm.git
synced 2026-01-17 09:28:05 +00:00
Merge branch 'eac'. Support for PKCS#12 imports with SCS3.
This commit is contained in:
commit
1a5e6a7edc
9 changed files with 896 additions and 239 deletions
|
|
@ -51,6 +51,8 @@ target_sources(pico_hsm PUBLIC
|
|||
${CMAKE_CURRENT_LIST_DIR}/src/fs/low_flash.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/rng/random.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/rng/neug.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/hsm/hash_utils.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/hsm/dkek.c
|
||||
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/sha256.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/aes.c
|
||||
|
|
|
|||
473
src/hsm/dkek.c
Normal file
473
src/hsm/dkek.c
Normal file
|
|
@ -0,0 +1,473 @@
|
|||
/*
|
||||
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
#include "stdlib.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include "dkek.h"
|
||||
#include "hash_utils.h"
|
||||
#include "random.h"
|
||||
#include "sc_hsm.h"
|
||||
#include "mbedtls/md.h"
|
||||
#include "mbedtls/cmac.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/ecdsa.h"
|
||||
|
||||
static uint8_t dkek[IV_SIZE+32];
|
||||
static uint8_t tmp_dkek[32];
|
||||
extern bool has_session_pin;
|
||||
extern uint8_t session_pin[32];
|
||||
|
||||
int load_dkek() {
|
||||
if (has_session_pin == false)
|
||||
return HSM_NO_LOGIN;
|
||||
file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF);
|
||||
if (!tf)
|
||||
return HSM_ERR_FILE_NOT_FOUND;
|
||||
memcpy(dkek, file_read(tf->data+sizeof(uint16_t)), IV_SIZE+32);
|
||||
int ret = aes_decrypt_cfb_256(session_pin, dkek, dkek+IV_SIZE, 32);
|
||||
if (ret != 0)
|
||||
return HSM_EXEC_ERROR;
|
||||
return HSM_OK;
|
||||
}
|
||||
|
||||
void release_dkek() {
|
||||
memset(dkek, 0, sizeof(dkek));
|
||||
}
|
||||
|
||||
void init_dkek() {
|
||||
release_dkek();
|
||||
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_by_fid(EF_DKEK, NULL, SPECIFY_EF);
|
||||
if (!tf)
|
||||
return HSM_ERR_FILE_NOT_FOUND;
|
||||
flash_write_data_to_file(tf, dkek, sizeof(dkek));
|
||||
low_flash_available();
|
||||
release_dkek();
|
||||
return HSM_OK;
|
||||
}
|
||||
|
||||
int save_dkek_key(const uint8_t *key) {
|
||||
const uint8_t *iv = random_bytes_get(32);
|
||||
memcpy(dkek, iv, IV_SIZE);
|
||||
if (!key)
|
||||
key = tmp_dkek;
|
||||
memcpy(dkek+IV_SIZE, key, 32);
|
||||
return store_dkek_key();
|
||||
}
|
||||
|
||||
void import_dkek_share(const uint8_t *share) {
|
||||
for (int i = 0; i < 32; i++)
|
||||
tmp_dkek[i] ^= share[i];
|
||||
}
|
||||
|
||||
int dkek_kcv(uint8_t *kcv) { //kcv 8 bytes
|
||||
uint8_t hsh[32];
|
||||
int r = load_dkek();
|
||||
if (r != HSM_OK)
|
||||
return r;
|
||||
hash256(dkek+IV_SIZE, 32, hsh);
|
||||
release_dkek();
|
||||
memcpy(kcv, hsh, 8);
|
||||
}
|
||||
|
||||
int dkek_kenc(uint8_t *kenc) { //kenc 32 bytes
|
||||
uint8_t buf[32+4];
|
||||
int r = load_dkek();
|
||||
if (r != HSM_OK)
|
||||
return r;
|
||||
memcpy(buf, dkek+IV_SIZE, 32);
|
||||
release_dkek();
|
||||
memcpy(buf+32, "\x0\x0\x0\x1", 4);
|
||||
hash256(buf, sizeof(buf), kenc);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
return HSM_OK;
|
||||
}
|
||||
|
||||
int dkek_kmac(uint8_t *kmac) { //kmac 32 bytes
|
||||
uint8_t buf[32+4];
|
||||
int r = load_dkek();
|
||||
if (r != HSM_OK)
|
||||
return r;
|
||||
memcpy(buf, dkek+IV_SIZE, 32);
|
||||
release_dkek();
|
||||
memcpy(buf+32, "\x0\x0\x0\x2", 4);
|
||||
hash256(buf, sizeof(buf), kmac);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
return HSM_OK;
|
||||
}
|
||||
|
||||
int dkek_encrypt(uint8_t *data, size_t len) {
|
||||
int r;
|
||||
if ((r = load_dkek()) != HSM_OK)
|
||||
return r;
|
||||
r = aes_encrypt_cfb_256(dkek+IV_SIZE, dkek, data, len);
|
||||
release_dkek();
|
||||
return r;
|
||||
}
|
||||
|
||||
int dkek_decrypt(uint8_t *data, size_t len) {
|
||||
int r;
|
||||
if ((r = load_dkek()) != HSM_OK)
|
||||
return r;
|
||||
r = aes_decrypt_cfb_256(dkek+IV_SIZE, dkek, data, len);
|
||||
release_dkek();
|
||||
return r;
|
||||
}
|
||||
|
||||
int dkek_encode_key(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))
|
||||
return HSM_WRONG_DATA;
|
||||
|
||||
uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes padding)
|
||||
memset(kb, 0, sizeof(kb));
|
||||
int kb_len = 0;
|
||||
uint8_t *algo = NULL;
|
||||
uint8_t algo_len = 0;
|
||||
uint8_t *allowed = NULL;
|
||||
uint8_t allowed_len = 0;
|
||||
uint8_t kenc[32];
|
||||
memset(kenc, 0, sizeof(kenc));
|
||||
dkek_kenc(kenc);
|
||||
|
||||
uint8_t kcv[8];
|
||||
memset(kcv, 0, sizeof(kcv));
|
||||
dkek_kcv(kcv);
|
||||
|
||||
uint8_t kmac[32];
|
||||
memset(kmac, 0, sizeof(kmac));
|
||||
dkek_kmac(kmac);
|
||||
|
||||
if (key_type & HSM_KEY_AES) {
|
||||
if (key_type & HSM_KEY_AES_128)
|
||||
kb_len = 16;
|
||||
else if (key_type & HSM_KEY_AES_192)
|
||||
kb_len = 24;
|
||||
else if (key_type & HSM_KEY_AES_256)
|
||||
kb_len = 32;
|
||||
|
||||
if (kb_len != 16 && kb_len != 24 && kb_len != 32)
|
||||
return HSM_WRONG_DATA;
|
||||
if (*out_len < 8+1+10+6+4+(2+32+14)+16)
|
||||
return HSM_WRONG_LENGTH;
|
||||
|
||||
put_uint16_t(kb_len, kb+8);
|
||||
memcpy(kb+10, key_ctx, kb_len);
|
||||
kb_len += 2;
|
||||
|
||||
algo = "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8)
|
||||
algo_len = 10;
|
||||
allowed = "\x00\x04\x10\x11\x18\x99"; //(2+4)
|
||||
allowed_len = 6;
|
||||
}
|
||||
else if (key_type & HSM_KEY_RSA) {
|
||||
if (*out_len < 8+1+12+6+(8+2*4+2*4096/8+3+13)+16) //13 bytes pading
|
||||
return HSM_WRONG_LENGTH;
|
||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx;
|
||||
kb_len = 0;
|
||||
put_uint16_t(mbedtls_rsa_get_len(rsa)*8, kb+8+kb_len); kb_len += 2;
|
||||
|
||||
put_uint16_t(mbedtls_mpi_size(&rsa->D), kb+8+kb_len); kb_len += 2;
|
||||
mbedtls_mpi_write_binary(&rsa->D, kb+8+kb_len, mbedtls_mpi_size(&rsa->D)); kb_len += mbedtls_mpi_size(&rsa->D);
|
||||
put_uint16_t(mbedtls_mpi_size(&rsa->N), kb+8+kb_len); kb_len += 2;
|
||||
mbedtls_mpi_write_binary(&rsa->N, kb+8+kb_len, mbedtls_mpi_size(&rsa->N)); kb_len += mbedtls_mpi_size(&rsa->N);
|
||||
put_uint16_t(mbedtls_mpi_size(&rsa->E), kb+8+kb_len); kb_len += 2;
|
||||
mbedtls_mpi_write_binary(&rsa->E, kb+8+kb_len, mbedtls_mpi_size(&rsa->E)); kb_len += mbedtls_mpi_size(&rsa->E);
|
||||
|
||||
algo = "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02";
|
||||
algo_len = 12;
|
||||
}
|
||||
else if (key_type & HSM_KEY_EC) {
|
||||
if (*out_len < 8+1+12+6+(8+2*8+9*66+2+4)+16) //4 bytes pading
|
||||
return HSM_WRONG_LENGTH;
|
||||
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx;
|
||||
kb_len = 0;
|
||||
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.P)*8, kb+8+kb_len); kb_len += 2;
|
||||
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.A), kb+8+kb_len); kb_len += 2;
|
||||
mbedtls_mpi_write_binary(&ecdsa->grp.A, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.A)); kb_len += mbedtls_mpi_size(&ecdsa->grp.A);
|
||||
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.B), kb+8+kb_len); kb_len += 2;
|
||||
mbedtls_mpi_write_binary(&ecdsa->grp.B, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.B)); kb_len += mbedtls_mpi_size(&ecdsa->grp.B);
|
||||
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.P), kb+8+kb_len); kb_len += 2;
|
||||
mbedtls_mpi_write_binary(&ecdsa->grp.P, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.P)); kb_len += mbedtls_mpi_size(&ecdsa->grp.P);
|
||||
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.N), kb+8+kb_len); kb_len += 2;
|
||||
mbedtls_mpi_write_binary(&ecdsa->grp.N, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.N)); kb_len += mbedtls_mpi_size(&ecdsa->grp.N);
|
||||
put_uint16_t(1+mbedtls_mpi_size(&ecdsa->grp.G.X)+mbedtls_mpi_size(&ecdsa->grp.G.Y), kb+8+kb_len); kb_len += 2;
|
||||
kb[8+kb_len++] = 0x4;
|
||||
mbedtls_mpi_write_binary(&ecdsa->grp.G.X, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.G.X)); kb_len += mbedtls_mpi_size(&ecdsa->grp.G.X);
|
||||
mbedtls_mpi_write_binary(&ecdsa->grp.G.Y, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.G.Y)); kb_len += mbedtls_mpi_size(&ecdsa->grp.G.Y);
|
||||
put_uint16_t(mbedtls_mpi_size(&ecdsa->d), kb+8+kb_len); kb_len += 2;
|
||||
mbedtls_mpi_write_binary(&ecdsa->d, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->d)); kb_len += mbedtls_mpi_size(&ecdsa->d);
|
||||
put_uint16_t(1+mbedtls_mpi_size(&ecdsa->Q.X)+mbedtls_mpi_size(&ecdsa->Q.Y), kb+8+kb_len); kb_len += 2;
|
||||
kb[8+kb_len++] = 0x4;
|
||||
mbedtls_mpi_write_binary(&ecdsa->Q.X, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->Q.X)); kb_len += mbedtls_mpi_size(&ecdsa->Q.X);
|
||||
mbedtls_mpi_write_binary(&ecdsa->Q.Y, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->Q.Y)); kb_len += mbedtls_mpi_size(&ecdsa->Q.Y);
|
||||
|
||||
algo = "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03";
|
||||
algo_len = 12;
|
||||
}
|
||||
memset(out, 0, *out_len);
|
||||
*out_len = 0;
|
||||
|
||||
memcpy(out+*out_len, kcv, 8);
|
||||
*out_len += 8;
|
||||
|
||||
if (key_type & HSM_KEY_AES)
|
||||
out[*out_len] = 15;
|
||||
else if (key_type & HSM_KEY_RSA)
|
||||
out[*out_len] = 5;
|
||||
else if (key_type & HSM_KEY_EC)
|
||||
out[*out_len] = 12;
|
||||
*out_len += 1;
|
||||
|
||||
if (algo) {
|
||||
memcpy(out+*out_len, algo, algo_len);
|
||||
*out_len += algo_len;
|
||||
}
|
||||
else
|
||||
*out_len += 2;
|
||||
|
||||
if (allowed) {
|
||||
memcpy(out+*out_len, allowed, allowed_len);
|
||||
*out_len += allowed_len;
|
||||
}
|
||||
else
|
||||
*out_len += 2;
|
||||
//add 4 zeros
|
||||
*out_len += 4;
|
||||
|
||||
memcpy(kb, random_bytes_get(8), 8);
|
||||
kb_len += 8; //8 random bytes
|
||||
int kb_len_pad = ((int)(kb_len/16))*16;
|
||||
if (kb_len % 16 > 0)
|
||||
kb_len_pad = ((int)(kb_len/16)+1)*16;
|
||||
//key already copied at kb+10
|
||||
if (kb_len < kb_len_pad) {
|
||||
kb[kb_len] = 0x80;
|
||||
}
|
||||
int r = aes_encrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, kb_len_pad);
|
||||
if (r != HSM_OK)
|
||||
return r;
|
||||
|
||||
memcpy(out+*out_len, kb, kb_len_pad);
|
||||
*out_len += kb_len_pad;
|
||||
|
||||
r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, out, *out_len, out+*out_len);
|
||||
|
||||
*out_len += 16;
|
||||
if (r != 0)
|
||||
return r;
|
||||
return HSM_OK;
|
||||
}
|
||||
|
||||
int dkek_type_key(const uint8_t *in) {
|
||||
if (in[8] == 5 || in[8] == 6)
|
||||
return HSM_KEY_RSA;
|
||||
else if (in[8] == 12)
|
||||
return HSM_KEY_EC;
|
||||
else if (in[8] == 15)
|
||||
return HSM_KEY_AES;
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out) {
|
||||
uint8_t kcv[8];
|
||||
memset(kcv, 0, sizeof(kcv));
|
||||
dkek_kcv(kcv);
|
||||
|
||||
uint8_t kmac[32];
|
||||
memset(kmac, 0, sizeof(kmac));
|
||||
dkek_kmac(kmac);
|
||||
|
||||
uint8_t kenc[32];
|
||||
memset(kenc, 0, sizeof(kenc));
|
||||
dkek_kenc(kenc);
|
||||
|
||||
if (memcmp(kcv, in, 8) != 0)
|
||||
return HSM_WRONG_DKEK;
|
||||
|
||||
uint8_t signature[16];
|
||||
int r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, in, in_len-16, signature);
|
||||
if (r != 0)
|
||||
return HSM_WRONG_SIGNATURE;
|
||||
if (memcmp(signature, in+in_len-16, 16) != 0)
|
||||
return HSM_WRONG_SIGNATURE;
|
||||
|
||||
int key_type = in[8];
|
||||
if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15)
|
||||
return HSM_WRONG_DATA;
|
||||
|
||||
if ((key_type == 5 || key_type == 6) && memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0)
|
||||
return HSM_WRONG_DATA;
|
||||
|
||||
if (key_type == 12 && memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0)
|
||||
return HSM_WRONG_DATA;
|
||||
|
||||
if (key_type == 15 && memcmp(in+9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0)
|
||||
return HSM_WRONG_DATA;
|
||||
|
||||
size_t ofs = 9;
|
||||
|
||||
//OID
|
||||
size_t len = get_uint16_t(in, ofs);
|
||||
ofs += len+2;
|
||||
|
||||
//Allowed algorithms
|
||||
len = get_uint16_t(in, ofs);
|
||||
ofs += len+2;
|
||||
|
||||
//Access conditions
|
||||
len = get_uint16_t(in, ofs);
|
||||
ofs += len+2;
|
||||
|
||||
//Key OID
|
||||
len = get_uint16_t(in, ofs);
|
||||
ofs += len+2;
|
||||
|
||||
if ((in_len-16-ofs) % 16 != 0)
|
||||
return HSM_WRONG_PADDING;
|
||||
uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes padding)
|
||||
memset(kb, 0, sizeof(kb));
|
||||
memcpy(kb, in+ofs, in_len-16-ofs);
|
||||
r = aes_decrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, in_len-16-ofs);
|
||||
if (r != HSM_OK)
|
||||
return r;
|
||||
|
||||
int key_size = get_uint16_t(kb, 8);
|
||||
if (key_size_out)
|
||||
*key_size_out = key_size;
|
||||
ofs = 10;
|
||||
if (key_type == 5 || key_type == 6) {
|
||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx;
|
||||
mbedtls_rsa_init(rsa);
|
||||
if (key_type == 5) {
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->D, kb+ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return HSM_WRONG_DATA;
|
||||
}
|
||||
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->N, kb+ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return HSM_WRONG_DATA;
|
||||
}
|
||||
}
|
||||
else if (key_type == 6) {
|
||||
//DP-1
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
|
||||
//DQ-1
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->P, kb+ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return HSM_WRONG_DATA;
|
||||
}
|
||||
|
||||
//PQ
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->Q, kb+ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return HSM_WRONG_DATA;
|
||||
}
|
||||
//N
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
}
|
||||
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->E, kb+ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return HSM_WRONG_DATA;
|
||||
}
|
||||
|
||||
if (key_type == 5) {
|
||||
r = mbedtls_rsa_import(rsa, &rsa->N, NULL, NULL, &rsa->D, &rsa->E);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return HSM_EXEC_ERROR;
|
||||
}
|
||||
}
|
||||
else if (key_type == 6) {
|
||||
r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return HSM_EXEC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
r = mbedtls_rsa_complete(rsa);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return HSM_EXEC_ERROR;
|
||||
}
|
||||
r = mbedtls_rsa_check_privkey(rsa);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return HSM_EXEC_ERROR;
|
||||
}
|
||||
}
|
||||
else if (key_type == 12) {
|
||||
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx;
|
||||
mbedtls_ecdsa_init(ecdsa);
|
||||
|
||||
//A
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
|
||||
//B
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
|
||||
//P
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(kb+ofs, len);
|
||||
if (ec_id == MBEDTLS_ECP_DP_NONE) {
|
||||
mbedtls_ecdsa_free(ecdsa);
|
||||
return HSM_WRONG_DATA;
|
||||
}
|
||||
ofs += len;
|
||||
|
||||
//N
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
|
||||
//G
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
|
||||
//d
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
r = mbedtls_ecp_read_key(ec_id, ecdsa, kb+ofs, len);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdsa_free(ecdsa);
|
||||
return HSM_EXEC_ERROR;
|
||||
}
|
||||
}
|
||||
else if (key_type == 15) {
|
||||
memcpy(key_ctx, kb+ofs, key_size);
|
||||
}
|
||||
return HSM_OK;
|
||||
}
|
||||
36
src/hsm/dkek.h
Normal file
36
src/hsm/dkek.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _DKEK_H_
|
||||
#define _DKEK_H_
|
||||
|
||||
extern int load_dkek();
|
||||
extern int save_dkek_key(const uint8_t *key);
|
||||
extern int store_dkek_key();
|
||||
extern void init_dkek();
|
||||
extern void release_dkek();
|
||||
extern void import_dkek_share(const uint8_t *share);
|
||||
extern int dkek_kcv(uint8_t *kcv);
|
||||
extern int dkek_encrypt(uint8_t *data, size_t len);
|
||||
extern int dkek_decrypt(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_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);
|
||||
|
||||
#define MAX_DKEK_ENCODE_KEY_BUFFER (8+1+12+6+(8+2*4+2*4096/8+3+13)+16)
|
||||
|
||||
#endif
|
||||
142
src/hsm/hash_utils.c
Normal file
142
src/hsm/hash_utils.c
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <pico/unique_id.h>
|
||||
#include "mbedtls/md.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "mbedtls/aes.h"
|
||||
#include "hash_utils.h"
|
||||
#include "sc_hsm.h"
|
||||
#include "libopensc/card-sc-hsm.h"
|
||||
|
||||
void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]) {
|
||||
uint8_t o1[32];
|
||||
hash_multi(pin, len, o1);
|
||||
for (int i = 0; i < sizeof(o1); i++)
|
||||
o1[i] ^= pin[i%len];
|
||||
hash_multi(o1, sizeof(o1), output);
|
||||
}
|
||||
|
||||
void hash_multi(const uint8_t *input, size_t len, uint8_t output[32]) {
|
||||
mbedtls_sha256_context ctx;
|
||||
mbedtls_sha256_init(&ctx);
|
||||
int iters = 256;
|
||||
pico_unique_board_id_t unique_id;
|
||||
|
||||
pico_get_unique_board_id(&unique_id);
|
||||
|
||||
mbedtls_sha256_starts (&ctx, 0);
|
||||
mbedtls_sha256_update (&ctx, unique_id.id, sizeof(unique_id.id));
|
||||
|
||||
while (iters > len)
|
||||
{
|
||||
mbedtls_sha256_update (&ctx, input, len);
|
||||
iters -= len;
|
||||
}
|
||||
if (iters > 0) // remaining iterations
|
||||
mbedtls_sha256_update (&ctx, input, iters);
|
||||
mbedtls_sha256_finish (&ctx, output);
|
||||
mbedtls_sha256_free (&ctx);
|
||||
}
|
||||
|
||||
void hash256(const uint8_t *input, size_t len, uint8_t output[32]) {
|
||||
mbedtls_sha256_context ctx;
|
||||
mbedtls_sha256_init(&ctx);
|
||||
|
||||
mbedtls_sha256_starts (&ctx, 0);
|
||||
mbedtls_sha256_update (&ctx, input, len);
|
||||
|
||||
mbedtls_sha256_finish (&ctx, output);
|
||||
mbedtls_sha256_free (&ctx);
|
||||
}
|
||||
|
||||
void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_t *output) {
|
||||
mbedtls_md_context_t ctx;
|
||||
mbedtls_md_init(&ctx);
|
||||
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md);
|
||||
mbedtls_md_setup(&ctx, md_info, 0);
|
||||
mbedtls_md_starts(&ctx);
|
||||
mbedtls_md_update(&ctx, input, len);
|
||||
mbedtls_md_finish(&ctx, output);
|
||||
mbedtls_md_free(&ctx);
|
||||
}
|
||||
|
||||
int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len) {
|
||||
mbedtls_aes_context aes;
|
||||
mbedtls_aes_init(&aes);
|
||||
uint8_t tmp_iv[IV_SIZE];
|
||||
size_t iv_offset = 0;
|
||||
memset(tmp_iv, 0, IV_SIZE);
|
||||
if (iv)
|
||||
memcpy(tmp_iv, iv, IV_SIZE);
|
||||
int r = mbedtls_aes_setkey_enc(&aes, key, key_size);
|
||||
if (r != 0)
|
||||
return HSM_EXEC_ERROR;
|
||||
if (mode == HSM_AES_MODE_CBC)
|
||||
return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, len, tmp_iv, data, data);
|
||||
return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, tmp_iv, data, data);
|
||||
}
|
||||
|
||||
int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len) {
|
||||
mbedtls_aes_context aes;
|
||||
mbedtls_aes_init(&aes);
|
||||
uint8_t tmp_iv[IV_SIZE];
|
||||
size_t iv_offset = 0;
|
||||
memset(tmp_iv, 0, IV_SIZE);
|
||||
if (iv)
|
||||
memcpy(tmp_iv, iv, IV_SIZE);
|
||||
int r = mbedtls_aes_setkey_dec(&aes, key, key_size);
|
||||
if (r != 0)
|
||||
return HSM_EXEC_ERROR;
|
||||
if (mode == HSM_AES_MODE_CBC)
|
||||
return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, len, tmp_iv, data, data);
|
||||
r = mbedtls_aes_setkey_enc(&aes, key, key_size); //CFB requires set_enc instead set_dec
|
||||
return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_DECRYPT, len, &iv_offset, tmp_iv, data, data);
|
||||
}
|
||||
|
||||
int aes_encrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) {
|
||||
return aes_encrypt(key, iv, 256, HSM_AES_MODE_CFB, data, len);
|
||||
}
|
||||
int aes_decrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) {
|
||||
return aes_decrypt(key, iv, 256, HSM_AES_MODE_CFB, data, len);
|
||||
}
|
||||
|
||||
struct ec_curve_mbed_id {
|
||||
struct sc_lv_data curve;
|
||||
mbedtls_ecp_group_id id;
|
||||
};
|
||||
struct ec_curve_mbed_id ec_curves_mbed[] = {
|
||||
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24}, MBEDTLS_ECP_DP_SECP192R1 },
|
||||
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32}, MBEDTLS_ECP_DP_SECP256R1 },
|
||||
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 48}, MBEDTLS_ECP_DP_SECP384R1 },
|
||||
{ { (unsigned char *) "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 66}, MBEDTLS_ECP_DP_SECP521R1 },
|
||||
{ { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32}, MBEDTLS_ECP_DP_BP256R1 },
|
||||
{ { (unsigned char *) "\x8C\xB9\x1E\x82\xA3\x38\x6D\x28\x0F\x5D\x6F\x7E\x50\xE6\x41\xDF\x15\x2F\x71\x09\xED\x54\x56\xB4\x12\xB1\xDA\x19\x7F\xB7\x11\x23\xAC\xD3\xA7\x29\x90\x1D\x1A\x71\x87\x47\x00\x13\x31\x07\xEC\x53", 48}, MBEDTLS_ECP_DP_BP384R1 },
|
||||
{ { (unsigned char *) "\xAA\xDD\x9D\xB8\xDB\xE9\xC4\x8B\x3F\xD4\xE6\xAE\x33\xC9\xFC\x07\xCB\x30\x8D\xB3\xB3\xC9\xD2\x0E\xD6\x63\x9C\xCA\x70\x33\x08\x71\x7D\x4D\x9B\x00\x9B\xC6\x68\x42\xAE\xCD\xA1\x2A\xE6\xA3\x80\xE6\x28\x81\xFF\x2F\x2D\x82\xC6\x85\x28\xAA\x60\x56\x58\x3A\x48\xF3", 64}, MBEDTLS_ECP_DP_BP512R1 },
|
||||
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xEE\x37", 24}, MBEDTLS_ECP_DP_SECP192K1 },
|
||||
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFC\x2F", 32}, MBEDTLS_ECP_DP_SECP256K1 },
|
||||
{ { NULL, 0 }, MBEDTLS_ECP_DP_NONE }
|
||||
};
|
||||
|
||||
mbedtls_ecp_group_id ec_get_curve_from_prime(const uint8_t *prime, size_t prime_len) {
|
||||
for (struct ec_curve_mbed_id *ec = ec_curves_mbed; ec->id != MBEDTLS_ECP_DP_NONE; ec++) {
|
||||
if (prime_len == ec->curve.len && memcmp(prime, ec->curve.value, prime_len) == 0) {
|
||||
return ec->id;
|
||||
}
|
||||
}
|
||||
return MBEDTLS_ECP_DP_NONE;
|
||||
}
|
||||
46
src/hsm/hash_utils.h
Normal file
46
src/hsm/hash_utils.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _HASH_UTILS_H_
|
||||
#define _HASH_UTILS_H_
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/md.h"
|
||||
|
||||
#define HSM_KEY_RSA 0x1
|
||||
#define HSM_KEY_EC 0x10
|
||||
#define HSM_KEY_AES 0x100
|
||||
#define HSM_KEY_AES_128 0x300
|
||||
#define HSM_KEY_AES_192 0x500
|
||||
#define HSM_KEY_AES_256 0x900
|
||||
|
||||
#define HSM_AES_MODE_CBC 1
|
||||
#define HSM_AES_MODE_CFB 2
|
||||
|
||||
extern void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]);
|
||||
extern void hash_multi(const uint8_t *input, size_t len, uint8_t output[32]);
|
||||
extern void hash256(const uint8_t *input, size_t len, uint8_t output[32]);
|
||||
extern void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_t *output);
|
||||
extern int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len);
|
||||
extern int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len);
|
||||
extern int aes_encrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len);
|
||||
extern int aes_decrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len);
|
||||
extern mbedtls_ecp_group_id ec_get_curve_from_prime(const uint8_t *prime, size_t prime_len);
|
||||
|
||||
#endif
|
||||
422
src/hsm/sc_hsm.c
422
src/hsm/sc_hsm.c
|
|
@ -30,6 +30,8 @@
|
|||
#include "mbedtls/hkdf.h"
|
||||
#include "version.h"
|
||||
#include "cvcerts.h"
|
||||
#include "hash_utils.h"
|
||||
#include "dkek.h"
|
||||
|
||||
const uint8_t sc_hsm_aid[] = {
|
||||
11,
|
||||
|
|
@ -39,7 +41,6 @@ const uint8_t sc_hsm_aid[] = {
|
|||
uint8_t session_pin[32], session_sopin[32];
|
||||
bool has_session_pin = false, has_session_sopin = false;
|
||||
static uint8_t dkeks = 0, current_dkeks = 0;
|
||||
static uint8_t tmp_dkek[IV_SIZE+32];
|
||||
|
||||
static int sc_hsm_process_apdu();
|
||||
|
||||
|
|
@ -73,49 +74,6 @@ int sc_hsm_unload() {
|
|||
return HSM_OK;
|
||||
}
|
||||
|
||||
static int encrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len)
|
||||
{
|
||||
mbedtls_aes_context aes;
|
||||
mbedtls_aes_init(&aes);
|
||||
uint8_t tmp_iv[IV_SIZE];
|
||||
size_t iv_offset = 0;
|
||||
memcpy(tmp_iv, iv, IV_SIZE);
|
||||
int r = mbedtls_aes_setkey_enc (&aes, key, 256);
|
||||
if (r != 0)
|
||||
return HSM_EXEC_ERROR;
|
||||
return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, tmp_iv, data, data);
|
||||
}
|
||||
|
||||
static int decrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len)
|
||||
{
|
||||
mbedtls_aes_context aes;
|
||||
mbedtls_aes_init(&aes);
|
||||
uint8_t tmp_iv[IV_SIZE];
|
||||
size_t iv_offset = 0;
|
||||
memcpy(tmp_iv, iv, IV_SIZE);
|
||||
int r = mbedtls_aes_setkey_enc (&aes, key, 256);
|
||||
if (r != 0)
|
||||
return HSM_EXEC_ERROR;
|
||||
return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_DECRYPT, len, &iv_offset, tmp_iv, data, data);
|
||||
}
|
||||
|
||||
int load_dkek() {
|
||||
if (has_session_pin == false)
|
||||
return HSM_NO_LOGIN;
|
||||
file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF);
|
||||
if (!tf)
|
||||
return HSM_ERR_FILE_NOT_FOUND;
|
||||
memcpy(tmp_dkek, file_read(tf->data+sizeof(uint16_t)), IV_SIZE+32);
|
||||
int ret = decrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32);
|
||||
if (ret != 0)
|
||||
return HSM_EXEC_ERROR;
|
||||
return HSM_OK;
|
||||
}
|
||||
|
||||
void release_dkek() {
|
||||
memset(tmp_dkek, 0, sizeof(tmp_dkek));
|
||||
}
|
||||
|
||||
void select_file(file_t *pe) {
|
||||
if (!pe)
|
||||
{
|
||||
|
|
@ -268,7 +226,7 @@ int cvc_prepare_signatures(sc_pkcs15_card_t *p15card, sc_cvc_t *cvc, size_t sig_
|
|||
free(cvcbin);
|
||||
return r;
|
||||
}
|
||||
hash(cvcbin, cvclen, hsh);
|
||||
hash256(cvcbin, cvclen, hsh);
|
||||
free(cvcbin);
|
||||
return HSM_OK;
|
||||
}
|
||||
|
|
@ -580,17 +538,13 @@ static int cmd_initialize() {
|
|||
}
|
||||
p += tag_len;
|
||||
}
|
||||
p = random_bytes_get(32);
|
||||
memset(tmp_dkek, 0, sizeof(tmp_dkek));
|
||||
memcpy(tmp_dkek, p, IV_SIZE);
|
||||
if (dkeks == 0) {
|
||||
p = random_bytes_get(32);
|
||||
memcpy(tmp_dkek+IV_SIZE, p, 32);
|
||||
encrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32);
|
||||
file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF);
|
||||
flash_write_data_to_file(tf, tmp_dkek, sizeof(tmp_dkek));
|
||||
int r = save_dkek_key(random_bytes_get(32));
|
||||
if (r != HSM_OK)
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
low_flash_available();
|
||||
else
|
||||
init_dkek();
|
||||
}
|
||||
else { //free memory bytes request
|
||||
int heap_left = heapLeft();
|
||||
|
|
@ -606,59 +560,6 @@ static int cmd_initialize() {
|
|||
return SW_OK();
|
||||
}
|
||||
|
||||
void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]) {
|
||||
uint8_t o1[32];
|
||||
hash_multi(pin, len, o1);
|
||||
for (int i = 0; i < sizeof(o1); i++)
|
||||
o1[i] ^= pin[i%len];
|
||||
hash_multi(o1, sizeof(o1), output);
|
||||
}
|
||||
|
||||
void hash_multi(const uint8_t *input, size_t len, uint8_t output[32])
|
||||
{
|
||||
mbedtls_sha256_context ctx;
|
||||
mbedtls_sha256_init(&ctx);
|
||||
int iters = 256;
|
||||
|
||||
pico_get_unique_board_id(&unique_id);
|
||||
|
||||
mbedtls_sha256_starts (&ctx, 0);
|
||||
mbedtls_sha256_update (&ctx, unique_id.id, sizeof(unique_id.id));
|
||||
|
||||
while (iters > len)
|
||||
{
|
||||
mbedtls_sha256_update (&ctx, input, len);
|
||||
iters -= len;
|
||||
}
|
||||
if (iters > 0) // remaining iterations
|
||||
mbedtls_sha256_update (&ctx, input, iters);
|
||||
mbedtls_sha256_finish (&ctx, output);
|
||||
mbedtls_sha256_free (&ctx);
|
||||
}
|
||||
|
||||
void hash(const uint8_t *input, size_t len, uint8_t output[32])
|
||||
{
|
||||
mbedtls_sha256_context ctx;
|
||||
mbedtls_sha256_init(&ctx);
|
||||
|
||||
mbedtls_sha256_starts (&ctx, 0);
|
||||
mbedtls_sha256_update (&ctx, input, len);
|
||||
|
||||
mbedtls_sha256_finish (&ctx, output);
|
||||
mbedtls_sha256_free (&ctx);
|
||||
}
|
||||
|
||||
void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_t *output) {
|
||||
mbedtls_md_context_t ctx;
|
||||
mbedtls_md_init(&ctx);
|
||||
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md);
|
||||
mbedtls_md_setup(&ctx, md_info, 0);
|
||||
mbedtls_md_starts(&ctx);
|
||||
mbedtls_md_update(&ctx, input, len);
|
||||
mbedtls_md_finish(&ctx, output);
|
||||
mbedtls_md_free(&ctx);
|
||||
}
|
||||
|
||||
static int cmd_import_dkek() {
|
||||
//if (dkeks == 0)
|
||||
// return SW_COMMAND_NOT_ALLOWED();
|
||||
|
|
@ -671,107 +572,92 @@ static int cmd_import_dkek() {
|
|||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (apdu.cmd_apdu_data_len > 0) {
|
||||
for (int i = 0; i < apdu.cmd_apdu_data_len; i++)
|
||||
tmp_dkek[IV_SIZE+i] ^= apdu.cmd_apdu_data[i];
|
||||
if (apdu.cmd_apdu_data_len < 32)
|
||||
return SW_WRONG_LENGTH();
|
||||
import_dkek_share(apdu.cmd_apdu_data);
|
||||
if (++current_dkeks == dkeks) {
|
||||
encrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32);
|
||||
flash_write_data_to_file(tf, tmp_dkek, sizeof(tmp_dkek));
|
||||
memset(tmp_dkek, 0, sizeof(tmp_dkek));
|
||||
low_flash_available();
|
||||
if (save_dkek_key(NULL) != HSM_OK)
|
||||
return SW_FILE_NOT_FOUND();
|
||||
|
||||
}
|
||||
}
|
||||
res_APDU[0] = dkeks;
|
||||
res_APDU[1] = dkeks-current_dkeks;
|
||||
//FNV hash
|
||||
uint64_t hash = 0xcbf29ce484222325;
|
||||
memcpy(tmp_dkek, file_read(tf->data+sizeof(uint16_t)), IV_SIZE+32);
|
||||
decrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32);
|
||||
for (int i = 0; i < 32; i++) {
|
||||
hash ^= tmp_dkek[IV_SIZE+i];
|
||||
hash *= 0x00000100000001B3;
|
||||
}
|
||||
memset(tmp_dkek, 0, sizeof(tmp_dkek));
|
||||
memcpy(res_APDU+2,&hash,sizeof(hash));
|
||||
res_APDU_size = 2+sizeof(hash);
|
||||
dkek_kcv(res_APDU+2);
|
||||
res_APDU_size = 2+8;
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
struct ec_curve_mbed_id {
|
||||
struct sc_lv_data curve;
|
||||
mbedtls_ecp_group_id id;
|
||||
};
|
||||
struct ec_curve_mbed_id ec_curves_mbed[] = {
|
||||
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24}, MBEDTLS_ECP_DP_SECP192R1 },
|
||||
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32}, MBEDTLS_ECP_DP_SECP256R1 },
|
||||
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 48}, MBEDTLS_ECP_DP_SECP384R1 },
|
||||
{ { (unsigned char *) "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 66}, MBEDTLS_ECP_DP_SECP521R1 },
|
||||
{ { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32}, MBEDTLS_ECP_DP_BP256R1 },
|
||||
{ { (unsigned char *) "\x8C\xB9\x1E\x82\xA3\x38\x6D\x28\x0F\x5D\x6F\x7E\x50\xE6\x41\xDF\x15\x2F\x71\x09\xED\x54\x56\xB4\x12\xB1\xDA\x19\x7F\xB7\x11\x23\xAC\xD3\xA7\x29\x90\x1D\x1A\x71\x87\x47\x00\x13\x31\x07\xEC\x53", 48}, MBEDTLS_ECP_DP_BP384R1 },
|
||||
{ { (unsigned char *) "\xAA\xDD\x9D\xB8\xDB\xE9\xC4\x8B\x3F\xD4\xE6\xAE\x33\xC9\xFC\x07\xCB\x30\x8D\xB3\xB3\xC9\xD2\x0E\xD6\x63\x9C\xCA\x70\x33\x08\x71\x7D\x4D\x9B\x00\x9B\xC6\x68\x42\xAE\xCD\xA1\x2A\xE6\xA3\x80\xE6\x28\x81\xFF\x2F\x2D\x82\xC6\x85\x28\xAA\x60\x56\x58\x3A\x48\xF3", 64}, MBEDTLS_ECP_DP_BP512R1 },
|
||||
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xEE\x37", 24}, MBEDTLS_ECP_DP_SECP192K1 },
|
||||
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFC\x2F", 32}, MBEDTLS_ECP_DP_SECP256K1 },
|
||||
{ { NULL, 0 }, MBEDTLS_ECP_DP_NONE }
|
||||
};
|
||||
|
||||
//Stores the private and public keys in flash
|
||||
int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) {
|
||||
int r, key_size;
|
||||
uint8_t *asn1bin, *kdata;
|
||||
uint8_t *asn1bin = NULL;
|
||||
size_t asn1len = 0;
|
||||
uint8_t kdata[4096/8]; //worst case
|
||||
if (type == SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx;
|
||||
key_size = mbedtls_mpi_size(&rsa->P)+mbedtls_mpi_size(&rsa->Q);
|
||||
kdata = (uint8_t *)calloc(1, key_size);
|
||||
mbedtls_mpi_write_binary(&rsa->P, kdata, key_size/2);
|
||||
mbedtls_mpi_write_binary(&rsa->Q, kdata+key_size/2, key_size/2);
|
||||
}
|
||||
else {
|
||||
else if (type == SC_PKCS15_TYPE_PRKEY_EC) {
|
||||
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx;
|
||||
key_size = mbedtls_mpi_size(&ecdsa->d);
|
||||
kdata = (uint8_t *)calloc(1, key_size+1);
|
||||
kdata[0] = ecdsa->grp.id & 0xff;
|
||||
mbedtls_mpi_write_binary(&ecdsa->d, kdata+1, key_size);
|
||||
key_size++;
|
||||
}
|
||||
if ((r = load_dkek()) != HSM_OK)
|
||||
else if (type & HSM_KEY_AES) {
|
||||
if (type == HSM_KEY_AES_128)
|
||||
key_size = 16;
|
||||
else if (type == HSM_KEY_AES_192)
|
||||
key_size = 24;
|
||||
else if (type == HSM_KEY_AES_256)
|
||||
key_size = 32;
|
||||
memcpy(kdata, key_ctx, key_size);
|
||||
}
|
||||
r = dkek_encrypt(kdata, key_size);
|
||||
if (r != HSM_OK) {
|
||||
return r;
|
||||
if ((r = encrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size)) != 0)
|
||||
return r;
|
||||
release_dkek();
|
||||
}
|
||||
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
|
||||
if (!fpk)
|
||||
return SW_MEMORY_FAILURE();
|
||||
r = flash_write_data_to_file(fpk, kdata, key_size);
|
||||
free(kdata);
|
||||
if (r != HSM_OK)
|
||||
return r;
|
||||
//add_file_to_chain(fpk, &ef_kf);
|
||||
if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == SC_PKCS15_TYPE_PRKEY_EC) {
|
||||
struct sc_pkcs15_object *p15o = (struct sc_pkcs15_object *)calloc(1,sizeof (struct sc_pkcs15_object));
|
||||
|
||||
struct sc_pkcs15_object *p15o = (struct sc_pkcs15_object *)calloc(1,sizeof (struct sc_pkcs15_object));
|
||||
sc_pkcs15_prkey_info_t *prkd = (sc_pkcs15_prkey_info_t *)calloc(1, sizeof (sc_pkcs15_prkey_info_t));
|
||||
memset(prkd, 0, sizeof(sc_pkcs15_prkey_info_t));
|
||||
prkd->id.len = 1;
|
||||
prkd->id.value[0] = key_id;
|
||||
prkd->usage = SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_UNWRAP;
|
||||
prkd->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE | SC_PKCS15_PRKEY_ACCESS_LOCAL;
|
||||
prkd->native = 1;
|
||||
prkd->key_reference = key_id;
|
||||
prkd->path.value[0] = PRKD_PREFIX;
|
||||
prkd->path.value[1] = key_id;
|
||||
prkd->path.len = 2;
|
||||
if (type == SC_PKCS15_TYPE_PRKEY_RSA)
|
||||
prkd->modulus_length = key_size;
|
||||
else
|
||||
prkd->field_length = key_size-1; //contains 1 byte for the grp id
|
||||
|
||||
p15o->data = prkd;
|
||||
p15o->type = SC_PKCS15_TYPE_PRKEY | (type & 0xff);
|
||||
|
||||
r = sc_pkcs15_encode_prkdf_entry(ctx, p15o, &asn1bin, &asn1len);
|
||||
free(prkd);
|
||||
//sc_asn1_print_tags(asn1bin, asn1len);
|
||||
}
|
||||
|
||||
sc_pkcs15_prkey_info_t *prkd = (sc_pkcs15_prkey_info_t *)calloc(1, sizeof (sc_pkcs15_prkey_info_t));
|
||||
memset(prkd, 0, sizeof(sc_pkcs15_prkey_info_t));
|
||||
prkd->id.len = 1;
|
||||
prkd->id.value[0] = key_id;
|
||||
prkd->usage = SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_UNWRAP;
|
||||
prkd->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE | SC_PKCS15_PRKEY_ACCESS_LOCAL;
|
||||
prkd->native = 1;
|
||||
prkd->key_reference = key_id;
|
||||
prkd->path.value[0] = PRKD_PREFIX;
|
||||
prkd->path.value[1] = key_id;
|
||||
prkd->path.len = 2;
|
||||
if (type == SC_PKCS15_TYPE_PRKEY_RSA)
|
||||
prkd->modulus_length = key_size;
|
||||
else
|
||||
prkd->field_length = key_size-1; //contains 1 byte for the grp id
|
||||
|
||||
p15o->data = prkd;
|
||||
p15o->type = SC_PKCS15_TYPE_PRKEY | (type & 0xff);
|
||||
|
||||
r = sc_pkcs15_encode_prkdf_entry(ctx, p15o, &asn1bin, &asn1len);
|
||||
free(prkd);
|
||||
//sc_asn1_print_tags(asn1bin, asn1len);
|
||||
fpk = file_new((PRKD_PREFIX << 8) | key_id);
|
||||
r = flash_write_data_to_file(fpk, asn1bin, asn1len);
|
||||
free(asn1bin);
|
||||
if (asn1bin)
|
||||
free(asn1bin);
|
||||
if (r != HSM_OK)
|
||||
return r;
|
||||
//add_file_to_chain(fpk, &ef_prkdf);
|
||||
|
|
@ -903,13 +789,7 @@ static int cmd_keypair_gen() {
|
|||
else if (memcmp(oid, "\x4\x0\x7F\x0\x7\x2\x2\x2\x2\x3",MIN(oid_len,10)) == 0) { //ECC
|
||||
size_t prime_len;
|
||||
const uint8_t *prime = sc_asn1_find_tag(ctx, p, tout, 0x81, &prime_len);
|
||||
mbedtls_ecp_group_id ec_id = MBEDTLS_ECP_DP_NONE;
|
||||
for (struct ec_curve_mbed_id *ec = ec_curves_mbed; ec->id != MBEDTLS_ECP_DP_NONE; ec++) {
|
||||
if (prime_len == ec->curve.len && memcmp(prime, ec->curve.value, prime_len) == 0) {
|
||||
ec_id = ec->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(prime, prime_len);
|
||||
printf("KEYPAIR ECC %d\r\n",ec_id);
|
||||
if (ec_id == MBEDTLS_ECP_DP_NONE) {
|
||||
sc_pkcs15emu_sc_hsm_free_cvc(&cvc);
|
||||
|
|
@ -1136,9 +1016,9 @@ static int cmd_update_ef() {
|
|||
if (!ef->data)
|
||||
return SW_DATA_INVALID();
|
||||
uint8_t *data_merge = (uint8_t *)calloc(1, offset+data_len);
|
||||
memcpy(data_merge, file_read(ef->data), offset);
|
||||
memcpy(data_merge, file_read(ef->data+2), offset);
|
||||
memcpy(data_merge+offset, data, data_len);
|
||||
int r = flash_write_data_to_file(ef, data_merge, data_len);
|
||||
int r = flash_write_data_to_file(ef, data_merge, offset+data_len);
|
||||
free(data_merge);
|
||||
if (r != HSM_OK)
|
||||
return SW_MEMORY_FAILURE();
|
||||
|
|
@ -1191,10 +1071,8 @@ static int cmd_change_pin() {
|
|||
//encrypt DKEK with new pin
|
||||
hash_multi(apdu.cmd_apdu_data+pin_len, apdu.cmd_apdu_data_len-pin_len, session_pin);
|
||||
has_session_pin = true;
|
||||
encrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32);
|
||||
file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF);
|
||||
flash_write_data_to_file(tf, tmp_dkek, sizeof(tmp_dkek));
|
||||
release_dkek();
|
||||
if (store_dkek_key() != HSM_OK)
|
||||
return SW_EXEC_ERROR();
|
||||
uint8_t dhash[33];
|
||||
dhash[0] = apdu.cmd_apdu_data_len-pin_len;
|
||||
double_hash_pin(apdu.cmd_apdu_data+pin_len, apdu.cmd_apdu_data_len-pin_len, dhash+1);
|
||||
|
|
@ -1221,21 +1099,16 @@ static int cmd_key_gen() {
|
|||
//at this moment, we do not use the template, as only CBC is supported by the driver (encrypt, decrypt and CMAC)
|
||||
uint8_t aes_key[32]; //maximum AES key size
|
||||
memcpy(aes_key, random_bytes_get(key_size), key_size);
|
||||
if ((r = load_dkek()) != HSM_OK)
|
||||
return SW_EXEC_ERROR() ;
|
||||
if ((r = encrypt(tmp_dkek+IV_SIZE, tmp_dkek, aes_key, key_size)) != 0)
|
||||
return SW_EXEC_ERROR() ;
|
||||
release_dkek();
|
||||
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
|
||||
if (!fpk)
|
||||
return SW_MEMORY_FAILURE();
|
||||
r = flash_write_data_to_file(fpk, aes_key, key_size);
|
||||
if (r != HSM_OK)
|
||||
return SW_MEMORY_FAILURE();
|
||||
fpk = file_new((PRKD_PREFIX << 8) | key_id);
|
||||
if (!fpk)
|
||||
return SW_MEMORY_FAILURE();
|
||||
r = flash_write_data_to_file(fpk, NULL, 0);
|
||||
int aes_type = 0x0;
|
||||
if (key_size == 16)
|
||||
aes_type = HSM_KEY_AES_128;
|
||||
else if (key_size == 24)
|
||||
aes_type = HSM_KEY_AES_192;
|
||||
else if (key_size == 32)
|
||||
aes_type = HSM_KEY_AES_256;
|
||||
sc_context_t *card_ctx = create_context();
|
||||
r = store_keys(aes_key, aes_type, key_id, card_ctx);
|
||||
free(card_ctx);
|
||||
if (r != HSM_OK)
|
||||
return SW_MEMORY_FAILURE();
|
||||
low_flash_available();
|
||||
|
|
@ -1244,26 +1117,19 @@ static int cmd_key_gen() {
|
|||
|
||||
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
|
||||
int key_size = file_read_uint16(fkey->data);
|
||||
if (load_dkek() != HSM_OK)
|
||||
return SW_EXEC_ERROR();
|
||||
uint8_t *kdata = (uint8_t *)calloc(1,key_size);
|
||||
uint8_t kdata[4096/8];
|
||||
memcpy(kdata, file_read(fkey->data+2), key_size);
|
||||
if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0) {
|
||||
free(kdata);
|
||||
if (dkek_decrypt(kdata, key_size) != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
release_dkek();
|
||||
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size/2) != 0) {
|
||||
mbedtls_rsa_free(ctx);
|
||||
free(kdata);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
if (mbedtls_mpi_read_binary(&ctx->Q, kdata+key_size/2, key_size/2) != 0) {
|
||||
mbedtls_rsa_free(ctx);
|
||||
free(kdata);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
free(kdata);
|
||||
if (mbedtls_mpi_lset(&ctx->E, 0x10001) != 0) {
|
||||
mbedtls_rsa_free(ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
|
|
@ -1285,23 +1151,17 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
|
|||
|
||||
int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) {
|
||||
int key_size = file_read_uint16(fkey->data);
|
||||
if (load_dkek() != HSM_OK)
|
||||
return HSM_EXEC_ERROR;
|
||||
uint8_t *kdata = (uint8_t *)calloc(1,key_size);
|
||||
uint8_t kdata[67]; //Worst case, 521 bit + 1byte
|
||||
memcpy(kdata, file_read(fkey->data+2), key_size);
|
||||
if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0) {
|
||||
free(kdata);
|
||||
if (dkek_decrypt(kdata, key_size) != 0) {
|
||||
return HSM_EXEC_ERROR;
|
||||
}
|
||||
release_dkek();
|
||||
mbedtls_ecp_group_id gid = kdata[0];
|
||||
int r = mbedtls_ecp_read_key(gid, ctx, kdata+1, key_size-1);
|
||||
if (r != 0) {
|
||||
free(kdata);
|
||||
mbedtls_ecdsa_free(ctx);
|
||||
return HSM_EXEC_ERROR;
|
||||
}
|
||||
free(kdata);
|
||||
return HSM_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1445,7 +1305,7 @@ static int cmd_signature() {
|
|||
}
|
||||
|
||||
static int cmd_key_wrap() {
|
||||
int key_id = P1(apdu);
|
||||
int key_id = P1(apdu), r = 0, key_type = 0x0;
|
||||
if (P2(apdu) != 0x92)
|
||||
return SW_WRONG_P1P2();
|
||||
if (!isUserAuthenticated)
|
||||
|
|
@ -1453,23 +1313,115 @@ static int cmd_key_wrap() {
|
|||
file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id);
|
||||
if (!ef)
|
||||
return SW_FILE_NOT_FOUND();
|
||||
int key_len = file_read_uint16(ef->data);
|
||||
memcpy(res_APDU, file_read(ef->data+2), key_len);
|
||||
res_APDU_size = key_len;
|
||||
file_t *prkd = search_dynamic_file((PRKD_PREFIX << 8) | key_id);
|
||||
if (!prkd)
|
||||
return SW_FILE_NOT_FOUND();
|
||||
const uint8_t *dprkd = file_read(prkd->data+2);
|
||||
size_t wrap_len = MAX_DKEK_ENCODE_KEY_BUFFER;
|
||||
if (*dprkd == P15_KEYTYPE_RSA) {
|
||||
mbedtls_rsa_context ctx;
|
||||
mbedtls_rsa_init(&ctx);
|
||||
r = load_private_key_rsa(&ctx, ef);
|
||||
if (r != HSM_OK) {
|
||||
mbedtls_rsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = dkek_encode_key(&ctx, HSM_KEY_RSA, res_APDU, &wrap_len);
|
||||
mbedtls_rsa_free(&ctx);
|
||||
}
|
||||
else if (*dprkd == P15_KEYTYPE_ECC) {
|
||||
mbedtls_ecdsa_context ctx;
|
||||
mbedtls_ecdsa_init(&ctx);
|
||||
r = load_private_key_ecdsa(&ctx, ef);
|
||||
if (r != HSM_OK) {
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = dkek_encode_key(&ctx, HSM_KEY_EC, res_APDU, &wrap_len);
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
}
|
||||
else if (*dprkd == P15_KEYTYPE_AES) {
|
||||
uint8_t kdata[32]; //maximum AES key size
|
||||
int key_size = file_read_uint16(ef->data), aes_type = HSM_KEY_AES;
|
||||
memcpy(kdata, file_read(ef->data+2), key_size);
|
||||
if (dkek_decrypt(kdata, key_size) != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
if (key_size == 32)
|
||||
aes_type = HSM_KEY_AES_256;
|
||||
else if (key_size == 24)
|
||||
aes_type = HSM_KEY_AES_192;
|
||||
else if (key_size == 16)
|
||||
aes_type = HSM_KEY_AES_128;
|
||||
r = dkek_encode_key(kdata, aes_type, res_APDU, &wrap_len);
|
||||
}
|
||||
if (r != HSM_OK)
|
||||
return SW_EXEC_ERROR();
|
||||
res_APDU_size = wrap_len;
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_key_unwrap() {
|
||||
int key_id = P1(apdu);
|
||||
int key_id = P1(apdu), r = 0;
|
||||
if (P2(apdu) != 0x93)
|
||||
return SW_WRONG_P1P2();
|
||||
if (!isUserAuthenticated)
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id);
|
||||
if (!ef)
|
||||
ef = file_new((KEY_PREFIX << 8) | key_id);
|
||||
flash_write_data_to_file(ef, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
|
||||
low_flash_available();
|
||||
int key_type = dkek_type_key(apdu.cmd_apdu_data);
|
||||
if (key_type == 0x0)
|
||||
return SW_DATA_INVALID();
|
||||
if (key_type == HSM_KEY_RSA) {
|
||||
mbedtls_rsa_context ctx;
|
||||
mbedtls_rsa_init(&ctx);
|
||||
r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, NULL);
|
||||
if (r != HSM_OK) {
|
||||
mbedtls_rsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
sc_context_t *card_ctx = create_context();
|
||||
r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_RSA, key_id, card_ctx);
|
||||
free(card_ctx);
|
||||
mbedtls_rsa_free(&ctx);
|
||||
if (r != HSM_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
else if (key_type == HSM_KEY_EC) {
|
||||
mbedtls_ecdsa_context ctx;
|
||||
mbedtls_ecdsa_init(&ctx);
|
||||
r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, NULL);
|
||||
if (r != HSM_OK) {
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
sc_context_t *card_ctx = create_context();
|
||||
r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_EC, key_id, card_ctx);
|
||||
free(card_ctx);
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
if (r != HSM_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
else if (key_type == HSM_KEY_AES) {
|
||||
uint8_t aes_key[32];
|
||||
int key_size = 0, aes_type;
|
||||
r = dkek_decode_key(aes_key, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, &key_size);
|
||||
if (r != HSM_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
if (key_size == 32)
|
||||
aes_type = HSM_KEY_AES_256;
|
||||
else if (key_size == 24)
|
||||
aes_type = HSM_KEY_AES_192;
|
||||
else if (key_size == 16)
|
||||
aes_type = HSM_KEY_AES_128;
|
||||
sc_context_t *card_ctx = create_context();
|
||||
r = store_keys(aes_key, aes_type, key_id, card_ctx);
|
||||
free(card_ctx);
|
||||
if (r != HSM_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
|
|
@ -1500,15 +1452,12 @@ static int cmd_decrypt_asym() {
|
|||
else if (P2(apdu) == ALGO_EC_DH) {
|
||||
mbedtls_ecdh_context ctx;
|
||||
int key_size = file_read_uint16(ef->data);
|
||||
if (load_dkek() != HSM_OK)
|
||||
return SW_EXEC_ERROR();
|
||||
uint8_t *kdata = (uint8_t *)calloc(1,key_size);
|
||||
memcpy(kdata, file_read(ef->data+2), key_size);
|
||||
if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0) {
|
||||
if (dkek_decrypt(kdata, key_size) != 0) {
|
||||
free(kdata);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
release_dkek();
|
||||
mbedtls_ecdh_init(&ctx);
|
||||
mbedtls_ecp_group_id gid = kdata[0];
|
||||
int r = 0;
|
||||
|
|
@ -1557,14 +1506,11 @@ static int cmd_cipher_sym() {
|
|||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
int key_size = file_read_uint16(ef->data);
|
||||
if (load_dkek() != HSM_OK)
|
||||
return SW_EXEC_ERROR();
|
||||
uint8_t kdata[32]; //maximum AES key size
|
||||
memcpy(kdata, file_read(ef->data+2), key_size);
|
||||
if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0) {
|
||||
if (dkek_decrypt(kdata, key_size) != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
release_dkek();
|
||||
if (algo == ALGO_AES_CBC_ENCRYPT || algo == ALGO_AES_CBC_DECRYPT) {
|
||||
mbedtls_aes_context aes;
|
||||
mbedtls_aes_init(&aes);
|
||||
|
|
@ -1610,7 +1556,7 @@ static int cmd_cipher_sym() {
|
|||
int r = mbedtls_cipher_cmac(cipher_info, kdata, key_size*8, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, res_APDU);
|
||||
if (r != 0)
|
||||
return SW_EXEC_ERROR();
|
||||
res_APDU_size = apdu.cmd_apdu_data_len;
|
||||
res_APDU_size = 16;
|
||||
}
|
||||
else if (algo == ALGO_AES_DERIVE) {
|
||||
int r = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), NULL, 0, file_read(ef->data+2), key_size, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, res_APDU, apdu.cmd_apdu_data_len);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,11 @@ extern const uint8_t sc_hsm_aid[];
|
|||
#define HSM_ERR_BLOCKED -1004
|
||||
#define HSM_NO_LOGIN -1005
|
||||
#define HSM_EXEC_ERROR -1006
|
||||
#define HSM_WRONG_LENGTH -1007
|
||||
#define HSM_WRONG_DATA -1008
|
||||
#define HSM_WRONG_DKEK -1009
|
||||
#define HSM_WRONG_SIGNATURE -1010
|
||||
#define HSM_WRONG_PADDING -1011
|
||||
|
||||
#define ALGO_RSA_RAW 0x20 /* RSA signature with external padding */
|
||||
#define ALGO_RSA_DECRYPT 0x21 /* RSA decrypt */
|
||||
|
|
@ -92,6 +97,10 @@ extern const uint8_t sc_hsm_aid[];
|
|||
#define HSM_OPT_COMBINED_AUTH 0x10
|
||||
#define HSM_OPT_RRC_RESET_ONLY 0x20
|
||||
|
||||
#define P15_KEYTYPE_RSA 0x30
|
||||
#define P15_KEYTYPE_ECC 0xA0
|
||||
#define P15_KEYTYPE_AES 0xA8
|
||||
|
||||
extern int pin_reset_retries(const file_t *pin, bool);
|
||||
extern int pin_wrong_retry(const file_t *pin);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef __VERSION_H_
|
||||
#define __VERSION_H_
|
||||
|
||||
#define HSM_VERSION 0x0106
|
||||
#define HSM_VERSION 0x0108
|
||||
|
||||
#define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff)
|
||||
#define HSM_VERSION_MINOR (HSM_VERSION & 0xff)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@
|
|||
#ifndef _RANDOM_H_
|
||||
#define _RANDOM_H_
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
void random_init (void);
|
||||
void random_fini (void);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue