mirror of
https://github.com/polhenarejos/pico-hsm.git
synced 2024-09-19 19:00:15 +00:00
Switching to new style.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
parent
e7495d11f2
commit
cd6e280f4f
317
.uncrustify.cfg
Normal file
317
.uncrustify.cfg
Normal file
@ -0,0 +1,317 @@
|
||||
#
|
||||
# Uncrustify Configuration File
|
||||
# File Created With UncrustifyX 0.4.3 (252)
|
||||
#
|
||||
|
||||
# Code-Modifying
|
||||
# --------------
|
||||
|
||||
## Braces
|
||||
|
||||
# Braces on single-line do statement
|
||||
mod_full_brace_do = add # string (add/force/ignore/remove)
|
||||
|
||||
# Braces on single-line else statement
|
||||
mod_full_brace_if = add # string (add/force/ignore/remove)
|
||||
|
||||
# Braces on single-line for statement
|
||||
mod_full_brace_for = add # string (add/force/ignore/remove)
|
||||
|
||||
# Braces on single-line while statement
|
||||
mod_full_brace_while = add # string (add/force/ignore/remove)
|
||||
|
||||
## Parentheses
|
||||
|
||||
# Remove unnecessary parentheses on return statement
|
||||
mod_paren_on_return = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Comments
|
||||
# --------
|
||||
|
||||
## Other
|
||||
|
||||
# Remove leading spaces from multi-line comments
|
||||
cmt_multi_check_last = false # boolean (false/true)
|
||||
|
||||
# General
|
||||
# -------
|
||||
|
||||
## Other
|
||||
|
||||
# Input tab size
|
||||
input_tab_size = 4 # number
|
||||
|
||||
# Indentation
|
||||
# -----------
|
||||
|
||||
## Indentation Size
|
||||
|
||||
# Indentation column size
|
||||
indent_columns = 4 # number
|
||||
|
||||
# Indentation size between case and switch
|
||||
indent_switch_case = 4 # number
|
||||
|
||||
## Other
|
||||
|
||||
# Align strings broken by backslash
|
||||
indent_align_string = true # boolean (false/true)
|
||||
|
||||
# Indent with tabs
|
||||
indent_with_tabs = 0 # number
|
||||
|
||||
# Line-Splitting
|
||||
# --------------
|
||||
|
||||
## Splitting
|
||||
|
||||
# Code width
|
||||
code_width = 100 # number
|
||||
|
||||
# Split long for statements at semicolons
|
||||
ls_for_split_full = true # boolean (false/true)
|
||||
|
||||
# Split long function prototypes/calls at commas
|
||||
ls_func_split_full = true # boolean (false/true)
|
||||
|
||||
# Newlines
|
||||
# --------
|
||||
|
||||
## Newline Between
|
||||
|
||||
# Newline between assignment and open brace
|
||||
nl_assign_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between close brace and else
|
||||
nl_brace_else = add # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between close brace and while
|
||||
nl_brace_while = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between do and open brace
|
||||
nl_do_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between else and open brace
|
||||
nl_else_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between enum and open brace
|
||||
nl_enum_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between for and open brace
|
||||
nl_for_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between function call and open brace
|
||||
nl_fcall_brace = add # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between function signature and open brace
|
||||
nl_fdef_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between if and open brace
|
||||
nl_if_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between struct and open brace
|
||||
nl_struct_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between switch and open brace
|
||||
nl_switch_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between union and open brace
|
||||
nl_union_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Newline between while and open brace
|
||||
nl_while_brace = remove # string (add/force/ignore/remove)
|
||||
|
||||
## Other
|
||||
|
||||
# Newline count at end of file
|
||||
nl_end_of_file_min = 1 # number
|
||||
|
||||
# Newlines at end of file
|
||||
nl_end_of_file = add # string (add/force/ignore/remove)
|
||||
|
||||
# Newlines at start of file
|
||||
nl_start_of_file = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Spacing
|
||||
# -------
|
||||
|
||||
## Space After
|
||||
|
||||
# Space after address-of operator
|
||||
sp_addr = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space after cast
|
||||
sp_after_cast = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space after comma
|
||||
sp_after_comma = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space after dereference operator
|
||||
sp_deref = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space after final semicolon in empty for statement
|
||||
sp_after_semi_for_empty = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space after invert operator
|
||||
sp_inv = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space after not operator
|
||||
sp_not = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space after pointer star
|
||||
sp_after_ptr_star = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space after pointer star followed by function
|
||||
sp_after_ptr_star_func = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space after semicolon
|
||||
sp_after_semi = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space after semicolon in non-empty for statements
|
||||
sp_after_semi_for = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space after sign in assignment
|
||||
sp_sign = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space after type
|
||||
sp_after_type = add # string (add/force/ignore/remove)
|
||||
|
||||
## Space Around
|
||||
|
||||
# Space around arithmetic operators
|
||||
sp_arith = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space around assignment operator
|
||||
sp_assign = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space around boolean operators
|
||||
sp_bool = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space around compare operators
|
||||
sp_compare = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space around increment/decrement operators
|
||||
sp_incdec = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space around member operators
|
||||
sp_member = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space around preprocessor concatenation operator
|
||||
sp_pp_concat = ignore # string (add/force/ignore/remove)
|
||||
|
||||
# Space around ternary condition colon
|
||||
sp_cond_colon = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space around ternary condition question mark
|
||||
sp_cond_question = add # string (add/force/ignore/remove)
|
||||
|
||||
## Space Before
|
||||
|
||||
# Space before backslash-newline at end of line
|
||||
sp_before_nl_cont = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space before case colon
|
||||
sp_before_case_colon = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space before comma
|
||||
sp_before_comma = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space before if/for/switch/while open parenthesis
|
||||
sp_before_sparen = force # string (add/force/ignore/remove)
|
||||
|
||||
# Space before pointer star
|
||||
sp_before_ptr_star = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space before semicolon
|
||||
sp_before_semi = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space before semicolon in empty for statement
|
||||
sp_before_semi_for_empty = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space before semicolon in for statements
|
||||
sp_before_semi_for = remove # string (add/force/ignore/remove)
|
||||
|
||||
## Space Between
|
||||
|
||||
# Space between __attribute__ and open parenthesis
|
||||
sp_attribute_paren = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space between close brace and else
|
||||
sp_brace_else = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space between close brace and typedef name
|
||||
sp_brace_typedef = force # string (add/force/ignore/remove)
|
||||
|
||||
# Space between closing parenthesis and open brace
|
||||
sp_fparen_brace = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space between defined and open parenthesis
|
||||
sp_defined_paren = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space between else and open brace
|
||||
sp_else_brace = force # string (add/force/ignore/remove)
|
||||
|
||||
# Space between function name and open parenthesis
|
||||
sp_func_call_paren = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space between function name and open parenthesis in declaration
|
||||
sp_func_proto_paren = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space between function name and open parenthesis in function definition
|
||||
sp_func_def_paren = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space between if/for/switch/while close parenthesis and open brace
|
||||
sp_sparen_brace = force # string (add/force/ignore/remove)
|
||||
|
||||
# Space between macro and value
|
||||
sp_macro = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space between macro function close parenthesis and value
|
||||
sp_macro_func = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space between nested parentheses
|
||||
sp_paren_paren = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space between pointer stars
|
||||
sp_between_ptr_star = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space between preprocessor else and comment
|
||||
sp_endif_cmt = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space between return type and function name
|
||||
sp_type_func = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space between sizeof and open parenthesis
|
||||
sp_sizeof_paren = remove # string (add/force/ignore/remove)
|
||||
|
||||
## Space Inside
|
||||
|
||||
# Space inside braces
|
||||
sp_inside_braces = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space inside cast parentheses
|
||||
sp_inside_paren_cast = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space inside empty function parentheses
|
||||
sp_inside_fparens = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space inside enum braces
|
||||
sp_inside_braces_enum = add # string (add/force/ignore/remove)
|
||||
|
||||
# Space inside function parentheses
|
||||
sp_inside_fparen = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space inside if-condition parentheses
|
||||
sp_inside_sparen = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space inside non-empty square brackets
|
||||
sp_inside_square = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space inside parentheses
|
||||
sp_inside_paren = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space inside parentheses in function type
|
||||
sp_inside_tparen = remove # string (add/force/ignore/remove)
|
||||
|
||||
# Space inside struct/union braces
|
||||
sp_inside_braces_struct = add # string (add/force/ignore/remove)
|
@ -1 +1 @@
|
||||
Subproject commit 12bdcbd1f91f5b5763ad66b212be897ae9eb87a8
|
||||
Subproject commit 43ef33d60b43ddeed5878ded08df37001636d811
|
@ -21,8 +21,7 @@
|
||||
uint8_t challenge[256];
|
||||
uint8_t challenge_len = 0;
|
||||
|
||||
int cmd_challenge()
|
||||
{
|
||||
int cmd_challenge() {
|
||||
uint8_t *rb = (uint8_t *) random_bytes_get(apdu.ne);
|
||||
if (!rb) {
|
||||
return SW_WRONG_LENGTH();
|
||||
|
@ -19,14 +19,14 @@
|
||||
#include "sc_hsm.h"
|
||||
#include "kek.h"
|
||||
|
||||
int cmd_change_pin()
|
||||
{
|
||||
int cmd_change_pin() {
|
||||
if (P1(apdu) == 0x0) {
|
||||
if (P2(apdu) == 0x81 || P2(apdu) == 0x88) {
|
||||
file_t *file_pin = NULL;
|
||||
if (P2(apdu) == 0x81) {
|
||||
file_pin = file_pin1;
|
||||
} else if (P2(apdu) == 0x88) {
|
||||
}
|
||||
else if (P2(apdu) == 0x88) {
|
||||
file_pin = file_sopin;
|
||||
}
|
||||
if (!file_pin) {
|
||||
@ -48,10 +48,11 @@ int cmd_change_pin()
|
||||
//encrypt MKEK with new pin
|
||||
|
||||
if (P2(apdu) == 0x81) {
|
||||
hash_multi(apdu.data+pin_len, apdu.nc-pin_len, session_pin);
|
||||
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_pin);
|
||||
has_session_pin = true;
|
||||
} else if (P2(apdu) == 0x88) {
|
||||
hash_multi(apdu.data+pin_len, apdu.nc-pin_len, session_sopin);
|
||||
}
|
||||
else if (P2(apdu) == 0x88) {
|
||||
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_sopin);
|
||||
has_session_sopin = true;
|
||||
}
|
||||
r = store_mkek(mkek);
|
||||
@ -60,8 +61,8 @@ int cmd_change_pin()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
uint8_t dhash[33];
|
||||
dhash[0] = apdu.nc-pin_len;
|
||||
double_hash_pin(apdu.data+pin_len, apdu.nc-pin_len, dhash+1);
|
||||
dhash[0] = apdu.nc - pin_len;
|
||||
double_hash_pin(apdu.data + pin_len, apdu.nc - pin_len, dhash + 1);
|
||||
flash_write_data_to_file(file_pin, dhash, sizeof(dhash));
|
||||
low_flash_available();
|
||||
return SW_OK();
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
|
||||
mbedtls_asn1_buf *salt, int *iterations,
|
||||
int *keylen, mbedtls_md_type_t *md_type)
|
||||
{
|
||||
int *keylen, mbedtls_md_type_t *md_type) {
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_asn1_buf prf_alg_oid;
|
||||
unsigned char *p = params->p;
|
||||
@ -107,8 +106,7 @@ int mbedtls_ansi_x936_kdf(mbedtls_md_type_t md_type,
|
||||
size_t shared_info_len,
|
||||
uint8_t *shared_info,
|
||||
size_t output_len,
|
||||
uint8_t *output)
|
||||
{
|
||||
uint8_t *output) {
|
||||
mbedtls_md_context_t md_ctx;
|
||||
const mbedtls_md_info_t *md_info = NULL;
|
||||
int hashlen = 0, exit_code = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
|
||||
@ -126,13 +124,13 @@ int mbedtls_ansi_x936_kdf(mbedtls_md_type_t md_type,
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
if (input_len + shared_info_len + 4 >= (1ULL<<61)-1) {
|
||||
if (input_len + shared_info_len + 4 >= (1ULL << 61) - 1) {
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
// keydatalen equals output_len
|
||||
hashlen = md_info->size;
|
||||
if (output_len >= hashlen * ((1ULL<<32)-1)) {
|
||||
if (output_len >= hashlen * ((1ULL << 32) - 1)) {
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
@ -159,8 +157,7 @@ int mbedtls_ansi_x936_kdf(mbedtls_md_type_t md_type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_cipher_sym()
|
||||
{
|
||||
int cmd_cipher_sym() {
|
||||
int key_id = P1(apdu);
|
||||
int algo = P2(apdu);
|
||||
if (!isUserAuthenticated) {
|
||||
@ -191,7 +188,7 @@ int cmd_cipher_sym()
|
||||
uint8_t tmp_iv[IV_SIZE];
|
||||
memset(tmp_iv, 0, sizeof(tmp_iv));
|
||||
if (algo == ALGO_AES_CBC_ENCRYPT) {
|
||||
int r = mbedtls_aes_setkey_enc(&aes, kdata, key_size*8);
|
||||
int r = mbedtls_aes_setkey_enc(&aes, kdata, key_size * 8);
|
||||
if (r != 0) {
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
mbedtls_aes_free(&aes);
|
||||
@ -208,8 +205,9 @@ int cmd_cipher_sym()
|
||||
mbedtls_aes_free(&aes);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
} else if (algo == ALGO_AES_CBC_DECRYPT) {
|
||||
int r = mbedtls_aes_setkey_dec(&aes, kdata, key_size*8);
|
||||
}
|
||||
else if (algo == ALGO_AES_CBC_DECRYPT) {
|
||||
int r = mbedtls_aes_setkey_dec(&aes, kdata, key_size * 8);
|
||||
if (r != 0) {
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
mbedtls_aes_free(&aes);
|
||||
@ -229,25 +227,30 @@ int cmd_cipher_sym()
|
||||
}
|
||||
res_APDU_size = apdu.nc;
|
||||
mbedtls_aes_free(&aes);
|
||||
} else if (algo == ALGO_AES_CMAC) {
|
||||
}
|
||||
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) {
|
||||
}
|
||||
else if (key_size == 24) {
|
||||
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_192_ECB);
|
||||
} else if (key_size == 32) {
|
||||
}
|
||||
else if (key_size == 32) {
|
||||
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
int r = mbedtls_cipher_cmac(cipher_info, kdata, key_size*8, apdu.data, apdu.nc, res_APDU);
|
||||
int r = mbedtls_cipher_cmac(cipher_info, kdata, key_size * 8, apdu.data, apdu.nc, res_APDU);
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
if (r != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = 16;
|
||||
} else if (algo == ALGO_AES_DERIVE) {
|
||||
}
|
||||
else if (algo == ALGO_AES_DERIVE) {
|
||||
int r = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
|
||||
NULL,
|
||||
0,
|
||||
@ -262,7 +265,8 @@ int cmd_cipher_sym()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = apdu.nc;
|
||||
} else if (algo == ALGO_EXT_CIPHER_ENCRYPT || algo == ALGO_EXT_CIPHER_DECRYPT) {
|
||||
}
|
||||
else if (algo == ALGO_EXT_CIPHER_ENCRYPT || algo == ALGO_EXT_CIPHER_DECRYPT) {
|
||||
size_t oid_len = 0, aad_len = 0, iv_len = 0, enc_len = 0;
|
||||
uint8_t *oid = NULL, *aad = NULL, *iv = NULL, *enc = NULL;
|
||||
if (!asn1_find_tag(apdu.data, apdu.nc, 0x6, &oid_len,
|
||||
@ -292,7 +296,8 @@ int cmd_cipher_sym()
|
||||
enc,
|
||||
res_APDU,
|
||||
res_APDU + enc_len);
|
||||
} else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
|
||||
}
|
||||
else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
|
||||
r = mbedtls_chachapoly_auth_decrypt(&ctx,
|
||||
enc_len - 16,
|
||||
iv ? iv : tmp_iv,
|
||||
@ -309,20 +314,26 @@ int cmd_cipher_sym()
|
||||
}
|
||||
if (algo == ALGO_EXT_CIPHER_ENCRYPT) {
|
||||
res_APDU_size = enc_len + 16;
|
||||
} else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
|
||||
}
|
||||
else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
|
||||
res_APDU_size = enc_len - 16;
|
||||
}
|
||||
} else if (memcmp(oid, OID_DIGEST, 7) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_DIGEST, 7) == 0) {
|
||||
const mbedtls_md_info_t *md_info = NULL;
|
||||
if (memcmp(oid, OID_HMAC_SHA1, oid_len) == 0) {
|
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
|
||||
} else if (memcmp(oid, OID_HMAC_SHA224, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_HMAC_SHA224, oid_len) == 0) {
|
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA224);
|
||||
} else if (memcmp(oid, OID_HMAC_SHA256, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_HMAC_SHA256, oid_len) == 0) {
|
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
|
||||
} else if (memcmp(oid, OID_HMAC_SHA384, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_HMAC_SHA384, oid_len) == 0) {
|
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
|
||||
} else if (memcmp(oid, OID_HMAC_SHA512, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_HMAC_SHA512, oid_len) == 0) {
|
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
|
||||
}
|
||||
if (md_info == NULL) {
|
||||
@ -334,16 +345,19 @@ int cmd_cipher_sym()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = md_info->size;
|
||||
} else if (memcmp(oid, OID_HKDF_SHA256,
|
||||
oid_len) == 0 ||
|
||||
memcmp(oid, OID_HKDF_SHA384,
|
||||
oid_len) == 0 || memcmp(oid, OID_HKDF_SHA512, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_HKDF_SHA256,
|
||||
oid_len) == 0 ||
|
||||
memcmp(oid, OID_HKDF_SHA384,
|
||||
oid_len) == 0 || memcmp(oid, OID_HKDF_SHA512, oid_len) == 0) {
|
||||
const mbedtls_md_info_t *md_info = NULL;
|
||||
if (memcmp(oid, OID_HKDF_SHA256, oid_len) == 0) {
|
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
|
||||
} else if (memcmp(oid, OID_HKDF_SHA384, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_HKDF_SHA384, oid_len) == 0) {
|
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
|
||||
} else if (memcmp(oid, OID_HKDF_SHA512, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_HKDF_SHA512, oid_len) == 0) {
|
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
|
||||
}
|
||||
int r = mbedtls_hkdf(md_info,
|
||||
@ -361,7 +375,8 @@ int cmd_cipher_sym()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : mbedtls_md_get_size(md_info);
|
||||
} else if (memcmp(oid, OID_PKCS5_PBKDF2, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_PKCS5_PBKDF2, oid_len) == 0) {
|
||||
int iterations = 0, keylen = 0;
|
||||
mbedtls_asn1_buf salt,
|
||||
params =
|
||||
@ -396,7 +411,8 @@ int cmd_cipher_sym()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = keylen ? keylen : (apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32);
|
||||
} else if (memcmp(oid, OID_PKCS5_PBES2, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_PKCS5_PBES2, oid_len) == 0) {
|
||||
mbedtls_asn1_buf params =
|
||||
{ .p = aad, .len = aad_len, .tag = (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) };
|
||||
int r = mbedtls_pkcs5_pbes2(¶ms,
|
||||
@ -411,17 +427,22 @@ int cmd_cipher_sym()
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
res_APDU_size = enc_len;
|
||||
} else if (memcmp(oid, OID_KDF_X963, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_KDF_X963, oid_len) == 0) {
|
||||
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
|
||||
if (memcmp(enc, OID_HMAC_SHA1, enc_len) == 0) {
|
||||
md_type = MBEDTLS_MD_SHA1;
|
||||
} else if (memcmp(enc, OID_HMAC_SHA224, enc_len) == 0) {
|
||||
}
|
||||
else if (memcmp(enc, OID_HMAC_SHA224, enc_len) == 0) {
|
||||
md_type = MBEDTLS_MD_SHA224;
|
||||
} else if (memcmp(enc, OID_HMAC_SHA256, enc_len) == 0) {
|
||||
}
|
||||
else if (memcmp(enc, OID_HMAC_SHA256, enc_len) == 0) {
|
||||
md_type = MBEDTLS_MD_SHA256;
|
||||
} else if (memcmp(enc, OID_HMAC_SHA384, enc_len) == 0) {
|
||||
}
|
||||
else if (memcmp(enc, OID_HMAC_SHA384, enc_len) == 0) {
|
||||
md_type = MBEDTLS_MD_SHA384;
|
||||
} else if (memcmp(enc, OID_HMAC_SHA512, enc_len) == 0) {
|
||||
}
|
||||
else if (memcmp(enc, OID_HMAC_SHA512, enc_len) == 0) {
|
||||
md_type = MBEDTLS_MD_SHA512;
|
||||
}
|
||||
int r = mbedtls_ansi_x936_kdf(md_type,
|
||||
@ -437,7 +458,8 @@ int cmd_cipher_sym()
|
||||
}
|
||||
res_APDU_size = apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
|
@ -26,8 +26,7 @@
|
||||
#include "random.h"
|
||||
#include "oid.h"
|
||||
|
||||
int cmd_decrypt_asym()
|
||||
{
|
||||
int cmd_decrypt_asym() {
|
||||
int key_id = P1(apdu);
|
||||
uint8_t p2 = P2(apdu);
|
||||
if (!isUserAuthenticated) {
|
||||
@ -59,7 +58,7 @@ int cmd_decrypt_asym()
|
||||
}
|
||||
int key_size = file_get_size(ef);
|
||||
if (apdu.nc < key_size) { //needs padding
|
||||
memset(apdu.data+apdu.nc, 0, key_size-apdu.nc);
|
||||
memset(apdu.data + apdu.nc, 0, key_size - apdu.nc);
|
||||
}
|
||||
if (p2 == ALGO_RSA_DECRYPT_PKCS1 || p2 == ALGO_RSA_DECRYPT_OEP) {
|
||||
size_t olen = apdu.nc;
|
||||
@ -67,7 +66,8 @@ int cmd_decrypt_asym()
|
||||
if (r == 0) {
|
||||
res_APDU_size = olen;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU);
|
||||
if (r == 0) {
|
||||
res_APDU_size = key_size;
|
||||
@ -78,7 +78,8 @@ int cmd_decrypt_asym()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
mbedtls_rsa_free(&ctx);
|
||||
} else if (p2 == ALGO_EC_DH || p2 == ALGO_EC_DH_XKEK) {
|
||||
}
|
||||
else if (p2 == ALGO_EC_DH || p2 == ALGO_EC_DH_XKEK) {
|
||||
mbedtls_ecdh_context ctx;
|
||||
if (wait_button_pressed() == true) { //timeout
|
||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||
@ -101,7 +102,7 @@ int cmd_decrypt_asym()
|
||||
free(kdata);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
r = mbedtls_mpi_read_binary(&ctx.ctx.mbed_ecdh.d, kdata+1, key_size-1);
|
||||
r = mbedtls_mpi_read_binary(&ctx.ctx.mbed_ecdh.d, kdata + 1, key_size - 1);
|
||||
mbedtls_platform_zeroize(kdata, key_size);
|
||||
free(kdata);
|
||||
if (r != 0) {
|
||||
@ -110,15 +111,16 @@ int cmd_decrypt_asym()
|
||||
}
|
||||
r = -1;
|
||||
if (p2 == ALGO_EC_DH) {
|
||||
r = mbedtls_ecdh_read_public(&ctx, apdu.data-1, apdu.nc+1);
|
||||
} else if (p2 == ALGO_EC_DH_XKEK) {
|
||||
r = mbedtls_ecdh_read_public(&ctx, apdu.data - 1, apdu.nc + 1);
|
||||
}
|
||||
else if (p2 == ALGO_EC_DH_XKEK) {
|
||||
size_t pub_len = 0;
|
||||
const uint8_t *pub = cvc_get_pub(apdu.data, apdu.nc, &pub_len);
|
||||
if (pub) {
|
||||
size_t t86_len = 0;
|
||||
const uint8_t *t86 = cvc_get_field(pub, pub_len, &t86_len, 0x86);
|
||||
if (t86) {
|
||||
r = mbedtls_ecdh_read_public(&ctx, t86-1, t86_len+1);
|
||||
r = mbedtls_ecdh_read_public(&ctx, t86 - 1, t86_len + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -136,7 +138,8 @@ int cmd_decrypt_asym()
|
||||
}
|
||||
if (p2 == ALGO_EC_DH) {
|
||||
res_APDU_size = olen;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
res_APDU_size = 0;
|
||||
size_t ext_len = 0;
|
||||
const uint8_t *ext = NULL;
|
||||
@ -167,11 +170,11 @@ int cmd_decrypt_asym()
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
for (int n = 0; n < MAX_KEY_DOMAINS; n++) {
|
||||
file_t *tf = search_dynamic_file(EF_XKEK+n);
|
||||
file_t *tf = search_dynamic_file(EF_XKEK + n);
|
||||
if (tf) {
|
||||
if (file_get_size(tf) == kdom_uid_len &&
|
||||
memcmp(file_get_data(tf), kdom_uid, kdom_uid_len) == 0) {
|
||||
file_new(EF_DKEK+n);
|
||||
file_new(EF_DKEK + n);
|
||||
if (store_dkek_key(n, res_APDU) != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
@ -181,7 +184,8 @@ int cmd_decrypt_asym()
|
||||
}
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
decrement_key_counter(ef);
|
||||
|
@ -17,8 +17,7 @@
|
||||
|
||||
#include "sc_hsm.h"
|
||||
|
||||
int cmd_delete_file()
|
||||
{
|
||||
int cmd_delete_file() {
|
||||
file_t *ef = NULL;
|
||||
if (!isUserAuthenticated) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
@ -29,7 +28,8 @@ int cmd_delete_file()
|
||||
if (!(ef = search_dynamic_file(ef->fid))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint16_t fid = (apdu.data[0] << 8) | apdu.data[1];
|
||||
if (!(ef = search_dynamic_file(fid))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
|
@ -28,8 +28,7 @@
|
||||
static inline int mbedtls_mpi_add_mod(const mbedtls_ecp_group *grp,
|
||||
mbedtls_mpi *X,
|
||||
const mbedtls_mpi *A,
|
||||
const mbedtls_mpi *B)
|
||||
{
|
||||
const mbedtls_mpi *B) {
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, A, B));
|
||||
MOD_ADD(*X);
|
||||
@ -37,8 +36,7 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cmd_derive_asym()
|
||||
{
|
||||
int cmd_derive_asym() {
|
||||
uint8_t key_id = P1(apdu);
|
||||
uint8_t dest_id = P2(apdu);
|
||||
file_t *fkey;
|
||||
@ -70,7 +68,7 @@ int cmd_derive_asym()
|
||||
mbedtls_mpi a, nd;
|
||||
mbedtls_mpi_init(&a);
|
||||
mbedtls_mpi_init(&nd);
|
||||
r = mbedtls_mpi_read_binary(&a, apdu.data+1, apdu.nc-1);
|
||||
r = mbedtls_mpi_read_binary(&a, apdu.data + 1, apdu.nc - 1);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
mbedtls_mpi_free(&a);
|
||||
@ -96,7 +94,8 @@ int cmd_derive_asym()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
return SW_OK();
|
||||
|
@ -24,8 +24,7 @@ extern file_t *ef_puk_aut;
|
||||
extern uint8_t challenge[256];
|
||||
extern uint8_t challenge_len;
|
||||
|
||||
int cmd_external_authenticate()
|
||||
{
|
||||
int cmd_external_authenticate() {
|
||||
if (P1(apdu) != 0x0 || P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@ -40,10 +39,10 @@ int cmd_external_authenticate()
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
uint8_t *puk_data = file_get_data(ef_puk);
|
||||
uint8_t *input = (uint8_t *) calloc(dev_name_len+challenge_len, sizeof(uint8_t)), hash[32];
|
||||
uint8_t *input = (uint8_t *) calloc(dev_name_len + challenge_len, sizeof(uint8_t)), hash[32];
|
||||
memcpy(input, dev_name, dev_name_len);
|
||||
memcpy(input+dev_name_len, challenge, challenge_len);
|
||||
hash256(input, dev_name_len+challenge_len, hash);
|
||||
memcpy(input + dev_name_len, challenge, challenge_len);
|
||||
hash256(input, dev_name_len + challenge_len, hash);
|
||||
int r =
|
||||
puk_verify(apdu.data,
|
||||
apdu.nc,
|
||||
@ -55,7 +54,7 @@ int cmd_external_authenticate()
|
||||
if (r != 0) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
puk_status[ef_puk_aut->fid & (MAX_PUK-1)] = 1;
|
||||
puk_status[ef_puk_aut->fid & (MAX_PUK - 1)] = 1;
|
||||
uint8_t auts = 0;
|
||||
for (int i = 0; i < puk_data[0]; i++) {
|
||||
auts += puk_status[i];
|
||||
|
@ -27,8 +27,7 @@
|
||||
#include "mbedtls/hkdf.h"
|
||||
#include "mbedtls/chachapoly.h"
|
||||
|
||||
int cmd_extras()
|
||||
{
|
||||
int cmd_extras() {
|
||||
if (P1(apdu) == 0xA) { //datetime operations
|
||||
if (P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
@ -48,7 +47,8 @@ int cmd_extras()
|
||||
res_APDU[res_APDU_size++] = dt.min;
|
||||
res_APDU[res_APDU_size++] = dt.sec;
|
||||
#endif
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (apdu.nc != 8) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
@ -66,7 +66,8 @@ int cmd_extras()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else if (P1(apdu) == 0x6) { //dynamic options
|
||||
}
|
||||
else if (P1(apdu) == 0x6) { //dynamic options
|
||||
if (P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@ -77,13 +78,15 @@ int cmd_extras()
|
||||
if (apdu.nc == 0) {
|
||||
res_APDU[res_APDU_size++] = opts >> 8;
|
||||
res_APDU[res_APDU_size++] = opts & 0xff;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint8_t newopts[] = { apdu.data[0], (opts & 0xff) };
|
||||
file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
|
||||
flash_write_data_to_file(tf, newopts, sizeof(newopts));
|
||||
low_flash_available();
|
||||
}
|
||||
} else if (P1(apdu) == 0x3A) { // secure lock
|
||||
}
|
||||
else if (P1(apdu) == 0x3A) { // secure lock
|
||||
if (apdu.nc == 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
@ -147,7 +150,8 @@ int cmd_extras()
|
||||
}
|
||||
mse.init = true;
|
||||
res_APDU_size = olen;
|
||||
} else if (P2(apdu) == 0x02 || P2(apdu) == 0x03 || P2(apdu) == 0x04) {
|
||||
}
|
||||
else if (P2(apdu) == 0x02 || P2(apdu) == 0x03 || P2(apdu) == 0x04) {
|
||||
if (mse.init == false) {
|
||||
return SW_COMMAND_NOT_ALLOWED();
|
||||
}
|
||||
@ -162,7 +166,7 @@ int cmd_extras()
|
||||
if ((P2(apdu) == 0x02 && !(opts & HSM_OPT_SECURE_LOCK)) ||
|
||||
(P2(apdu) == 0x04 && (opts & HSM_OPT_SECURE_LOCK))) {
|
||||
uint16_t tfids[] = { EF_MKEK, EF_MKEK_SO };
|
||||
for (int t = 0; t < sizeof(tfids)/sizeof(uint16_t); t++) {
|
||||
for (int t = 0; t < sizeof(tfids) / sizeof(uint16_t); t++) {
|
||||
file_t *tf = search_by_fid(tfids[t], NULL, SPECIFY_EF);
|
||||
if (tf) {
|
||||
uint8_t *tmp = (uint8_t *) calloc(1, file_get_size(tf));
|
||||
@ -177,18 +181,21 @@ int cmd_extras()
|
||||
}
|
||||
if (P2(apdu) == 0x02) {
|
||||
newopts[0] |= HSM_OPT_SECURE_LOCK >> 8;
|
||||
} else if (P2(apdu) == 0x04) {
|
||||
}
|
||||
else if (P2(apdu) == 0x04) {
|
||||
newopts[0] &= ~HSM_OPT_SECURE_LOCK >> 8;
|
||||
}
|
||||
file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
|
||||
flash_write_data_to_file(tf, newopts, sizeof(newopts));
|
||||
low_flash_available();
|
||||
} else if (P2(apdu) == 0x03) {
|
||||
}
|
||||
else if (P2(apdu) == 0x03) {
|
||||
memcpy(mkek_mask, apdu.data, apdu.nc);
|
||||
has_mkek_mask = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
return SW_OK();
|
||||
|
@ -24,8 +24,7 @@
|
||||
#include "eac.h"
|
||||
#include "files.h"
|
||||
|
||||
int cmd_general_authenticate()
|
||||
{
|
||||
int cmd_general_authenticate() {
|
||||
if (P1(apdu) == 0x0 && P2(apdu) == 0x0) {
|
||||
if (apdu.data[0] == 0x7C) {
|
||||
int r = 0;
|
||||
@ -34,10 +33,10 @@ int cmd_general_authenticate()
|
||||
uint16_t tag = 0x0;
|
||||
uint8_t *tag_data = NULL, *p = NULL;
|
||||
size_t tag_len = 0;
|
||||
while (walk_tlv(apdu.data+2, apdu.nc-2, &p, &tag, &tag_len, &tag_data)) {
|
||||
while (walk_tlv(apdu.data + 2, apdu.nc - 2, &p, &tag, &tag_len, &tag_data)) {
|
||||
if (tag == 0x80) {
|
||||
pubkey = tag_data-1; //mbedtls ecdh starts reading one pos before
|
||||
pubkey_len = tag_len+1;
|
||||
pubkey = tag_data - 1; //mbedtls ecdh starts reading one pos before
|
||||
pubkey_len = tag_len + 1;
|
||||
}
|
||||
}
|
||||
file_t *fkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF);
|
||||
@ -86,24 +85,24 @@ int cmd_general_authenticate()
|
||||
|
||||
sm_derive_all_keys(derived, olen);
|
||||
|
||||
uint8_t *t = (uint8_t *) calloc(1, pubkey_len+16);
|
||||
uint8_t *t = (uint8_t *) calloc(1, pubkey_len + 16);
|
||||
memcpy(t, "\x7F\x49\x4F\x06\x0A", 5);
|
||||
if (sm_get_protocol() == MSE_AES) {
|
||||
memcpy(t+5, OID_ID_CA_ECDH_AES_CBC_CMAC_128, 10);
|
||||
memcpy(t + 5, OID_ID_CA_ECDH_AES_CBC_CMAC_128, 10);
|
||||
}
|
||||
t[15] = 0x86;
|
||||
memcpy(t+16, pubkey, pubkey_len);
|
||||
memcpy(t + 16, pubkey, pubkey_len);
|
||||
|
||||
res_APDU[res_APDU_size++] = 0x7C;
|
||||
res_APDU[res_APDU_size++] = 20;
|
||||
res_APDU[res_APDU_size++] = 0x81;
|
||||
res_APDU[res_APDU_size++] = 8;
|
||||
memcpy(res_APDU+res_APDU_size, sm_get_nonce(), 8);
|
||||
memcpy(res_APDU + res_APDU_size, sm_get_nonce(), 8);
|
||||
res_APDU_size += 8;
|
||||
res_APDU[res_APDU_size++] = 0x82;
|
||||
res_APDU[res_APDU_size++] = 8;
|
||||
|
||||
r = sm_sign(t, pubkey_len+16, res_APDU+res_APDU_size);
|
||||
r = sm_sign(t, pubkey_len + 16, res_APDU + res_APDU_size);
|
||||
|
||||
free(t);
|
||||
if (r != CCID_OK) {
|
||||
|
@ -27,20 +27,18 @@
|
||||
extern void scan_all();
|
||||
|
||||
extern char __StackLimit;
|
||||
int heapLeft()
|
||||
{
|
||||
int heapLeft() {
|
||||
#ifndef ENABLE_EMULATION
|
||||
char *p = malloc(256); // try to avoid undue fragmentation
|
||||
int left = &__StackLimit - p;
|
||||
free(p);
|
||||
#else
|
||||
int left = 1024*1024;
|
||||
int left = 1024 * 1024;
|
||||
#endif
|
||||
return left;
|
||||
}
|
||||
|
||||
int cmd_initialize()
|
||||
{
|
||||
int cmd_initialize() {
|
||||
if (apdu.nc > 0) {
|
||||
uint8_t mkek[MKEK_SIZE];
|
||||
int ret_mkek = load_mkek(mkek); //Try loading MKEK with previous session
|
||||
@ -54,25 +52,28 @@ int cmd_initialize()
|
||||
if (tag == 0x80) { //options
|
||||
file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
|
||||
flash_write_data_to_file(tf, tag_data, tag_len);
|
||||
} else if (tag == 0x81) { //user pin
|
||||
}
|
||||
else if (tag == 0x81) { //user pin
|
||||
if (file_pin1 && file_pin1->data) {
|
||||
uint8_t dhash[33];
|
||||
dhash[0] = tag_len;
|
||||
double_hash_pin(tag_data, tag_len, dhash+1);
|
||||
double_hash_pin(tag_data, tag_len, dhash + 1);
|
||||
flash_write_data_to_file(file_pin1, dhash, sizeof(dhash));
|
||||
hash_multi(tag_data, tag_len, session_pin);
|
||||
has_session_pin = true;
|
||||
}
|
||||
} else if (tag == 0x82) { //sopin pin
|
||||
}
|
||||
else if (tag == 0x82) { //sopin pin
|
||||
if (file_sopin && file_sopin->data) {
|
||||
uint8_t dhash[33];
|
||||
dhash[0] = tag_len;
|
||||
double_hash_pin(tag_data, tag_len, dhash+1);
|
||||
double_hash_pin(tag_data, tag_len, dhash + 1);
|
||||
flash_write_data_to_file(file_sopin, dhash, sizeof(dhash));
|
||||
hash_multi(tag_data, tag_len, session_sopin);
|
||||
has_session_sopin = true;
|
||||
}
|
||||
} else if (tag == 0x91) { //retries user pin
|
||||
}
|
||||
else if (tag == 0x91) { //retries user pin
|
||||
file_t *tf = search_by_fid(0x1082, NULL, SPECIFY_EF);
|
||||
if (tf && tf->data) {
|
||||
flash_write_data_to_file(tf, tag_data, tag_len);
|
||||
@ -80,7 +81,8 @@ int cmd_initialize()
|
||||
if (file_retries_pin1 && file_retries_pin1->data) {
|
||||
flash_write_data_to_file(file_retries_pin1, tag_data, tag_len);
|
||||
}
|
||||
} else if (tag == 0x92) {
|
||||
}
|
||||
else if (tag == 0x92) {
|
||||
dkeks = tag_data;
|
||||
file_t *tf = file_new(EF_DKEK);
|
||||
if (!tf) {
|
||||
@ -88,7 +90,8 @@ int cmd_initialize()
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
flash_write_data_to_file(tf, NULL, 0);
|
||||
} else if (tag == 0x93) {
|
||||
}
|
||||
else if (tag == 0x93) {
|
||||
file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF);
|
||||
if (!ef_puk) {
|
||||
release_mkek(mkek);
|
||||
@ -101,14 +104,15 @@ int cmd_initialize()
|
||||
pk_status[2] = tag_data[1];
|
||||
flash_write_data_to_file(ef_puk, pk_status, sizeof(pk_status));
|
||||
for (int i = 0; i < puks; i++) {
|
||||
file_t *tf = file_new(EF_PUK+i);
|
||||
file_t *tf = file_new(EF_PUK + i);
|
||||
if (!tf) {
|
||||
release_mkek(mkek);
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
flash_write_data_to_file(tf, NULL, 0);
|
||||
}
|
||||
} else if (tag == 0x97) {
|
||||
}
|
||||
else if (tag == 0x97) {
|
||||
kds = tag_data;
|
||||
/*
|
||||
for (int i = 0; i < MIN(*kds,MAX_KEY_DOMAINS); i++) {
|
||||
@ -139,7 +143,8 @@ int cmd_initialize()
|
||||
if (flash_write_data_to_file(tf_kd, (const uint8_t *) &d, sizeof(d)) != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
int r = save_dkek_key(0, random_bytes_get(32));
|
||||
if (r != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
@ -149,16 +154,17 @@ int cmd_initialize()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint16_t d = 0x0000;
|
||||
if (flash_write_data_to_file(tf_kd, (const uint8_t *) &d, sizeof(d)) != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
if (kds) {
|
||||
uint8_t t[MAX_KEY_DOMAINS*2], k = MIN(*kds, MAX_KEY_DOMAINS);
|
||||
memset(t, 0xff, 2*k);
|
||||
if (flash_write_data_to_file(tf_kd, t, 2*k) != CCID_OK) {
|
||||
uint8_t t[MAX_KEY_DOMAINS * 2], k = MIN(*kds, MAX_KEY_DOMAINS);
|
||||
memset(t, 0xff, 2 * k);
|
||||
if (flash_write_data_to_file(tf_kd, t, 2 * k) != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
@ -215,7 +221,8 @@ int cmd_initialize()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
low_flash_available();
|
||||
} else { //free memory bytes request
|
||||
}
|
||||
else { //free memory bytes request
|
||||
int heap_left = heapLeft();
|
||||
res_APDU[0] = ((heap_left >> 24) & 0xff);
|
||||
res_APDU[1] = ((heap_left >> 16) & 0xff);
|
||||
|
@ -21,8 +21,7 @@
|
||||
#include "kek.h"
|
||||
#include "files.h"
|
||||
|
||||
uint8_t get_key_domain(file_t *fkey)
|
||||
{
|
||||
uint8_t get_key_domain(file_t *fkey) {
|
||||
size_t tag_len = 0;
|
||||
const uint8_t *meta_tag = get_meta_tag(fkey, 0x92, &tag_len);
|
||||
if (meta_tag) {
|
||||
@ -31,8 +30,7 @@ uint8_t get_key_domain(file_t *fkey)
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
int cmd_key_domain()
|
||||
{
|
||||
int cmd_key_domain() {
|
||||
//if (dkeks == 0)
|
||||
// return SW_COMMAND_NOT_ALLOWED();
|
||||
uint8_t p1 = P1(apdu), p2 = P2(apdu);
|
||||
@ -51,11 +49,11 @@ int cmd_key_domain()
|
||||
if (tf_kd_size == 0) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
uint8_t *kdata = file_get_data(tf_kd), dkeks = kdata ? kdata[2*p2] : 0,
|
||||
current_dkeks = kdata ? kdata[2*p2+1] : 0;
|
||||
uint8_t *kdata = file_get_data(tf_kd), dkeks = kdata ? kdata[2 * p2] : 0,
|
||||
current_dkeks = kdata ? kdata[2 * p2 + 1] : 0;
|
||||
if (p1 == 0x0) { //dkek import
|
||||
if (apdu.nc > 0) {
|
||||
file_t *tf = file_new(EF_DKEK+p2);
|
||||
file_t *tf = file_new(EF_DKEK + p2);
|
||||
if (!tf) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
@ -73,23 +71,25 @@ int cmd_key_domain()
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
}
|
||||
uint8_t t[MAX_KEY_DOMAINS*2];
|
||||
uint8_t t[MAX_KEY_DOMAINS * 2];
|
||||
memcpy(t, kdata, tf_kd_size);
|
||||
t[2*p2+1] = current_dkeks;
|
||||
t[2 * p2 + 1] = current_dkeks;
|
||||
if (flash_write_data_to_file(tf_kd, t, tf_kd_size) != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
low_flash_available();
|
||||
} else {
|
||||
file_t *tf = search_dynamic_file(EF_XKEK+p2);
|
||||
if (2*p2 >= tf_kd_size) {
|
||||
}
|
||||
else {
|
||||
file_t *tf = search_dynamic_file(EF_XKEK + p2);
|
||||
if (2 * p2 >= tf_kd_size) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
if (current_dkeks == 0xff && !tf) { //XKEK have always 0xff
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
}
|
||||
} else if (p1 == 0x1 || p1 == 0x3 || p1 == 0x4) { //key domain setup
|
||||
}
|
||||
else if (p1 == 0x1 || p1 == 0x3 || p1 == 0x4) { //key domain setup
|
||||
if (p1 == 0x1 && apdu.nc != 1) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
@ -100,27 +100,29 @@ int cmd_key_domain()
|
||||
}
|
||||
}
|
||||
}
|
||||
uint8_t t[MAX_KEY_DOMAINS*2];
|
||||
uint8_t t[MAX_KEY_DOMAINS * 2];
|
||||
memcpy(t, kdata, tf_kd_size);
|
||||
if (p1 == 0x1) {
|
||||
t[2*p2] = dkeks = apdu.data[0];
|
||||
t[2*p2+1] = current_dkeks = 0;
|
||||
} else if (p1 == 0x3) {
|
||||
t[2*p2] = dkeks = 0xff;
|
||||
t[2*p2+1] = 0xff;
|
||||
} else if (p1 == 0x4) {
|
||||
t[2*p2+1] = current_dkeks = 0;
|
||||
t[2 * p2] = dkeks = apdu.data[0];
|
||||
t[2 * p2 + 1] = current_dkeks = 0;
|
||||
}
|
||||
else if (p1 == 0x3) {
|
||||
t[2 * p2] = dkeks = 0xff;
|
||||
t[2 * p2 + 1] = 0xff;
|
||||
}
|
||||
else if (p1 == 0x4) {
|
||||
t[2 * p2 + 1] = current_dkeks = 0;
|
||||
}
|
||||
if (flash_write_data_to_file(tf_kd, t, tf_kd_size) != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
file_t *tf = NULL;
|
||||
if ((tf = search_dynamic_file(EF_DKEK+p2))) {
|
||||
if ((tf = search_dynamic_file(EF_DKEK + p2))) {
|
||||
if (delete_file(tf) != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
if (p1 == 0x3 && (tf = search_dynamic_file(EF_XKEK+p2))) {
|
||||
if (p1 == 0x3 && (tf = search_dynamic_file(EF_XKEK + p2))) {
|
||||
if (delete_file(tf) != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
@ -129,7 +131,8 @@ int cmd_key_domain()
|
||||
if (p1 == 0x3) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
} else if (p1 == 0x2) { //XKEK Key Domain creation
|
||||
}
|
||||
else if (p1 == 0x2) { //XKEK Key Domain creation
|
||||
if (apdu.nc > 0) {
|
||||
size_t pub_len = 0;
|
||||
file_t *fterm = search_by_fid(EF_TERMCA, NULL, SPECIFY_EF);
|
||||
@ -150,16 +153,16 @@ int cmd_key_domain()
|
||||
if (!t54) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
uint8_t hash[32], *input = (uint8_t *) calloc(1, (t86_len-1)/2+1);
|
||||
uint8_t hash[32], *input = (uint8_t *) calloc(1, (t86_len - 1) / 2 + 1);
|
||||
input[0] = 0x54;
|
||||
memcpy(input+1, t86+1, (t86_len-1)/2);
|
||||
hash256(input, (t86_len-1)/2+1, hash);
|
||||
memcpy(input + 1, t86 + 1, (t86_len - 1) / 2);
|
||||
hash256(input, (t86_len - 1) / 2 + 1, hash);
|
||||
free(input);
|
||||
int r = puk_verify(t54, t54_len, hash, 32, apdu.data, apdu.nc);
|
||||
if (r != 0) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
file_t *tf = file_new(EF_XKEK+p2);
|
||||
file_t *tf = file_new(EF_XKEK + p2);
|
||||
if (!tf) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
@ -170,22 +173,23 @@ int cmd_key_domain()
|
||||
size_t t86_len = 0;
|
||||
const uint8_t *t86 = cvc_get_field(pub, pub_len, &t86_len, 0x86);
|
||||
if (t86) {
|
||||
flash_write_data_to_file(tf, t86+1, t86_len-1);
|
||||
flash_write_data_to_file(tf, t86 + 1, t86_len - 1);
|
||||
low_flash_available();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
memset(res_APDU, 0, 10);
|
||||
res_APDU[0] = dkeks;
|
||||
res_APDU[1] = dkeks > current_dkeks ? dkeks-current_dkeks : 0;
|
||||
dkek_kcv(p2, res_APDU+2);
|
||||
res_APDU_size = 2+8;
|
||||
file_t *tf = search_dynamic_file(EF_XKEK+p2);
|
||||
res_APDU[1] = dkeks > current_dkeks ? dkeks - current_dkeks : 0;
|
||||
dkek_kcv(p2, res_APDU + 2);
|
||||
res_APDU_size = 2 + 8;
|
||||
file_t *tf = search_dynamic_file(EF_XKEK + p2);
|
||||
if (tf) {
|
||||
memcpy(res_APDU+10, file_get_data(tf), file_get_size(tf));
|
||||
memcpy(res_APDU + 10, file_get_data(tf), file_get_size(tf));
|
||||
res_APDU_size += file_get_size(tf);
|
||||
}
|
||||
return SW_OK();
|
||||
|
@ -19,8 +19,7 @@
|
||||
#include "sc_hsm.h"
|
||||
#include "random.h"
|
||||
|
||||
int cmd_key_gen()
|
||||
{
|
||||
int cmd_key_gen() {
|
||||
uint8_t key_id = P1(apdu);
|
||||
uint8_t p2 = P2(apdu);
|
||||
uint8_t key_size = 32;
|
||||
@ -30,9 +29,11 @@ int cmd_key_gen()
|
||||
}
|
||||
if (p2 == 0xB2) {
|
||||
key_size = 32;
|
||||
} else if (p2 == 0xB1) {
|
||||
}
|
||||
else if (p2 == 0xB1) {
|
||||
key_size = 24;
|
||||
} else if (p2 == 0xB0) {
|
||||
}
|
||||
else if (p2 == 0xB0) {
|
||||
key_size = 16;
|
||||
}
|
||||
//at this moment, we do not use the template, as only CBC is supported by the driver (encrypt, decrypt and CMAC)
|
||||
@ -41,9 +42,11 @@ int cmd_key_gen()
|
||||
int aes_type = 0x0;
|
||||
if (key_size == 16) {
|
||||
aes_type = HSM_KEY_AES_128;
|
||||
} else if (key_size == 24) {
|
||||
}
|
||||
else if (key_size == 24) {
|
||||
aes_type = HSM_KEY_AES_192;
|
||||
} else if (key_size == 32) {
|
||||
}
|
||||
else if (key_size == 32) {
|
||||
aes_type = HSM_KEY_AES_256;
|
||||
}
|
||||
r = store_keys(aes_key, aes_type, key_id);
|
||||
|
@ -20,8 +20,7 @@
|
||||
#include "kek.h"
|
||||
#include "cvc.h"
|
||||
|
||||
int cmd_key_unwrap()
|
||||
{
|
||||
int cmd_key_unwrap() {
|
||||
int key_id = P1(apdu), r = 0;
|
||||
if (P2(apdu) != 0x93) {
|
||||
return SW_WRONG_P1P2();
|
||||
@ -54,7 +53,8 @@ int cmd_key_unwrap()
|
||||
if (r != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
} else if (key_type == HSM_KEY_EC) {
|
||||
}
|
||||
else if (key_type == HSM_KEY_EC) {
|
||||
mbedtls_ecdsa_context ctx;
|
||||
mbedtls_ecdsa_init(&ctx);
|
||||
do {
|
||||
@ -73,7 +73,8 @@ int cmd_key_unwrap()
|
||||
if (r != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
} else if (key_type == HSM_KEY_AES) {
|
||||
}
|
||||
else if (key_type == HSM_KEY_AES) {
|
||||
uint8_t aes_key[32];
|
||||
int key_size = 0, aes_type = 0;
|
||||
do {
|
||||
@ -90,11 +91,14 @@ int cmd_key_unwrap()
|
||||
}
|
||||
if (key_size == 32) {
|
||||
aes_type = HSM_KEY_AES_256;
|
||||
} else if (key_size == 24) {
|
||||
}
|
||||
else if (key_size == 24) {
|
||||
aes_type = HSM_KEY_AES_192;
|
||||
} else if (key_size == 16) {
|
||||
}
|
||||
else if (key_size == 16) {
|
||||
aes_type = HSM_KEY_AES_128;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = store_keys(aes_key, aes_type, key_id);
|
||||
@ -103,7 +107,7 @@ int cmd_key_unwrap()
|
||||
}
|
||||
}
|
||||
if ((allowed != NULL && allowed_len > 0) || kdom >= 0) {
|
||||
size_t meta_len = (allowed_len > 0 ? 2+allowed_len : 0) + (kdom >= 0 ? 3 : 0);
|
||||
size_t meta_len = (allowed_len > 0 ? 2 + allowed_len : 0) + (kdom >= 0 ? 3 : 0);
|
||||
uint8_t *meta = (uint8_t *) calloc(1, meta_len), *m = meta;
|
||||
if (allowed_len > 0) {
|
||||
*m++ = 0x91;
|
||||
|
@ -22,8 +22,7 @@
|
||||
|
||||
extern uint8_t get_key_domain(file_t *fkey);
|
||||
|
||||
int cmd_key_wrap()
|
||||
{
|
||||
int cmd_key_wrap() {
|
||||
int key_id = P1(apdu), r = 0;
|
||||
if (P2(apdu) != 0x92) {
|
||||
return SW_WRONG_P1P2();
|
||||
@ -61,7 +60,8 @@ int cmd_key_wrap()
|
||||
}
|
||||
r = dkek_encode_key(kdom, &ctx, HSM_KEY_RSA, res_APDU, &wrap_len, meta_tag, tag_len);
|
||||
mbedtls_rsa_free(&ctx);
|
||||
} else if (*dprkd == P15_KEYTYPE_ECC) {
|
||||
}
|
||||
else if (*dprkd == P15_KEYTYPE_ECC) {
|
||||
mbedtls_ecdsa_context ctx;
|
||||
mbedtls_ecdsa_init(&ctx);
|
||||
r = load_private_key_ecdsa(&ctx, ef);
|
||||
@ -74,7 +74,8 @@ int cmd_key_wrap()
|
||||
}
|
||||
r = dkek_encode_key(kdom, &ctx, HSM_KEY_EC, res_APDU, &wrap_len, meta_tag, tag_len);
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
} else if (*dprkd == P15_KEYTYPE_AES) {
|
||||
}
|
||||
else if (*dprkd == P15_KEYTYPE_AES) {
|
||||
uint8_t kdata[32]; //maximum AES key size
|
||||
if (wait_button_pressed() == true) { //timeout
|
||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||
@ -87,9 +88,11 @@ int cmd_key_wrap()
|
||||
}
|
||||
if (key_size == 32) {
|
||||
aes_type = HSM_KEY_AES_256;
|
||||
} else if (key_size == 24) {
|
||||
}
|
||||
else if (key_size == 24) {
|
||||
aes_type = HSM_KEY_AES_192;
|
||||
} else if (key_size == 16) {
|
||||
}
|
||||
else if (key_size == 16) {
|
||||
aes_type = HSM_KEY_AES_128;
|
||||
}
|
||||
r = dkek_encode_key(kdom, kdata, aes_type, res_APDU, &wrap_len, meta_tag, tag_len);
|
||||
|
@ -24,8 +24,7 @@
|
||||
#include "random.h"
|
||||
#include "kek.h"
|
||||
|
||||
int cmd_keypair_gen()
|
||||
{
|
||||
int cmd_keypair_gen() {
|
||||
uint8_t key_id = P1(apdu);
|
||||
if (!isUserAuthenticated) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
@ -79,7 +78,8 @@ int cmd_keypair_gen()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
mbedtls_rsa_free(&rsa);
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, MIN(oid_len, 10)) == 0) { //ECC
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, MIN(oid_len, 10)) == 0) { //ECC
|
||||
size_t prime_len;
|
||||
uint8_t *prime = NULL;
|
||||
if (asn1_find_tag(p, tout, 0x81, &prime_len, &prime) != true) {
|
||||
@ -112,15 +112,16 @@ int cmd_keypair_gen()
|
||||
if (p92[0] > MAX_KEY_DOMAINS) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
file_t *tf_xkek = search_dynamic_file(EF_XKEK+p92[0]);
|
||||
file_t *tf_xkek = search_dynamic_file(EF_XKEK + p92[0]);
|
||||
if (!tf_xkek) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
ext_len = 2+2+strlen(OID_ID_KEY_DOMAIN_UID)+2+file_get_size(tf_xkek);
|
||||
ext_len = 2 + 2 + strlen(OID_ID_KEY_DOMAIN_UID) + 2 + file_get_size(
|
||||
tf_xkek);
|
||||
ext = (uint8_t *) calloc(1, ext_len);
|
||||
uint8_t *pe = ext;
|
||||
*pe++ = 0x73;
|
||||
*pe++ = ext_len-2;
|
||||
*pe++ = ext_len - 2;
|
||||
*pe++ = 0x6;
|
||||
*pe++ = strlen(OID_ID_KEY_DOMAIN_UID);
|
||||
memcpy(pe, OID_ID_KEY_DOMAIN_UID, strlen(OID_ID_KEY_DOMAIN_UID));
|
||||
@ -150,7 +151,8 @@ int cmd_keypair_gen()
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (find_and_store_meta_key(key_id) != CCID_OK) {
|
||||
|
@ -18,8 +18,7 @@
|
||||
#include "sc_hsm.h"
|
||||
#include "files.h"
|
||||
|
||||
int cmd_list_keys()
|
||||
{
|
||||
int cmd_list_keys() {
|
||||
/* First we send DEV private key */
|
||||
/* Both below conditions should be always TRUE */
|
||||
if (search_by_fid(EF_PRKD_DEV, NULL, SPECIFY_EF)) {
|
||||
|
@ -24,8 +24,7 @@
|
||||
|
||||
file_t *ef_puk_aut = NULL;
|
||||
|
||||
int cmd_mse()
|
||||
{
|
||||
int cmd_mse() {
|
||||
int p1 = P1(apdu);
|
||||
int p2 = P2(apdu);
|
||||
if (p2 != 0xA4 && p2 != 0xA6 && p2 != 0xAA && p2 != 0xB4 && p2 != 0xB6 && p2 != 0xB8) {
|
||||
@ -43,17 +42,20 @@ int cmd_mse()
|
||||
sm_set_protocol(MSE_AES);
|
||||
}
|
||||
}
|
||||
} else if (tag == 0x83) {
|
||||
}
|
||||
else if (tag == 0x83) {
|
||||
if (tag_len == 1) {
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (p2 == 0xB6) {
|
||||
if (puk_store_select_chr(tag_data) == CCID_OK) {
|
||||
return SW_OK();
|
||||
}
|
||||
} else if (p2 == 0xA4) { /* Aut */
|
||||
}
|
||||
else if (p2 == 0xA4) { /* Aut */
|
||||
for (int i = 0; i < MAX_PUK; i++) {
|
||||
file_t *ef = search_dynamic_file(EF_PUK+i);
|
||||
file_t *ef = search_dynamic_file(EF_PUK + i);
|
||||
if (!ef) {
|
||||
break;
|
||||
}
|
||||
@ -74,7 +76,8 @@ int cmd_mse()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
return SW_OK();
|
||||
|
@ -23,8 +23,7 @@
|
||||
extern int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy);
|
||||
extern PUK *current_puk;
|
||||
|
||||
int cmd_pso()
|
||||
{
|
||||
int cmd_pso() {
|
||||
uint8_t p1 = P1(apdu), p2 = P2(apdu);
|
||||
if (p1 == 0x0 && (p2 == 0x92 || p2 == 0xAE || p2 == 0xBE)) { /* Verify certificate */
|
||||
if (apdu.nc == 0) {
|
||||
@ -34,17 +33,18 @@ int cmd_pso()
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (apdu.data[0] != 0x7F || apdu.data[1] != 0x21) {
|
||||
uint8_t tlv_len = 2+format_tlv_len(apdu.nc, NULL);
|
||||
memmove(apdu.data+tlv_len, apdu.data, apdu.nc);
|
||||
uint8_t tlv_len = 2 + format_tlv_len(apdu.nc, NULL);
|
||||
memmove(apdu.data + tlv_len, apdu.data, apdu.nc);
|
||||
memcpy(apdu.data, "\x7F\x21", 2);
|
||||
format_tlv_len(apdu.nc, apdu.data+2);
|
||||
format_tlv_len(apdu.nc, apdu.data + 2);
|
||||
apdu.nc += tlv_len;
|
||||
}
|
||||
int r = cvc_verify(apdu.data, apdu.nc, current_puk->cvcert, current_puk->cvcert_len);
|
||||
if (r != CCID_OK) {
|
||||
if (r == CCID_WRONG_DATA) {
|
||||
return SW_DATA_INVALID();
|
||||
} else if (r == CCID_WRONG_SIGNATURE) {
|
||||
}
|
||||
else if (r == CCID_WRONG_SIGNATURE) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
return SW_EXEC_ERROR();
|
||||
@ -80,7 +80,8 @@ int cmd_pso()
|
||||
if (!puk_bin) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
|
||||
mbedtls_ecp_group_id ec_id = cvc_inherite_ec_group(apdu.data, apdu.nc);
|
||||
mbedtls_ecp_group grp;
|
||||
mbedtls_ecp_group_init(&grp);
|
||||
@ -98,22 +99,25 @@ int cmd_pso()
|
||||
}
|
||||
puk_bin = t86;
|
||||
puk_bin_len = t86_len;
|
||||
} else if (mbedtls_ecp_get_type(&grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
|
||||
}
|
||||
else if (mbedtls_ecp_get_type(&grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
|
||||
if (t86[0] == 0x2 || t86[0] == 0x3) {
|
||||
if (t86_len != plen+1) {
|
||||
if (t86_len != plen + 1) {
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
} else if (t86[0] == 0x4) {
|
||||
if (t86_len != 2*plen+1) {
|
||||
}
|
||||
else if (t86[0] == 0x4) {
|
||||
if (t86_len != 2 * plen + 1) {
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
puk_bin = t86+1;
|
||||
puk_bin = t86 + 1;
|
||||
puk_bin_len = plen;
|
||||
}
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
@ -150,7 +154,8 @@ int cmd_pso()
|
||||
}
|
||||
}
|
||||
return SW_OK();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
return SW_OK();
|
||||
|
@ -19,8 +19,7 @@
|
||||
#include "files.h"
|
||||
#include "cvc.h"
|
||||
|
||||
int cmd_puk_auth()
|
||||
{
|
||||
int cmd_puk_auth() {
|
||||
uint8_t p1 = P1(apdu), p2 = P2(apdu);
|
||||
file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF);
|
||||
if (!file_has_data(ef_puk)) {
|
||||
@ -35,7 +34,7 @@ int cmd_puk_auth()
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
for (int i = 0; i < puk_data[0]; i++) {
|
||||
ef = search_dynamic_file(EF_PUK+i);
|
||||
ef = search_dynamic_file(EF_PUK + i);
|
||||
if (!ef) { /* Never should not happen */
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
@ -45,22 +44,24 @@ int cmd_puk_auth()
|
||||
}
|
||||
uint8_t *tmp = (uint8_t *) calloc(file_get_size(ef_puk), sizeof(uint8_t));
|
||||
memcpy(tmp, puk_data, file_get_size(ef_puk));
|
||||
tmp[1] = puk_data[1]-1;
|
||||
tmp[1] = puk_data[1] - 1;
|
||||
flash_write_data_to_file(ef_puk, tmp, file_get_size(ef_puk));
|
||||
puk_data = file_get_data(ef_puk);
|
||||
free(tmp);
|
||||
} else if (p1 == 0x1) { /* Replace */
|
||||
}
|
||||
else if (p1 == 0x1) { /* Replace */
|
||||
if (p2 >= puk_data[0]) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
ef = search_dynamic_file(EF_PUK+p2);
|
||||
ef = search_dynamic_file(EF_PUK + p2);
|
||||
if (!ef) { /* Never should not happen */
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
}
|
||||
flash_write_data_to_file(ef, apdu.data, apdu.nc);
|
||||
low_flash_available();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
}
|
||||
@ -68,7 +69,7 @@ int cmd_puk_auth()
|
||||
if (p2 >= puk_data[0]) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
file_t *ef = search_dynamic_file(EF_PUK+p2);
|
||||
file_t *ef = search_dynamic_file(EF_PUK + p2);
|
||||
if (!ef) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@ -82,7 +83,8 @@ int cmd_puk_auth()
|
||||
res_APDU_size = chr_len;
|
||||
}
|
||||
return set_res_sw(0x90, puk_status[p2]);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
memcpy(res_APDU, puk_data, 3);
|
||||
res_APDU[3] = 0;
|
||||
for (int i = 0; i < puk_data[0]; i++) {
|
||||
|
@ -17,8 +17,7 @@
|
||||
|
||||
#include "sc_hsm.h"
|
||||
|
||||
int cmd_read_binary()
|
||||
{
|
||||
int cmd_read_binary() {
|
||||
uint16_t fid = 0x0;
|
||||
uint32_t offset = 0;
|
||||
uint8_t ins = INS(apdu), p1 = P1(apdu), p2 = P2(apdu);
|
||||
@ -26,26 +25,30 @@ int cmd_read_binary()
|
||||
|
||||
if ((ins & 0x1) == 0) {
|
||||
if ((p1 & 0x80) != 0) {
|
||||
if (!(ef = search_by_fid(p1&0x1f, NULL, SPECIFY_EF))) {
|
||||
if (!(ef = search_by_fid(p1 & 0x1f, NULL, SPECIFY_EF))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
offset = p2;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
offset = make_uint16_t(p1, p2) & 0x7fff;
|
||||
ef = currentEF;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (p1 == 0 && (p2 & 0xE0) == 0 && (p2 & 0x1f) != 0 && (p2 & 0x1f) != 0x1f) {
|
||||
if (!(ef = search_by_fid(p2&0x1f, NULL, SPECIFY_EF))) {
|
||||
if (!(ef = search_by_fid(p2 & 0x1f, NULL, SPECIFY_EF))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint16_t file_id = make_uint16_t(p1, p2); // & 0x7fff;
|
||||
if (file_id == 0x0) {
|
||||
ef = currentEF;
|
||||
} else if (!(ef =
|
||||
search_by_fid(file_id, NULL,
|
||||
SPECIFY_EF)) && !(ef = search_dynamic_file(file_id))) {
|
||||
}
|
||||
else if (!(ef =
|
||||
search_by_fid(file_id, NULL,
|
||||
SPECIFY_EF)) && !(ef = search_dynamic_file(file_id))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
|
||||
@ -55,7 +58,7 @@ int cmd_read_binary()
|
||||
|
||||
offset = 0;
|
||||
for (int d = 0; d < apdu.data[1]; d++) {
|
||||
offset |= apdu.data[2+d]<<(apdu.data[1]-1-d)*8;
|
||||
offset |= apdu.data[2 + d] << (apdu.data[1] - 1 - d) * 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,27 +72,28 @@ int cmd_read_binary()
|
||||
if (offset > data_len) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
uint16_t maxle = data_len-offset;
|
||||
uint16_t maxle = data_len - offset;
|
||||
if (apdu.ne > maxle) {
|
||||
apdu.ne = maxle;
|
||||
}
|
||||
if (offset) {
|
||||
memmove(res_APDU, res_APDU+offset, res_APDU_size-offset);
|
||||
memmove(res_APDU, res_APDU + offset, res_APDU_size - offset);
|
||||
//res_APDU += offset;
|
||||
res_APDU_size -= offset;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint16_t data_len = file_get_size(ef);
|
||||
if (offset > data_len) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
|
||||
uint16_t maxle = data_len-offset;
|
||||
uint16_t maxle = data_len - offset;
|
||||
if (apdu.ne > maxle) {
|
||||
apdu.ne = maxle;
|
||||
}
|
||||
memcpy(res_APDU, file_get_data(ef)+offset, data_len-offset);
|
||||
res_APDU_size = data_len-offset;
|
||||
memcpy(res_APDU, file_get_data(ef) + offset, data_len - offset);
|
||||
res_APDU_size = data_len - offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,7 @@
|
||||
#include "sc_hsm.h"
|
||||
#include "kek.h"
|
||||
|
||||
int cmd_reset_retry()
|
||||
{
|
||||
int cmd_reset_retry() {
|
||||
if (P2(apdu) != 0x81) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
@ -44,10 +43,11 @@ int cmd_reset_retry()
|
||||
if (r != 0x9000) {
|
||||
return r;
|
||||
}
|
||||
newpin_len = apdu.nc-8;
|
||||
newpin_len = apdu.nc - 8;
|
||||
has_session_sopin = true;
|
||||
hash_multi(apdu.data, 8, session_sopin);
|
||||
} else if (P1(apdu) == 0x2) {
|
||||
}
|
||||
else if (P1(apdu) == 0x2) {
|
||||
if (!has_session_sopin) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
@ -58,7 +58,7 @@ int cmd_reset_retry()
|
||||
}
|
||||
uint8_t dhash[33];
|
||||
dhash[0] = newpin_len;
|
||||
double_hash_pin(apdu.data+(apdu.nc-newpin_len), newpin_len, dhash+1);
|
||||
double_hash_pin(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 1);
|
||||
flash_write_data_to_file(file_pin1, dhash, sizeof(dhash));
|
||||
if (pin_reset_retries(file_pin1, true) != CCID_OK) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
@ -68,7 +68,7 @@ int cmd_reset_retry()
|
||||
if (r != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
hash_multi(apdu.data+(apdu.nc-newpin_len), newpin_len, session_pin);
|
||||
hash_multi(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pin);
|
||||
has_session_pin = true;
|
||||
r = store_mkek(mkek);
|
||||
release_mkek(mkek);
|
||||
@ -77,7 +77,8 @@ int cmd_reset_retry()
|
||||
}
|
||||
low_flash_available();
|
||||
return SW_OK();
|
||||
} else if (P1(apdu) == 0x1 || P1(apdu) == 0x3) {
|
||||
}
|
||||
else if (P1(apdu) == 0x1 || P1(apdu) == 0x3) {
|
||||
if (!(opts & HSM_OPT_RRC_RESET_ONLY)) {
|
||||
return SW_COMMAND_NOT_ALLOWED();
|
||||
}
|
||||
@ -91,7 +92,8 @@ int cmd_reset_retry()
|
||||
}
|
||||
has_session_sopin = true;
|
||||
hash_multi(apdu.data, 8, session_sopin);
|
||||
} else if (P1(apdu) == 0x3) {
|
||||
}
|
||||
else if (P1(apdu) == 0x3) {
|
||||
if (!has_session_sopin) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
|
@ -18,15 +18,16 @@
|
||||
#include "sc_hsm.h"
|
||||
#include "version.h"
|
||||
|
||||
void select_file(file_t *pe)
|
||||
{
|
||||
void select_file(file_t *pe) {
|
||||
if (!pe) {
|
||||
currentDF = (file_t *) MF;
|
||||
currentEF = NULL;
|
||||
} else if (pe->type & FILE_TYPE_INTERNAL_EF) {
|
||||
}
|
||||
else if (pe->type & FILE_TYPE_INTERNAL_EF) {
|
||||
currentEF = pe;
|
||||
currentDF = &file_entries[pe->parent];
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
currentDF = pe;
|
||||
}
|
||||
if (currentEF == file_openpgp || currentEF == file_sc_hsm) {
|
||||
@ -35,8 +36,7 @@ void select_file(file_t *pe)
|
||||
}
|
||||
}
|
||||
|
||||
int cmd_select()
|
||||
{
|
||||
int cmd_select() {
|
||||
uint8_t p1 = P1(apdu);
|
||||
uint8_t p2 = P2(apdu);
|
||||
file_t *pe = NULL;
|
||||
@ -72,35 +72,42 @@ int cmd_select()
|
||||
if (apdu.nc == 0) {
|
||||
pe = (file_t *) MF;
|
||||
//ac_fini();
|
||||
} else if (apdu.nc == 2) {
|
||||
}
|
||||
else if (apdu.nc == 2) {
|
||||
if (!(pe = search_by_fid(fid, NULL, SPECIFY_ANY))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
}
|
||||
} else if (p1 == 0x01) { //Select child DF - DF identifier
|
||||
}
|
||||
else if (p1 == 0x01) { //Select child DF - DF identifier
|
||||
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_DF))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
} else if (p1 == 0x02) { //Select EF under the current DF - EF identifier
|
||||
}
|
||||
else if (p1 == 0x02) { //Select EF under the current DF - EF identifier
|
||||
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_EF))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
} else if (p1 == 0x03) { //Select parent DF of the current DF - Absent
|
||||
}
|
||||
else if (p1 == 0x03) { //Select parent DF of the current DF - Absent
|
||||
if (apdu.nc != 0) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
} else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier
|
||||
}
|
||||
else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier
|
||||
if (!(pe = search_by_name(apdu.data, apdu.nc))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
if (card_terminated) {
|
||||
return set_res_sw(0x62, 0x85);
|
||||
}
|
||||
} else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier
|
||||
}
|
||||
else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier
|
||||
if (!(pe = search_by_path(apdu.data, apdu.nc, MF))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
} else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier
|
||||
}
|
||||
else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier
|
||||
if (!(pe = search_by_path(apdu.data, apdu.nc, currentDF))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
@ -117,9 +124,10 @@ int cmd_select()
|
||||
res_APDU[res_APDU_size++] = 0xFF;
|
||||
res_APDU[res_APDU_size++] = HSM_VERSION_MAJOR;
|
||||
res_APDU[res_APDU_size++] = HSM_VERSION_MINOR;
|
||||
res_APDU[1] = res_APDU_size-2;
|
||||
res_APDU[1] = res_APDU_size - 2;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
select_file(pe);
|
||||
|
@ -19,8 +19,7 @@
|
||||
#include "random.h"
|
||||
#include "eac.h"
|
||||
|
||||
int cmd_session_pin()
|
||||
{
|
||||
int cmd_session_pin() {
|
||||
if (P1(apdu) == 0x01 && P2(apdu) == 0x81) {
|
||||
memcpy(sm_session_pin, random_bytes_get(8), 8);
|
||||
sm_session_pin_len = 8;
|
||||
@ -28,7 +27,8 @@ int cmd_session_pin()
|
||||
memcpy(res_APDU, sm_session_pin, sm_session_pin_len);
|
||||
res_APDU_size = sm_session_pin_len;
|
||||
apdu.ne = sm_session_pin_len;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
return SW_OK();
|
||||
|
@ -70,8 +70,7 @@ int pkcs1_strip_digest_info_prefix(mbedtls_md_type_t *algorithm,
|
||||
const uint8_t *in_dat,
|
||||
size_t in_len,
|
||||
uint8_t *out_dat,
|
||||
size_t *out_len)
|
||||
{
|
||||
size_t *out_len) {
|
||||
for (int i = 0; digest_info_prefix[i].algorithm != 0; i++) {
|
||||
size_t hdr_len = digest_info_prefix[i].hdr_len, hash_len = digest_info_prefix[i].hash_len;
|
||||
const uint8_t *hdr = digest_info_prefix[i].hdr;
|
||||
@ -94,8 +93,7 @@ int pkcs1_strip_digest_info_prefix(mbedtls_md_type_t *algorithm,
|
||||
}
|
||||
//-----
|
||||
|
||||
int cmd_signature()
|
||||
{
|
||||
int cmd_signature() {
|
||||
uint8_t key_id = P1(apdu);
|
||||
uint8_t p2 = P2(apdu);
|
||||
mbedtls_md_type_t md = MBEDTLS_MD_NONE;
|
||||
@ -115,13 +113,17 @@ int cmd_signature()
|
||||
int key_size = file_get_size(fkey);
|
||||
if (p2 == ALGO_RSA_PKCS1_SHA1 || p2 == ALGO_RSA_PSS_SHA1 || p2 == ALGO_EC_SHA1) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
} else if (p2 == ALGO_RSA_PKCS1_SHA256 || p2 == ALGO_RSA_PSS_SHA256 || p2 == ALGO_EC_SHA256) {
|
||||
}
|
||||
else if (p2 == ALGO_RSA_PKCS1_SHA256 || p2 == ALGO_RSA_PSS_SHA256 || p2 == ALGO_EC_SHA256) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
} else if (p2 == ALGO_EC_SHA224 || p2 == ALGO_RSA_PKCS1_SHA224 || p2 == ALGO_RSA_PSS_SHA224) {
|
||||
}
|
||||
else if (p2 == ALGO_EC_SHA224 || p2 == ALGO_RSA_PKCS1_SHA224 || p2 == ALGO_RSA_PSS_SHA224) {
|
||||
md = MBEDTLS_MD_SHA224;
|
||||
} else if (p2 == ALGO_EC_SHA384 || p2 == ALGO_RSA_PKCS1_SHA384 || p2 == ALGO_RSA_PSS_SHA384) {
|
||||
}
|
||||
else if (p2 == ALGO_EC_SHA384 || p2 == ALGO_RSA_PKCS1_SHA384 || p2 == ALGO_RSA_PSS_SHA384) {
|
||||
md = MBEDTLS_MD_SHA384;
|
||||
} else if (p2 == ALGO_EC_SHA512 || p2 == ALGO_RSA_PKCS1_SHA512 || p2 == ALGO_RSA_PSS_SHA512) {
|
||||
}
|
||||
else if (p2 == ALGO_EC_SHA512 || p2 == ALGO_RSA_PKCS1_SHA512 || p2 == ALGO_RSA_PSS_SHA512) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
}
|
||||
if (p2 == ALGO_RSA_PKCS1_SHA1 || p2 == ALGO_RSA_PSS_SHA1 || p2 == ALGO_EC_SHA1 ||
|
||||
@ -153,7 +155,8 @@ int cmd_signature()
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
apdu.nc = nc;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
//sc_asn1_print_tags(apdu.data, apdu.nc);
|
||||
size_t tout = 0, oid_len = 0;
|
||||
uint8_t *p = NULL, *oid = NULL;
|
||||
@ -168,13 +171,17 @@ int cmd_signature()
|
||||
if (oid && oid_len > 0) {
|
||||
if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA1, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
} else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA224, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA224, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA224;
|
||||
} else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA256, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA256, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
} else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA384, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA384, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA384;
|
||||
} else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA512, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA512, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
}
|
||||
}
|
||||
@ -182,13 +189,17 @@ int cmd_signature()
|
||||
if (p2 == ALGO_RSA_PSS && !oid) {
|
||||
if (apdu.nc == 20) { //default is sha1
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
} else if (apdu.nc == 28) {
|
||||
}
|
||||
else if (apdu.nc == 28) {
|
||||
md = MBEDTLS_MD_SHA224;
|
||||
} else if (apdu.nc == 32) {
|
||||
}
|
||||
else if (apdu.nc == 32) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
} else if (apdu.nc == 48) {
|
||||
}
|
||||
else if (apdu.nc == 48) {
|
||||
md = MBEDTLS_MD_SHA384;
|
||||
} else if (apdu.nc == 64) {
|
||||
}
|
||||
else if (apdu.nc == 64) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
}
|
||||
}
|
||||
@ -197,10 +208,11 @@ int cmd_signature()
|
||||
}
|
||||
if (md == MBEDTLS_MD_NONE) {
|
||||
if (apdu.nc < key_size) { //needs padding
|
||||
memset(apdu.data+apdu.nc, 0, key_size-apdu.nc);
|
||||
memset(apdu.data + apdu.nc, 0, key_size - apdu.nc);
|
||||
}
|
||||
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint8_t *signature = (uint8_t *) calloc(key_size, sizeof(uint8_t));
|
||||
r = mbedtls_rsa_pkcs1_sign(&ctx, random_gen, NULL, md, hash_len, hash, signature);
|
||||
memcpy(res_APDU, signature, key_size);
|
||||
@ -213,32 +225,41 @@ int cmd_signature()
|
||||
res_APDU_size = key_size;
|
||||
apdu.ne = key_size;
|
||||
mbedtls_rsa_free(&ctx);
|
||||
} else if (p2 >= ALGO_EC_RAW && p2 <= ALGO_EC_SHA512) {
|
||||
}
|
||||
else if (p2 >= ALGO_EC_RAW && p2 <= ALGO_EC_SHA512) {
|
||||
mbedtls_ecdsa_context ctx;
|
||||
mbedtls_ecdsa_init(&ctx);
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
if (p2 == ALGO_EC_RAW) {
|
||||
if (apdu.nc == 32) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
} else if (apdu.nc == 20) {
|
||||
}
|
||||
else if (apdu.nc == 20) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
} else if (apdu.nc == 28) {
|
||||
}
|
||||
else if (apdu.nc == 28) {
|
||||
md = MBEDTLS_MD_SHA224;
|
||||
} else if (apdu.nc == 48) {
|
||||
}
|
||||
else if (apdu.nc == 48) {
|
||||
md = MBEDTLS_MD_SHA384;
|
||||
} else if (apdu.nc == 64) {
|
||||
}
|
||||
else if (apdu.nc == 64) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
}
|
||||
}
|
||||
if (p2 == ALGO_EC_SHA1) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
} else if (p2 == ALGO_EC_SHA224) {
|
||||
}
|
||||
else if (p2 == ALGO_EC_SHA224) {
|
||||
md = MBEDTLS_MD_SHA224;
|
||||
} else if (p2 == ALGO_EC_SHA256) {
|
||||
}
|
||||
else if (p2 == ALGO_EC_SHA256) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
} else if (p2 == ALGO_EC_SHA384) {
|
||||
}
|
||||
else if (p2 == ALGO_EC_SHA384) {
|
||||
md = MBEDTLS_MD_SHA384;
|
||||
} else if (p2 == ALGO_EC_SHA512) {
|
||||
}
|
||||
else if (p2 == ALGO_EC_SHA512) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
}
|
||||
int r = load_private_key_ecdsa(&ctx, fkey);
|
||||
@ -259,7 +280,8 @@ int cmd_signature()
|
||||
memcpy(res_APDU, buf, olen);
|
||||
res_APDU_size = olen;
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
decrement_key_counter(fkey);
|
||||
|
@ -20,8 +20,7 @@
|
||||
|
||||
extern void select_file(file_t *pe);
|
||||
|
||||
int cmd_update_ef()
|
||||
{
|
||||
int cmd_update_ef() {
|
||||
uint8_t p1 = P1(apdu), p2 = P2(apdu);
|
||||
uint16_t fid = (p1 << 8) | p2;
|
||||
uint8_t *data = NULL;
|
||||
@ -33,9 +32,10 @@ int cmd_update_ef()
|
||||
}
|
||||
if (fid == 0x0) {
|
||||
ef = currentEF;
|
||||
} else if (p1 != EE_CERTIFICATE_PREFIX && p1 != PRKD_PREFIX && p1 != CA_CERTIFICATE_PREFIX &&
|
||||
p1 != CD_PREFIX && p1 != DATA_PREFIX && p1 != DCOD_PREFIX &&
|
||||
p1 != PROT_DATA_PREFIX) {
|
||||
}
|
||||
else if (p1 != EE_CERTIFICATE_PREFIX && p1 != PRKD_PREFIX && p1 != CA_CERTIFICATE_PREFIX &&
|
||||
p1 != CD_PREFIX && p1 != DATA_PREFIX && p1 != DCOD_PREFIX &&
|
||||
p1 != PROT_DATA_PREFIX) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
|
||||
@ -49,9 +49,10 @@ int cmd_update_ef()
|
||||
while (walk_tlv(apdu.data, apdu.nc, &p, &tag, &tag_len, &tag_data)) {
|
||||
if (tag == 0x54) { //ofset tag
|
||||
for (int i = 1; i <= tag_len; i++) {
|
||||
offset |= (*tag_data++ << (8*(tag_len-i)));
|
||||
offset |= (*tag_data++ << (8 * (tag_len - i)));
|
||||
}
|
||||
} else if (tag == 0x53) { //data
|
||||
}
|
||||
else if (tag == 0x53) { //data
|
||||
data_len = tag_len;
|
||||
data = tag_data;
|
||||
}
|
||||
@ -61,13 +62,15 @@ int cmd_update_ef()
|
||||
//if ((fid & 0xff00) == (EE_CERTIFICATE_PREFIX << 8))
|
||||
// add_file_to_chain(ef, &ef_pukdf);
|
||||
select_file(ef);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (fid == 0x0 && !ef) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
} else if (fid != 0x0 &&
|
||||
!(ef =
|
||||
search_by_fid(fid, NULL,
|
||||
SPECIFY_EF)) && !(ef = search_dynamic_file(fid))) { //if does not exist, create it
|
||||
}
|
||||
else if (fid != 0x0 &&
|
||||
!(ef =
|
||||
search_by_fid(fid, NULL,
|
||||
SPECIFY_EF)) && !(ef = search_dynamic_file(fid))) { //if does not exist, create it
|
||||
//return SW_FILE_NOT_FOUND();
|
||||
ef = file_new(fid);
|
||||
}
|
||||
@ -76,15 +79,16 @@ int cmd_update_ef()
|
||||
if (r != CCID_OK) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (!file_has_data(ef)) {
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
|
||||
uint8_t *data_merge = (uint8_t *) calloc(1, offset+data_len);
|
||||
uint8_t *data_merge = (uint8_t *) calloc(1, offset + data_len);
|
||||
memcpy(data_merge, file_get_data(ef), offset);
|
||||
memcpy(data_merge+offset, data, data_len);
|
||||
int r = flash_write_data_to_file(ef, data_merge, offset+data_len);
|
||||
memcpy(data_merge + offset, data, data_len);
|
||||
int r = flash_write_data_to_file(ef, data_merge, offset + data_len);
|
||||
free(data_merge);
|
||||
if (r != CCID_OK) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
|
@ -17,8 +17,7 @@
|
||||
|
||||
#include "sc_hsm.h"
|
||||
|
||||
int cmd_verify()
|
||||
{
|
||||
int cmd_verify() {
|
||||
uint8_t p1 = P1(apdu);
|
||||
uint8_t p2 = P2(apdu);
|
||||
|
||||
@ -44,7 +43,8 @@ int cmd_verify()
|
||||
return SW_PIN_BLOCKED();
|
||||
}
|
||||
return set_res_sw(0x63, 0xc0 | file_read_uint8(file_get_data(file_retries_pin1)));
|
||||
} else if (p2 == 0x88) { //SOPin
|
||||
}
|
||||
else if (p2 == 0x88) { //SOPin
|
||||
if (file_read_uint8(file_get_data(file_sopin)) == 0) { //not initialized
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
@ -58,7 +58,8 @@ int cmd_verify()
|
||||
return SW_OK();
|
||||
}
|
||||
return set_res_sw(0x63, 0xc0 | file_read_uint8(file_get_data(file_retries_sopin)));
|
||||
} else if (p2 == 0x85) {
|
||||
}
|
||||
else if (p2 == 0x85) {
|
||||
return SW_OK();
|
||||
}
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
|
233
src/hsm/cvc.c
233
src/hsm/cvc.c
@ -31,13 +31,12 @@
|
||||
extern const uint8_t *dev_name;
|
||||
extern size_t dev_name_len;
|
||||
|
||||
size_t asn1_cvc_public_key_rsa(mbedtls_rsa_context *rsa, uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
size_t asn1_cvc_public_key_rsa(mbedtls_rsa_context *rsa, uint8_t *buf, size_t buf_len) {
|
||||
const uint8_t oid_rsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x01, 0x02 };
|
||||
size_t n_size = mbedtls_mpi_size(&rsa->N), e_size = mbedtls_mpi_size(&rsa->E);
|
||||
size_t ntot_size = asn1_len_tag(0x81, n_size), etot_size = asn1_len_tag(0x82, e_size);
|
||||
size_t oid_len = asn1_len_tag(0x6, sizeof(oid_rsa));
|
||||
size_t tot_len = asn1_len_tag(0x7f49, oid_len+ntot_size+etot_size);
|
||||
size_t tot_len = asn1_len_tag(0x7f49, oid_len + ntot_size + etot_size);
|
||||
if (buf == NULL || buf_len == 0) {
|
||||
return tot_len;
|
||||
}
|
||||
@ -46,7 +45,7 @@ size_t asn1_cvc_public_key_rsa(mbedtls_rsa_context *rsa, uint8_t *buf, size_t bu
|
||||
}
|
||||
uint8_t *p = buf;
|
||||
memcpy(p, "\x7F\x49", 2); p += 2;
|
||||
p += format_tlv_len(oid_len+ntot_size+etot_size, p);
|
||||
p += format_tlv_len(oid_len + ntot_size + etot_size, p);
|
||||
//oid
|
||||
*p++ = 0x6; p += format_tlv_len(sizeof(oid_rsa), p); memcpy(p, oid_rsa, sizeof(oid_rsa));
|
||||
p += sizeof(oid_rsa);
|
||||
@ -73,13 +72,12 @@ const uint8_t *pointA[] = {
|
||||
"\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\xFC",
|
||||
};
|
||||
|
||||
size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, size_t buf_len) {
|
||||
uint8_t Y_buf[MBEDTLS_ECP_MAX_PT_LEN];
|
||||
const uint8_t oid_ecdsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03 };
|
||||
size_t p_size = mbedtls_mpi_size(&ecdsa->grp.P), a_size = mbedtls_mpi_size(&ecdsa->grp.A);
|
||||
size_t b_size = mbedtls_mpi_size(&ecdsa->grp.B),
|
||||
g_size = 1+mbedtls_mpi_size(&ecdsa->grp.G.X)+mbedtls_mpi_size(&ecdsa->grp.G.X);
|
||||
g_size = 1 + mbedtls_mpi_size(&ecdsa->grp.G.X) + mbedtls_mpi_size(&ecdsa->grp.G.X);
|
||||
size_t o_size = mbedtls_mpi_size(&ecdsa->grp.N), y_size = 0;
|
||||
mbedtls_ecp_point_write_binary(&ecdsa->grp,
|
||||
&ecdsa->Q,
|
||||
@ -99,7 +97,7 @@ size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, siz
|
||||
size_t ctot_size = asn1_len_tag(0x87, c_size);
|
||||
size_t oid_len = asn1_len_tag(0x6, sizeof(oid_ecdsa));
|
||||
size_t tot_len = asn1_len_tag(0x7f49,
|
||||
oid_len+ptot_size+atot_size+btot_size+gtot_size+otot_size+ytot_size+
|
||||
oid_len + ptot_size + atot_size + btot_size + gtot_size + otot_size + ytot_size +
|
||||
ctot_size);
|
||||
if (buf == NULL || buf_len == 0) {
|
||||
return tot_len;
|
||||
@ -110,7 +108,7 @@ size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, siz
|
||||
uint8_t *p = buf;
|
||||
memcpy(p, "\x7F\x49", 2); p += 2;
|
||||
p += format_tlv_len(
|
||||
oid_len+ptot_size+atot_size+btot_size+gtot_size+otot_size+ytot_size+ctot_size,
|
||||
oid_len + ptot_size + atot_size + btot_size + gtot_size + otot_size + ytot_size + ctot_size,
|
||||
p);
|
||||
//oid
|
||||
*p++ = 0x6; p += format_tlv_len(sizeof(oid_ecdsa), p); memcpy(p, oid_ecdsa, sizeof(oid_ecdsa));
|
||||
@ -123,11 +121,13 @@ size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, siz
|
||||
*p++ = 0x82; p += format_tlv_len(a_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.A,
|
||||
p,
|
||||
a_size); p += a_size;
|
||||
} else { //mbedtls does not set point A for some curves
|
||||
}
|
||||
else { //mbedtls does not set point A for some curves
|
||||
if (pointA[ecdsa->grp.id] && ecdsa->grp.id < 6) {
|
||||
*p++ = 0x82; p += format_tlv_len(p_size, p); memcpy(p, pointA[ecdsa->grp.id], p_size);
|
||||
p += p_size;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
*p++ = 0x82; p += format_tlv_len(1, p);
|
||||
*p++ = 0x0;
|
||||
}
|
||||
@ -153,9 +153,11 @@ size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, siz
|
||||
*p++ = 0x87; p += format_tlv_len(c_size, p);
|
||||
if (ecdsa->grp.id == MBEDTLS_ECP_DP_CURVE448) {
|
||||
*p++ = 4;
|
||||
} else if (ecdsa->grp.id == MBEDTLS_ECP_DP_CURVE25519) {
|
||||
}
|
||||
else if (ecdsa->grp.id == MBEDTLS_ECP_DP_CURVE25519) {
|
||||
*p++ = 8;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
*p++ = 1;
|
||||
}
|
||||
return tot_len;
|
||||
@ -166,12 +168,12 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa,
|
||||
uint8_t *buf,
|
||||
size_t buf_len,
|
||||
const uint8_t *ext,
|
||||
size_t ext_len)
|
||||
{
|
||||
size_t ext_len) {
|
||||
size_t pubkey_size = 0;
|
||||
if (key_type == HSM_KEY_RSA) {
|
||||
pubkey_size = asn1_cvc_public_key_rsa(rsa_ecdsa, NULL, 0);
|
||||
} else if (key_type == HSM_KEY_EC) {
|
||||
}
|
||||
else if (key_type == HSM_KEY_EC) {
|
||||
pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0);
|
||||
}
|
||||
size_t cpi_size = 4;
|
||||
@ -195,7 +197,7 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa,
|
||||
}
|
||||
size_t car_size = asn1_len_tag(0x42, lencar), chr_size = asn1_len_tag(0x5f20, lenchr);
|
||||
|
||||
size_t tot_len = asn1_len_tag(0x7f4e, cpi_size+car_size+pubkey_size+chr_size+ext_size);
|
||||
size_t tot_len = asn1_len_tag(0x7f4e, cpi_size + car_size + pubkey_size + chr_size + ext_size);
|
||||
|
||||
if (buf_len == 0 || buf == NULL) {
|
||||
return tot_len;
|
||||
@ -205,7 +207,7 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa,
|
||||
}
|
||||
uint8_t *p = buf;
|
||||
memcpy(p, "\x7F\x4E", 2); p += 2;
|
||||
p += format_tlv_len(cpi_size+car_size+pubkey_size+chr_size+ext_size, p);
|
||||
p += format_tlv_len(cpi_size + car_size + pubkey_size + chr_size + ext_size, p);
|
||||
//cpi
|
||||
*p++ = 0x5f; *p++ = 0x29; *p++ = 1; *p++ = 0;
|
||||
//car
|
||||
@ -213,7 +215,8 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa,
|
||||
//pubkey
|
||||
if (key_type == HSM_KEY_RSA) {
|
||||
p += asn1_cvc_public_key_rsa(rsa_ecdsa, p, pubkey_size);
|
||||
} else if (key_type == HSM_KEY_EC) {
|
||||
}
|
||||
else if (key_type == HSM_KEY_EC) {
|
||||
p += asn1_cvc_public_key_ecdsa(rsa_ecdsa, p, pubkey_size);
|
||||
}
|
||||
//chr
|
||||
@ -232,20 +235,20 @@ size_t asn1_cvc_cert(void *rsa_ecdsa,
|
||||
uint8_t *buf,
|
||||
size_t buf_len,
|
||||
const uint8_t *ext,
|
||||
size_t ext_len)
|
||||
{
|
||||
size_t ext_len) {
|
||||
size_t key_size = 0;
|
||||
if (key_type == HSM_KEY_RSA) {
|
||||
key_size = mbedtls_mpi_size(&((mbedtls_rsa_context *) rsa_ecdsa)->N);
|
||||
} else if (key_type == HSM_KEY_EC) {
|
||||
key_size = 2*
|
||||
}
|
||||
else if (key_type == HSM_KEY_EC) {
|
||||
key_size = 2 *
|
||||
(int) ((mbedtls_ecp_curve_info_from_grp_id(((mbedtls_ecdsa_context *) rsa_ecdsa)
|
||||
->grp.id)->
|
||||
bit_size + 7)/8);
|
||||
bit_size + 7) / 8);
|
||||
}
|
||||
size_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0, ext, ext_len),
|
||||
sig_size = asn1_len_tag(0x5f37, key_size);
|
||||
size_t tot_len = asn1_len_tag(0x7f21, body_size+sig_size);
|
||||
size_t tot_len = asn1_len_tag(0x7f21, body_size + sig_size);
|
||||
if (buf_len == 0 || buf == NULL) {
|
||||
return tot_len;
|
||||
}
|
||||
@ -254,7 +257,7 @@ size_t asn1_cvc_cert(void *rsa_ecdsa,
|
||||
}
|
||||
uint8_t *p = buf, *body = NULL;
|
||||
memcpy(p, "\x7F\x21", 2); p += 2;
|
||||
p += format_tlv_len(body_size+sig_size, p);
|
||||
p += format_tlv_len(body_size + sig_size, p);
|
||||
body = p;
|
||||
p += asn1_cvc_cert_body(rsa_ecdsa, key_type, p, body_size, ext, ext_len);
|
||||
uint8_t hsh[32];
|
||||
@ -267,7 +270,8 @@ size_t asn1_cvc_cert(void *rsa_ecdsa,
|
||||
memset(p, 0, key_size);
|
||||
}
|
||||
p += key_size;
|
||||
} else if (key_type == HSM_KEY_EC) {
|
||||
}
|
||||
else if (key_type == HSM_KEY_EC) {
|
||||
mbedtls_mpi r, s;
|
||||
int ret = 0;
|
||||
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) rsa_ecdsa;
|
||||
@ -276,16 +280,17 @@ size_t asn1_cvc_cert(void *rsa_ecdsa,
|
||||
ret =
|
||||
mbedtls_ecdsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, hsh, sizeof(hsh), random_gen, NULL);
|
||||
if (ret == 0) {
|
||||
mbedtls_mpi_write_binary(&r, p, key_size/2); p += key_size/2;
|
||||
mbedtls_mpi_write_binary(&s, p, key_size/2); p += key_size/2;
|
||||
} else {
|
||||
mbedtls_mpi_write_binary(&r, p, key_size / 2); p += key_size / 2;
|
||||
mbedtls_mpi_write_binary(&s, p, key_size / 2); p += key_size / 2;
|
||||
}
|
||||
else {
|
||||
memset(p, 0, key_size);
|
||||
p += key_size;
|
||||
}
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_mpi_free(&s);
|
||||
}
|
||||
return p-buf;
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
size_t asn1_cvc_aut(void *rsa_ecdsa,
|
||||
@ -293,8 +298,7 @@ size_t asn1_cvc_aut(void *rsa_ecdsa,
|
||||
uint8_t *buf,
|
||||
size_t buf_len,
|
||||
const uint8_t *ext,
|
||||
size_t ext_len)
|
||||
{
|
||||
size_t ext_len) {
|
||||
size_t cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0, ext, ext_len);
|
||||
size_t outcar_len = dev_name_len;
|
||||
const uint8_t *outcar = dev_name;
|
||||
@ -309,9 +313,9 @@ size_t asn1_cvc_aut(void *rsa_ecdsa,
|
||||
mbedtls_ecdsa_free(&ectx);
|
||||
return 0;
|
||||
}
|
||||
int ret = 0, key_size = 2*mbedtls_mpi_size(&ectx.d);
|
||||
int ret = 0, key_size = 2 * mbedtls_mpi_size(&ectx.d);
|
||||
size_t outsig_size = asn1_len_tag(0x5f37, key_size), tot_len = asn1_len_tag(0x67,
|
||||
cvcert_size+outcar_size+
|
||||
cvcert_size + outcar_size +
|
||||
outsig_size);
|
||||
if (buf_len == 0 || buf == NULL) {
|
||||
return tot_len;
|
||||
@ -321,7 +325,7 @@ size_t asn1_cvc_aut(void *rsa_ecdsa,
|
||||
}
|
||||
uint8_t *p = buf;
|
||||
*p++ = 0x67;
|
||||
p += format_tlv_len(cvcert_size+outcar_size+outsig_size, p);
|
||||
p += format_tlv_len(cvcert_size + outcar_size + outsig_size, p);
|
||||
uint8_t *body = p;
|
||||
//cvcert
|
||||
p += asn1_cvc_cert(rsa_ecdsa, key_type, p, cvcert_size, ext, ext_len);
|
||||
@ -330,7 +334,7 @@ size_t asn1_cvc_aut(void *rsa_ecdsa,
|
||||
uint8_t hsh[32];
|
||||
memcpy(p, "\x5f\x37", 2); p += 2;
|
||||
p += format_tlv_len(key_size, p);
|
||||
hash256(body, cvcert_size+outcar_size, hsh);
|
||||
hash256(body, cvcert_size + outcar_size, hsh);
|
||||
mbedtls_mpi r, s;
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
@ -345,7 +349,7 @@ size_t asn1_cvc_aut(void *rsa_ecdsa,
|
||||
mbedtls_mpi_write_binary(&s, p, mbedtls_mpi_size(&s)); p += mbedtls_mpi_size(&s);
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_mpi_free(&s);
|
||||
return p-buf;
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
size_t asn1_build_cert_description(const uint8_t *label,
|
||||
@ -354,15 +358,15 @@ size_t asn1_build_cert_description(const uint8_t *label,
|
||||
size_t puk_len,
|
||||
uint16_t fid,
|
||||
uint8_t *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
size_t buf_len) {
|
||||
size_t opt_len = 2;
|
||||
size_t seq1_size = asn1_len_tag(0x30, asn1_len_tag(0xC, label_len)+asn1_len_tag(0x3, opt_len));
|
||||
size_t seq1_size =
|
||||
asn1_len_tag(0x30, asn1_len_tag(0xC, label_len) + asn1_len_tag(0x3, opt_len));
|
||||
size_t seq2_size = asn1_len_tag(0x30, asn1_len_tag(0x4, 20)); /* SHA1 is 20 bytes length */
|
||||
size_t seq3_size =
|
||||
asn1_len_tag(0xA1,
|
||||
asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t)))));
|
||||
size_t tot_len = asn1_len_tag(0x30, seq1_size+seq2_size+seq3_size);
|
||||
size_t tot_len = asn1_len_tag(0x30, seq1_size + seq2_size + seq3_size);
|
||||
if (buf_len == 0 || buf == NULL) {
|
||||
return tot_len;
|
||||
}
|
||||
@ -371,10 +375,10 @@ size_t asn1_build_cert_description(const uint8_t *label,
|
||||
}
|
||||
uint8_t *p = buf;
|
||||
*p++ = 0x30;
|
||||
p += format_tlv_len(seq1_size+seq2_size+seq3_size, p);
|
||||
p += format_tlv_len(seq1_size + seq2_size + seq3_size, p);
|
||||
//Seq 1
|
||||
*p++ = 0x30;
|
||||
p += format_tlv_len(asn1_len_tag(0xC, label_len)+asn1_len_tag(0x3, opt_len), p);
|
||||
p += format_tlv_len(asn1_len_tag(0xC, label_len) + asn1_len_tag(0x3, opt_len), p);
|
||||
*p++ = 0xC;
|
||||
p += format_tlv_len(label_len, p);
|
||||
memcpy(p, label, label_len); p += label_len;
|
||||
@ -401,7 +405,7 @@ size_t asn1_build_cert_description(const uint8_t *label,
|
||||
p += format_tlv_len(sizeof(uint16_t), p);
|
||||
*p++ = fid >> 8;
|
||||
*p++ = fid & 0xff;
|
||||
return p-buf;
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
size_t asn1_build_prkd_generic(const uint8_t *label,
|
||||
@ -412,15 +416,15 @@ size_t asn1_build_prkd_generic(const uint8_t *label,
|
||||
const uint8_t *seq,
|
||||
size_t seq_len,
|
||||
uint8_t *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
size_t buf_len) {
|
||||
size_t seq1_size = asn1_len_tag(0x30, asn1_len_tag(0xC, label_len));
|
||||
size_t seq2_size = asn1_len_tag(0x30, asn1_len_tag(0x4, keyid_len)+asn1_len_tag(0x3, seq_len));
|
||||
size_t seq2_size =
|
||||
asn1_len_tag(0x30, asn1_len_tag(0x4, keyid_len) + asn1_len_tag(0x3, seq_len));
|
||||
size_t seq3_size =
|
||||
asn1_len_tag(0xA1,
|
||||
asn1_len_tag(0x30,
|
||||
asn1_len_tag(0x30, asn1_len_tag(0x4, 0))+asn1_len_tag(0x2, 2)));
|
||||
size_t tot_len = asn1_len_tag(0xA0, seq1_size+seq2_size+seq3_size);
|
||||
asn1_len_tag(0x30, asn1_len_tag(0x4, 0)) + asn1_len_tag(0x2, 2)));
|
||||
size_t tot_len = asn1_len_tag(0xA0, seq1_size + seq2_size + seq3_size);
|
||||
if (buf_len == 0 || buf == NULL) {
|
||||
return tot_len;
|
||||
}
|
||||
@ -429,7 +433,7 @@ size_t asn1_build_prkd_generic(const uint8_t *label,
|
||||
}
|
||||
uint8_t *p = buf;
|
||||
*p++ = 0xA0;
|
||||
p += format_tlv_len(seq1_size+seq2_size+seq3_size, p);
|
||||
p += format_tlv_len(seq1_size + seq2_size + seq3_size, p);
|
||||
//Seq 1
|
||||
*p++ = 0x30;
|
||||
p += format_tlv_len(asn1_len_tag(0xC, label_len), p);
|
||||
@ -439,7 +443,7 @@ size_t asn1_build_prkd_generic(const uint8_t *label,
|
||||
|
||||
//Seq 2
|
||||
*p++ = 0x30;
|
||||
p += format_tlv_len(asn1_len_tag(0x4, keyid_len)+asn1_len_tag(0x3, seq_len), p);
|
||||
p += format_tlv_len(asn1_len_tag(0x4, keyid_len) + asn1_len_tag(0x3, seq_len), p);
|
||||
*p++ = 0x4;
|
||||
p += format_tlv_len(keyid_len, p);
|
||||
memcpy(p, keyid, keyid_len); p += keyid_len;
|
||||
@ -450,11 +454,12 @@ size_t asn1_build_prkd_generic(const uint8_t *label,
|
||||
//Seq 3
|
||||
*p++ = 0xA1;
|
||||
p +=
|
||||
format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0))+asn1_len_tag(0x2,
|
||||
2)),
|
||||
format_tlv_len(asn1_len_tag(0x30,
|
||||
asn1_len_tag(0x30, asn1_len_tag(0x4, 0)) + asn1_len_tag(0x2,
|
||||
2)),
|
||||
p);
|
||||
*p++ = 0x30;
|
||||
p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x4, 0))+asn1_len_tag(0x2, 2), p);
|
||||
p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x4, 0)) + asn1_len_tag(0x2, 2), p);
|
||||
*p++ = 0x30;
|
||||
p += format_tlv_len(asn1_len_tag(0x4, 0), p);
|
||||
*p++ = 0x4;
|
||||
@ -463,7 +468,7 @@ size_t asn1_build_prkd_generic(const uint8_t *label,
|
||||
p += format_tlv_len(2, p);
|
||||
*p++ = (keysize >> 8) & 0xff;
|
||||
*p++ = keysize & 0xff;
|
||||
return p-buf;
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
size_t asn1_build_prkd_ecc(const uint8_t *label,
|
||||
@ -472,8 +477,7 @@ size_t asn1_build_prkd_ecc(const uint8_t *label,
|
||||
size_t keyid_len,
|
||||
size_t keysize,
|
||||
uint8_t *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
size_t buf_len) {
|
||||
return asn1_build_prkd_generic(label,
|
||||
label_len,
|
||||
keyid,
|
||||
@ -491,8 +495,7 @@ size_t asn1_build_prkd_rsa(const uint8_t *label,
|
||||
size_t keyid_len,
|
||||
size_t keysize,
|
||||
uint8_t *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
size_t buf_len) {
|
||||
return asn1_build_prkd_generic(label,
|
||||
label_len,
|
||||
keyid,
|
||||
@ -504,8 +507,7 @@ size_t asn1_build_prkd_rsa(const uint8_t *label,
|
||||
buf_len);
|
||||
}
|
||||
|
||||
const uint8_t *cvc_get_field(const uint8_t *data, size_t len, size_t *olen, uint16_t tag)
|
||||
{
|
||||
const uint8_t *cvc_get_field(const uint8_t *data, size_t len, size_t *olen, uint16_t tag) {
|
||||
uint8_t *rdata = NULL;
|
||||
if (data == NULL || len == 0) {
|
||||
return NULL;
|
||||
@ -516,8 +518,7 @@ const uint8_t *cvc_get_field(const uint8_t *data, size_t len, size_t *olen, uint
|
||||
return rdata;
|
||||
}
|
||||
|
||||
const uint8_t *cvc_get_body(const uint8_t *data, size_t len, size_t *olen)
|
||||
{
|
||||
const uint8_t *cvc_get_body(const uint8_t *data, size_t len, size_t *olen) {
|
||||
const uint8_t *bkdata = data;
|
||||
if ((data = cvc_get_field(data, len, olen, 0x67)) == NULL) { /* Check for CSR */
|
||||
data = bkdata;
|
||||
@ -528,8 +529,7 @@ const uint8_t *cvc_get_body(const uint8_t *data, size_t len, size_t *olen)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint8_t *cvc_get_sig(const uint8_t *data, size_t len, size_t *olen)
|
||||
{
|
||||
const uint8_t *cvc_get_sig(const uint8_t *data, size_t len, size_t *olen) {
|
||||
const uint8_t *bkdata = data;
|
||||
if ((data = cvc_get_field(data, len, olen, 0x67)) == NULL) { /* Check for CSR */
|
||||
data = bkdata;
|
||||
@ -540,32 +540,28 @@ const uint8_t *cvc_get_sig(const uint8_t *data, size_t len, size_t *olen)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint8_t *cvc_get_car(const uint8_t *data, size_t len, size_t *olen)
|
||||
{
|
||||
const uint8_t *cvc_get_car(const uint8_t *data, size_t len, size_t *olen) {
|
||||
if ((data = cvc_get_body(data, len, olen)) != NULL) {
|
||||
return cvc_get_field(data, len, olen, 0x42);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint8_t *cvc_get_chr(const uint8_t *data, size_t len, size_t *olen)
|
||||
{
|
||||
const uint8_t *cvc_get_chr(const uint8_t *data, size_t len, size_t *olen) {
|
||||
if ((data = cvc_get_body(data, len, olen)) != NULL) {
|
||||
return cvc_get_field(data, len, olen, 0x5F20);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint8_t *cvc_get_pub(const uint8_t *data, size_t len, size_t *olen)
|
||||
{
|
||||
const uint8_t *cvc_get_pub(const uint8_t *data, size_t len, size_t *olen) {
|
||||
if ((data = cvc_get_body(data, len, olen)) != NULL) {
|
||||
return cvc_get_field(data, len, olen, 0x7F49);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint8_t *cvc_get_ext(const uint8_t *data, size_t len, size_t *olen)
|
||||
{
|
||||
const uint8_t *cvc_get_ext(const uint8_t *data, size_t len, size_t *olen) {
|
||||
if ((data = cvc_get_body(data, len, olen)) != NULL) {
|
||||
return cvc_get_field(data, len, olen, 0x65);
|
||||
}
|
||||
@ -575,8 +571,7 @@ const uint8_t *cvc_get_ext(const uint8_t *data, size_t len, size_t *olen)
|
||||
extern PUK puk_store[MAX_PUK_STORE_ENTRIES];
|
||||
extern int puk_store_entries;
|
||||
|
||||
int puk_store_index(const uint8_t *chr, size_t chr_len)
|
||||
{
|
||||
int puk_store_index(const uint8_t *chr, size_t chr_len) {
|
||||
for (int i = 0; i < puk_store_entries; i++) {
|
||||
if (memcmp(puk_store[i].chr, chr, chr_len) == 0) {
|
||||
return i;
|
||||
@ -585,8 +580,7 @@ int puk_store_index(const uint8_t *chr, size_t chr_len)
|
||||
return -1;
|
||||
}
|
||||
|
||||
mbedtls_ecp_group_id cvc_inherite_ec_group(const uint8_t *ca, size_t ca_len)
|
||||
{
|
||||
mbedtls_ecp_group_id cvc_inherite_ec_group(const uint8_t *ca, size_t ca_len) {
|
||||
size_t chr_len = 0, car_len = 0;
|
||||
const uint8_t *chr = NULL, *car = NULL;
|
||||
int eq = -1;
|
||||
@ -599,7 +593,8 @@ mbedtls_ecp_group_id cvc_inherite_ec_group(const uint8_t *ca, size_t ca_len)
|
||||
if (idx != -1) {
|
||||
ca = puk_store[idx].cvcert;
|
||||
ca_len = puk_store[idx].cvcert_len;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ca = NULL;
|
||||
}
|
||||
}
|
||||
@ -623,8 +618,7 @@ int puk_verify(const uint8_t *sig,
|
||||
const uint8_t *hash,
|
||||
size_t hash_len,
|
||||
const uint8_t *ca,
|
||||
size_t ca_len)
|
||||
{
|
||||
size_t ca_len) {
|
||||
size_t puk_len = 0;
|
||||
const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len);
|
||||
if (!puk) {
|
||||
@ -649,17 +643,22 @@ int puk_verify(const uint8_t *sig,
|
||||
mbedtls_md_type_t md = MBEDTLS_MD_NONE;
|
||||
if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_1, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
} else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_256, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_256, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
} else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_512, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_512, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
} else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_1, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_1, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, md);
|
||||
} else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_256, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_256, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, md);
|
||||
} else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_512, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_512, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, md);
|
||||
}
|
||||
@ -692,17 +691,22 @@ int puk_verify(const uint8_t *sig,
|
||||
if (r != 0) {
|
||||
return CCID_WRONG_SIGNATURE;
|
||||
}
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
|
||||
mbedtls_md_type_t md = MBEDTLS_MD_NONE;
|
||||
if (memcmp(oid, OID_ID_TA_ECDSA_SHA_1, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_224, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_224, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA224;
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_384, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_384, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA384;
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_512, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_512, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
}
|
||||
if (md == MBEDTLS_MD_NONE) {
|
||||
@ -738,14 +742,14 @@ int puk_verify(const uint8_t *sig,
|
||||
mbedtls_mpi r, s;
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
ret = mbedtls_mpi_read_binary(&r, sig, sig_len/2);
|
||||
ret = mbedtls_mpi_read_binary(&r, sig, sig_len / 2);
|
||||
if (ret != 0) {
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_mpi_free(&s);
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
return CCID_EXEC_ERROR;
|
||||
}
|
||||
ret = mbedtls_mpi_read_binary(&s, sig+sig_len/2, sig_len/2);
|
||||
ret = mbedtls_mpi_read_binary(&s, sig + sig_len / 2, sig_len / 2);
|
||||
if (ret != 0) {
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_mpi_free(&s);
|
||||
@ -763,8 +767,7 @@ int puk_verify(const uint8_t *sig,
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int cvc_verify(const uint8_t *cert, size_t cert_len, const uint8_t *ca, size_t ca_len)
|
||||
{
|
||||
int cvc_verify(const uint8_t *cert, size_t cert_len, const uint8_t *ca, size_t ca_len) {
|
||||
size_t puk_len = 0;
|
||||
const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len);
|
||||
if (!puk) {
|
||||
@ -787,27 +790,37 @@ int cvc_verify(const uint8_t *cert, size_t cert_len, const uint8_t *ca, size_t c
|
||||
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
|
||||
if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_1, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
} else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_256, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_256, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
} else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_512, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
} else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_1, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
} else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_256, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
} else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_512, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_512, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
}
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
|
||||
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_1, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_256, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_512, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
}
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
|
||||
if (memcmp(oid, OID_ID_TA_ECDSA_SHA_1, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_224, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_224, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA224;
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_384, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_384, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA384;
|
||||
} else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_512, oid_len) == 0) {
|
||||
}
|
||||
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_512, oid_len) == 0) {
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
}
|
||||
}
|
||||
@ -816,8 +829,8 @@ int cvc_verify(const uint8_t *cert, size_t cert_len, const uint8_t *ca, size_t c
|
||||
}
|
||||
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md);
|
||||
uint8_t hash[64], hash_len = mbedtls_md_get_size(md_info);
|
||||
uint8_t tlv_body = 2+format_tlv_len(cv_body_len, NULL);
|
||||
int r = mbedtls_md(md_info, cv_body-tlv_body, cv_body_len+tlv_body, hash);
|
||||
uint8_t tlv_body = 2 + format_tlv_len(cv_body_len, NULL);
|
||||
int r = mbedtls_md(md_info, cv_body - tlv_body, cv_body_len + tlv_body, hash);
|
||||
if (r != 0) {
|
||||
return CCID_EXEC_ERROR;
|
||||
}
|
||||
|
@ -106,9 +106,9 @@ file_t file_entries[] = {
|
||||
};
|
||||
|
||||
const file_t *MF = &file_entries[0];
|
||||
const file_t *file_last = &file_entries[sizeof(file_entries)/sizeof(file_t)-1];
|
||||
const file_t *file_openpgp = &file_entries[sizeof(file_entries)/sizeof(file_t)-3];
|
||||
const file_t *file_sc_hsm = &file_entries[sizeof(file_entries)/sizeof(file_t)-2];
|
||||
const file_t *file_last = &file_entries[sizeof(file_entries) / sizeof(file_t) - 1];
|
||||
const file_t *file_openpgp = &file_entries[sizeof(file_entries) / sizeof(file_t) - 3];
|
||||
const file_t *file_sc_hsm = &file_entries[sizeof(file_entries) / sizeof(file_t) - 2];
|
||||
file_t *file_pin1 = NULL;
|
||||
file_t *file_retries_pin1 = NULL;
|
||||
file_t *file_sopin = NULL;
|
||||
|
274
src/hsm/kek.c
274
src/hsm/kek.c
@ -39,8 +39,7 @@ bool has_mkek_mask = false;
|
||||
|
||||
#define POLY 0xedb88320
|
||||
|
||||
uint32_t crc32c(const uint8_t *buf, size_t len)
|
||||
{
|
||||
uint32_t crc32c(const uint8_t *buf, size_t len) {
|
||||
uint32_t crc = ~0;
|
||||
while (len--) {
|
||||
crc ^= *buf++;
|
||||
@ -51,8 +50,7 @@ uint32_t crc32c(const uint8_t *buf, size_t len)
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
int load_mkek(uint8_t *mkek)
|
||||
{
|
||||
int load_mkek(uint8_t *mkek) {
|
||||
if (has_session_pin == false && has_session_sopin == false) {
|
||||
return CCID_NO_LOGIN;
|
||||
}
|
||||
@ -81,7 +79,7 @@ int load_mkek(uint8_t *mkek)
|
||||
}
|
||||
}
|
||||
int ret =
|
||||
aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE);
|
||||
aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE);
|
||||
if (ret != 0) {
|
||||
return CCID_EXEC_ERROR;
|
||||
}
|
||||
@ -93,8 +91,7 @@ int load_mkek(uint8_t *mkek)
|
||||
|
||||
mse_t mse = { .init = false };
|
||||
|
||||
int mse_decrypt_ct(uint8_t *data, size_t len)
|
||||
{
|
||||
int mse_decrypt_ct(uint8_t *data, size_t len) {
|
||||
mbedtls_chachapoly_context chatx;
|
||||
mbedtls_chachapoly_init(&chatx);
|
||||
mbedtls_chachapoly_setkey(&chatx, mse.key_enc + 12);
|
||||
@ -110,9 +107,8 @@ int mse_decrypt_ct(uint8_t *data, size_t len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int load_dkek(uint8_t id, uint8_t *dkek)
|
||||
{
|
||||
file_t *tf = search_dynamic_file(EF_DKEK+id);
|
||||
int load_dkek(uint8_t id, uint8_t *dkek) {
|
||||
file_t *tf = search_dynamic_file(EF_DKEK + id);
|
||||
if (!tf) {
|
||||
return CCID_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
@ -120,21 +116,20 @@ int load_dkek(uint8_t id, uint8_t *dkek)
|
||||
return mkek_decrypt(dkek, DKEK_KEY_SIZE);
|
||||
}
|
||||
|
||||
void release_mkek(uint8_t *mkek)
|
||||
{
|
||||
void release_mkek(uint8_t *mkek) {
|
||||
mbedtls_platform_zeroize(mkek, MKEK_SIZE);
|
||||
}
|
||||
|
||||
int store_mkek(const uint8_t *mkek)
|
||||
{
|
||||
int store_mkek(const uint8_t *mkek) {
|
||||
if (has_session_pin == false && has_session_sopin == false) {
|
||||
return CCID_NO_LOGIN;
|
||||
}
|
||||
uint8_t tmp_mkek[MKEK_SIZE];
|
||||
if (mkek == NULL) {
|
||||
const uint8_t *rd = random_bytes_get(MKEK_IV_SIZE+MKEK_KEY_SIZE);
|
||||
memcpy(tmp_mkek, rd, MKEK_IV_SIZE+MKEK_KEY_SIZE);
|
||||
} else {
|
||||
const uint8_t *rd = random_bytes_get(MKEK_IV_SIZE + MKEK_KEY_SIZE);
|
||||
memcpy(tmp_mkek, rd, MKEK_IV_SIZE + MKEK_KEY_SIZE);
|
||||
}
|
||||
else {
|
||||
memcpy(tmp_mkek, mkek, MKEK_SIZE);
|
||||
}
|
||||
*(uint32_t *) MKEK_CHECKSUM(tmp_mkek) = crc32c(MKEK_KEY(tmp_mkek), MKEK_KEY_SIZE);
|
||||
@ -150,7 +145,7 @@ int store_mkek(const uint8_t *mkek)
|
||||
aes_encrypt_cfb_256(session_pin,
|
||||
MKEK_IV(tmp_mkek_pin),
|
||||
MKEK_KEY(tmp_mkek_pin),
|
||||
MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE);
|
||||
MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE);
|
||||
flash_write_data_to_file(tf, tmp_mkek_pin, MKEK_SIZE);
|
||||
release_mkek(tmp_mkek_pin);
|
||||
}
|
||||
@ -175,9 +170,8 @@ int store_mkek(const uint8_t *mkek)
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int store_dkek_key(uint8_t id, uint8_t *dkek)
|
||||
{
|
||||
file_t *tf = search_dynamic_file(EF_DKEK+id);
|
||||
int store_dkek_key(uint8_t id, uint8_t *dkek) {
|
||||
file_t *tf = search_dynamic_file(EF_DKEK + id);
|
||||
if (!tf) {
|
||||
return CCID_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
@ -190,25 +184,24 @@ int store_dkek_key(uint8_t id, uint8_t *dkek)
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int save_dkek_key(uint8_t id, const uint8_t *key)
|
||||
{
|
||||
int save_dkek_key(uint8_t id, const uint8_t *key) {
|
||||
uint8_t dkek[DKEK_KEY_SIZE];
|
||||
if (!key) {
|
||||
file_t *tf = search_dynamic_file(EF_DKEK+id);
|
||||
file_t *tf = search_dynamic_file(EF_DKEK + id);
|
||||
if (!tf) {
|
||||
return CCID_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
memcpy(dkek, key, DKEK_KEY_SIZE);
|
||||
}
|
||||
return store_dkek_key(id, dkek);
|
||||
}
|
||||
|
||||
int import_dkek_share(uint8_t id, const uint8_t *share)
|
||||
{
|
||||
int import_dkek_share(uint8_t id, const uint8_t *share) {
|
||||
uint8_t tmp_dkek[DKEK_KEY_SIZE];
|
||||
file_t *tf = search_dynamic_file(EF_DKEK+id);
|
||||
file_t *tf = search_dynamic_file(EF_DKEK + id);
|
||||
if (!tf) {
|
||||
return CCID_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
@ -224,8 +217,7 @@ int import_dkek_share(uint8_t id, const uint8_t *share)
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int dkek_kcv(uint8_t id, uint8_t *kcv) //kcv 8 bytes
|
||||
{
|
||||
int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes
|
||||
uint8_t hsh[32], dkek[DKEK_KEY_SIZE];
|
||||
memset(kcv, 0, 8);
|
||||
memset(hsh, 0, sizeof(hsh));
|
||||
@ -239,38 +231,35 @@ int dkek_kcv(uint8_t id, uint8_t *kcv) //kcv 8 bytes
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int dkek_kenc(uint8_t id, uint8_t *kenc) //kenc 32 bytes
|
||||
{
|
||||
uint8_t dkek[DKEK_KEY_SIZE+4];
|
||||
int dkek_kenc(uint8_t id, uint8_t *kenc) { //kenc 32 bytes
|
||||
uint8_t dkek[DKEK_KEY_SIZE + 4];
|
||||
memset(kenc, 0, 32);
|
||||
int r = load_dkek(id, dkek);
|
||||
if (r != CCID_OK) {
|
||||
return r;
|
||||
}
|
||||
memcpy(dkek+DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4);
|
||||
memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4);
|
||||
hash256(dkek, sizeof(dkek), kenc);
|
||||
mbedtls_platform_zeroize(dkek, sizeof(dkek));
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int dkek_kmac(uint8_t id, uint8_t *kmac) //kmac 32 bytes
|
||||
{
|
||||
uint8_t dkek[DKEK_KEY_SIZE+4];
|
||||
int dkek_kmac(uint8_t id, uint8_t *kmac) { //kmac 32 bytes
|
||||
uint8_t dkek[DKEK_KEY_SIZE + 4];
|
||||
memset(kmac, 0, 32);
|
||||
int r = load_dkek(id, dkek);
|
||||
if (r != CCID_OK) {
|
||||
return r;
|
||||
}
|
||||
memcpy(dkek+DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4);
|
||||
hash256(dkek, DKEK_KEY_SIZE+4, kmac);
|
||||
memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4);
|
||||
hash256(dkek, DKEK_KEY_SIZE + 4, kmac);
|
||||
mbedtls_platform_zeroize(dkek, sizeof(dkek));
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int mkek_encrypt(uint8_t *data, size_t len)
|
||||
{
|
||||
int mkek_encrypt(uint8_t *data, size_t len) {
|
||||
int r;
|
||||
uint8_t mkek[MKEK_SIZE+4];
|
||||
uint8_t mkek[MKEK_SIZE + 4];
|
||||
if ((r = load_mkek(mkek)) != CCID_OK) {
|
||||
return r;
|
||||
}
|
||||
@ -279,10 +268,9 @@ int mkek_encrypt(uint8_t *data, size_t len)
|
||||
return r;
|
||||
}
|
||||
|
||||
int mkek_decrypt(uint8_t *data, size_t len)
|
||||
{
|
||||
int mkek_decrypt(uint8_t *data, size_t len) {
|
||||
int r;
|
||||
uint8_t mkek[MKEK_SIZE+4];
|
||||
uint8_t mkek[MKEK_SIZE + 4];
|
||||
if ((r = load_mkek(mkek)) != CCID_OK) {
|
||||
return r;
|
||||
}
|
||||
@ -297,13 +285,12 @@ int dkek_encode_key(uint8_t id,
|
||||
uint8_t *out,
|
||||
size_t *out_len,
|
||||
const uint8_t *allowed,
|
||||
size_t allowed_len)
|
||||
{
|
||||
size_t allowed_len) {
|
||||
if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES)) {
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
|
||||
uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes 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));
|
||||
int kb_len = 0, r = 0;
|
||||
uint8_t *algo = NULL;
|
||||
@ -332,80 +319,87 @@ int dkek_encode_key(uint8_t id,
|
||||
if (key_type & HSM_KEY_AES) {
|
||||
if (key_type & HSM_KEY_AES_128) {
|
||||
kb_len = 16;
|
||||
} else if (key_type & HSM_KEY_AES_192) {
|
||||
}
|
||||
else if (key_type & HSM_KEY_AES_192) {
|
||||
kb_len = 24;
|
||||
} else if (key_type & HSM_KEY_AES_256) {
|
||||
}
|
||||
else if (key_type & HSM_KEY_AES_256) {
|
||||
kb_len = 32;
|
||||
}
|
||||
|
||||
if (kb_len != 16 && kb_len != 24 && kb_len != 32) {
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
if (*out_len < 8+1+10+6+4+(2+32+14)+16) {
|
||||
if (*out_len < 8 + 1 + 10 + 6 + 4 + (2 + 32 + 14) + 16) {
|
||||
return CCID_WRONG_LENGTH;
|
||||
}
|
||||
|
||||
put_uint16_t(kb_len, kb+8);
|
||||
memcpy(kb+10, key_ctx, kb_len);
|
||||
put_uint16_t(kb_len, kb + 8);
|
||||
memcpy(kb + 10, key_ctx, kb_len);
|
||||
kb_len += 2;
|
||||
|
||||
algo = (uint8_t *) "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8)
|
||||
algo_len = 10;
|
||||
} 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
|
||||
}
|
||||
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 CCID_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_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));
|
||||
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));
|
||||
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));
|
||||
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 = (uint8_t *) "\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
|
||||
}
|
||||
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 CCID_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));
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
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);
|
||||
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[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));
|
||||
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 = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03";
|
||||
@ -414,30 +408,34 @@ int dkek_encode_key(uint8_t id,
|
||||
memset(out, 0, *out_len);
|
||||
*out_len = 0;
|
||||
|
||||
memcpy(out+*out_len, kcv, 8);
|
||||
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) {
|
||||
}
|
||||
else if (key_type & HSM_KEY_RSA) {
|
||||
out[*out_len] = 5;
|
||||
} else if (key_type & HSM_KEY_EC) {
|
||||
}
|
||||
else if (key_type & HSM_KEY_EC) {
|
||||
out[*out_len] = 12;
|
||||
}
|
||||
*out_len += 1;
|
||||
|
||||
if (algo) {
|
||||
memcpy(out+*out_len, algo, algo_len);
|
||||
memcpy(out + *out_len, algo, algo_len);
|
||||
*out_len += algo_len;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
*out_len += 2;
|
||||
}
|
||||
|
||||
if (allowed && allowed_len > 0) {
|
||||
put_uint16_t(allowed_len, out+*out_len); *out_len += 2;
|
||||
memcpy(out+*out_len, allowed, allowed_len);
|
||||
put_uint16_t(allowed_len, out + *out_len); *out_len += 2;
|
||||
memcpy(out + *out_len, allowed, allowed_len);
|
||||
*out_len += allowed_len;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
*out_len += 2;
|
||||
}
|
||||
//add 4 zeros
|
||||
@ -445,9 +443,9 @@ int dkek_encode_key(uint8_t id,
|
||||
|
||||
memcpy(kb, random_bytes_get(8), 8);
|
||||
kb_len += 8; //8 random bytes
|
||||
int kb_len_pad = ((int) (kb_len/16))*16;
|
||||
int kb_len_pad = ((int) (kb_len / 16)) * 16;
|
||||
if (kb_len % 16 > 0) {
|
||||
kb_len_pad = ((int) (kb_len/16)+1)*16;
|
||||
kb_len_pad = ((int) (kb_len / 16) + 1) * 16;
|
||||
}
|
||||
//key already copied at kb+10
|
||||
if (kb_len < kb_len_pad) {
|
||||
@ -458,7 +456,7 @@ int dkek_encode_key(uint8_t id,
|
||||
return r;
|
||||
}
|
||||
|
||||
memcpy(out+*out_len, kb, kb_len_pad);
|
||||
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),
|
||||
@ -466,7 +464,7 @@ int dkek_encode_key(uint8_t id,
|
||||
256,
|
||||
out,
|
||||
*out_len,
|
||||
out+*out_len);
|
||||
out + *out_len);
|
||||
|
||||
*out_len += 16;
|
||||
if (r != 0) {
|
||||
@ -475,13 +473,14 @@ int dkek_encode_key(uint8_t id,
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int dkek_type_key(const uint8_t *in)
|
||||
{
|
||||
int dkek_type_key(const uint8_t *in) {
|
||||
if (in[8] == 5 || in[8] == 6) {
|
||||
return HSM_KEY_RSA;
|
||||
} else if (in[8] == 12) {
|
||||
}
|
||||
else if (in[8] == 12) {
|
||||
return HSM_KEY_EC;
|
||||
} else if (in[8] == 15) {
|
||||
}
|
||||
else if (in[8] == 15) {
|
||||
return HSM_KEY_AES;
|
||||
}
|
||||
return 0x0;
|
||||
@ -493,8 +492,7 @@ int dkek_decode_key(uint8_t id,
|
||||
size_t in_len,
|
||||
int *key_size_out,
|
||||
uint8_t **allowed,
|
||||
size_t *allowed_len)
|
||||
{
|
||||
size_t *allowed_len) {
|
||||
uint8_t kcv[8];
|
||||
int r = 0;
|
||||
memset(kcv, 0, sizeof(kcv));
|
||||
@ -526,12 +524,12 @@ int dkek_decode_key(uint8_t id,
|
||||
kmac,
|
||||
256,
|
||||
in,
|
||||
in_len-16,
|
||||
in_len - 16,
|
||||
signature);
|
||||
if (r != 0) {
|
||||
return CCID_WRONG_SIGNATURE;
|
||||
}
|
||||
if (memcmp(signature, in+in_len-16, 16) != 0) {
|
||||
if (memcmp(signature, in + in_len - 16, 16) != 0) {
|
||||
return CCID_WRONG_SIGNATURE;
|
||||
}
|
||||
|
||||
@ -541,16 +539,16 @@ int dkek_decode_key(uint8_t id,
|
||||
}
|
||||
|
||||
if ((key_type == 5 || key_type == 6) &&
|
||||
memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0) {
|
||||
memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0) {
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
|
||||
if (key_type == 12 &&
|
||||
memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0) {
|
||||
memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0) {
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
|
||||
if (key_type == 15 && memcmp(in+9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0) {
|
||||
if (key_type == 15 && memcmp(in + 9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0) {
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
|
||||
@ -558,29 +556,29 @@ int dkek_decode_key(uint8_t id,
|
||||
|
||||
//OID
|
||||
size_t len = get_uint16_t(in, ofs);
|
||||
ofs += len+2;
|
||||
ofs += len + 2;
|
||||
|
||||
//Allowed algorithms
|
||||
len = get_uint16_t(in, ofs);
|
||||
*allowed = (uint8_t *) (in+ofs+2);
|
||||
*allowed = (uint8_t *) (in + ofs + 2);
|
||||
*allowed_len = len;
|
||||
ofs += len+2;
|
||||
ofs += len + 2;
|
||||
|
||||
//Access conditions
|
||||
len = get_uint16_t(in, ofs);
|
||||
ofs += len+2;
|
||||
ofs += len + 2;
|
||||
|
||||
//Key OID
|
||||
len = get_uint16_t(in, ofs);
|
||||
ofs += len+2;
|
||||
ofs += len + 2;
|
||||
|
||||
if ((in_len-16-ofs) % 16 != 0) {
|
||||
if ((in_len - 16 - ofs) % 16 != 0) {
|
||||
return CCID_WRONG_PADDING;
|
||||
}
|
||||
uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes 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);
|
||||
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 != CCID_OK) {
|
||||
return r;
|
||||
}
|
||||
@ -595,47 +593,48 @@ int dkek_decode_key(uint8_t id,
|
||||
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;
|
||||
r = mbedtls_mpi_read_binary(&rsa->D, kb + ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->N, kb+ofs, len); ofs += len;
|
||||
r = mbedtls_mpi_read_binary(&rsa->N, kb + ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
} else if (key_type == 6) {
|
||||
}
|
||||
else if (key_type == 6) {
|
||||
//DP-1
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
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 += len + 2;
|
||||
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->P, kb+ofs, len); ofs += len;
|
||||
r = mbedtls_mpi_read_binary(&rsa->P, kb + ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
|
||||
//PQ
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
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;
|
||||
r = mbedtls_mpi_read_binary(&rsa->Q, kb + ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
//N
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
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;
|
||||
r = mbedtls_mpi_read_binary(&rsa->E, kb + ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return CCID_WRONG_DATA;
|
||||
@ -647,7 +646,8 @@ int dkek_decode_key(uint8_t id,
|
||||
mbedtls_rsa_free(rsa);
|
||||
return CCID_EXEC_ERROR;
|
||||
}
|
||||
} else if (key_type == 6) {
|
||||
}
|
||||
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);
|
||||
@ -665,19 +665,20 @@ int dkek_decode_key(uint8_t id,
|
||||
mbedtls_rsa_free(rsa);
|
||||
return CCID_EXEC_ERROR;
|
||||
}
|
||||
} else if (key_type == 12) {
|
||||
}
|
||||
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;
|
||||
len = get_uint16_t(kb, ofs); ofs += len + 2;
|
||||
|
||||
//B
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
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);
|
||||
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 CCID_WRONG_DATA;
|
||||
@ -685,14 +686,14 @@ int dkek_decode_key(uint8_t id,
|
||||
ofs += len;
|
||||
|
||||
//N
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
len = get_uint16_t(kb, ofs); ofs += len + 2;
|
||||
|
||||
//G
|
||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||
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);
|
||||
r = mbedtls_ecp_read_key(ec_id, ecdsa, kb + ofs, len);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdsa_free(ecdsa);
|
||||
return CCID_EXEC_ERROR;
|
||||
@ -711,8 +712,9 @@ int dkek_decode_key(uint8_t id,
|
||||
mbedtls_ecdsa_free(ecdsa);
|
||||
return CCID_EXEC_ERROR;
|
||||
}
|
||||
} else if (key_type == 15) {
|
||||
memcpy(key_ctx, kb+ofs, key_size);
|
||||
}
|
||||
else if (key_type == 15) {
|
||||
memcpy(key_ctx, kb + ofs, key_size);
|
||||
}
|
||||
return CCID_OK;
|
||||
}
|
||||
|
@ -49,17 +49,17 @@ extern int dkek_decode_key(uint8_t,
|
||||
uint8_t **,
|
||||
size_t *);
|
||||
|
||||
#define MAX_DKEK_ENCODE_KEY_BUFFER (8+1+12+6+(8+2*4+2*4096/8+3+13)+16)
|
||||
#define MAX_DKEK_ENCODE_KEY_BUFFER (8 + 1 + 12 + 6 + (8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13) + 16)
|
||||
|
||||
#define MAX_KEY_DOMAINS 16
|
||||
|
||||
#define MKEK_IV_SIZE (IV_SIZE)
|
||||
#define MKEK_KEY_SIZE (32)
|
||||
#define MKEK_KEY_CS_SIZE (4)
|
||||
#define MKEK_SIZE (MKEK_IV_SIZE+MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE)
|
||||
#define MKEK_SIZE (MKEK_IV_SIZE + MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE)
|
||||
#define MKEK_IV(p) (p)
|
||||
#define MKEK_KEY(p) (MKEK_IV(p)+MKEK_IV_SIZE)
|
||||
#define MKEK_CHECKSUM(p) (MKEK_KEY(p)+MKEK_KEY_SIZE)
|
||||
#define MKEK_KEY(p) (MKEK_IV(p) + MKEK_IV_SIZE)
|
||||
#define MKEK_CHECKSUM(p) (MKEK_KEY(p) + MKEK_KEY_SIZE)
|
||||
#define DKEK_KEY_SIZE (32)
|
||||
|
||||
extern uint8_t mkek_mask[MKEK_KEY_SIZE];
|
||||
|
158
src/hsm/sc_hsm.c
158
src/hsm/sc_hsm.c
@ -78,9 +78,8 @@ extern int cmd_pso();
|
||||
|
||||
extern const uint8_t *ccid_atr;
|
||||
|
||||
app_t *sc_hsm_select_aid(app_t *a, const uint8_t *aid, uint8_t aid_len)
|
||||
{
|
||||
if (!memcmp(aid, sc_hsm_aid+1, MIN(aid_len, sc_hsm_aid[0]))) {
|
||||
app_t *sc_hsm_select_aid(app_t *a, const uint8_t *aid, uint8_t aid_len) {
|
||||
if (!memcmp(aid, sc_hsm_aid + 1, MIN(aid_len, sc_hsm_aid[0]))) {
|
||||
a->aid = sc_hsm_aid;
|
||||
a->process_apdu = sc_hsm_process_apdu;
|
||||
a->unload = sc_hsm_unload;
|
||||
@ -90,14 +89,12 @@ app_t *sc_hsm_select_aid(app_t *a, const uint8_t *aid, uint8_t aid_len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void __attribute__((constructor)) sc_hsm_ctor()
|
||||
{
|
||||
void __attribute__((constructor)) sc_hsm_ctor() {
|
||||
ccid_atr = atr_sc_hsm;
|
||||
register_app(sc_hsm_select_aid);
|
||||
}
|
||||
|
||||
void scan_files()
|
||||
{
|
||||
void scan_files() {
|
||||
file_pin1 = search_by_fid(0x1081, NULL, SPECIFY_EF);
|
||||
if (file_pin1) {
|
||||
if (!file_pin1->data) {
|
||||
@ -105,7 +102,8 @@ void scan_files()
|
||||
const uint8_t empty[33] = { 0 };
|
||||
flash_write_data_to_file(file_pin1, empty, sizeof(empty));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("FATAL ERROR: PIN1 not found in memory!\r\n");
|
||||
}
|
||||
file_sopin = search_by_fid(0x1088, NULL, SPECIFY_EF);
|
||||
@ -115,7 +113,8 @@ void scan_files()
|
||||
const uint8_t empty[33] = { 0 };
|
||||
flash_write_data_to_file(file_sopin, empty, sizeof(empty));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("FATAL ERROR: SOPIN not found in memory!\r\n");
|
||||
}
|
||||
file_retries_pin1 = search_by_fid(0x1083, NULL, SPECIFY_EF);
|
||||
@ -125,7 +124,8 @@ void scan_files()
|
||||
const uint8_t retries = 3;
|
||||
flash_write_data_to_file(file_retries_pin1, &retries, sizeof(uint8_t));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("FATAL ERROR: Retries PIN1 not found in memory!\r\n");
|
||||
}
|
||||
file_retries_sopin = search_by_fid(0x108A, NULL, SPECIFY_EF);
|
||||
@ -135,7 +135,8 @@ void scan_files()
|
||||
const uint8_t retries = 15;
|
||||
flash_write_data_to_file(file_retries_sopin, &retries, sizeof(uint8_t));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("FATAL ERROR: Retries SOPIN not found in memory!\r\n");
|
||||
}
|
||||
file_t *tf = NULL;
|
||||
@ -147,7 +148,8 @@ void scan_files()
|
||||
const uint8_t retries = 3;
|
||||
flash_write_data_to_file(tf, &retries, sizeof(uint8_t));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("FATAL ERROR: Max Retries PIN1 not found in memory!\r\n");
|
||||
}
|
||||
tf = search_by_fid(0x1089, NULL, SPECIFY_EF);
|
||||
@ -157,14 +159,14 @@ void scan_files()
|
||||
const uint8_t retries = 15;
|
||||
flash_write_data_to_file(tf, &retries, sizeof(uint8_t));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("FATAL ERROR: Retries SOPIN not found in memory!\r\n");
|
||||
}
|
||||
low_flash_available();
|
||||
}
|
||||
|
||||
void scan_all()
|
||||
{
|
||||
void scan_all() {
|
||||
scan_flash();
|
||||
scan_files();
|
||||
}
|
||||
@ -174,8 +176,7 @@ int puk_store_entries = 0;
|
||||
PUK *current_puk = NULL;
|
||||
uint8_t puk_status[MAX_PUK];
|
||||
|
||||
int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy)
|
||||
{
|
||||
int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy) {
|
||||
if (data == NULL || data_len == 0) {
|
||||
return CCID_ERR_NULL_PARAM;
|
||||
}
|
||||
@ -188,7 +189,8 @@ int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy)
|
||||
uint8_t *tmp = (uint8_t *) calloc(data_len, sizeof(uint8_t));
|
||||
memcpy(tmp, data, data_len);
|
||||
puk_store[puk_store_entries].cvcert = tmp;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
puk_store[puk_store_entries].cvcert = data;
|
||||
}
|
||||
puk_store[puk_store_entries].cvcert_len = data_len;
|
||||
@ -206,8 +208,7 @@ int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy)
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int puk_store_select_chr(const uint8_t *chr)
|
||||
{
|
||||
int puk_store_select_chr(const uint8_t *chr) {
|
||||
for (int i = 0; i < puk_store_entries; i++) {
|
||||
if (memcmp(puk_store[i].chr, chr, puk_store[i].chr_len) == 0) {
|
||||
current_puk = &puk_store[i];
|
||||
@ -217,8 +218,7 @@ int puk_store_select_chr(const uint8_t *chr)
|
||||
return CCID_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
void init_sc_hsm()
|
||||
{
|
||||
void init_sc_hsm() {
|
||||
scan_all();
|
||||
has_session_pin = has_session_sopin = false;
|
||||
isUserAuthenticated = false;
|
||||
@ -246,27 +246,24 @@ void init_sc_hsm()
|
||||
memset(puk_status, 0, sizeof(puk_status));
|
||||
}
|
||||
|
||||
int sc_hsm_unload()
|
||||
{
|
||||
int sc_hsm_unload() {
|
||||
has_session_pin = has_session_sopin = false;
|
||||
isUserAuthenticated = false;
|
||||
sm_session_pin_len = 0;
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
uint16_t get_device_options()
|
||||
{
|
||||
uint16_t get_device_options() {
|
||||
file_t *ef = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef)) {
|
||||
return (file_read_uint8(file_get_data(ef)) << 8) | file_read_uint8(file_get_data(ef)+1);
|
||||
return (file_read_uint8(file_get_data(ef)) << 8) | file_read_uint8(file_get_data(ef) + 1);
|
||||
}
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
extern uint32_t board_button_read(void);
|
||||
|
||||
bool wait_button_pressed()
|
||||
{
|
||||
bool wait_button_pressed() {
|
||||
uint32_t val = EV_PRESS_BUTTON;
|
||||
#ifndef ENABLE_EMULATION
|
||||
uint16_t opts = get_device_options();
|
||||
@ -280,8 +277,7 @@ bool wait_button_pressed()
|
||||
return val == EV_BUTTON_TIMEOUT;
|
||||
}
|
||||
|
||||
int parse_token_info(const file_t *f, int mode)
|
||||
{
|
||||
int parse_token_info(const file_t *f, int mode) {
|
||||
char *label = "SmartCard-HSM";
|
||||
char *manu = "Pol Henarejos";
|
||||
if (mode == 1) {
|
||||
@ -297,19 +293,18 @@ int parse_token_info(const file_t *f, int mode)
|
||||
*p++ = 0xC; *p++ = strlen(manu); strcpy((char *) p, manu); p += strlen(manu);
|
||||
*p++ = 0x80; *p++ = strlen(label); strcpy((char *) p, label); p += strlen(label);
|
||||
*p++ = 0x3; *p++ = 2; *p++ = 4; *p++ = 0x30;
|
||||
res_APDU_size = p-res_APDU;
|
||||
res_APDU[1] = res_APDU_size-2;
|
||||
res_APDU_size = p - res_APDU;
|
||||
res_APDU[1] = res_APDU_size - 2;
|
||||
}
|
||||
return 2+(2+1)+(2+8)+(2+strlen(manu))+(2+strlen(label))+(2+2);
|
||||
return 2 + (2 + 1) + (2 + 8) + (2 + strlen(manu)) + (2 + strlen(label)) + (2 + 2);
|
||||
}
|
||||
|
||||
int pin_reset_retries(const file_t *pin, bool force)
|
||||
{
|
||||
int pin_reset_retries(const file_t *pin, bool force) {
|
||||
if (!pin) {
|
||||
return CCID_ERR_NULL_PARAM;
|
||||
}
|
||||
const file_t *max = search_by_fid(pin->fid+1, NULL, SPECIFY_EF);
|
||||
const file_t *act = search_by_fid(pin->fid+2, NULL, SPECIFY_EF);
|
||||
const file_t *max = search_by_fid(pin->fid + 1, NULL, SPECIFY_EF);
|
||||
const file_t *act = search_by_fid(pin->fid + 2, NULL, SPECIFY_EF);
|
||||
if (!max || !act) {
|
||||
return CCID_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
@ -323,12 +318,11 @@ int pin_reset_retries(const file_t *pin, bool force)
|
||||
return r;
|
||||
}
|
||||
|
||||
int pin_wrong_retry(const file_t *pin)
|
||||
{
|
||||
int pin_wrong_retry(const file_t *pin) {
|
||||
if (!pin) {
|
||||
return CCID_ERR_NULL_PARAM;
|
||||
}
|
||||
const file_t *act = search_by_fid(pin->fid+2, NULL, SPECIFY_EF);
|
||||
const file_t *act = search_by_fid(pin->fid + 2, NULL, SPECIFY_EF);
|
||||
if (!act) {
|
||||
return CCID_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
@ -348,14 +342,12 @@ int pin_wrong_retry(const file_t *pin)
|
||||
return CCID_ERR_BLOCKED;
|
||||
}
|
||||
|
||||
bool pka_enabled()
|
||||
{
|
||||
bool pka_enabled() {
|
||||
file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF);
|
||||
return file_has_data(ef_puk) && file_read_uint8(file_get_data(ef_puk)) > 0;
|
||||
}
|
||||
|
||||
int check_pin(const file_t *pin, const uint8_t *data, size_t len)
|
||||
{
|
||||
int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
|
||||
if (!file_has_data((file_t *) pin)) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
@ -371,13 +363,14 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len)
|
||||
}
|
||||
return set_res_sw(0x63, 0xc0 | retries);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint8_t dhash[32];
|
||||
double_hash_pin(data, len, dhash);
|
||||
if (sizeof(dhash) != file_get_size(pin)-1) { //1 byte for pin len
|
||||
if (sizeof(dhash) != file_get_size(pin) - 1) { //1 byte for pin len
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
if (memcmp(file_get_data(pin)+1, dhash, sizeof(dhash)) != 0) {
|
||||
if (memcmp(file_get_data(pin) + 1, dhash, sizeof(dhash)) != 0) {
|
||||
int retries;
|
||||
if ((retries = pin_wrong_retry(pin)) < CCID_OK) {
|
||||
return SW_PIN_BLOCKED();
|
||||
@ -398,15 +391,15 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len)
|
||||
if (pin == file_pin1) {
|
||||
hash_multi(data, len, session_pin);
|
||||
has_session_pin = true;
|
||||
} else if (pin == file_sopin) {
|
||||
}
|
||||
else if (pin == file_sopin) {
|
||||
hash_multi(data, len, session_sopin);
|
||||
has_session_sopin = true;
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, size_t *tag_len)
|
||||
{
|
||||
const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, size_t *tag_len) {
|
||||
if (ef == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -424,8 +417,7 @@ const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, size_t *tag_len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t get_key_counter(file_t *fkey)
|
||||
{
|
||||
uint32_t get_key_counter(file_t *fkey) {
|
||||
size_t tag_len = 0;
|
||||
const uint8_t *meta_tag = get_meta_tag(fkey, 0x90, &tag_len);
|
||||
if (meta_tag) {
|
||||
@ -434,8 +426,7 @@ uint32_t get_key_counter(file_t *fkey)
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
bool key_has_purpose(file_t *ef, uint8_t purpose)
|
||||
{
|
||||
bool key_has_purpose(file_t *ef, uint8_t purpose) {
|
||||
size_t tag_len = 0;
|
||||
const uint8_t *meta_tag = get_meta_tag(ef, 0x91, &tag_len);
|
||||
if (meta_tag) {
|
||||
@ -449,8 +440,7 @@ bool key_has_purpose(file_t *ef, uint8_t purpose)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t decrement_key_counter(file_t *fkey)
|
||||
{
|
||||
uint32_t decrement_key_counter(file_t *fkey) {
|
||||
if (!fkey) {
|
||||
return 0xffffff;
|
||||
}
|
||||
@ -488,31 +478,35 @@ uint32_t decrement_key_counter(file_t *fkey)
|
||||
}
|
||||
|
||||
//Stores the private and public keys in flash
|
||||
int store_keys(void *key_ctx, int type, uint8_t key_id)
|
||||
{
|
||||
int store_keys(void *key_ctx, int type, uint8_t key_id) {
|
||||
int r, key_size = 0;
|
||||
uint8_t kdata[4096/8]; //worst case
|
||||
uint8_t kdata[4096 / 8]; //worst case
|
||||
if (type == HSM_KEY_RSA) {
|
||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
|
||||
key_size = mbedtls_mpi_size(&rsa->P)+mbedtls_mpi_size(&rsa->Q);
|
||||
mbedtls_mpi_write_binary(&rsa->P, kdata, key_size/2);
|
||||
mbedtls_mpi_write_binary(&rsa->Q, kdata+key_size/2, key_size/2);
|
||||
} else if (type == HSM_KEY_EC) {
|
||||
key_size = mbedtls_mpi_size(&rsa->P) + mbedtls_mpi_size(&rsa->Q);
|
||||
mbedtls_mpi_write_binary(&rsa->P, kdata, key_size / 2);
|
||||
mbedtls_mpi_write_binary(&rsa->Q, kdata + key_size / 2, key_size / 2);
|
||||
}
|
||||
else if (type == HSM_KEY_EC) {
|
||||
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
|
||||
key_size = mbedtls_mpi_size(&ecdsa->d);
|
||||
kdata[0] = ecdsa->grp.id & 0xff;
|
||||
mbedtls_mpi_write_binary(&ecdsa->d, kdata+1, key_size);
|
||||
mbedtls_mpi_write_binary(&ecdsa->d, kdata + 1, key_size);
|
||||
key_size++;
|
||||
} else if (type & HSM_KEY_AES) {
|
||||
}
|
||||
else if (type & HSM_KEY_AES) {
|
||||
if (type == HSM_KEY_AES_128) {
|
||||
key_size = 16;
|
||||
} else if (type == HSM_KEY_AES_192) {
|
||||
}
|
||||
else if (type == HSM_KEY_AES_192) {
|
||||
key_size = 24;
|
||||
} else if (type == HSM_KEY_AES_256) {
|
||||
}
|
||||
else if (type == HSM_KEY_AES_256) {
|
||||
key_size = 32;
|
||||
}
|
||||
memcpy(kdata, key_ctx, key_size);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
|
||||
@ -531,18 +525,17 @@ int store_keys(void *key_ctx, int type, uint8_t key_id)
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int find_and_store_meta_key(uint8_t key_id)
|
||||
{
|
||||
int find_and_store_meta_key(uint8_t key_id) {
|
||||
size_t lt[4] = { 0, 0, 0, 0 }, meta_size = 0;
|
||||
uint8_t *pt[4] = { NULL, NULL, NULL, NULL };
|
||||
uint8_t t90[4] = { 0xFF, 0xFF, 0xFF, 0xFE };
|
||||
for (int t = 0; t < 4; t++) {
|
||||
uint8_t *ptt = NULL;
|
||||
size_t ltt = 0;
|
||||
if (asn1_find_tag(apdu.data, apdu.nc, 0x90+t, <t, &ptt) && ptt != NULL && ltt > 0) {
|
||||
if (asn1_find_tag(apdu.data, apdu.nc, 0x90 + t, <t, &ptt) && ptt != NULL && ltt > 0) {
|
||||
lt[t] = ltt;
|
||||
pt[t] = ptt;
|
||||
meta_size += asn1_len_tag(0x90+t, lt[t]);
|
||||
meta_size += asn1_len_tag(0x90 + t, lt[t]);
|
||||
}
|
||||
}
|
||||
if (lt[0] == 0 && pt[0] == NULL) {
|
||||
@ -557,7 +550,7 @@ int find_and_store_meta_key(uint8_t key_id)
|
||||
uint8_t *meta = (uint8_t *) calloc(1, meta_size), *m = meta;
|
||||
for (int t = 0; t < 4; t++) {
|
||||
if (lt[t] > 0 && pt[t] != NULL) {
|
||||
*m++ = 0x90+t;
|
||||
*m++ = 0x90 + t;
|
||||
m += format_tlv_len(lt[t], m);
|
||||
memcpy(m, pt[t], lt[t]);
|
||||
m += lt[t];
|
||||
@ -572,24 +565,23 @@ int find_and_store_meta_key(uint8_t key_id)
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey)
|
||||
{
|
||||
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
|
||||
if (wait_button_pressed() == true) { //timeout
|
||||
return CCID_VERIFICATION_FAILED;
|
||||
}
|
||||
|
||||
int key_size = file_get_size(fkey);
|
||||
uint8_t kdata[4096/8];
|
||||
uint8_t kdata[4096 / 8];
|
||||
memcpy(kdata, file_get_data(fkey), key_size);
|
||||
if (mkek_decrypt(kdata, key_size) != 0) {
|
||||
return CCID_EXEC_ERROR;
|
||||
}
|
||||
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size/2) != 0) {
|
||||
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) {
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
mbedtls_rsa_free(ctx);
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
if (mbedtls_mpi_read_binary(&ctx->Q, kdata+key_size/2, key_size/2) != 0) {
|
||||
if (mbedtls_mpi_read_binary(&ctx->Q, kdata + key_size / 2, key_size / 2) != 0) {
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
mbedtls_rsa_free(ctx);
|
||||
return CCID_WRONG_DATA;
|
||||
@ -617,8 +609,7 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey)
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey)
|
||||
{
|
||||
int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) {
|
||||
if (wait_button_pressed() == true) { //timeout
|
||||
return CCID_VERIFICATION_FAILED;
|
||||
}
|
||||
@ -630,7 +621,7 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey)
|
||||
return CCID_EXEC_ERROR;
|
||||
}
|
||||
mbedtls_ecp_group_id gid = kdata[0];
|
||||
int r = mbedtls_ecp_read_key(gid, ctx, kdata+1, key_size-1);
|
||||
int r = mbedtls_ecp_read_key(gid, ctx, kdata + 1, key_size - 1);
|
||||
if (r != 0) {
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
mbedtls_ecdsa_free(ctx);
|
||||
@ -699,8 +690,7 @@ static const cmd_t cmds[] = {
|
||||
{ 0x00, 0x0 }
|
||||
};
|
||||
|
||||
int sc_hsm_process_apdu()
|
||||
{
|
||||
int sc_hsm_process_apdu() {
|
||||
int r = sm_unwrap();
|
||||
if (r != CCID_OK) {
|
||||
return SW_DATA_INVALID();
|
||||
|
Loading…
Reference in New Issue
Block a user