Merge branch 'eac'. Support for PKCS#12 imports with SCS3.

This commit is contained in:
Pol Henarejos 2022-03-31 11:37:18 +02:00
commit 1a5e6a7edc
No known key found for this signature in database
GPG key ID: C0095B7870A4CCD3
9 changed files with 896 additions and 239 deletions

View file

@ -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
View 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
View 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
View 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
View 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

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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);