diff --git a/src/hsm/eac.c b/src/hsm/eac.c index b7cdbb1..0d29525 100644 --- a/src/hsm/eac.c +++ b/src/hsm/eac.c @@ -116,6 +116,61 @@ int sm_unwrap() { return HSM_OK; } +int sm_wrap() { + uint8_t sm_indicator = (CLA(apdu) >> 2) & 0x3; + if (sm_indicator == 0) + return HSM_OK; + uint8_t wrap[1024], input[1024]; + size_t input_len = 0; + memset(input, 0, sizeof(input)); + mbedtls_mpi ssc; + mbedtls_mpi_init(&ssc); + mbedtls_mpi_add_int(&ssc, &sm_mSSC, 1); + mbedtls_mpi_copy(&sm_mSSC, &ssc); + int r = mbedtls_mpi_write_binary(&ssc, input, sm_blocksize); + input_len += sm_blocksize; + mbedtls_mpi_free(&ssc); + if (res_APDU_size > 0) { + res_APDU[res_APDU_size++] = 0x80; + memset(res_APDU+res_APDU_size, 0, (sm_blocksize - (res_APDU_size%sm_blocksize))); + res_APDU_size += (sm_blocksize - (res_APDU_size%sm_blocksize)); + sm_update_iv(); + aes_encrypt(sm_kenc, sm_iv, 128, HSM_AES_MODE_CBC, res_APDU, res_APDU_size); + memmove(res_APDU+1, res_APDU, res_APDU_size); + res_APDU[0] = 0x1; + res_APDU_size++; + if (res_APDU_size < 128) { + memmove(res_APDU+2, res_APDU, res_APDU_size); + res_APDU[1] = res_APDU_size; + } + else if (res_APDU_size < 256) { + memmove(res_APDU+3, res_APDU, res_APDU_size); + res_APDU[1] = 0x81; + res_APDU[2] = res_APDU_size; + } + else { + memmove(res_APDU+4, res_APDU, res_APDU_size); + res_APDU[1] = 0x82; + res_APDU[2] = res_APDU_size >> 8; + res_APDU[3] = res_APDU_size & 0xff; + } + res_APDU[0] = 0x87; + } + res_APDU[res_APDU_size++] = 0x99; + res_APDU[res_APDU_size++] = 2; + res_APDU[res_APDU_size++] = apdu.sw >> 8; + res_APDU[res_APDU_size++] = apdu.sw & 0xff; + memcpy(input+input_len, res_APDU, res_APDU_size); + input_len += res_APDU_size; + input[input_len++] = 0x80; + input_len += (sm_blocksize - (input_len%sm_blocksize)); + r = sm_sign(input, input_len, res_APDU+res_APDU_size+2); + res_APDU[res_APDU_size++] = 0x8E; + res_APDU[res_APDU_size++] = 8; + res_APDU_size += 8; + return HSM_OK; +} + int sm_get_le() { const uint8_t *p = apdu.cmd_apdu_data; while (p-apdu.cmd_apdu_data < apdu.cmd_apdu_data_len) { diff --git a/src/hsm/eac.h b/src/hsm/eac.h index e6c2662..207c5a5 100644 --- a/src/hsm/eac.h +++ b/src/hsm/eac.h @@ -38,5 +38,6 @@ void sm_update_iv(); int sm_get_le(); extern int sm_unwrap(); int sm_remove_padding(const uint8_t *data, size_t data_len); +extern int sm_wrap(); #endif diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index c290bb4..931f459 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -1965,8 +1965,11 @@ static const cmd_t cmds[] = { int sc_hsm_process_apdu() { int r = sm_unwrap(); for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) { - if (cmd->ins == INS(apdu)) - return cmd->cmd_handler(); + if (cmd->ins == INS(apdu)) { + int r = cmd->cmd_handler(); + sm_wrap(); + return r; + } } return SW_INS_NOT_SUPPORTED(); } \ No newline at end of file