Upgrade to version 3.2
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
117
CMakeLists.txt
117
CMakeLists.txt
@@ -18,26 +18,30 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
if(ESP_PLATFORM)
|
||||
set(EXTRA_COMPONENT_DIRS src pico-keys-sdk/src)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(EXTRA_COMPONENT_DIRS src pico-keys-sdk/src)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
else()
|
||||
if(NOT ENABLE_EMULATION)
|
||||
include(pico_sdk_import.cmake)
|
||||
endif()
|
||||
|
||||
if(ENABLE_EMULATION)
|
||||
else()
|
||||
include(pico_sdk_import.cmake)
|
||||
endif()
|
||||
project(pico_openpgp C CXX ASM)
|
||||
|
||||
project(pico_openpgp C CXX ASM)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
if(NOT ENABLE_EMULATION)
|
||||
pico_sdk_init()
|
||||
endif()
|
||||
|
||||
if(ENABLE_EMULATION)
|
||||
else()
|
||||
pico_sdk_init()
|
||||
endif()
|
||||
if(NOT DEFINED __FOR_CI)
|
||||
set(__FOR_CI 0)
|
||||
endif()
|
||||
if(__FOR_CI)
|
||||
add_definitions(-D__FOR_CI)
|
||||
endif()
|
||||
|
||||
add_executable(pico_openpgp)
|
||||
add_executable(pico_openpgp)
|
||||
endif()
|
||||
|
||||
set(SOURCES ${SOURCES}
|
||||
@@ -45,56 +49,75 @@ set(SOURCES ${SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/piv.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/management.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_select.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_get_data.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_verify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_put_data.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_select_data.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_import_data.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_version.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_change_pin.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_mse.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_internal_aut.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_challenge.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_activate_file.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_terminate_df.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_pso.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_keypair_gen.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_reset_retry.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/do.c
|
||||
)
|
||||
|
||||
set(USB_ITF_CCID 1)
|
||||
set(USB_ITF_WCID 1)
|
||||
include(pico-keys-sdk/pico_keys_sdk_import.cmake)
|
||||
|
||||
SET_VERSION(ver_major ver_minor "${CMAKE_CURRENT_LIST_DIR}/src/openpgp/version.h" 1)
|
||||
|
||||
if(ESP_PLATFORM)
|
||||
project(pico_openpgp)
|
||||
project(pico_openpgp)
|
||||
endif()
|
||||
|
||||
set(INCLUDES ${INCLUDES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp
|
||||
)
|
||||
if(NOT ESP_PLATFORM)
|
||||
target_sources(pico_openpgp PUBLIC ${SOURCES})
|
||||
target_include_directories(pico_openpgp PUBLIC ${INCLUDES})
|
||||
target_sources(pico_openpgp PUBLIC ${SOURCES})
|
||||
target_include_directories(pico_openpgp PUBLIC ${INCLUDES})
|
||||
|
||||
target_compile_options(pico_openpgp PUBLIC
|
||||
-Wall
|
||||
)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(pico_openpgp PUBLIC
|
||||
-Wall
|
||||
-Werror
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_EMULATION)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(pico_openpgp PUBLIC
|
||||
-Werror
|
||||
)
|
||||
target_compile_options(pico_openpgp PUBLIC
|
||||
-fdata-sections
|
||||
-ffunction-sections
|
||||
)
|
||||
endif()
|
||||
if(APPLE)
|
||||
target_link_options(pico_openpgp PUBLIC
|
||||
-Wl,-dead_strip
|
||||
)
|
||||
elseif(MSVC)
|
||||
target_compile_options(pico_openpgp PUBLIC
|
||||
-WX
|
||||
)
|
||||
|
||||
if(ENABLE_EMULATION)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(pico_openpgp PUBLIC
|
||||
-fdata-sections
|
||||
-ffunction-sections
|
||||
)
|
||||
endif()
|
||||
if(APPLE)
|
||||
target_link_options(pico_openpgp PUBLIC
|
||||
-Wl,-dead_strip
|
||||
)
|
||||
elseif(MSVC)
|
||||
target_compile_options(pico_openpgp PUBLIC
|
||||
-WX
|
||||
)
|
||||
|
||||
target_link_libraries(pico_openpgp PUBLIC wsock32 ws2_32 Bcrypt)
|
||||
else()
|
||||
target_link_options(pico_openpgp PUBLIC
|
||||
-Wl,--gc-sections
|
||||
)
|
||||
endif(APPLE)
|
||||
target_link_libraries(pico_openpgp PRIVATE pthread m)
|
||||
target_link_libraries(pico_openpgp PUBLIC wsock32 ws2_32 Bcrypt)
|
||||
else()
|
||||
pico_add_extra_outputs(${CMAKE_PROJECT_NAME})
|
||||
endif()
|
||||
target_link_options(pico_openpgp PUBLIC
|
||||
-Wl,--gc-sections
|
||||
)
|
||||
endif(APPLE)
|
||||
target_link_libraries(pico_openpgp PRIVATE pthread m)
|
||||
else()
|
||||
pico_add_extra_outputs(${CMAKE_PROJECT_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION_MAJOR="3"
|
||||
VERSION_MINOR="0-eddsa1"
|
||||
VERSION_MINOR="2-eddsa1"
|
||||
SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}"
|
||||
#if ! [[ -z "${GITHUB_SHA}" ]]; then
|
||||
# SUFFIX="${SUFFIX}.${GITHUB_SHA}"
|
||||
|
||||
Submodule pico-keys-sdk updated: c42a6e1a83...edc2b3a498
22
src/openpgp/cmd_activate_file.c
Normal file
22
src/openpgp/cmd_activate_file.c
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_activate_file() {
|
||||
return SW_OK();
|
||||
}
|
||||
29
src/openpgp/cmd_challenge.c
Normal file
29
src/openpgp/cmd_challenge.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
#include "random.h"
|
||||
|
||||
int cmd_challenge() {
|
||||
uint8_t *rb = (uint8_t *) random_bytes_get(apdu.ne);
|
||||
if (!rb) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
memcpy(res_APDU, rb, apdu.ne);
|
||||
res_APDU_size = apdu.ne;
|
||||
return SW_OK();
|
||||
}
|
||||
69
src/openpgp/cmd_change_pin.c
Normal file
69
src/openpgp/cmd_change_pin.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
#include "otp.h"
|
||||
|
||||
int cmd_change_pin() {
|
||||
if (P1(apdu) != 0x0) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
uint16_t fid = 0x1000 | P2(apdu);
|
||||
file_t *pw;
|
||||
if (!(pw = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
uint8_t pin_len = file_get_data(pw)[0];
|
||||
uint16_t r = 0;
|
||||
if ((r = load_dek()) != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
|
||||
if (otp_key_1) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
dek[IV_SIZE + i] ^= otp_key_1[i];
|
||||
}
|
||||
}
|
||||
r = check_pin(pw, apdu.data, pin_len);
|
||||
if (r != 0x9000) {
|
||||
return r;
|
||||
}
|
||||
uint8_t dhash[33];
|
||||
dhash[0] = apdu.nc - pin_len;
|
||||
double_hash_pin(apdu.data + pin_len, apdu.nc - pin_len, dhash + 1);
|
||||
file_put_data(pw, dhash, sizeof(dhash));
|
||||
|
||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||
if (!tf) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32] = {0};
|
||||
memcpy(def, file_get_data(tf), file_get_size(tf));
|
||||
if (P2(apdu) == 0x81) {
|
||||
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_pw1);
|
||||
memcpy(def + IV_SIZE, dek + IV_SIZE, 32);
|
||||
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
|
||||
}
|
||||
else if (P2(apdu) == 0x83) {
|
||||
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_pw3);
|
||||
memcpy(def + IV_SIZE + 32 + 32, dek + IV_SIZE, 32);
|
||||
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32 + 32, 32);
|
||||
}
|
||||
file_put_data(tf, def, sizeof(def));
|
||||
low_flash_available();
|
||||
return SW_OK();
|
||||
}
|
||||
91
src/openpgp/cmd_get_data.c
Normal file
91
src/openpgp/cmd_get_data.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
#include "asn1.h"
|
||||
|
||||
int cmd_get_data() {
|
||||
if (apdu.nc > 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
uint16_t fid = (P1(apdu) << 8) | P2(apdu);
|
||||
file_t *ef;
|
||||
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!authenticate_action(ef, ACL_OP_READ_SEARCH)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (currentEF && (currentEF->fid & 0x1FF0) == (fid & 0x1FF0)) { //previously selected
|
||||
ef = currentEF;
|
||||
}
|
||||
else {
|
||||
select_file(ef);
|
||||
}
|
||||
if (ef->data) {
|
||||
uint16_t fids[] = { 1, fid };
|
||||
uint16_t data_len = parse_do(fids, 1);
|
||||
uint8_t *p = NULL;
|
||||
uint16_t tg = 0;
|
||||
uint16_t tg_len = 0;
|
||||
asn1_ctx_t ctxi;
|
||||
asn1_ctx_init(res_APDU, data_len, &ctxi);
|
||||
if (walk_tlv(&ctxi, &p, &tg, &tg_len, NULL)) {
|
||||
uint8_t dec = 2;
|
||||
if ((tg & 0x1f) == 0x1f) {
|
||||
dec++;
|
||||
}
|
||||
if ((res_APDU[dec - 1] & 0xF0) == 0x80) {
|
||||
dec += (res_APDU[dec - 1] & 0x0F);
|
||||
}
|
||||
if (tg_len + dec == data_len) {
|
||||
memmove(res_APDU, res_APDU + dec, data_len - dec);
|
||||
data_len -= dec;
|
||||
res_APDU_size -= dec;
|
||||
}
|
||||
}
|
||||
//if (apdu.ne > data_len)
|
||||
// apdu.ne = data_len;
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_get_next_data() {
|
||||
file_t *ef = NULL;
|
||||
if (apdu.nc > 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
if (!currentEF) {
|
||||
return SW_RECORD_NOT_FOUND();
|
||||
}
|
||||
uint16_t fid = (P1(apdu) << 8) | P2(apdu);
|
||||
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if ((currentEF->fid & 0x1FF0) != (fid & 0x1FF0)) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
fid = currentEF->fid + 1; //curentEF contains private DO. so, we select the next one
|
||||
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
select_file(ef);
|
||||
return cmd_get_data();
|
||||
}
|
||||
213
src/openpgp/cmd_import_data.c
Normal file
213
src/openpgp/cmd_import_data.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "esp_compat.h"
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#else
|
||||
#include "common.h"
|
||||
#endif
|
||||
#include "openpgp.h"
|
||||
#include "random.h"
|
||||
#include "do.h"
|
||||
|
||||
uint16_t tag_len(uint8_t **data) {
|
||||
size_t len = *(*data)++;
|
||||
if (len == 0x82) {
|
||||
len = *(*data)++ << 8;
|
||||
len |= *(*data)++;
|
||||
}
|
||||
else if (len == 0x81) {
|
||||
len = *(*data)++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int cmd_import_data() {
|
||||
file_t *ef = NULL;
|
||||
uint16_t fid = 0x0;
|
||||
if (P1(apdu) != 0x3F || P2(apdu) != 0xFF) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
if (apdu.nc < 5) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
uint8_t *start = apdu.data;
|
||||
if (*start++ != 0x4D) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
uint16_t tgl = tag_len(&start);
|
||||
if (*start != 0xB6 && *start != 0xB8 && *start != 0xA4) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (*start == 0xB6) {
|
||||
fid = EF_PK_SIG;
|
||||
}
|
||||
else if (*start == 0xB8) {
|
||||
fid = EF_PK_DEC;
|
||||
}
|
||||
else if (*start == 0xA4) {
|
||||
fid = EF_PK_AUT;
|
||||
}
|
||||
else {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
start++;
|
||||
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
start += (*start + 1);
|
||||
if (*start++ != 0x7F || *start++ != 0x48) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
tgl = tag_len(&start);
|
||||
uint8_t *end = start + tgl, *p[9] = { 0 };
|
||||
uint16_t len[9] = { 0 };
|
||||
while (start < end) {
|
||||
uint8_t tag = *start++;
|
||||
if ((tag >= 0x91 && tag <= 0x97) || tag == 0x99) {
|
||||
len[tag - 0x91] = tag_len(&start);
|
||||
}
|
||||
else {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
}
|
||||
if (*start++ != 0x5F || *start++ != 0x48) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
tgl = tag_len(&start);
|
||||
end = start + tgl;
|
||||
for (int t = 0; start < end && t < 9; t++) {
|
||||
if (len[t] > 0) {
|
||||
p[t] = start;
|
||||
start += len[t];
|
||||
}
|
||||
}
|
||||
|
||||
file_t *algo_ef = search_by_fid(fid - 0x0010, NULL, SPECIFY_EF);
|
||||
if (!algo_ef) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
const uint8_t *algo = algorithm_attr_rsa2k + 1;
|
||||
uint16_t algo_len = algorithm_attr_rsa2k[0];
|
||||
if (algo_ef && algo_ef->data) {
|
||||
algo = file_get_data(algo_ef);
|
||||
algo_len = file_get_size(algo_ef);
|
||||
}
|
||||
int r = 0;
|
||||
if (algo[0] == ALGO_RSA) {
|
||||
mbedtls_rsa_context rsa;
|
||||
if (p[0] == NULL || len[0] == 0 || p[1] == NULL || len[1] == 0 || p[2] == NULL ||
|
||||
len[2] == 0) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
mbedtls_rsa_init(&rsa);
|
||||
r = mbedtls_mpi_read_binary(&rsa.E, p[0], len[0]);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = mbedtls_mpi_read_binary(&rsa.P, p[1], len[1]);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = mbedtls_mpi_read_binary(&rsa.Q, p[2], len[2]);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = mbedtls_rsa_import(&rsa, NULL, &rsa.P, &rsa.Q, NULL, &rsa.E);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = mbedtls_rsa_complete(&rsa);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = mbedtls_rsa_check_privkey(&rsa);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = store_keys(&rsa, ALGO_RSA, fid, true);
|
||||
make_rsa_response(&rsa);
|
||||
mbedtls_rsa_free(&rsa);
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
else if (algo[0] == ALGO_ECDSA || algo[0] == ALGO_ECDH || algo[0] == ALGO_EDDSA) {
|
||||
mbedtls_ecp_keypair ecdsa;
|
||||
if (p[1] == NULL || len[1] == 0) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
mbedtls_ecp_group_id gid = get_ec_group_id_from_attr(algo + 1, algo_len - 1);
|
||||
if (gid == MBEDTLS_ECP_DP_NONE) {
|
||||
return SW_FUNC_NOT_SUPPORTED();
|
||||
}
|
||||
mbedtls_ecp_keypair_init(&ecdsa);
|
||||
if (gid == MBEDTLS_ECP_DP_CURVE25519) {
|
||||
mbedtls_ecp_group_load(&ecdsa.grp, gid);
|
||||
r = mbedtls_mpi_read_binary(&ecdsa.d, p[1], len[1]);
|
||||
}
|
||||
else {
|
||||
r = mbedtls_ecp_read_key(gid, &ecdsa, p[1], len[1]);
|
||||
}
|
||||
if (r != 0) {
|
||||
mbedtls_ecp_keypair_free(&ecdsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
if (ecdsa.grp.id == MBEDTLS_ECP_DP_ED25519) {
|
||||
r = mbedtls_ecp_point_edwards(&ecdsa.grp, &ecdsa.Q, &ecdsa.d, random_gen, NULL);
|
||||
}
|
||||
else {
|
||||
r = mbedtls_ecp_mul(&ecdsa.grp, &ecdsa.Q, &ecdsa.d, &ecdsa.grp.G, random_gen, NULL);
|
||||
}
|
||||
if (r != 0) {
|
||||
mbedtls_ecp_keypair_free(&ecdsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = store_keys(&ecdsa, ALGO_ECDSA, fid, true);
|
||||
make_ecdsa_response(&ecdsa);
|
||||
mbedtls_ecp_keypair_free(&ecdsa);
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
else {
|
||||
return SW_FUNC_NOT_SUPPORTED();
|
||||
}
|
||||
if (fid == EF_PK_SIG) {
|
||||
reset_sig_count();
|
||||
}
|
||||
file_t *pbef = search_by_fid(fid + 3, NULL, SPECIFY_EF);
|
||||
if (!pbef) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
r = file_put_data(pbef, res_APDU, res_APDU_size);
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = 0; //make_*_response sets a response. we need to overwrite
|
||||
return SW_OK();
|
||||
}
|
||||
77
src/openpgp/cmd_internal_aut.c
Normal file
77
src/openpgp/cmd_internal_aut.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
#include "do.h"
|
||||
|
||||
int cmd_internal_aut() {
|
||||
if (P1(apdu) != 0x00 || P2(apdu) != 0x00) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
if (!has_pw3 && !has_pw2) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
file_t *algo_ef = search_by_fid(algo_aut, NULL, SPECIFY_EF);
|
||||
if (!algo_ef) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
const uint8_t *algo = algorithm_attr_rsa2k + 1;
|
||||
if (algo_ef && algo_ef->data) {
|
||||
algo = file_get_data(algo_ef);
|
||||
}
|
||||
file_t *ef = search_by_fid(pk_aut, NULL, SPECIFY_EF);
|
||||
if (!ef) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (wait_button_pressed(EF_UIF_AUT) == true) {
|
||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||
}
|
||||
int r = PICOKEY_OK;
|
||||
if (algo[0] == ALGO_RSA) {
|
||||
mbedtls_rsa_context ctx;
|
||||
mbedtls_rsa_init(&ctx);
|
||||
r = load_private_key_rsa(&ctx, ef, true);
|
||||
if (r != PICOKEY_OK) {
|
||||
mbedtls_rsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
size_t olen = 0;
|
||||
r = rsa_sign(&ctx, apdu.data, apdu.nc, res_APDU, &olen);
|
||||
mbedtls_rsa_free(&ctx);
|
||||
if (r != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = olen;
|
||||
}
|
||||
else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) {
|
||||
mbedtls_ecp_keypair ctx;
|
||||
mbedtls_ecp_keypair_init(&ctx);
|
||||
r = load_private_key_ecdsa(&ctx, ef, true);
|
||||
if (r != PICOKEY_OK) {
|
||||
mbedtls_ecp_keypair_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
size_t olen = 0;
|
||||
r = ecdsa_sign(&ctx, apdu.data, apdu.nc, res_APDU, &olen);
|
||||
mbedtls_ecp_keypair_free(&ctx);
|
||||
if (r != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = olen;
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
138
src/openpgp/cmd_keypair_gen.c
Normal file
138
src/openpgp/cmd_keypair_gen.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
#include "do.h"
|
||||
#include "random.h"
|
||||
|
||||
int cmd_keypair_gen() {
|
||||
if (P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
if (apdu.nc != 2 && apdu.nc != 5) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
if (!has_pw3 && P1(apdu) == 0x80) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
|
||||
uint16_t fid = 0x0;
|
||||
int r = PICOKEY_OK;
|
||||
if (apdu.data[0] == 0xB6) {
|
||||
fid = EF_PK_SIG;
|
||||
}
|
||||
else if (apdu.data[0] == 0xB8) {
|
||||
fid = EF_PK_DEC;
|
||||
}
|
||||
else if (apdu.data[0] == 0xA4) {
|
||||
fid = EF_PK_AUT;
|
||||
}
|
||||
else {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
|
||||
file_t *algo_ef = search_by_fid(fid - 0x0010, NULL, SPECIFY_EF);
|
||||
if (!algo_ef) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
const uint8_t *algo = algorithm_attr_rsa2k + 1;
|
||||
uint16_t algo_len = algorithm_attr_rsa2k[0];
|
||||
if (algo_ef && algo_ef->data) {
|
||||
algo = file_get_data(algo_ef);
|
||||
algo_len = file_get_size(algo_ef);
|
||||
}
|
||||
if (P1(apdu) == 0x80) { //generate
|
||||
if (algo[0] == ALGO_RSA) {
|
||||
int exponent = 65537, nlen = (algo[1] << 8) | algo[2];
|
||||
printf("KEYPAIR RSA %d\r\n", nlen);
|
||||
//if (nlen != 2048 && nlen != 4096)
|
||||
// return SW_FUNC_NOT_SUPPORTED();
|
||||
mbedtls_rsa_context rsa;
|
||||
mbedtls_rsa_init(&rsa);
|
||||
uint8_t index = 0;
|
||||
r = mbedtls_rsa_gen_key(&rsa, random_gen, &index, nlen, exponent);
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = store_keys(&rsa, ALGO_RSA, fid, true);
|
||||
make_rsa_response(&rsa);
|
||||
mbedtls_rsa_free(&rsa);
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) {
|
||||
printf("KEYPAIR ECDSA\r\n");
|
||||
mbedtls_ecp_group_id gid = get_ec_group_id_from_attr(algo + 1, algo_len - 1);
|
||||
if (gid == MBEDTLS_ECP_DP_NONE) {
|
||||
return SW_FUNC_NOT_SUPPORTED();
|
||||
}
|
||||
mbedtls_ecp_keypair ecdsa;
|
||||
mbedtls_ecp_keypair_init(&ecdsa);
|
||||
uint8_t index = 0;
|
||||
r = mbedtls_ecdsa_genkey(&ecdsa, gid, random_gen, &index);
|
||||
if (r != 0) {
|
||||
mbedtls_ecp_keypair_free(&ecdsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = store_keys(&ecdsa, algo[0], fid, true);
|
||||
make_ecdsa_response(&ecdsa);
|
||||
mbedtls_ecp_keypair_free(&ecdsa);
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
}
|
||||
else {
|
||||
return SW_FUNC_NOT_SUPPORTED();
|
||||
}
|
||||
file_t *pbef = search_by_fid(fid + 3, NULL, SPECIFY_EF);
|
||||
if (!pbef) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
r = file_put_data(pbef, res_APDU, res_APDU_size);
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
if (fid == EF_PK_SIG) {
|
||||
reset_sig_count();
|
||||
}
|
||||
else if (fid == EF_PK_DEC) {
|
||||
// OpenPGP does not allow generating AES keys. So, we generate a new one when gen for DEC is called.
|
||||
// It is a 256 AES key by default.
|
||||
uint8_t aes_key[32]; //maximum AES key size
|
||||
uint8_t key_size = 32;
|
||||
memcpy(aes_key, random_bytes_get(key_size), key_size);
|
||||
r = store_keys(aes_key, ALGO_AES_256, EF_AES_KEY, true);
|
||||
/* if storing the key fails, we silently continue */
|
||||
//if (r != PICOKEY_OK)
|
||||
// return SW_EXEC_ERROR();
|
||||
}
|
||||
low_flash_available();
|
||||
return SW_OK();
|
||||
}
|
||||
else if (P1(apdu) == 0x81) { //read
|
||||
file_t *ef = search_by_fid(fid + 3, NULL, SPECIFY_EF);
|
||||
if (!ef || !ef->data) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
res_APDU_size = file_get_size(ef);
|
||||
memcpy(res_APDU, file_get_data(ef), res_APDU_size);
|
||||
return SW_OK();
|
||||
}
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
49
src/openpgp/cmd_mse.c
Normal file
49
src/openpgp/cmd_mse.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_mse() {
|
||||
if (P1(apdu) != 0x41 || (P2(apdu) != 0xA4 && P2(apdu) != 0xB8)) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
if (apdu.data[0] != 0x83 || apdu.data[1] != 0x1 ||
|
||||
(apdu.data[2] != 0x2 && apdu.data[2] != 0x3)) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (P2(apdu) == 0xA4) {
|
||||
if (apdu.data[2] == 0x2) {
|
||||
algo_dec = EF_ALGO_PRIV2;
|
||||
pk_dec = EF_PK_DEC;
|
||||
}
|
||||
else if (apdu.data[2] == 0x3) {
|
||||
algo_dec = EF_ALGO_PRIV3;
|
||||
pk_dec = EF_PK_AUT;
|
||||
}
|
||||
}
|
||||
else if (P2(apdu) == 0xB8) {
|
||||
if (apdu.data[2] == 0x2) {
|
||||
algo_aut = EF_ALGO_PRIV2;
|
||||
pk_aut = EF_PK_DEC;
|
||||
}
|
||||
else if (apdu.data[2] == 0x3) {
|
||||
algo_aut = EF_ALGO_PRIV3;
|
||||
pk_aut = EF_PK_AUT;
|
||||
}
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
213
src/openpgp/cmd_pso.c
Normal file
213
src/openpgp/cmd_pso.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "esp_compat.h"
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#else
|
||||
#include "common.h"
|
||||
#endif
|
||||
#include "openpgp.h"
|
||||
#include "do.h"
|
||||
#include "random.h"
|
||||
#include "mbedtls/ecdh.h"
|
||||
#include "mbedtls/asn1.h"
|
||||
|
||||
int cmd_pso() {
|
||||
uint16_t algo_fid = 0x0, pk_fid = 0x0;
|
||||
bool is_aes = false;
|
||||
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
|
||||
if (!has_pw3 && !has_pw1) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
algo_fid = EF_ALGO_PRIV1;
|
||||
pk_fid = EF_PK_SIG;
|
||||
}
|
||||
else if (P1(apdu) == 0x80 && P2(apdu) == 0x86) {
|
||||
if (!has_pw3 && !has_pw2) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
algo_fid = algo_dec;
|
||||
pk_fid = pk_dec;
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
file_t *algo_ef = search_by_fid(algo_fid, NULL, SPECIFY_EF);
|
||||
if (!algo_ef) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
const uint8_t *algo = algorithm_attr_rsa2k + 1;
|
||||
if (algo_ef && algo_ef->data) {
|
||||
algo = file_get_data(algo_ef);
|
||||
}
|
||||
if (apdu.data[0] == 0x2) { //AES PSO?
|
||||
if (((apdu.nc - 1) % 16 == 0 && P1(apdu) == 0x80 && P2(apdu) == 0x86) ||
|
||||
(apdu.nc % 16 == 0 && P1(apdu) == 0x86 && P2(apdu) == 0x80)) {
|
||||
pk_fid = EF_AES_KEY;
|
||||
is_aes = true;
|
||||
}
|
||||
}
|
||||
file_t *ef = search_by_fid(pk_fid, NULL, SPECIFY_EF);
|
||||
if (!ef) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (wait_button_pressed(pk_fid == EF_PK_SIG ? EF_UIF_SIG : EF_UIF_DEC) == true) {
|
||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||
}
|
||||
int r = PICOKEY_OK;
|
||||
int key_size = file_get_size(ef);
|
||||
if (is_aes) {
|
||||
uint8_t aes_key[32];
|
||||
r = load_aes_key(aes_key, ef);
|
||||
if (r != PICOKEY_OK) {
|
||||
memset(aes_key, 0, sizeof(aes_key));
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
if (P1(apdu) == 0x80 && P2(apdu) == 0x86) { //decipher
|
||||
r = aes_decrypt(aes_key, NULL, key_size, PICO_KEYS_AES_MODE_CBC, apdu.data + 1, apdu.nc - 1);
|
||||
memset(aes_key, 0, sizeof(aes_key));
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
memcpy(res_APDU, apdu.data + 1, apdu.nc - 1);
|
||||
res_APDU_size = apdu.nc - 1;
|
||||
}
|
||||
else if (P1(apdu) == 0x86 && P2(apdu) == 0x80) { //encipher
|
||||
r = aes_encrypt(aes_key, NULL, key_size, PICO_KEYS_AES_MODE_CBC, apdu.data, apdu.nc);
|
||||
memset(aes_key, 0, sizeof(aes_key));
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU[0] = 0x2;
|
||||
memcpy(res_APDU + 1, apdu.data, apdu.nc);
|
||||
res_APDU_size = apdu.nc + 1;
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
if (algo[0] == ALGO_RSA) {
|
||||
mbedtls_rsa_context ctx;
|
||||
mbedtls_rsa_init(&ctx);
|
||||
r = load_private_key_rsa(&ctx, ef, true);
|
||||
if (r != PICOKEY_OK) {
|
||||
mbedtls_rsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
|
||||
size_t olen = 0;
|
||||
r = rsa_sign(&ctx, apdu.data, apdu.nc, res_APDU, &olen);
|
||||
mbedtls_rsa_free(&ctx);
|
||||
if (r != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = olen;
|
||||
//apdu.ne = key_size;
|
||||
inc_sig_count();
|
||||
}
|
||||
else if (P1(apdu) == 0x80 && P2(apdu) == 0x86) {
|
||||
if (apdu.nc < key_size) { //needs padding
|
||||
memset(apdu.data + apdu.nc, 0, key_size - apdu.nc);
|
||||
}
|
||||
size_t olen = 0;
|
||||
r = mbedtls_rsa_pkcs1_decrypt(&ctx,
|
||||
random_gen,
|
||||
NULL,
|
||||
&olen,
|
||||
apdu.data + 1,
|
||||
res_APDU,
|
||||
key_size);
|
||||
mbedtls_rsa_free(&ctx);
|
||||
if (r != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = olen;
|
||||
}
|
||||
}
|
||||
else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) {
|
||||
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
|
||||
mbedtls_ecp_keypair ctx;
|
||||
mbedtls_ecp_keypair_init(&ctx);
|
||||
r = load_private_key_ecdsa(&ctx, ef, true);
|
||||
if (r != PICOKEY_OK) {
|
||||
mbedtls_ecp_keypair_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
size_t olen = 0;
|
||||
r = ecdsa_sign(&ctx, apdu.data, apdu.nc, res_APDU, &olen);
|
||||
mbedtls_ecp_keypair_free(&ctx);
|
||||
if (r != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = olen;
|
||||
inc_sig_count();
|
||||
}
|
||||
else if (P1(apdu) == 0x80 && P2(apdu) == 0x86) {
|
||||
mbedtls_ecdh_context ctx;
|
||||
uint8_t kdata[67];
|
||||
uint8_t *data = apdu.data, *end = data + apdu.nc;
|
||||
size_t len = 0;
|
||||
if (mbedtls_asn1_get_tag(&data, end, &len, 0xA6) != 0) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (*data++ != 0x7f) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (mbedtls_asn1_get_tag(&data, end, &len,
|
||||
0x49) != 0 ||
|
||||
mbedtls_asn1_get_tag(&data, end, &len, 0x86) != 0) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
//if (len != 2*key_size-1)
|
||||
// return SW_WRONG_LENGTH();
|
||||
memcpy(kdata, file_get_data(ef), key_size);
|
||||
if (dek_decrypt(kdata, key_size) != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
mbedtls_ecdh_init(&ctx);
|
||||
mbedtls_ecp_group_id gid = kdata[0];
|
||||
r = mbedtls_ecdh_setup(&ctx, gid);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
r = mbedtls_ecp_read_key(gid, (mbedtls_ecdsa_context *)&ctx.ctx.mbed_ecdh, kdata + 1, key_size - 1);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
r = mbedtls_ecdh_read_public(&ctx, data - 1, len + 1);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
size_t olen = 0;
|
||||
r = mbedtls_ecdh_calc_secret(&ctx,
|
||||
&olen,
|
||||
res_APDU,
|
||||
MBEDTLS_ECP_MAX_BYTES,
|
||||
random_gen,
|
||||
NULL);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
res_APDU_size = olen;
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
}
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
74
src/openpgp/cmd_put_data.c
Normal file
74
src/openpgp/cmd_put_data.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_put_data() {
|
||||
uint16_t fid = (P1(apdu) << 8) | P2(apdu);
|
||||
file_t *ef;
|
||||
if (fid == EF_RESET_CODE) {
|
||||
fid = EF_RC;
|
||||
}
|
||||
else if (fid == EF_ALGO_SIG || fid == EF_ALGO_DEC || fid == EF_ALGO_AUT) {
|
||||
fid |= 0x1000;
|
||||
}
|
||||
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (fid == EF_PW_STATUS) {
|
||||
fid = EF_PW_PRIV;
|
||||
apdu.nc = 4; //we silently ommit the reset parameters
|
||||
}
|
||||
if (currentEF && (currentEF->fid & 0x1FF0) == (fid & 0x1FF0)) { //previously selected
|
||||
ef = currentEF;
|
||||
}
|
||||
if (apdu.nc > 0 && (ef->type & FILE_DATA_FLASH)) {
|
||||
int r = 0;
|
||||
if (fid == EF_RC) {
|
||||
has_rc = false;
|
||||
if ((r = load_dek()) != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
uint8_t dhash[33];
|
||||
dhash[0] = apdu.nc;
|
||||
double_hash_pin(apdu.data, apdu.nc, dhash + 1);
|
||||
r = file_put_data(ef, dhash, sizeof(dhash));
|
||||
|
||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||
if (!tf) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
|
||||
memcpy(def, file_get_data(tf), file_get_size(tf));
|
||||
hash_multi(apdu.data, apdu.nc, session_rc);
|
||||
memcpy(def + IV_SIZE + 32, dek + IV_SIZE, 32);
|
||||
aes_encrypt_cfb_256(session_rc, def, def + IV_SIZE + 32, 32);
|
||||
r = file_put_data(tf, def, sizeof(def));
|
||||
}
|
||||
else {
|
||||
r = file_put_data(ef, apdu.data, apdu.nc);
|
||||
}
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
low_flash_available();
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
80
src/openpgp/cmd_reset_retry.c
Normal file
80
src/openpgp/cmd_reset_retry.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_reset_retry() {
|
||||
if (P2(apdu) != 0x81) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (P1(apdu) == 0x0 || P1(apdu) == 0x2) {
|
||||
int newpin_len = 0;
|
||||
file_t *pw = NULL;
|
||||
has_pw1 = false;
|
||||
if (!(pw = search_by_fid(EF_PW1, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (P1(apdu) == 0x0) {
|
||||
file_t *rc;
|
||||
if (!(rc = search_by_fid(EF_RC, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
uint8_t pin_len = file_get_data(rc)[0];
|
||||
if (apdu.nc <= pin_len) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
uint16_t r = check_pin(rc, apdu.data, pin_len);
|
||||
if (r != 0x9000) {
|
||||
return r;
|
||||
}
|
||||
newpin_len = apdu.nc - pin_len;
|
||||
has_rc = true;
|
||||
hash_multi(apdu.data, pin_len, session_rc);
|
||||
}
|
||||
else if (P1(apdu) == 0x2) {
|
||||
if (!has_pw3) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
newpin_len = apdu.nc;
|
||||
}
|
||||
int r = 0;
|
||||
if ((r = load_dek()) != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||
if (!tf) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
|
||||
memcpy(def, file_get_data(tf), file_get_size(tf));
|
||||
hash_multi(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pw1);
|
||||
memcpy(def + IV_SIZE, dek + IV_SIZE, 32);
|
||||
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
|
||||
r = file_put_data(tf, def, sizeof(def));
|
||||
|
||||
uint8_t dhash[33];
|
||||
dhash[0] = newpin_len;
|
||||
double_hash_pin(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 1);
|
||||
file_put_data(pw, dhash, sizeof(dhash));
|
||||
if (pin_reset_retries(pw, true) != PICOKEY_OK) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
low_flash_available();
|
||||
return SW_OK();
|
||||
}
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
86
src/openpgp/cmd_select.c
Normal file
86
src/openpgp/cmd_select.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_select() {
|
||||
uint8_t p1 = P1(apdu);
|
||||
uint8_t p2 = P2(apdu);
|
||||
file_t *pe = NULL;
|
||||
uint16_t fid = 0x0;
|
||||
|
||||
if (apdu.nc >= 2) {
|
||||
fid = get_uint16_t_be(apdu.data);
|
||||
}
|
||||
|
||||
if (!pe) {
|
||||
if (p1 == 0x0) { //Select MF, DF or EF - File identifier or absent
|
||||
if (apdu.nc == 0) {
|
||||
pe = (file_t *) MF;
|
||||
//ac_fini();
|
||||
}
|
||||
else if (apdu.nc == 2) {
|
||||
if (!(pe = search_by_fid(fid, NULL, SPECIFY_ANY))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (p1 == 0x01) { //Select child DF - DF identifier
|
||||
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_DF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
}
|
||||
else if (p1 == 0x02) { //Select EF under the current DF - EF identifier
|
||||
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
}
|
||||
else if (p1 == 0x03) { //Select parent DF of the current DF - Absent
|
||||
if (apdu.nc != 0) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
}
|
||||
else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier
|
||||
if (!(pe = search_by_name(apdu.data, apdu.nc))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (card_terminated) {
|
||||
return set_res_sw(0x62, 0x85);
|
||||
}
|
||||
}
|
||||
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_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
}
|
||||
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_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) {
|
||||
if ((p2 & 0xfc) == 0x04) {
|
||||
process_fci(pe, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
select_file(pe);
|
||||
return SW_OK();
|
||||
}
|
||||
54
src/openpgp/cmd_select_data.c
Normal file
54
src/openpgp/cmd_select_data.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_select_data() {
|
||||
file_t *ef = NULL;
|
||||
uint16_t fid = 0x0;
|
||||
if (P2(apdu) != 0x4) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
if (apdu.data[0] != 0x60) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (apdu.nc != apdu.data[1] + 2 || apdu.nc < 5) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
if (apdu.data[2] != 0x5C) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (apdu.data[3] == 2) {
|
||||
fid = (apdu.data[4] << 8) | apdu.data[5];
|
||||
}
|
||||
else {
|
||||
fid = apdu.data[4];
|
||||
}
|
||||
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
fid &= ~0x6000; //Now get private DO
|
||||
fid += P1(apdu);
|
||||
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
select_file(ef);
|
||||
return SW_OK();
|
||||
}
|
||||
37
src/openpgp/cmd_terminate_df.c
Normal file
37
src/openpgp/cmd_terminate_df.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_terminate_df() {
|
||||
if (P1(apdu) != 0x0 || P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
file_t *retries;
|
||||
if (!(retries = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!has_pw3 && *(file_get_data(retries) + 6) > 0) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (apdu.nc != 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
initialize_flash(true);
|
||||
scan_files();
|
||||
return SW_OK();
|
||||
}
|
||||
67
src/openpgp/cmd_verify.c
Normal file
67
src/openpgp/cmd_verify.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_verify() {
|
||||
uint8_t p1 = P1(apdu);
|
||||
uint8_t p2 = P2(apdu);
|
||||
|
||||
if (p1 == 0xFF) {
|
||||
if (apdu.nc != 0) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (p2 == 0x81) {
|
||||
has_pw1 = false;
|
||||
}
|
||||
else if (p2 == 0x82) {
|
||||
has_pw2 = false;
|
||||
}
|
||||
else if (p2 == 0x83) {
|
||||
has_pw3 = false;
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
else if (p1 != 0x0 || (p2 & 0x60) != 0x0) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
uint16_t fid = 0x1000 | p2;
|
||||
if (fid == EF_RC && apdu.nc > 0) {
|
||||
fid = EF_PW1;
|
||||
}
|
||||
file_t *pw, *pw_status;
|
||||
if (!(pw = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!(pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (file_get_data(pw)[0] == 0) { //not initialized
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (apdu.nc > 0) {
|
||||
return check_pin(pw, apdu.data, apdu.nc);
|
||||
}
|
||||
uint8_t retries = *(file_get_data(pw_status) + 3 + (fid & 0xf));
|
||||
if (retries == 0) {
|
||||
return SW_PIN_BLOCKED();
|
||||
}
|
||||
if ((p2 == 0x81 && has_pw1) || (p2 == 0x82 && has_pw2) || (p2 == 0x83 && has_pw3)) {
|
||||
return SW_OK();
|
||||
}
|
||||
return set_res_sw(0x63, 0xc0 | retries);
|
||||
}
|
||||
26
src/openpgp/cmd_version.c
Normal file
26
src/openpgp/cmd_version.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
#include "version.h"
|
||||
|
||||
int cmd_version() {
|
||||
res_APDU[res_APDU_size++] = PIPGP_VERSION_MAJOR;
|
||||
res_APDU[res_APDU_size++] = PIPGP_VERSION_MINOR;
|
||||
res_APDU[res_APDU_size++] = 0x0;
|
||||
return SW_OK();
|
||||
}
|
||||
394
src/openpgp/do.c
Normal file
394
src/openpgp/do.c
Normal file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
#include "asn1.h"
|
||||
|
||||
int parse_do(uint16_t *fids, int mode) {
|
||||
int len = 0;
|
||||
file_t *ef;
|
||||
for (int i = 0; i < fids[0]; i++) {
|
||||
if ((ef = search_by_fid(fids[i + 1], NULL, SPECIFY_EF))) {
|
||||
uint16_t data_len;
|
||||
if ((ef->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) {
|
||||
data_len = ((int (*)(const file_t *, int))(ef->data))((const file_t *) ef, mode);
|
||||
}
|
||||
else {
|
||||
if (ef->data) {
|
||||
data_len = file_get_size(ef);
|
||||
}
|
||||
else {
|
||||
data_len = 0;
|
||||
}
|
||||
if (mode == 1) {
|
||||
if (fids[0] > 1 && res_APDU_size > 0) {
|
||||
if (fids[i + 1] < 0x0100) {
|
||||
res_APDU[res_APDU_size++] = fids[i + 1] & 0xff;
|
||||
}
|
||||
else {
|
||||
res_APDU[res_APDU_size++] = fids[i + 1] >> 8;
|
||||
res_APDU[res_APDU_size++] = fids[i + 1] & 0xff;
|
||||
}
|
||||
res_APDU_size += format_tlv_len(data_len, res_APDU + res_APDU_size);
|
||||
}
|
||||
if (ef->data) {
|
||||
memcpy(res_APDU + res_APDU_size, file_get_data(ef), data_len);
|
||||
}
|
||||
res_APDU_size += data_len;
|
||||
}
|
||||
}
|
||||
len += data_len;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int parse_trium(uint16_t fid, uint8_t num, size_t size) {
|
||||
for (uint8_t i = 0; i < num; i++) {
|
||||
file_t *ef;
|
||||
if ((ef = search_by_fid(fid + i, NULL, SPECIFY_EF)) && ef->data) {
|
||||
uint16_t data_len = file_get_size(ef);
|
||||
memcpy(res_APDU + res_APDU_size, file_get_data(ef), data_len);
|
||||
res_APDU_size += data_len;
|
||||
}
|
||||
else {
|
||||
memset(res_APDU + res_APDU_size, 0, size);
|
||||
res_APDU_size += size;
|
||||
}
|
||||
}
|
||||
return num * size;
|
||||
}
|
||||
|
||||
int parse_ch_data(const file_t *f, int mode) {
|
||||
uint16_t fids[] = {
|
||||
3,
|
||||
EF_CH_NAME, EF_LANG_PREF, EF_SEX,
|
||||
};
|
||||
res_APDU[res_APDU_size++] = EF_CH_DATA & 0xff;
|
||||
res_APDU[res_APDU_size++] = 0x82;
|
||||
uint8_t *lp = res_APDU + res_APDU_size;
|
||||
res_APDU_size += 2;
|
||||
parse_do(fids, mode);
|
||||
uint16_t lpdif = res_APDU + res_APDU_size - lp - 2;
|
||||
*lp++ = lpdif >> 8;
|
||||
*lp++ = lpdif & 0xff;
|
||||
return lpdif + 4;
|
||||
}
|
||||
|
||||
int parse_sec_tpl(const file_t *f, int mode) {
|
||||
res_APDU[res_APDU_size++] = EF_SEC_TPL & 0xff;
|
||||
res_APDU[res_APDU_size++] = 5;
|
||||
file_t *ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY);
|
||||
if (ef && ef->data) {
|
||||
res_APDU[res_APDU_size++] = EF_SIG_COUNT & 0xff;
|
||||
res_APDU[res_APDU_size++] = 3;
|
||||
memcpy(res_APDU + res_APDU_size, file_get_data(ef), 3);
|
||||
res_APDU_size += 3;
|
||||
}
|
||||
return 5 + 2;
|
||||
}
|
||||
|
||||
int parse_ch_cert(const file_t *f, int mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_fp(const file_t *f, int mode) {
|
||||
res_APDU[res_APDU_size++] = EF_FP & 0xff;
|
||||
res_APDU[res_APDU_size++] = 60;
|
||||
return parse_trium(EF_FP_SIG, 3, 20) + 2;
|
||||
}
|
||||
|
||||
int parse_cafp(const file_t *f, int mode) {
|
||||
res_APDU[res_APDU_size++] = EF_CA_FP & 0xff;
|
||||
res_APDU[res_APDU_size++] = 60;
|
||||
return parse_trium(EF_FP_CA1, 3, 20) + 2;
|
||||
}
|
||||
|
||||
int parse_ts(const file_t *f, int mode) {
|
||||
res_APDU[res_APDU_size++] = EF_TS_ALL & 0xff;
|
||||
res_APDU[res_APDU_size++] = 12;
|
||||
return parse_trium(EF_TS_SIG, 3, 4) + 2;
|
||||
}
|
||||
|
||||
int parse_keyinfo(const file_t *f, int mode) {
|
||||
int init_len = res_APDU_size;
|
||||
if (res_APDU_size > 0) {
|
||||
res_APDU[res_APDU_size++] = EF_KEY_INFO & 0xff;
|
||||
res_APDU[res_APDU_size++] = 6;
|
||||
}
|
||||
file_t *ef = search_by_fid(EF_PK_SIG, NULL, SPECIFY_ANY);
|
||||
res_APDU[res_APDU_size++] = 0x00;
|
||||
if (ef && ef->data) {
|
||||
res_APDU[res_APDU_size++] = 0x01;
|
||||
}
|
||||
else {
|
||||
res_APDU[res_APDU_size++] = 0x00;
|
||||
}
|
||||
|
||||
ef = search_by_fid(EF_PK_DEC, NULL, SPECIFY_ANY);
|
||||
res_APDU[res_APDU_size++] = 0x01;
|
||||
if (ef && ef->data) {
|
||||
res_APDU[res_APDU_size++] = 0x01;
|
||||
}
|
||||
else {
|
||||
res_APDU[res_APDU_size++] = 0x00;
|
||||
}
|
||||
|
||||
ef = search_by_fid(EF_PK_AUT, NULL, SPECIFY_ANY);
|
||||
res_APDU[res_APDU_size++] = 0x02;
|
||||
if (ef && ef->data) {
|
||||
res_APDU[res_APDU_size++] = 0x01;
|
||||
}
|
||||
else {
|
||||
res_APDU[res_APDU_size++] = 0x00;
|
||||
}
|
||||
return res_APDU_size - init_len;
|
||||
}
|
||||
|
||||
int parse_pw_status(const file_t *f, int mode) {
|
||||
file_t *ef;
|
||||
int init_len = res_APDU_size;
|
||||
if (res_APDU_size > 0) {
|
||||
res_APDU[res_APDU_size++] = EF_PW_STATUS & 0xff;
|
||||
res_APDU[res_APDU_size++] = 7;
|
||||
}
|
||||
ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY);
|
||||
if (ef && ef->data) {
|
||||
memcpy(res_APDU + res_APDU_size, file_get_data(ef), 7);
|
||||
res_APDU_size += 7;
|
||||
}
|
||||
return res_APDU_size - init_len;
|
||||
}
|
||||
|
||||
#define ALGO_RSA_1K 0
|
||||
#define ALGO_RSA_2k 1
|
||||
#define ALGO_RSA_3K 2
|
||||
#define ALGO_RSA_4K 3
|
||||
#define ALGO_X448 4
|
||||
#define ALGO_P256K1 5
|
||||
#define ALGO_P256R1 6
|
||||
#define ALGO_P384R1 7
|
||||
#define ALGO_P521R1 8
|
||||
#define ALGO_BP256R1 9
|
||||
#define ALGO_BP384R1 10
|
||||
#define ALGO_BP512R1 11
|
||||
#define ALGO_CV22519 12
|
||||
|
||||
const uint8_t algorithm_attr_x448[] = {
|
||||
4,
|
||||
ALGO_ECDH,
|
||||
/* OID of X448 */
|
||||
0x2b, 0x65, 0x6f
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_rsa1k[] = {
|
||||
6,
|
||||
ALGO_RSA,
|
||||
0x04, 0x00, /* Length modulus (in bit): 1024 */
|
||||
0x00, 0x20, /* Length exponent (in bit): 32 */
|
||||
0x00 /* 0: Acceptable format is: P and Q */
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_rsa2k[] = {
|
||||
6,
|
||||
ALGO_RSA,
|
||||
0x08, 0x00, /* Length modulus (in bit): 2048 */
|
||||
0x00, 0x20, /* Length exponent (in bit): 32 */
|
||||
0x00 /* 0: Acceptable format is: P and Q */
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_rsa3k[] = {
|
||||
6,
|
||||
ALGO_RSA,
|
||||
0x0C, 0x00, /* Length modulus (in bit): 3072 */
|
||||
0x00, 0x20, /* Length exponent (in bit): 32 */
|
||||
0x00 /* 0: Acceptable format is: P and Q */
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_rsa4k[] = {
|
||||
6,
|
||||
ALGO_RSA,
|
||||
0x10, 0x00, /* Length modulus (in bit): 4096 */
|
||||
0x00, 0x20, /* Length exponent (in bit): 32 */
|
||||
0x00 /* 0: Acceptable format is: P and Q */
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_p256k1[] = {
|
||||
6,
|
||||
ALGO_ECDSA,
|
||||
0x2b, 0x81, 0x04, 0x00, 0x0a
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_p256r1[] = {
|
||||
9,
|
||||
ALGO_ECDSA,
|
||||
0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_p384r1[] = {
|
||||
6,
|
||||
ALGO_ECDSA,
|
||||
0x2B, 0x81, 0x04, 0x00, 0x22
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_p521r1[] = {
|
||||
6,
|
||||
ALGO_ECDSA,
|
||||
0x2B, 0x81, 0x04, 0x00, 0x23
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_bp256r1[] = {
|
||||
10,
|
||||
ALGO_ECDSA,
|
||||
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_bp384r1[] = {
|
||||
10,
|
||||
ALGO_ECDSA,
|
||||
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_bp512r1[] = {
|
||||
10,
|
||||
ALGO_ECDSA,
|
||||
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_cv25519[] = {
|
||||
11,
|
||||
ALGO_ECDH,
|
||||
0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_ed25519[] = {
|
||||
10,
|
||||
ALGO_EDDSA,
|
||||
0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01
|
||||
};
|
||||
|
||||
int parse_algo(const uint8_t *algo, uint16_t tag) {
|
||||
res_APDU[res_APDU_size++] = tag & 0xff;
|
||||
memcpy(res_APDU + res_APDU_size, algo, algo[0] + 1);
|
||||
res_APDU_size += algo[0] + 1;
|
||||
return algo[0] + 2;
|
||||
}
|
||||
|
||||
int parse_algoinfo(const file_t *f, int mode) {
|
||||
int datalen = 0;
|
||||
if (f->fid == EF_ALGO_INFO) {
|
||||
res_APDU[res_APDU_size++] = EF_ALGO_INFO & 0xff;
|
||||
res_APDU[res_APDU_size++] = 0x82;
|
||||
uint8_t *lp = res_APDU + res_APDU_size;
|
||||
res_APDU_size += 2;
|
||||
datalen += parse_algo(algorithm_attr_rsa1k, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_rsa2k, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_rsa3k, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_rsa4k, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_p256k1, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_p256r1, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_p384r1, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_p521r1, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_bp256r1, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_bp384r1, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_bp512r1, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_ed25519, EF_ALGO_SIG);
|
||||
|
||||
datalen += parse_algo(algorithm_attr_rsa1k, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_rsa2k, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_rsa3k, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_rsa4k, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_p256k1, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_p256r1, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_p384r1, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_p521r1, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_bp256r1, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_bp384r1, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_bp512r1, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_cv25519, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_x448, EF_ALGO_DEC);
|
||||
|
||||
datalen += parse_algo(algorithm_attr_rsa1k, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_rsa2k, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_rsa3k, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_rsa4k, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_p256k1, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_p256r1, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_p384r1, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_p521r1, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_bp256r1, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_bp384r1, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_bp512r1, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_ed25519, EF_ALGO_AUT);
|
||||
uint16_t lpdif = res_APDU + res_APDU_size - lp - 2;
|
||||
*lp++ = lpdif >> 8;
|
||||
*lp++ = lpdif & 0xff;
|
||||
datalen = lpdif + 4;
|
||||
}
|
||||
else if (f->fid == EF_ALGO_SIG || f->fid == EF_ALGO_DEC || f->fid == EF_ALGO_AUT) {
|
||||
uint16_t fid = 0x1000 | f->fid;
|
||||
file_t *ef;
|
||||
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF)) || !ef->data) {
|
||||
datalen += parse_algo(algorithm_attr_rsa2k, f->fid);
|
||||
}
|
||||
else {
|
||||
uint16_t len = file_get_size(ef);
|
||||
if (res_APDU_size > 0) {
|
||||
res_APDU[res_APDU_size++] = f->fid & 0xff;
|
||||
res_APDU[res_APDU_size++] = len & 0xff;
|
||||
datalen += 2;
|
||||
}
|
||||
memcpy(res_APDU + res_APDU_size, file_get_data(ef), len);
|
||||
res_APDU_size += len;
|
||||
datalen += len;
|
||||
}
|
||||
}
|
||||
return datalen;
|
||||
}
|
||||
|
||||
int parse_app_data(const file_t *f, int mode) {
|
||||
uint16_t fids[] = {
|
||||
6,
|
||||
EF_FULL_AID, EF_HIST_BYTES, EF_EXLEN_INFO, EF_GFM, EF_DISCRETE_DO, EF_KEY_INFO
|
||||
};
|
||||
res_APDU[res_APDU_size++] = EF_APP_DATA & 0xff;
|
||||
res_APDU[res_APDU_size++] = 0x82;
|
||||
uint8_t *lp = res_APDU + res_APDU_size;
|
||||
res_APDU_size += 2;
|
||||
parse_do(fids, mode);
|
||||
uint16_t lpdif = res_APDU + res_APDU_size - lp - 2;
|
||||
*lp++ = lpdif >> 8;
|
||||
*lp++ = lpdif & 0xff;
|
||||
return lpdif + 4;
|
||||
}
|
||||
|
||||
int parse_discrete_do(const file_t *f, int mode) {
|
||||
uint16_t fids[] = {
|
||||
11,
|
||||
EF_EXT_CAP, EF_ALGO_SIG, EF_ALGO_DEC, EF_ALGO_AUT, EF_PW_STATUS, EF_FP, EF_CA_FP, EF_TS_ALL,
|
||||
EF_UIF_SIG, EF_UIF_DEC, EF_UIF_AUT
|
||||
};
|
||||
res_APDU[res_APDU_size++] = EF_DISCRETE_DO & 0xff;
|
||||
res_APDU[res_APDU_size++] = 0x82;
|
||||
uint8_t *lp = res_APDU + res_APDU_size;
|
||||
res_APDU_size += 2;
|
||||
parse_do(fids, mode);
|
||||
uint16_t lpdif = res_APDU + res_APDU_size - lp - 2;
|
||||
*lp++ = lpdif >> 8;
|
||||
*lp++ = lpdif & 0xff;
|
||||
return lpdif + 4;
|
||||
}
|
||||
29
src/openpgp/do.h
Normal file
29
src/openpgp/do.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
extern const uint8_t algorithm_attr_p256k1[];
|
||||
extern const uint8_t algorithm_attr_p256r1[];
|
||||
extern const uint8_t algorithm_attr_p384r1[];
|
||||
extern const uint8_t algorithm_attr_p521r1[];
|
||||
extern const uint8_t algorithm_attr_bp256r1[];
|
||||
extern const uint8_t algorithm_attr_bp384r1[];
|
||||
extern const uint8_t algorithm_attr_bp512r1[];
|
||||
extern const uint8_t algorithm_attr_cv25519[];
|
||||
extern const uint8_t algorithm_attr_x448[];
|
||||
extern const uint8_t algorithm_attr_rsa2k[];
|
||||
extern const uint8_t algorithm_attr_rsa4096[];
|
||||
extern const uint8_t algorithm_attr_ed25519[];
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido).
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido).
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,9 +27,17 @@
|
||||
#include "apdu.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/ecdsa.h"
|
||||
#include "crypto_utils.h"
|
||||
#include "files.h"
|
||||
|
||||
extern bool has_pw1;
|
||||
extern bool has_pw2;
|
||||
extern bool has_pw3;
|
||||
extern bool has_rc;
|
||||
extern uint8_t session_pw1[32];
|
||||
extern uint8_t session_rc[32];
|
||||
extern uint8_t session_pw3[32];
|
||||
extern uint8_t dek[IV_SIZE + 32];
|
||||
|
||||
extern int store_keys(void *key_ctx, int type, uint16_t key_id, bool use_kek);
|
||||
extern void make_rsa_response(mbedtls_rsa_context *rsa);
|
||||
@@ -57,4 +65,18 @@ extern int pin_reset_retries(const file_t *pin, bool force);
|
||||
#define ALGO_AES_192 0x72
|
||||
#define ALGO_AES_256 0x74
|
||||
|
||||
extern void select_file(file_t *pe);
|
||||
extern int parse_do(uint16_t *fids, int mode);
|
||||
extern int load_dek();
|
||||
extern int check_pin(const file_t *pin, const uint8_t *data, size_t len);
|
||||
extern mbedtls_ecp_group_id get_ec_group_id_from_attr(const uint8_t *algo, size_t algo_len);
|
||||
extern int reset_sig_count();
|
||||
extern uint16_t algo_dec, algo_aut, pk_dec, pk_aut;
|
||||
extern bool wait_button_pressed(uint16_t fid);
|
||||
extern void scan_files();
|
||||
extern int load_aes_key(uint8_t *aes_key, file_t *fkey);
|
||||
extern int inc_sig_count();
|
||||
extern int dek_encrypt(uint8_t *data, size_t len);
|
||||
extern int dek_decrypt(uint8_t *data, size_t len);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -165,7 +165,7 @@ static int x509_create_cert(void *pk_ctx, uint8_t algo, uint8_t slot, bool attes
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void scan_files() {
|
||||
static void scan_files_piv() {
|
||||
scan_flash();
|
||||
file_t *ef = search_by_fid(EF_PIV_KEY_CARDMGM, NULL, SPECIFY_EF);
|
||||
if ((ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY))) {
|
||||
@@ -264,7 +264,7 @@ static void scan_files() {
|
||||
}
|
||||
|
||||
void init_piv() {
|
||||
scan_files();
|
||||
scan_files_piv();
|
||||
has_pwpiv = false;
|
||||
// cmd_select();
|
||||
}
|
||||
@@ -945,7 +945,7 @@ static int cmd_asym_keygen() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_put_data() {
|
||||
static int cmd_put_data() {
|
||||
if (P1(apdu) != 0x3F || P2(apdu) != 0xFF) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
|
||||
@@ -23,15 +23,15 @@
|
||||
#define OPGP_VERSION_MAJOR ((OPGP_VERSION >> 8) & 0xff)
|
||||
#define OPGP_VERSION_MINOR (OPGP_VERSION & 0xff)
|
||||
|
||||
|
||||
#define PIPGP_VERSION 0x0300
|
||||
|
||||
#define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff)
|
||||
#define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff)
|
||||
|
||||
#define PIV_VERSION 0x0507
|
||||
|
||||
#define PIV_VERSION_MAJOR ((PIV_VERSION >> 8) & 0xff)
|
||||
#define PIV_VERSION_MINOR (PIV_VERSION & 0xff)
|
||||
|
||||
|
||||
#define PIPGP_VERSION 0x0302
|
||||
|
||||
#define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff)
|
||||
#define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff)
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user