Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78d71a6d9c | ||
|
|
0a2740fbab | ||
|
|
3192e928ff | ||
|
|
ae1e2ac111 | ||
|
|
d87073f4cc | ||
|
|
36a8f78313 | ||
|
|
0628d5015c | ||
|
|
daf0f98660 | ||
|
|
1f06c44a89 | ||
|
|
ab1490a50b | ||
|
|
23f53a6095 |
@@ -53,6 +53,20 @@ target_sources(pico_hsm PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/md5.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/ripemd160.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/sha1.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/ecdh.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/cmac.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/cipher.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/cipher_wrap.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/chachapoly.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/camellia.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/chacha20.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/aria.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/poly1305.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/gcm.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/ccm.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/des.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/nist_kw.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/hkdf.c
|
||||
|
||||
${CMAKE_CURRENT_LIST_DIR}/OpenSC/src/libopensc/pkcs15.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/OpenSC/src/libopensc/pkcs15-prkey.c
|
||||
|
||||
@@ -4,6 +4,7 @@ Pico HSM supports in place decryption with the following algorithms:
|
||||
* RSA-PKCS
|
||||
* RSA-X-509
|
||||
* RSA-PKCS-OAEP
|
||||
* ECDH-DERIVE
|
||||
|
||||
First, we generate the data:
|
||||
```
|
||||
@@ -76,3 +77,35 @@ OAEP parameters: hashAlg=SHA256, mgf=MGF1-SHA256, source_type=0, source_ptr=0x0,
|
||||
This is a test string. Be safe, be secure.
|
||||
```
|
||||
|
||||
## ECDH-DERIVE
|
||||
ECC keys do not allow ciphering operations. Instead, the ECDH scheme provides a mechanism to exchange a shared symmetric key without transmitting it to the remote part. The shared key is composed by multiplying the local private key and the remote public key.
|
||||
|
||||
First, we create the remote part, Bob, by generating an ECC keypair and getting the public key:
|
||||
```
|
||||
$ openssl ecparam -genkey -name prime192v1 > bob.pem
|
||||
$ openssl ec -in bob.pem -pubout -outform DER > bob.der
|
||||
```
|
||||
|
||||
We derive the shared key by giving the Bob's public key to the Pico HSM:
|
||||
```
|
||||
$ pkcs11-tool --pin 648219 --id 11 --derive -i bob.der -o mine-bob.der
|
||||
```
|
||||
|
||||
We compute the other shared key, with Bob's private key and our public key:
|
||||
```
|
||||
$ openssl pkeyutl -derive -out bob-mine.der -inkey bob.pem -peerkey 11.pub
|
||||
```
|
||||
|
||||
Finally, we compare both shared keys:
|
||||
```
|
||||
$ cmp bob-mine.der mine-bob.der
|
||||
```
|
||||
No output is displayed if both are equal.
|
||||
|
||||
You can also view the contents of both keys:
|
||||
```
|
||||
$ xxd -p bob-mine.der
|
||||
9874558aefa9d92cc051e5da6d1753987e5314925d6d78bf
|
||||
$ xxd -p mine-bob.der
|
||||
9874558aefa9d92cc051e5da6d1753987e5314925d6d78bf
|
||||
```
|
||||
|
||||
@@ -279,8 +279,8 @@ void scan_flash() {
|
||||
if (base == 0x0) //all is empty
|
||||
break;
|
||||
|
||||
uint16_t fid = flash_read_uint16(base+sizeof(uintptr_t));
|
||||
printf("scan fid %x\r\n",fid);
|
||||
uint16_t fid = flash_read_uint16(base+sizeof(uintptr_t)+sizeof(uintptr_t));
|
||||
printf("[%x] scan fid %x, len %d\r\n",base,fid,flash_read_uint16(base+sizeof(uintptr_t)+sizeof(uintptr_t)+sizeof(uint16_t)));
|
||||
file_t *file = (file_t *)search_by_fid(fid, NULL, SPECIFY_EF);
|
||||
if (!file) {
|
||||
file = file_new(fid);
|
||||
@@ -301,7 +301,7 @@ void scan_flash() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
file->data = (uint8_t *)(base+sizeof(uintptr_t)+sizeof(uint16_t));
|
||||
file->data = (uint8_t *)(base+sizeof(uintptr_t)+sizeof(uintptr_t)+sizeof(uint16_t));
|
||||
if (flash_read_uintptr(base) == 0x0) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -8,10 +8,17 @@
|
||||
#include "file.h"
|
||||
#include "sc_hsm.h"
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* | |
|
||||
* | next_addr | prev_addr | fid | data (len + payload) |
|
||||
* | |
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
#define FLASH_TARGET_OFFSET (PICO_FLASH_SIZE_BYTES >> 1) // DATA starts at the mid of flash
|
||||
#define FLASH_DATA_HEADER_SIZE (sizeof(uintptr_t)+sizeof(uint32_t))
|
||||
|
||||
//To avoid possible future allocations, data region starts at the begining of flash and goes upwards to the center region
|
||||
//To avoid possible future allocations, data region starts at the end of flash and goes upwards to the center region
|
||||
|
||||
const uintptr_t start_data_pool = (XIP_BASE + FLASH_TARGET_OFFSET);
|
||||
const uintptr_t end_data_pool = (XIP_BASE + PICO_FLASH_SIZE_BYTES)-FLASH_DATA_HEADER_SIZE; //This is a fixed value. DO NOT CHANGE
|
||||
@@ -25,33 +32,10 @@ extern uint16_t flash_read_uint16(uintptr_t addr);
|
||||
|
||||
extern void low_flash_available();
|
||||
|
||||
/*
|
||||
* Flash data pool managenent
|
||||
*
|
||||
* Flash data pool consists of two parts:
|
||||
* 2-byte header
|
||||
* contents
|
||||
*
|
||||
* Flash data pool objects:
|
||||
* Data Object (DO) (of smart card)
|
||||
* Internal objects:
|
||||
* NONE (0x0000)
|
||||
* 123-counter
|
||||
* 14-bit counter
|
||||
* bool object
|
||||
* small enum
|
||||
*
|
||||
* Format of a Data Object:
|
||||
* NR: 8-bit tag_number
|
||||
* LEN: 8-bit length
|
||||
* DATA: data * LEN
|
||||
* PAD: optional byte for 16-bit alignment
|
||||
*/
|
||||
|
||||
uintptr_t allocate_free_addr(uint16_t size) {
|
||||
if (size > FLASH_SECTOR_SIZE)
|
||||
return 0x0; //ERROR
|
||||
size_t real_size = size+sizeof(uint16_t)+sizeof(uintptr_t)+sizeof(uint16_t); //len+len size+next address+fid
|
||||
size_t real_size = size+sizeof(uint16_t)+sizeof(uintptr_t)+sizeof(uint16_t)+sizeof(uintptr_t); //len+len size+next address+fid+prev_addr size
|
||||
uintptr_t next_base = 0x0;
|
||||
for (uintptr_t base = end_data_pool; base >= start_data_pool; base = next_base) {
|
||||
uintptr_t addr_alg = base & -FLASH_SECTOR_SIZE; //start address of sector
|
||||
@@ -64,20 +48,23 @@ uintptr_t allocate_free_addr(uint16_t size) {
|
||||
if (addr_alg <= potential_addr) //it fits in the current sector
|
||||
{
|
||||
flash_program_uintptr(potential_addr, 0x0);
|
||||
flash_program_uintptr(potential_addr+sizeof(uintptr_t), base);
|
||||
flash_program_uintptr(base, potential_addr);
|
||||
return potential_addr;
|
||||
}
|
||||
else if (addr_alg-FLASH_SECTOR_SIZE >= start_data_pool) { //check whether it fits in the next sector, so we take addr_aligned as the base
|
||||
potential_addr = addr_alg-real_size;
|
||||
flash_program_uintptr(potential_addr, 0x0);
|
||||
flash_program_uintptr(potential_addr+sizeof(uintptr_t), base);
|
||||
flash_program_uintptr(base, potential_addr);
|
||||
return potential_addr;
|
||||
}
|
||||
return 0x0;
|
||||
}
|
||||
//we check if |base-(next_addr+size_next_addr)| > |base-potential_addr| only if fid != 1xxx (not size blocked)
|
||||
else if (addr_alg <= potential_addr && base-(next_base+flash_read_uint16(next_base+sizeof(uintptr_t)+sizeof(uint16_t))+2*sizeof(uint16_t)) > base-potential_addr && flash_read_uint16(next_base+sizeof(uintptr_t)) & 0x1000 != 0x1000) {
|
||||
else if (addr_alg <= potential_addr && base-(next_base+flash_read_uint16(next_base+sizeof(uintptr_t)+sizeof(uintptr_t)+sizeof(uint16_t))+2*sizeof(uint16_t)+2*sizeof(uintptr_t)) > base-potential_addr && flash_read_uint16(next_base+sizeof(uintptr_t)) & 0x1000 != 0x1000) {
|
||||
flash_program_uintptr(potential_addr, next_base);
|
||||
flash_program_uintptr(potential_addr+sizeof(uintptr_t), base);
|
||||
flash_program_uintptr(base, potential_addr);
|
||||
return potential_addr;
|
||||
}
|
||||
@@ -86,13 +73,16 @@ uintptr_t allocate_free_addr(uint16_t size) {
|
||||
}
|
||||
|
||||
int flash_clear_file(file_t *file) {
|
||||
uintptr_t prev_addr = (uintptr_t)(file->data+flash_read_uint16((uintptr_t)file->data)+sizeof(uint16_t));
|
||||
uintptr_t base_addr = (uintptr_t)(file->data-sizeof(uintptr_t)-sizeof(uint16_t));
|
||||
uintptr_t base_addr = (uintptr_t)(file->data-sizeof(uintptr_t)-sizeof(uint16_t)-sizeof(uintptr_t));
|
||||
uintptr_t prev_addr = flash_read_uintptr(base_addr+sizeof(uintptr_t));
|
||||
uintptr_t next_addr = flash_read_uintptr(base_addr);
|
||||
//printf("nc %x %x %x\r\n",prev_addr,base_addr,next_addr);
|
||||
//printf("nc %x->%x %x->%x\r\n",prev_addr,flash_read_uintptr(prev_addr),base_addr,next_addr);
|
||||
flash_program_uintptr(prev_addr, next_addr);
|
||||
flash_program_halfword((uintptr_t)file->data, 0);
|
||||
return 0;
|
||||
if (next_addr > 0)
|
||||
flash_program_uintptr(next_addr+sizeof(uintptr_t), prev_addr);
|
||||
//printf("na %x->%x\r\n",prev_addr,flash_read_uintptr(prev_addr));
|
||||
return HSM_OK;
|
||||
}
|
||||
|
||||
int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len) {
|
||||
@@ -116,8 +106,8 @@ int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len) {
|
||||
//printf("na %x\r\n",new_addr);
|
||||
if (new_addr == 0x0)
|
||||
return HSM_ERR_NO_MEMORY;
|
||||
file->data = (uint8_t *)new_addr+sizeof(uintptr_t)+sizeof(uint16_t); //next addr+fid
|
||||
flash_program_halfword(new_addr+sizeof(uintptr_t), file->fid);
|
||||
file->data = (uint8_t *)new_addr+sizeof(uintptr_t)+sizeof(uint16_t)+sizeof(uintptr_t); //next addr+fid+prev addr
|
||||
flash_program_halfword(new_addr+sizeof(uintptr_t)+sizeof(uintptr_t), file->fid);
|
||||
flash_program_halfword((uintptr_t)file->data, len);
|
||||
if (data)
|
||||
flash_program_block((uintptr_t)file->data+sizeof(uint16_t), data, len);
|
||||
|
||||
135
src/hsm/sc_hsm.c
135
src/hsm/sc_hsm.c
@@ -8,6 +8,9 @@
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/ecdsa.h"
|
||||
#include "mbedtls/ecdh.h"
|
||||
#include "mbedtls/cmac.h"
|
||||
#include "mbedtls/hkdf.h"
|
||||
#include "version.h"
|
||||
|
||||
const uint8_t sc_hsm_aid[] = {
|
||||
@@ -110,7 +113,7 @@ void select_file(file_t *pe) {
|
||||
}
|
||||
if (currentEF == file_openpgp || currentEF == file_sc_hsm) {
|
||||
selected_applet = currentEF;
|
||||
sc_hsm_unload(); //reset auth status
|
||||
//sc_hsm_unload(); //reset auth status
|
||||
}
|
||||
}
|
||||
static int cmd_select() {
|
||||
@@ -483,8 +486,8 @@ static int cmd_initialize() {
|
||||
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));
|
||||
low_flash_available();
|
||||
}
|
||||
low_flash_available();
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
@@ -679,7 +682,7 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) {
|
||||
free(pukd);
|
||||
free(p15o);
|
||||
//sc_asn1_print_tags(asn1bin, asn1len);
|
||||
fpk = file_new((CD_PREFIX << 8) | key_id);
|
||||
fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id);
|
||||
r = flash_write_data_to_file(fpk, asn1bin, asn1len);
|
||||
free(asn1bin);
|
||||
if (r != HSM_OK)
|
||||
@@ -1218,21 +1221,23 @@ static int cmd_key_gen() {
|
||||
key_size = 24;
|
||||
else if (p2 == 0xB0)
|
||||
key_size = 16;
|
||||
if (!isUserAuthenticated)
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
//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 r;
|
||||
return SW_EXEC_ERROR() ;
|
||||
if ((r = encrypt(tmp_dkek+IV_SIZE, tmp_dkek, aes_key, key_size)) != 0)
|
||||
return r;
|
||||
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);
|
||||
if (r != HSM_OK)
|
||||
return SW_MEMORY_FAILURE();
|
||||
@@ -1246,15 +1251,19 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
|
||||
return SW_EXEC_ERROR();
|
||||
uint8_t *kdata = (uint8_t *)calloc(1,key_size);
|
||||
memcpy(kdata, file_read(fkey->data+2), key_size);
|
||||
if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0)
|
||||
if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0) {
|
||||
free(kdata);
|
||||
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);
|
||||
@@ -1283,15 +1292,19 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) {
|
||||
return SW_EXEC_ERROR();
|
||||
uint8_t *kdata = (uint8_t *)calloc(1,key_size);
|
||||
memcpy(kdata, file_read(fkey->data+2), key_size);
|
||||
if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0)
|
||||
if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0) {
|
||||
free(kdata);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
release_dkek();
|
||||
mbedtls_ecp_group_id gid = kdata[0];
|
||||
if (mbedtls_ecp_group_load(&ctx->grp, gid) != 0) {
|
||||
free(kdata);
|
||||
mbedtls_ecdsa_free(ctx);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
if (mbedtls_mpi_read_binary(&ctx->d, kdata+1, key_size-1) != 0) {
|
||||
free(kdata);
|
||||
mbedtls_ecdsa_free(ctx);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
@@ -1385,10 +1398,8 @@ static int cmd_signature() {
|
||||
}
|
||||
else {
|
||||
uint8_t *signature = (uint8_t *)calloc(key_size, sizeof(uint8_t));
|
||||
printf("md %d\r\n",md);
|
||||
DEBUG_PAYLOAD(hash,hash_len);
|
||||
r = mbedtls_rsa_pkcs1_sign(&ctx, random_gen, NULL, md, hash_len, hash, signature);
|
||||
printf("r %d\r\n",r);
|
||||
memcpy(res_APDU, signature, key_size);
|
||||
free(signature);
|
||||
}
|
||||
@@ -1471,28 +1482,73 @@ static int cmd_key_unwrap() {
|
||||
|
||||
static int cmd_decrypt_asym() {
|
||||
int key_id = P1(apdu);
|
||||
if (P2(apdu) != ALGO_RSA_DECRYPT)
|
||||
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)
|
||||
return SW_FILE_NOT_FOUND();
|
||||
mbedtls_rsa_context ctx;
|
||||
mbedtls_rsa_init(&ctx);
|
||||
int r = load_private_key_rsa(&ctx, ef);
|
||||
if (r != HSM_OK)
|
||||
return r;
|
||||
int key_size = file_read_uint16(ef->data);
|
||||
if (apdu.cmd_apdu_data_len < key_size) //needs padding
|
||||
memset(apdu.cmd_apdu_data+apdu.cmd_apdu_data_len, 0, key_size-apdu.cmd_apdu_data_len);
|
||||
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.cmd_apdu_data, res_APDU);
|
||||
if (r != 0) {
|
||||
if (P2(apdu) == ALGO_RSA_DECRYPT) {
|
||||
mbedtls_rsa_context ctx;
|
||||
mbedtls_rsa_init(&ctx);
|
||||
int r = load_private_key_rsa(&ctx, ef);
|
||||
if (r != HSM_OK)
|
||||
return r;
|
||||
int key_size = file_read_uint16(ef->data);
|
||||
if (apdu.cmd_apdu_data_len < key_size) //needs padding
|
||||
memset(apdu.cmd_apdu_data+apdu.cmd_apdu_data_len, 0, key_size-apdu.cmd_apdu_data_len);
|
||||
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.cmd_apdu_data, res_APDU);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = key_size;
|
||||
mbedtls_rsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = key_size;
|
||||
mbedtls_rsa_free(&ctx);
|
||||
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) {
|
||||
free(kdata);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
release_dkek();
|
||||
mbedtls_ecdh_init(&ctx);
|
||||
mbedtls_ecp_group_id gid = kdata[0];
|
||||
int r = 0;
|
||||
r = mbedtls_ecdh_setup(&ctx, gid);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
free(kdata);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
r = mbedtls_mpi_read_binary(&ctx.ctx.mbed_ecdh.d, kdata+1, key_size-1);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
free(kdata);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
free(kdata);
|
||||
r = mbedtls_ecdh_read_public(&ctx, apdu.cmd_apdu_data-1, apdu.cmd_apdu_data_len+1);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
size_t olen = 0;
|
||||
res_APDU[0] = 0x04;
|
||||
r = mbedtls_ecdh_calc_secret(&ctx, &olen, res_APDU+1, MBEDTLS_ECP_MAX_BYTES, random_gen, NULL);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = olen+1;
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
}
|
||||
else
|
||||
return SW_WRONG_P1P2();
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
@@ -1504,6 +1560,9 @@ static int cmd_cipher_sym() {
|
||||
file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id);
|
||||
if (!ef)
|
||||
return SW_FILE_NOT_FOUND();
|
||||
if ((apdu.cmd_apdu_data_len % 16) != 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
int key_size = file_read_uint16(ef->data);
|
||||
if (load_dkek() != HSM_OK)
|
||||
return SW_EXEC_ERROR();
|
||||
@@ -1514,9 +1573,6 @@ static int cmd_cipher_sym() {
|
||||
}
|
||||
release_dkek();
|
||||
if (algo == ALGO_AES_CBC_ENCRYPT || algo == ALGO_AES_CBC_DECRYPT) {
|
||||
if ((apdu.cmd_apdu_data_len % 16) != 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
mbedtls_aes_context aes;
|
||||
mbedtls_aes_init(&aes);
|
||||
uint8_t tmp_iv[IV_SIZE];
|
||||
@@ -1548,6 +1604,27 @@ static int cmd_cipher_sym() {
|
||||
res_APDU_size = apdu.cmd_apdu_data_len;
|
||||
mbedtls_aes_free(&aes);
|
||||
}
|
||||
else if (algo == ALGO_AES_CMAC) {
|
||||
const mbedtls_cipher_info_t *cipher_info;
|
||||
if (key_size == 16)
|
||||
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
|
||||
else if (key_size == 24)
|
||||
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_192_ECB);
|
||||
else if (key_size == 32)
|
||||
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB);
|
||||
else
|
||||
return SW_WRONG_DATA();
|
||||
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;
|
||||
}
|
||||
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);
|
||||
if (r != 0)
|
||||
return SW_EXEC_ERROR();
|
||||
res_APDU_size = apdu.cmd_apdu_data_len;
|
||||
}
|
||||
else {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __VERSION_H_
|
||||
#define __VERSION_H_
|
||||
|
||||
#define HSM_VERSION 0x0102
|
||||
#define HSM_VERSION 0x0104
|
||||
|
||||
#define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff)
|
||||
#define HSM_VERSION_MINOR (HSM_VERSION & 0xff)
|
||||
|
||||
Reference in New Issue
Block a user