mirror of
https://github.com/polhenarejos/pico-openpgp.git
synced 2026-05-30 18:11:22 +02:00
Compare commits
12 Commits
f34cdac00b
...
41ae81067c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41ae81067c | ||
|
|
9c878cc5b6 | ||
|
|
31ac28c7de | ||
|
|
33ce1c50aa | ||
|
|
edfcd087c1 | ||
|
|
a713eb4e03 | ||
|
|
f2fe6dd5c2 | ||
|
|
1a24a9ed1b | ||
|
|
b62573a6bd | ||
|
|
58a9d9cf97 | ||
|
|
bc9681e7b0 | ||
|
|
c39b87019e |
7
.github/workflows/nightly.yml
vendored
7
.github/workflows/nightly.yml
vendored
@@ -19,13 +19,20 @@ jobs:
|
||||
with:
|
||||
ref: ${{ matrix.refs }}
|
||||
submodules: 'recursive'
|
||||
- name: Restore private key
|
||||
run: |
|
||||
echo "${{ secrets.PRIVATE_KEY_B64 }}" | base64 -d > private.pem
|
||||
chmod 600 private.pem
|
||||
- name : Build
|
||||
env:
|
||||
PICO_SDK_PATH: ../pico-sdk
|
||||
SECURE_BOOT_PKEY: ../private.pem
|
||||
run: |
|
||||
./workflows/autobuild.sh pico
|
||||
./build_pico_openpgp.sh --no-eddsa
|
||||
./workflows/autobuild.sh esp32
|
||||
- name: Delete private key
|
||||
run: rm private.pem
|
||||
- name: Update nightly release
|
||||
uses: pyTooling/Actions/releaser@main
|
||||
with:
|
||||
|
||||
@@ -45,6 +45,13 @@ else()
|
||||
add_executable(pico_openpgp)
|
||||
endif()
|
||||
|
||||
set(USB_ITF_CCID 1)
|
||||
set(USB_ITF_WCID 1)
|
||||
include(pico-keys-sdk/pico_keys_sdk_import.cmake)
|
||||
|
||||
if(NOT ESP_PLATFORM)
|
||||
set(SOURCES ${PICO_KEYS_SOURCES})
|
||||
endif()
|
||||
set(SOURCES ${SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/openpgp.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.c
|
||||
@@ -70,10 +77,6 @@ set(SOURCES ${SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/defs.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)
|
||||
|
||||
@@ -3,6 +3,8 @@ This project aims at transforming your Raspberry Pico or ESP32 microcontroller i
|
||||
|
||||
OpenPGP cards are used to manage PGP keys and do cryptographic operations, such as keypair generation, signing and asymmetric deciphering. Pico OpenPGP follows the [**OpenPGP 3.4.1** specifications](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.pdf "**OpenPGP 3.4.1** specifications"), available at [GnuPG](http://gnupg.org "GnuPG").
|
||||
|
||||
If you are looking for a OpenPGP + Fido, see: https://github.com/polhenarejos/pico-fido2
|
||||
|
||||
## Features
|
||||
Pico OpenPGP has implemented the following features:
|
||||
|
||||
|
||||
@@ -23,12 +23,13 @@ fi
|
||||
cd build_release
|
||||
|
||||
PICO_SDK_PATH="${PICO_SDK_PATH:-../../pico-sdk}"
|
||||
SECURE_BOOT_PKEY="${SECURE_BOOT_PKEY:-../../ec_private_key.pem}"
|
||||
board_dir=${PICO_SDK_PATH}/src/boards/include/boards
|
||||
for board in "$board_dir"/*
|
||||
do
|
||||
board_name="$(basename -- "$board" .h)"
|
||||
rm -rf -- ./*
|
||||
PICO_SDK_PATH="${PICO_SDK_PATH}" cmake .. -DPICO_BOARD=$board_name -DSECURE_BOOT_PKEY=../../ec_private_key.pem
|
||||
PICO_SDK_PATH="${PICO_SDK_PATH}" cmake .. -DPICO_BOARD=$board_name -DSECURE_BOOT_PKEY=${SECURE_BOOT_PKEY}
|
||||
make -j`nproc`
|
||||
mv pico_openpgp.uf2 ../release/pico_openpgp_$board_name-$SUFFIX.uf2
|
||||
done
|
||||
@@ -40,7 +41,7 @@ if [[ $NO_EDDSA -eq 0 ]]; then
|
||||
do
|
||||
board_name="$(basename -- "$board" .h)"
|
||||
rm -rf -- ./*
|
||||
PICO_SDK_PATH="${PICO_SDK_PATH}" cmake .. -DPICO_BOARD=$board_name -DSECURE_BOOT_PKEY=../../ec_private_key.pem -DENABLE_EDDSA=1
|
||||
PICO_SDK_PATH="${PICO_SDK_PATH}" cmake .. -DPICO_BOARD=$board_name -DSECURE_BOOT_PKEY=${SECURE_BOOT_PKEY} -DENABLE_EDDSA=1
|
||||
make -j`nproc`
|
||||
mv pico_openpgp.uf2 ../release_eddsa/pico_openpgp_$board_name-$SUFFIX-eddsa1.uf2
|
||||
done
|
||||
|
||||
Submodule pico-keys-sdk updated: 580b0acffa...113e720fca
@@ -1,6 +1,6 @@
|
||||
idf_component_register(
|
||||
SRCS ${SOURCES}
|
||||
INCLUDE_DIRS . ../../pico-keys-sdk/src ../../pico-keys-sdk/src/fs ../../pico-keys-sdk/src/rng ../../pico-keys-sdk/src/usb ../../pico-keys-sdk/tinycbor/src
|
||||
REQUIRES bootloader_support esp_partition esp_tinyusb zorxx__neopixel mbedtls efuse
|
||||
REQUIRES mbedtls efuse
|
||||
)
|
||||
idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE ON)
|
||||
|
||||
@@ -127,7 +127,7 @@ int cmd_keypair_gen() {
|
||||
}
|
||||
else if (P1(apdu) == 0x81) { //read
|
||||
file_t *ef = search_by_fid(fid + 3, NULL, SPECIFY_EF);
|
||||
if (!ef || !ef->data) {
|
||||
if (!file_has_data(ef)) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
res_APDU_size = file_get_size(ef);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "openpgp.h"
|
||||
#include "otp.h"
|
||||
|
||||
int cmd_reset_retry() {
|
||||
if (P2(apdu) != 0x81) {
|
||||
@@ -44,6 +45,8 @@ int cmd_reset_retry() {
|
||||
newpin_len = apdu.nc - pin_len;
|
||||
has_rc = true;
|
||||
hash_multi(apdu.data, pin_len, session_rc);
|
||||
has_pw1 = has_pw3 = false;
|
||||
isUserAuthenticated = false;
|
||||
}
|
||||
else if (P1(apdu) == 0x2) {
|
||||
if (!has_pw3) {
|
||||
@@ -59,6 +62,11 @@ int cmd_reset_retry() {
|
||||
if (!tf) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (otp_key_1) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
dek[IV_SIZE + i] ^= otp_key_1[i];
|
||||
}
|
||||
}
|
||||
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);
|
||||
@@ -74,6 +82,9 @@ int cmd_reset_retry() {
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
low_flash_available();
|
||||
if ((r = load_dek()) != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
return SW_INCORRECT_P1P2();
|
||||
|
||||
@@ -28,12 +28,7 @@ int parse_do(uint16_t *fids, int mode) {
|
||||
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) {
|
||||
@@ -45,7 +40,7 @@ int parse_do(uint16_t *fids, int mode) {
|
||||
}
|
||||
res_APDU_size += format_tlv_len(data_len, res_APDU + res_APDU_size);
|
||||
}
|
||||
if (ef->data) {
|
||||
if (file_has_data(ef)) {
|
||||
memcpy(res_APDU + res_APDU_size, file_get_data(ef), data_len);
|
||||
}
|
||||
res_APDU_size += data_len;
|
||||
@@ -174,20 +169,6 @@ int parse_pw_status(const file_t *f, int mode) {
|
||||
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,
|
||||
@@ -275,12 +256,20 @@ const uint8_t algorithm_attr_cv25519[] = {
|
||||
0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01
|
||||
};
|
||||
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
const uint8_t algorithm_attr_ed25519[] = {
|
||||
10,
|
||||
ALGO_EDDSA,
|
||||
0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01
|
||||
};
|
||||
|
||||
const uint8_t algorithm_attr_ed448[] = {
|
||||
4,
|
||||
ALGO_EDDSA,
|
||||
0x2b, 0x65, 0x71
|
||||
};
|
||||
#endif
|
||||
|
||||
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);
|
||||
@@ -306,7 +295,10 @@ int parse_algoinfo(const file_t *f, int mode) {
|
||||
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);
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
datalen += parse_algo(algorithm_attr_ed25519, EF_ALGO_SIG);
|
||||
datalen += parse_algo(algorithm_attr_ed448, EF_ALGO_SIG);
|
||||
#endif
|
||||
|
||||
datalen += parse_algo(algorithm_attr_rsa1k, EF_ALGO_DEC);
|
||||
datalen += parse_algo(algorithm_attr_rsa2k, EF_ALGO_DEC);
|
||||
@@ -333,7 +325,10 @@ int parse_algoinfo(const file_t *f, int mode) {
|
||||
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);
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
datalen += parse_algo(algorithm_attr_ed25519, EF_ALGO_AUT);
|
||||
datalen += parse_algo(algorithm_attr_ed448, EF_ALGO_AUT);
|
||||
#endif
|
||||
uint16_t lpdif = res_APDU + res_APDU_size - lp - 2;
|
||||
*lp++ = lpdif >> 8;
|
||||
*lp++ = lpdif & 0xff;
|
||||
|
||||
@@ -26,4 +26,7 @@ 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[];
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
extern const uint8_t algorithm_attr_ed25519[];
|
||||
extern const uint8_t algorithm_attr_ed448[];
|
||||
#endif
|
||||
|
||||
@@ -574,7 +574,7 @@ int load_private_key_ecdsa(mbedtls_ecp_keypair *ctx, file_t *fkey, bool use_dek)
|
||||
}
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
if (ctx->grp.id == MBEDTLS_ECP_DP_ED25519) {
|
||||
if (ctx->grp.id == MBEDTLS_ECP_DP_ED25519 || ctx->grp.id == MBEDTLS_ECP_DP_ED448) {
|
||||
r = mbedtls_ecp_point_edwards(&ctx->grp, &ctx->Q, &ctx->d, random_gen, NULL);
|
||||
}
|
||||
else
|
||||
@@ -630,6 +630,9 @@ mbedtls_ecp_group_id get_ec_group_id_from_attr(const uint8_t *algo, size_t algo_
|
||||
else if (memcmp(algorithm_attr_ed25519 + 2, algo, algo_len) == 0) {
|
||||
return MBEDTLS_ECP_DP_ED25519;
|
||||
}
|
||||
else if (memcmp(algorithm_attr_ed448 + 2, algo, algo_len) == 0) {
|
||||
return MBEDTLS_ECP_DP_ED448;
|
||||
}
|
||||
#endif
|
||||
return MBEDTLS_ECP_DP_NONE;
|
||||
}
|
||||
@@ -750,8 +753,8 @@ int ecdsa_sign(mbedtls_ecp_keypair *ctx,
|
||||
|
||||
int r = 0;
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
if (ctx->grp.id == MBEDTLS_ECP_DP_ED25519) {
|
||||
r = mbedtls_eddsa_write_signature(ctx, data, data_len, out, 64, out_len, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL);
|
||||
if (ctx->grp.id == MBEDTLS_ECP_DP_ED25519 || ctx->grp.id == MBEDTLS_ECP_DP_ED448) {
|
||||
r = mbedtls_eddsa_write_signature(ctx, data, data_len, out, 114, out_len, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
@@ -218,7 +218,7 @@ static void scan_files_piv() {
|
||||
uint8_t *key = (uint8_t *)"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08";
|
||||
file_t *ef = search_by_fid(EF_PIV_KEY_CARDMGM, NULL, SPECIFY_ANY);
|
||||
file_put_data(ef, key, 24);
|
||||
uint8_t meta[] = { PIV_ALGO_AES192, PINPOLICY_ALWAYS, TOUCHPOLICY_ALWAYS, ORIGIN_GENERATED };
|
||||
uint8_t meta[] = { PIV_ALGO_AES192, PINPOLICY_ALWAYS, TOUCHPOLICY_ALWAYS };
|
||||
meta_add(EF_PIV_KEY_CARDMGM, meta, sizeof(meta));
|
||||
has_pwpiv = false;
|
||||
memset(session_pwpiv, 0, sizeof(session_pwpiv));
|
||||
@@ -458,6 +458,7 @@ static int cmd_get_metadata() {
|
||||
res_APDU[res_APDU_size++] = 2;
|
||||
res_APDU[res_APDU_size++] = meta[1];
|
||||
res_APDU[res_APDU_size++] = meta[2];
|
||||
if (key_ref != EF_PIV_KEY_CARDMGM) {
|
||||
res_APDU[res_APDU_size++] = 0x3;
|
||||
res_APDU[res_APDU_size++] = 1;
|
||||
res_APDU[res_APDU_size++] = meta[3];
|
||||
@@ -523,9 +524,10 @@ static int cmd_get_metadata() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key_ref == EF_PIV_PIN || key_ref == EF_PIV_PUK || key_ref == EF_PIV_KEY_CARDMGM) {
|
||||
uint8_t dhash[32];
|
||||
int32_t eq = false;
|
||||
int32_t eq = 0;
|
||||
if (key_ref == EF_PIV_PIN) {
|
||||
double_hash_pin((const uint8_t *)"\x31\x32\x33\x34\x35\x36\xFF\xFF", 8, dhash);
|
||||
eq = memcmp(dhash, file_get_data(ef_key) + 1, file_get_size(ef_key) - 1);
|
||||
@@ -539,7 +541,7 @@ static int cmd_get_metadata() {
|
||||
}
|
||||
res_APDU[res_APDU_size++] = 0x5;
|
||||
res_APDU[res_APDU_size++] = 1;
|
||||
res_APDU[res_APDU_size++] = eq;
|
||||
res_APDU[res_APDU_size++] = eq == 0;
|
||||
if (key_ref == EF_PIV_PIN || key_ref == EF_PIV_PUK) {
|
||||
file_t *pw_status;
|
||||
if (!(pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF))) {
|
||||
@@ -983,13 +985,14 @@ static int cmd_set_mgmkey() {
|
||||
}
|
||||
uint8_t touch = P2(apdu);
|
||||
if (touch != 0xFF && touch != 0xFE) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
if (touch == 0xFF) {
|
||||
touch = TOUCHPOLICY_NEVER;
|
||||
}
|
||||
else if (touch == 0xFE) {
|
||||
touch = TOUCHPOLICY_ALWAYS;
|
||||
}
|
||||
}
|
||||
uint8_t algo = apdu.data[0], key_ref = apdu.data[1], pinlen = apdu.data[2];
|
||||
if ((key_ref != EF_PIV_KEY_CARDMGM) || (!(algo == PIV_ALGO_AES128 && pinlen == 16) && !(algo == PIV_ALGO_AES192 && pinlen == 24) && !(algo == PIV_ALGO_AES256 && pinlen == 32) && !(algo == PIV_ALGO_3DES && pinlen == 24))) {
|
||||
return SW_WRONG_DATA();
|
||||
|
||||
Reference in New Issue
Block a user