From c4f06cceadf1fa0aae0370e2feb19bd22110208d Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 1 Jun 2022 08:58:58 +0200 Subject: [PATCH] Not used anymore. --- src/openpgp/ac.c | 302 ---- src/openpgp/affine.h | 8 - src/openpgp/bn.c | 427 ----- src/openpgp/bn.h | 23 - src/openpgp/call-ec.c | 136 -- src/openpgp/call-ec_p256k1.c | 34 - src/openpgp/call-rsa.c | 291 ---- src/openpgp/config.h | 17 - src/openpgp/debug.c | 136 -- src/openpgp/ec_p256k1.c | 233 --- src/openpgp/ec_p256k1.h | 4 - src/openpgp/ecc-ed25519.c | 955 ----------- src/openpgp/ecc-ed448.c | 824 --------- src/openpgp/ecc-mont.c | 226 --- src/openpgp/ecc-x448.c | 177 -- src/openpgp/ecc.c | 398 ----- src/openpgp/field-group-select.h | 7 - src/openpgp/flash_openpgp.c | 763 --------- src/openpgp/gnuk.h | 465 ------ src/openpgp/jpc-ac_p256k1.h | 14 - src/openpgp/jpc.c | 199 --- src/openpgp/jpc_p256k1.c | 36 - src/openpgp/mod.c | 352 ---- src/openpgp/mod.h | 3 - src/openpgp/mod25638.c | 287 ---- src/openpgp/mod25638.h | 7 - src/openpgp/modp256k1.c | 315 ---- src/openpgp/modp256k1.h | 9 - src/openpgp/muladd_256.h | 50 - src/openpgp/openpgp-do.c | 2656 ------------------------------ src/openpgp/openpgp.c | 1610 ------------------ src/openpgp/p448.c | 666 -------- src/openpgp/p448.h | 15 - src/openpgp/shake256.c | 202 --- src/openpgp/shake256.h | 13 - src/openpgp/status-code.h | 14 - 36 files changed, 11874 deletions(-) delete mode 100644 src/openpgp/ac.c delete mode 100644 src/openpgp/affine.h delete mode 100644 src/openpgp/bn.c delete mode 100644 src/openpgp/bn.h delete mode 100644 src/openpgp/call-ec.c delete mode 100644 src/openpgp/call-ec_p256k1.c delete mode 100644 src/openpgp/call-rsa.c delete mode 100644 src/openpgp/config.h delete mode 100644 src/openpgp/debug.c delete mode 100644 src/openpgp/ec_p256k1.c delete mode 100644 src/openpgp/ec_p256k1.h delete mode 100644 src/openpgp/ecc-ed25519.c delete mode 100644 src/openpgp/ecc-ed448.c delete mode 100644 src/openpgp/ecc-mont.c delete mode 100644 src/openpgp/ecc-x448.c delete mode 100644 src/openpgp/ecc.c delete mode 100644 src/openpgp/field-group-select.h delete mode 100644 src/openpgp/flash_openpgp.c delete mode 100644 src/openpgp/gnuk.h delete mode 100644 src/openpgp/jpc-ac_p256k1.h delete mode 100644 src/openpgp/jpc.c delete mode 100644 src/openpgp/jpc_p256k1.c delete mode 100644 src/openpgp/mod.c delete mode 100644 src/openpgp/mod.h delete mode 100644 src/openpgp/mod25638.c delete mode 100644 src/openpgp/mod25638.h delete mode 100644 src/openpgp/modp256k1.c delete mode 100644 src/openpgp/modp256k1.h delete mode 100644 src/openpgp/muladd_256.h delete mode 100644 src/openpgp/openpgp-do.c delete mode 100644 src/openpgp/openpgp.c delete mode 100644 src/openpgp/p448.c delete mode 100644 src/openpgp/p448.h delete mode 100644 src/openpgp/shake256.c delete mode 100644 src/openpgp/shake256.h delete mode 100644 src/openpgp/status-code.h diff --git a/src/openpgp/ac.c b/src/openpgp/ac.c deleted file mode 100644 index 69a32b1..0000000 --- a/src/openpgp/ac.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * ac.c -- Check access condition - * - * Copyright (C) 2010, 2012, 2013, 2017 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include - -#include "config.h" - -#include "gnuk.h" -#include "mbedtls/sha256.h" -#include "random.h" -#include "hsm2040.h" - -uint8_t volatile auth_status; /* Initialized to AC_NONE_AUTHORIZED */ - -int -ac_check_status (uint8_t ac_flag) -{ - if (ac_flag == AC_ALWAYS) - return 1; - else if (ac_flag == AC_NEVER) - return 0; - else - return (ac_flag & auth_status)? 1 : 0; -} - -void -ac_reset_pso_cds (void) -{ - gpg_do_clear_prvkey (GPG_KEY_FOR_SIGNING); - auth_status &= ~AC_PSO_CDS_AUTHORIZED; -} - -void -ac_reset_other (void) -{ - gpg_do_clear_prvkey (GPG_KEY_FOR_DECRYPTION); - gpg_do_clear_prvkey (GPG_KEY_FOR_AUTHENTICATION); - auth_status &= ~AC_OTHER_AUTHORIZED; -} - -int -verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known, - const uint8_t *ks_pw1, int save_ks) -{ - int pw_len; - int r; - uint8_t keystring[KEYSTRING_MD_SIZE]; - const uint8_t *salt; - int salt_len; - - if (gpg_pw_locked (PW_ERR_PW1)) - return 0; - - if (ks_pw1 == NULL) - { - const uint8_t *initial_pw; - - salt = NULL; - salt_len = 0; - gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw); - if ((pw_len_known >= 0 && pw_len_known != pw_len) - || buf_len < pw_len - || memcmp (pw, initial_pw, pw_len)) - goto failure; - } - else - { - pw_len = ks_pw1[0] & PW_LEN_MASK; - salt = KS_GET_SALT (ks_pw1); - salt_len = SALT_SIZE; - - if ((pw_len_known >= 0 && pw_len_known != pw_len) - || buf_len < pw_len) - goto failure; - } - - s2k (salt, salt_len, pw, pw_len, keystring); - if (save_ks) - memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE); - - if (access == AC_PSO_CDS_AUTHORIZED) - r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring); - else - { - int r1, r2; - - r1 = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER, keystring); - r2 = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER, keystring); - - if (r1 < 0 || r2 < 0) - r = -1; - else if (r1 == 0) - { - if (r2 == 0) - /* No encryption/authentication keys, then, check signing key. */ - r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring); - else - r = r2; - } - else if (r2 == 0) - r = r1; - else - r = 1; - } - - if (r < 0) - { - failure: - gpg_pw_increment_err_counter (PW_ERR_PW1); - return -1; - } - - gpg_pw_reset_err_counter (PW_ERR_PW1); - return pw_len; -} - -/* - * Verify for "Perform Security Operation : Compute Digital Signature" - */ -int -verify_pso_cds (const uint8_t *pw, int pw_len) -{ - const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - int r; - - DEBUG_INFO ("verify_pso_cds\r\n"); - DEBUG_BYTE (pw_len); - - r = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, pw_len, pw_len, ks_pw1, 0); - if (r > 0) - auth_status |= AC_PSO_CDS_AUTHORIZED; - return r; -} - -int -verify_other (const uint8_t *pw, int pw_len) -{ - const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - int r; - - DEBUG_INFO ("verify_other\r\n"); - DEBUG_BYTE (pw_len); - - r = verify_user_0 (AC_OTHER_AUTHORIZED, pw, pw_len, pw_len, ks_pw1, 0); - if (r > 0) - auth_status |= AC_OTHER_AUTHORIZED; - return r; -} - - -static int -verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known, - const uint8_t *ks, int save_ks) -{ - int pw_len; - int r; - uint8_t keystring[KEYSTRING_MD_SIZE]; - const uint8_t *salt; - int salt_len; - - pw_len = ks[0] & PW_LEN_MASK; - salt = KS_GET_SALT (ks); - salt_len = SALT_SIZE; - - if ((pw_len_known >= 0 && pw_len_known != pw_len) || buf_len < pw_len) - return -1; - - s2k (salt, salt_len, pw, pw_len, keystring); - if (save_ks) - memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE); - - r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_ADMIN, keystring); - - if (r < 0) - return -1; - else if (r == 0) - if ((ks[0] & PW_LEN_KEYSTRING_BIT) == 0 - || memcmp (KS_GET_KEYSTRING (ks), keystring, KEYSTRING_MD_SIZE) != 0) - return -1; - - return pw_len; -} - -uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE]; -uint8_t admin_authorized; - -int -verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known, - const uint8_t *pw3_keystring, int save_ks) -{ - int pw_len; - - if (pw3_keystring != NULL) - { - if (gpg_pw_locked (PW_ERR_PW3)) - return 0; - - pw_len = verify_admin_00 (pw, buf_len, pw_len_known, pw3_keystring, - save_ks); - if (pw_len < 0) - { - failure: - gpg_pw_increment_err_counter (PW_ERR_PW3); - return -1; - } - - admin_authorized = BY_ADMIN; - success: /* OK, the admin is now authenticated. */ - gpg_pw_reset_err_counter (PW_ERR_PW3); - return pw_len; - } - else - { - const uint8_t *initial_pw; - const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - - if (ks_pw1 != NULL) - { /* empty PW3, but PW1 exists */ - int r = verify_user_0 (AC_PSO_CDS_AUTHORIZED, - pw, buf_len, pw_len_known, ks_pw1, save_ks); - - if (r > 0) - admin_authorized = BY_USER; - - return r; - } - - if (gpg_pw_locked (PW_ERR_PW3)) - return 0; - - /* - * For the case of empty PW3 (with empty PW1), passphrase is - * OPENPGP_CARD_INITIAL_PW3, or defined by KDF DO. - */ - gpg_do_get_initial_pw_setting (1, &pw_len, &initial_pw); - if ((pw_len_known >=0 && pw_len_known != pw_len) - || buf_len < pw_len - || memcmp (pw, initial_pw, pw_len)) - goto failure; - - admin_authorized = BY_ADMIN; - if (save_ks) - s2k (NULL, 0, pw, pw_len, keystring_md_pw3); - goto success; - } -} - - -int -verify_admin (const uint8_t *pw, int pw_len) -{ - int r; - const uint8_t *pw3_keystring; - - pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); - r = verify_admin_0 (pw, pw_len, pw_len, pw3_keystring, 1); - if (r <= 0) - return r; - - auth_status |= AC_ADMIN_AUTHORIZED; - return 1; -} - -void -ac_reset_admin (void) -{ - memset (keystring_md_pw3, 0, KEYSTRING_MD_SIZE); - auth_status &= ~AC_ADMIN_AUTHORIZED; - admin_authorized = 0; -} - -void -ac_fini (void) -{ - memset (keystring_md_pw3, 0, KEYSTRING_MD_SIZE); - gpg_do_clear_prvkey (GPG_KEY_FOR_SIGNING); - gpg_do_clear_prvkey (GPG_KEY_FOR_DECRYPTION); - gpg_do_clear_prvkey (GPG_KEY_FOR_AUTHENTICATION); - auth_status = AC_NONE_AUTHORIZED; - admin_authorized = 0; -} diff --git a/src/openpgp/affine.h b/src/openpgp/affine.h deleted file mode 100644 index 2f6e875..0000000 --- a/src/openpgp/affine.h +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @brief Affine coordinates - */ -typedef struct -{ - bn256 x[1]; - bn256 y[1]; -} ac; diff --git a/src/openpgp/bn.c b/src/openpgp/bn.c deleted file mode 100644 index 24e0c48..0000000 --- a/src/openpgp/bn.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * bn.c -- 256-bit (and 512-bit) bignum calculation - * - * Copyright (C) 2011, 2013, 2014, 2019 - * Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include -#ifndef BN256_NO_RANDOM -#include "random.h" -#endif -#include "bn.h" - -uint32_t -bn256_add (bn256 *X, const bn256 *A, const bn256 *B) -{ - int i; - uint32_t v; - uint32_t carry = 0; - uint32_t *px; - const uint32_t *pa, *pb; - - px = X->word; - pa = A->word; - pb = B->word; - - for (i = 0; i < BN256_WORDS; i++) - { - v = *pb; - *px = *pa + carry; - carry = (*px < carry); - *px += v; - carry += (*px < v); - px++; - pa++; - pb++; - } - - return carry; -} - -uint32_t -bn256_sub (bn256 *X, const bn256 *A, const bn256 *B) -{ - int i; - uint32_t v; - uint32_t borrow = 0; - uint32_t *px; - const uint32_t *pa, *pb; - - px = X->word; - pa = A->word; - pb = B->word; - - for (i = 0; i < BN256_WORDS; i++) - { - uint32_t borrow0 = (*pa < borrow); - - v = *pb; - *px = *pa - borrow; - borrow = (*px < v) + borrow0; - *px -= v; - px++; - pa++; - pb++; - } - - return borrow; -} - -uint32_t -bn256_add_uint (bn256 *X, const bn256 *A, uint32_t w) -{ - int i; - uint32_t carry = w; - uint32_t *px; - const uint32_t *pa; - - px = X->word; - pa = A->word; - - for (i = 0; i < BN256_WORDS; i++) - { - *px = *pa + carry; - carry = (*px < carry); - px++; - pa++; - } - - return carry; -} - -uint32_t -bn256_sub_uint (bn256 *X, const bn256 *A, uint32_t w) -{ - int i; - uint32_t borrow = w; - uint32_t *px; - const uint32_t *pa; - - px = X->word; - pa = A->word; - - for (i = 0; i < BN256_WORDS; i++) - { - uint32_t borrow0 = (*pa < borrow); - - *px = *pa - borrow; - borrow = borrow0; - px++; - pa++; - } - - return borrow; -} - -#ifndef BN256_C_IMPLEMENTATION -#define ASM_IMPLEMENTATION 0 -#endif -void -bn256_mul (bn512 *X, const bn256 *A, const bn256 *B) -{ -#if ASM_IMPLEMENTATION -#include "muladd_256.h" - const uint32_t *s; - uint32_t *d; - uint32_t w; - uint32_t c; - - memset (X->word, 0, sizeof (uint32_t)*BN256_WORDS*2); - - s = A->word; d = &X->word[0]; w = B->word[0]; MULADD_256 (s, d, w, c); - s = A->word; d = &X->word[1]; w = B->word[1]; MULADD_256 (s, d, w, c); - s = A->word; d = &X->word[2]; w = B->word[2]; MULADD_256 (s, d, w, c); - s = A->word; d = &X->word[3]; w = B->word[3]; MULADD_256 (s, d, w, c); - s = A->word; d = &X->word[4]; w = B->word[4]; MULADD_256 (s, d, w, c); - s = A->word; d = &X->word[5]; w = B->word[5]; MULADD_256 (s, d, w, c); - s = A->word; d = &X->word[6]; w = B->word[6]; MULADD_256 (s, d, w, c); - s = A->word; d = &X->word[7]; w = B->word[7]; MULADD_256 (s, d, w, c); -#else - int i, j, k; - int i_beg, i_end; - uint32_t r0, r1, r2; - - r0 = r1 = r2 = 0; - for (k = 0; k <= (BN256_WORDS - 1)*2; k++) - { - if (k < BN256_WORDS) - { - i_beg = 0; - i_end = k; - } - else - { - i_beg = k - BN256_WORDS + 1; - i_end = BN256_WORDS - 1; - } - - for (i = i_beg; i <= i_end; i++) - { - uint64_t uv; - uint32_t u, v; - uint32_t carry; - - j = k - i; - - uv = ((uint64_t )A->word[i])*((uint64_t )B->word[j]); - v = uv; - u = (uv >> 32); - r0 += v; - carry = (r0 < v); - r1 += carry; - carry = (r1 < carry); - r1 += u; - carry += (r1 < u); - r2 += carry; - } - - X->word[k] = r0; - r0 = r1; - r1 = r2; - r2 = 0; - } - - X->word[k] = r0; -#endif -} - -void -bn256_sqr (bn512 *X, const bn256 *A) -{ -#if ASM_IMPLEMENTATION - int i; - - memset (X->word, 0, sizeof (bn512)); - for (i = 0; i < BN256_WORDS; i++) - { - uint32_t *wij = &X->word[i*2]; - const uint32_t *xj = &A->word[i]; - uint32_t x_i = *xj++; - uint32_t c; - - asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */ - "mov %[c], #0\n\t" - "ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */ - "mov r4, %[c]\n\t" - "umlal r5, r4, %[x_i], %[x_i]\n\t" - "str r5, [%[wij]], #4\n\t" - "cmp %[xj], %[x_max1]\n\t" - "bhi 0f\n\t" - "mov r9, %[c]\n\t" /* R9 := 0, the constant ZERO from here. */ - "beq 1f\n" - "2:\n\t" - "ldmia %[xj]!, { r7, r8 }\n\t" - "ldmia %[wij], { r5, r6 }\n\t" - /* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */ - "umull r7, r12, %[x_i], r7\n\t" - "adds r5, r5, r4\n\t" - "adc r4, %[c], r9\n\t" - "adds r5, r5, r7\n\t" - "adcs r4, r4, r12\n\t" - "adc %[c], r9, r9\n\t" - "adds r5, r5, r7\n\t" - "adcs r4, r4, r12\n\t" - "adc %[c], %[c], r9\n\t" - /* (C,R4,R6) := (C,R4) + w_i_j + 2*x_i*x_j; */ - "adds r6, r6, r4\n\t" - "adc r4, %[c], r9\n\t" - "umull r7, r12, %[x_i], r8\n\t" - "adds r6, r6, r7\n\t" - "adcs r4, r4, r12\n\t" - "adc %[c], r9, r9\n\t" - "adds r6, r6, r7\n\t" - "adcs r4, r4, r12\n\t" - "adc %[c], %[c], r9\n\t" - /**/ - "stmia %[wij]!, { r5, r6 }\n\t" - "cmp %[xj], %[x_max1]\n\t" - "bcc 2b\n\t" - "bne 0f\n" - "1:\n\t" - /* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */ - "ldr r5, [%[wij]]\n\t" - "ldr r6, [%[xj]], #4\n\t" - "adds r5, r5, r4\n\t" - "adc r4, %[c], r9\n\t" - "umull r7, r12, %[x_i], r6\n\t" - "adds r5, r5, r7\n\t" - "adcs r4, r4, r12\n\t" - "adc %[c], r9, r9\n\t" - "adds r5, r5, r7\n\t" - "adcs r4, r4, r12\n\t" - "adc %[c], %[c], r9\n\t" - "str r5, [%[wij]], #4\n" - "0:\n\t" - "ldr r5, [%[wij]]\n\t" - "adds r4, r4, r5\n\t" - "adc %[c], %[c], #0\n\t" - "str r4, [%[wij]], #4" - : [c] "=&r" (c), [wij] "=r" (wij), [xj] "=r" (xj) - : [x_i] "r" (x_i), [x_max1] "r" (&A->word[BN256_WORDS-1]), - "[wij]" (wij), "[xj]" (xj) - : "r4", "r5", "r6", "r7", "r8", "r9", "r12", "memory", "cc"); - - if (i < BN256_WORDS - 1) - *wij = c; - } -#else - int i, j, k; - int i_beg, i_end; - uint32_t r0, r1, r2; - - r0 = r1 = r2 = 0; - for (k = 0; k <= (BN256_WORDS - 1)*2; k++) - { - if (k < BN256_WORDS) - { - i_beg = 0; - i_end = k/2; - } - else - { - i_beg = k - BN256_WORDS + 1; - i_end = k/2; - } - - for (i = i_beg; i <= i_end; i++) - { - uint64_t uv; - uint32_t u, v; - uint32_t carry; - - j = k - i; - - uv = ((uint64_t )A->word[i])*((uint64_t )A->word[j]); - if (i < j) - { - r2 += ((uv >> 63) != 0); - uv <<= 1; - } - v = uv; - u = (uv >> 32); - r0 += v; - carry = (r0 < v); - r1 += carry; - carry = (r1 < carry); - r1 += u; - carry += (r1 < u); - r2 += carry; - } - - X->word[k] = r0; - r0 = r1; - r1 = r2; - r2 = 0; - } - - X->word[k] = r0; -#endif -} - -uint32_t -bn256_shift (bn256 *X, const bn256 *A, int shift) -{ - int i; - uint32_t carry = 0, next_carry; - - if (shift > 0) - { - for (i = 0; i < BN256_WORDS; i++) - { - next_carry = A->word[i] >> (32 - shift); - X->word[i] = (A->word[i] << shift) | carry; - carry = next_carry; - } - } - else - { - shift = -shift; - - for (i = BN256_WORDS - 1; i >= 0; i--) - { - next_carry = A->word[i] & ((1 << shift) - 1); - X->word[i] = (A->word[i] >> shift) | (carry << (32 - shift)); - carry = next_carry; - } - } - - return carry; -} - -int -bn256_is_zero (const bn256 *X) -{ - int i; - int r = 1; - - for (i = 0; i < BN256_WORDS; i++) - r &= (X->word[i] == 0); - - return r; -} - -int -bn256_is_even (const bn256 *X) -{ - return !(X->word[0] & 1); -} - -int -bn256_is_ge (const bn256 *A, const bn256 *B) -{ - uint32_t borrow; - bn256 tmp[1]; - - borrow = bn256_sub (tmp, A, B); - return borrow == 0; -} - - -int -bn256_cmp (const bn256 *A, const bn256 *B) -{ - uint32_t borrow; - int is_zero; - bn256 tmp[1]; - - borrow = bn256_sub (tmp, A, B); - is_zero = bn256_is_zero (tmp); - return is_zero ? 0 : (borrow ? -1 : 1); -} - - -#ifndef BN256_NO_RANDOM -void -bn256_random (bn256 *X) -{ - int i, j; - const uint8_t *rand; - - for (i = 0; i < 256/256; i++) - { - rand = random_bytes_get (32); - for (j = 0; j < BN256_WORDS; j++) - X->word[i*BN256_WORDS+j] = ((uint32_t *)rand)[j]; - random_bytes_free (rand); - } -} -#endif diff --git a/src/openpgp/bn.h b/src/openpgp/bn.h deleted file mode 100644 index d22eea0..0000000 --- a/src/openpgp/bn.h +++ /dev/null @@ -1,23 +0,0 @@ -#define BN256_WORDS 8 -typedef struct bn256 { - uint32_t word[ BN256_WORDS ]; /* Little endian */ -} bn256; - -#define BN512_WORDS 16 -typedef struct bn512 { - uint32_t word[ BN512_WORDS ]; /* Little endian */ -} bn512; - -uint32_t bn256_add (bn256 *X, const bn256 *A, const bn256 *B); -uint32_t bn256_sub (bn256 *X, const bn256 *A, const bn256 *B); -uint32_t bn256_add_uint (bn256 *X, const bn256 *A, uint32_t w); -uint32_t bn256_sub_uint (bn256 *X, const bn256 *A, uint32_t w); - -void bn256_mul (bn512 *X, const bn256 *A, const bn256 *B); -void bn256_sqr (bn512 *X, const bn256 *A); -uint32_t bn256_shift (bn256 *X, const bn256 *A, int shift); -int bn256_is_zero (const bn256 *X); -int bn256_is_even (const bn256 *X); -int bn256_is_ge (const bn256 *A, const bn256 *B); -int bn256_cmp (const bn256 *A, const bn256 *B); -void bn256_random (bn256 *X); diff --git a/src/openpgp/call-ec.c b/src/openpgp/call-ec.c deleted file mode 100644 index c739173..0000000 --- a/src/openpgp/call-ec.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * call-ec.c - interface between Gnuk and Elliptic curve over GF(prime) - * - * Copyright (C) 2013, 2014, 2017 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include "field-group-select.h" - -/* We are little-endian in the computation, but the protocol is big-endian. */ - -#define ECDSA_BYTE_SIZE 32 -#define ECDH_BYTE_SIZE 32 - -int -FUNC(ecdsa_sign) (const uint8_t *hash, uint8_t *output, - const uint8_t *key_data) -{ - int i; - bn256 r[1], s[1], z[1], d[1]; - uint8_t *p; - - p = (uint8_t *)d; - for (i = 0; i < ECDSA_BYTE_SIZE; i++) - p[ECDSA_BYTE_SIZE - i - 1] = key_data[i]; - - p = (uint8_t *)z; - for (i = 0; i < ECDSA_BYTE_SIZE; i++) - p[ECDSA_BYTE_SIZE - i - 1] = hash[i]; - - FUNC(ecdsa) (r, s, z, d); - p = (uint8_t *)r; - for (i = 0; i < ECDSA_BYTE_SIZE; i++) - *output++ = p[ECDSA_BYTE_SIZE - i - 1]; - p = (uint8_t *)s; - for (i = 0; i < ECDSA_BYTE_SIZE; i++) - *output++ = p[ECDSA_BYTE_SIZE - i - 1]; - return 0; -} - -int -FUNC(ecc_compute_public) (const uint8_t *key_data, uint8_t *pubkey) -{ - uint8_t *p, *p1; - ac q[1]; - bn256 k[1]; - int i; - - p = (uint8_t *)k; - for (i = 0; i < ECDSA_BYTE_SIZE; i++) - p[ECDSA_BYTE_SIZE - i - 1] = key_data[i]; - if (FUNC(compute_kG) (q, k) < 0) - return -1; - - p = pubkey; - p1 = (uint8_t *)q->x; - for (i = 0; i < ECDSA_BYTE_SIZE; i++) - *p++ = p1[ECDSA_BYTE_SIZE - i - 1]; - p1 = (uint8_t *)q->y; - for (i = 0; i < ECDSA_BYTE_SIZE; i++) - *p++ = p1[ECDSA_BYTE_SIZE - i - 1]; - - return 0; -} - -int -FUNC(ecdh_decrypt) (const uint8_t *input, uint8_t *output, - const uint8_t *key_data) -{ - bn256 k[1]; - ac X[1], P[1]; - int i; - uint8_t *p0; - const uint8_t *p1; - int r; - - p0 = (uint8_t *)k; - for (i = 0; i < ECDH_BYTE_SIZE; i++) - p0[ECDH_BYTE_SIZE - i - 1] = key_data[i]; - - p1 = input+1; /* skip '04' */ - p0 = (uint8_t *)P->x; - for (i = 0; i < ECDH_BYTE_SIZE; i++) - p0[ECDH_BYTE_SIZE - i - 1] = *p1++; - p0 = (uint8_t *)P->y; - for (i = 0; i < ECDH_BYTE_SIZE; i++) - p0[ECDH_BYTE_SIZE - i - 1] = *p1++; - - r = FUNC(compute_kP) (X, k, P); - if (r == 0) - { - p0 = output; - p1 = (const uint8_t *)X->x; - *p0++ = 4; - for (i = 0; i < ECDH_BYTE_SIZE; i++) - *p0++ = p1[ECDH_BYTE_SIZE - i - 1]; - p1 = (const uint8_t *)X->y; - for (i = 0; i < ECDH_BYTE_SIZE; i++) - *p0++ = p1[ECDH_BYTE_SIZE - i - 1]; - } - - return r; -} - - -/** - * @brief Check if a secret d0 is valid or not - * - * @param D0 scalar D0: secret - * @param D1 scalar D1: secret candidate N-D0 - * - * Return 0 on error. - * Return -1 when D1 should be used as the secret - * Return 1 when D0 should be used as the secret - */ -int -FUNC(ecc_check_secret) (const uint8_t *d0, uint8_t *d1) -{ - return FUNC(check_secret) ((const bn256 *)d0, (bn256 *)d1); -} diff --git a/src/openpgp/call-ec_p256k1.c b/src/openpgp/call-ec_p256k1.c deleted file mode 100644 index efc7cad..0000000 --- a/src/openpgp/call-ec_p256k1.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * call-ec_p256k1.c - interface between Gnuk and Elliptic curve over - * GF(p256k1) - * - * Copyright (C) 2014, 2017 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include -#include "bn.h" -#include "affine.h" -#include "jpc-ac_p256k1.h" -#include "ec_p256k1.h" - -#define FIELD p256k1 - -#include "call-ec.c" diff --git a/src/openpgp/call-rsa.c b/src/openpgp/call-rsa.c deleted file mode 100644 index c826410..0000000 --- a/src/openpgp/call-rsa.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol - * - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2017 - * Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include - -#include "common.h" - -//#include - -#include "config.h" - -#include "gnuk.h" -#include "status-code.h" -#include "random.h" -//#include "polarssl/config.h" -#include "mbedtls/rsa.h" -#include "hsm2040.h" - -static mbedtls_rsa_context rsa_ctx; -//static struct chx_cleanup clp; - -static void -rsa_cleanup (void *arg) -{ - (void)arg; - mbedtls_rsa_free (&rsa_ctx); -} - - -int -rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len, - struct key_data *kd, int pubkey_len) -{ - mbedtls_mpi P1, Q1, H; - int ret = 0; - unsigned char temp[pubkey_len]; - - mbedtls_rsa_init (&rsa_ctx); - - mbedtls_mpi_init (&P1); mbedtls_mpi_init (&Q1); mbedtls_mpi_init (&H); - - rsa_ctx.len = pubkey_len; - MBEDTLS_MPI_CHK( mbedtls_mpi_lset (&rsa_ctx.E, 0x10001) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary (&rsa_ctx.P, &kd->data[0], pubkey_len / 2) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary (&rsa_ctx.Q, &kd->data[pubkey_len / 2], - pubkey_len / 2) ); -#if 0 - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q) ); -#endif - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int (&P1, &rsa_ctx.P, 1) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int (&Q1, &rsa_ctx.Q, 1) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi (&H, &P1, &Q1) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P) ); - cleanup: - mbedtls_mpi_free (&P1); mbedtls_mpi_free (&Q1); mbedtls_mpi_free (&H); - if (ret == 0) - { - int cs; - - DEBUG_INFO ("RSA sign..."); - //clp.next = NULL; - //clp.routine = rsa_cleanup; - //clp.arg = NULL; - //chopstx_cleanup_push (&clp); - //cs = chopstx_setcancelstate (0); /* Allow cancellation. */ - ret = mbedtls_rsa_rsassa_pkcs1_v15_sign (&rsa_ctx, NULL, NULL, - MBEDTLS_MD_NONE, - msg_len, raw_message, temp); - memcpy (output, temp, pubkey_len); - rsa_cleanup(NULL); - //chopstx_setcancelstate (cs); - //chopstx_cleanup_pop (0); - } - - mbedtls_rsa_free (&rsa_ctx); - if (ret != 0) - { - DEBUG_INFO ("fail:"); - DEBUG_SHORT (ret); - return -1; - } - else - { - DEBUG_INFO ("done.\r\n"); - GPG_SUCCESS (); - return 0; - } -} - -/* - * LEN: length in byte - */ -int -modulus_calc (const uint8_t *p, int len, uint8_t *pubkey) -{ - mbedtls_mpi P, Q, N; - int ret; - - mbedtls_mpi_init (&P); mbedtls_mpi_init (&Q); mbedtls_mpi_init (&N); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary (&P, p, len / 2) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary (&Q, p + len / 2, len / 2) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi (&N, &P, &Q) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary (&N, pubkey, len) ); - cleanup: - mbedtls_mpi_free (&P); mbedtls_mpi_free (&Q); mbedtls_mpi_free (&N); - if (ret != 0) - return -1; - - return 0; -} - - -int -rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, - struct key_data *kd, unsigned int *output_len_p) -{ - mbedtls_mpi P1, Q1, H; - int ret; - - DEBUG_INFO ("RSA decrypt:"); - DEBUG_WORD ((uint32_t)&ret); - - mbedtls_rsa_init (&rsa_ctx); - mbedtls_mpi_init (&P1); mbedtls_mpi_init (&Q1); mbedtls_mpi_init (&H); - - rsa_ctx.len = msg_len; - DEBUG_WORD (msg_len); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset (&rsa_ctx.E, 0x10001) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary (&rsa_ctx.P, &kd->data[0], msg_len / 2) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary (&rsa_ctx.Q, &kd->data[msg_len / 2], msg_len / 2) ); -#if 0 - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q) ); -#endif - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int (&P1, &rsa_ctx.P, 1) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int (&Q1, &rsa_ctx.Q, 1) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi (&H, &P1, &Q1) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P) ); - cleanup: - mbedtls_mpi_free (&P1); mbedtls_mpi_free (&Q1); mbedtls_mpi_free (&H); - if (ret == 0) - { - int cs; - - DEBUG_INFO ("RSA decrypt ..."); - //clp.next = NULL; - //clp.routine = rsa_cleanup; - //clp.arg = NULL; - //chopstx_cleanup_push (&clp); - //cs = chopstx_setcancelstate (0); /* Allow cancellation. */ - ret = mbedtls_rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL, - output_len_p, input, - output, MAX_RES_APDU_DATA_SIZE); - rsa_cleanup(NULL); - //chopstx_setcancelstate (cs); - //chopstx_cleanup_pop (0); - } - - mbedtls_rsa_free (&rsa_ctx); - if (ret != 0) - { - DEBUG_INFO ("fail:"); - DEBUG_SHORT (ret); - return -1; - } - else - { - DEBUG_INFO ("done.\r\n"); - GPG_SUCCESS (); - return 0; - } -} - -int -rsa_verify (const uint8_t *pubkey, int pubkey_len, - const uint8_t *hash, const uint8_t *sig) -{ - int ret; - - mbedtls_rsa_init (&rsa_ctx); - rsa_ctx.len = pubkey_len; - MBEDTLS_MPI_CHK( mbedtls_mpi_lset (&rsa_ctx.E, 0x10001) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary (&rsa_ctx.N, pubkey, pubkey_len) ); - - DEBUG_INFO ("RSA verify..."); - - MBEDTLS_MPI_CHK( mbedtls_rsa_rsassa_pkcs1_v15_verify (&rsa_ctx, - MBEDTLS_MD_SHA256, 32, - hash, sig) ); - cleanup: - mbedtls_rsa_free (&rsa_ctx); - if (ret != 0) - { - DEBUG_INFO ("fail:"); - - DEBUG_SHORT (ret); - return -1; - } - else - { - DEBUG_INFO ("verified.\r\n"); - return 0; - } -} - -#define RSA_EXPONENT 0x10001 - -struct jkiss_state { uint32_t x, y, z, c; }; -static struct jkiss_state jkiss_state_v; - - -int prng_seed (int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - int ret; - - struct jkiss_state *s = &jkiss_state_v; - - MBEDTLS_MPI_CHK ( f_rng (p_rng, (unsigned char *)s, sizeof (struct jkiss_state)) ); - while (s->y == 0) - MBEDTLS_MPI_CHK ( f_rng (p_rng, (unsigned char *)&s->y, sizeof (uint32_t)) ); - s->z |= 1; /* avoiding z=c=0 */ - -cleanup: - return ret; -} - - -int -rsa_genkey (int pubkey_len, uint8_t *pubkey, uint8_t *p_q) -{ - int ret; - uint8_t index = 0; - uint8_t *p = p_q; - uint8_t *q = p_q + pubkey_len / 2; - int cs; - - extern void neug_flush (void); - - neug_flush (); - prng_seed (random_gen, &index); - mbedtls_rsa_init (&rsa_ctx); - - //clp.next = NULL; - //clp.routine = rsa_cleanup; - //clp.arg = NULL; - //chopstx_cleanup_push (&clp); - //cs = chopstx_setcancelstate (0); /* Allow cancellation. */ - MBEDTLS_MPI_CHK( mbedtls_rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8, - RSA_EXPONENT) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary (&rsa_ctx.P, p, pubkey_len / 2) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary (&rsa_ctx.Q, q, pubkey_len / 2) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary (&rsa_ctx.N, pubkey, pubkey_len) ); - - cleanup: - //chopstx_setcancelstate (cs); - //chopstx_cleanup_pop (1); - rsa_cleanup(NULL); - if (ret != 0) - return -1; - else - return 0; -} diff --git a/src/openpgp/config.h b/src/openpgp/config.h deleted file mode 100644 index c533464..0000000 --- a/src/openpgp/config.h +++ /dev/null @@ -1,17 +0,0 @@ -#define DEBUG -#ifdef DEBUG -#define ENABLE_VIRTUAL_COM_PORT 1 -#endif -#undef DFU_SUPPORT -#define ORIGIN 0x08000000 -#define ORIGIN_REAL 0x08000000 -#undef PINPAD_SUPPORT - -#define CERTDO_SUPPORT 1 -#undef HID_CARD_CHANGE_SUPPORT -#define LIFE_CYCLE_MANAGEMENT_SUPPORT 1 -#undef ACKBTN_SUPPORT -#define SERIALNO_STR_LEN 12 -#undef KDF_DO_REQUIRED - -#define MHZ 133 \ No newline at end of file diff --git a/src/openpgp/debug.c b/src/openpgp/debug.c deleted file mode 100644 index 8e3315d..0000000 --- a/src/openpgp/debug.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * debug.c -- Debuging with virtual COM port - * - * Copyright (C) 2010 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include -#include "tusb.h" -#include "config.h" - -void my_write (const char *s, int len) -{ - if (len == 0) - return; - - TU_LOG1(s); -} - - -static void -put_hex (uint8_t nibble) -{ - uint8_t c; - - if (nibble < 0x0a) - c = '0' + nibble; - else - c = 'a' + nibble - 0x0a; - - //my_write ((const char *)&c, 1); - printf("%X",nibble); -} - -void -put_byte (uint8_t b) -{ - put_hex (b >> 4); - put_hex (b &0x0f); - my_write ("\r\n", 2); -} - -void -put_byte_with_no_nl (uint8_t b) -{ - my_write (" ", 1); - put_hex (b >> 4); - put_hex (b &0x0f); -} - -void -put_short (uint16_t x) -{ - put_hex (x >> 12); - put_hex ((x >> 8)&0x0f); - put_hex ((x >> 4)&0x0f); - put_hex (x & 0x0f); - my_write ("\r\n", 2); -} - -void -put_word (uint32_t x) -{ - put_hex (x >> 28); - put_hex ((x >> 24)&0x0f); - put_hex ((x >> 20)&0x0f); - put_hex ((x >> 16)&0x0f); - put_hex ((x >> 12)&0x0f); - put_hex ((x >> 8)&0x0f); - put_hex ((x >> 4)&0x0f); - put_hex (x & 0x0f); - my_write ("\r\n", 2); -} - -void -put_int (uint32_t x) -{ - char s[10]; - int i; - - for (i = 0; i < 10; i++) - { - s[i] = '0' + (x % 10); - x /= 10; - if (x == 0) - break; - } - - while (i) - { - my_write (s+i, 1); - i--; - } - - my_write (s, 1); - my_write ("\r\n", 2); -} - -void -put_binary (const char *s, int len) -{ - int i; - - for (i = 0; i < len; i++) - { - put_byte_with_no_nl (s[i]); - if ((i & 0x0f) == 0x0f) - my_write ("\r\n", 2); - } - my_write ("\r\n", 2); -} - -void -put_string (const char *s) -{ - my_write (s, strlen (s)); -} - - diff --git a/src/openpgp/ec_p256k1.c b/src/openpgp/ec_p256k1.c deleted file mode 100644 index c63978e..0000000 --- a/src/openpgp/ec_p256k1.c +++ /dev/null @@ -1,233 +0,0 @@ -/* -*- coding: utf-8 -*- - * ec_p256k1.c - Elliptic curve over GF(p256k1) - * - * Copyright (C) 2014 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -/* - * Note: we don't take advantage of the specific feature of this curve, - * but use same method of computation as NIST P-256 curve. That's due - * to some software patent(s). - */ - -#include -#include -#include "bn.h" -#include "modp256k1.h" -#include "affine.h" -#include "jpc-ac_p256k1.h" -#include "mod.h" -#include "ec_p256k1.h" - -#define FIELD p256k1 -#define COEFFICIENT_A_IS_ZERO 1 - -/* - * a = 0, b = 7 - */ -#if 0 -static const bn256 coefficient_a[1] = { - {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }} -}; -#endif - -static const bn256 coefficient_b[1] = { - {{ 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }} -}; - - -static const ac precomputed_KG[15] = { - { - {{{ 0x16f81798, 0x59f2815b, 0x2dce28d9, 0x029bfcdb, - 0xce870b07, 0x55a06295, 0xf9dcbbac, 0x79be667e }}}, - {{{ 0xfb10d4b8, 0x9c47d08f, 0xa6855419, 0xfd17b448, - 0x0e1108a8, 0x5da4fbfc, 0x26a3c465, 0x483ada77 }}} - }, { - {{{ 0x42d0e6bd, 0x13b7e0e7, 0xdb0f5e53, 0xf774d163, - 0x104d6ecb, 0x82a2147c, 0x243c4e25, 0x3322d401 }}}, - {{{ 0x6c28b2a0, 0x24f3a2e9, 0xa2873af6, 0x2805f63e, - 0x4ddaf9b7, 0xbfb019bc, 0xe9664ef5, 0x56e70797 }}} - }, { - {{{ 0x829d122a, 0xdca81127, 0x67e99549, 0x8f17f314, - 0x6a8a9e73, 0x9b889085, 0x846dd99d, 0x583fdfd9 }}}, - {{{ 0x63c4eac4, 0xf3c7719e, 0xb734b37a, 0xb44685a3, - 0x572a47a6, 0x9f92d2d6, 0x2ff57d81, 0xabc6232f }}} - }, { - {{{ 0x9ec4c0da, 0x1b7b444c, 0x723ea335, 0xe88c5678, - 0x981f162e, 0x9239c1ad, 0xf63b5f33, 0x8f68b9d2 }}}, - {{{ 0x501fff82, 0xf23cbf79, 0x95510bfd, 0xbbea2cfe, - 0xb6be215d, 0xde1d90c2, 0xba063986, 0x662a9f2d }}} - }, { - {{{ 0x114cbf09, 0x63c5e885, 0x7be77e3e, 0x2f27ce93, - 0xf54a3e33, 0xdaa6d12d, 0x3eff872c, 0x8b300e51 }}}, - {{{ 0xb3b10a39, 0x26c6ff28, 0x9aaf7169, 0x08f6a7aa, - 0x6b8238ea, 0x446f0d46, 0x7f43c0cc, 0x1cec3067 }}} - }, { - {{{ 0x075e9070, 0xba16ce6a, 0x9b5cfe37, 0xbc26893d, - 0x9c510774, 0xe1ddadfe, 0xfe3ae2f4, 0x90922d88 }}}, - {{{ 0x5c08824a, 0x653943cc, 0xfce8f4bc, 0x06d74475, - 0x533c615d, 0x8d101fa7, 0x742108a9, 0x7b1903f6 }}} - }, { - {{{ 0x6ebdc96c, 0x1bcfa45c, 0x1c7584ba, 0xe400bc04, - 0x74cf531f, 0x6395e20e, 0xc5131b30, 0x1edd0bb1 }}}, - {{{ 0xe358cf9e, 0xa117161b, 0x2724d11c, 0xe490d6f0, - 0xee6dd8c9, 0xf75062f6, 0xfba373e4, 0x31e03b2b }}} - }, { - {{{ 0x2120e2b3, 0x7f3b58fa, 0x7f47f9aa, 0x7a58fdce, - 0x4ce6e521, 0xe7be4ae3, 0x1f51bdba, 0xeaa649f2 }}}, - {{{ 0xba5ad93d, 0xd47a5305, 0xf13f7e59, 0x01a6b965, - 0x9879aa5a, 0xc69a80f8, 0x5bbbb03a, 0xbe3279ed }}} - }, { - {{{ 0x27bb4d71, 0xcf291a33, 0x33524832, 0x6caf7d6b, - 0x766584ee, 0x6e0ee131, 0xd064c589, 0x160cb0f6 }}}, - {{{ 0x17136e8d, 0x9d5de554, 0x1aab720e, 0xe3f2d468, - 0xccf75cc2, 0xd1378b49, 0xc4ff16e1, 0x6920c375 }}} - }, { - {{{ 0x1a9ee611, 0x3eef9e96, 0x9cc37faf, 0xfe4d7bf3, - 0xb321d965, 0x462aa9b3, 0x208736c5, 0x1702da3e }}}, - {{{ 0x3a545ceb, 0xfba57bbf, 0x7ea858f5, 0x6dbcd766, - 0x680d92f1, 0x088e897c, 0xbc626c80, 0x468c1fd8 }}} - }, { - {{{ 0xb188660a, 0xb40f85c7, 0x99bc3c36, 0xc5873c19, - 0x7f33b54c, 0x3c7b4541, 0x1f8c9bf8, 0x4cd3a93c }}}, - {{{ 0x33099cb0, 0xf8dce380, 0x2edd2f33, 0x7a167dd6, - 0x0ffe35b7, 0x576d8987, 0xc68ace5c, 0xd2de0386 }}} - }, { - {{{ 0x6658bb08, 0x9a9e0a72, 0xc589607b, 0xe23c5f2a, - 0xf2bfb4c8, 0xa048ca14, 0xc62c2291, 0x4d9a0f89 }}}, - {{{ 0x0f827294, 0x427b5f31, 0x9f2c35cd, 0x1ea7a8b5, - 0x85a3c00f, 0x95442e56, 0x9b57975a, 0x8cb83121 }}} - }, { - {{{ 0x51f5cf67, 0x4333f0da, 0xf4f0d3cb, 0x6d3ea47c, - 0xa05a831f, 0x442fda14, 0x016d3e81, 0x6a496013 }}}, - {{{ 0xe52e0f48, 0xf647318c, 0x4a0d5ff1, 0x5ff3a66e, - 0x61199ba8, 0x046ed81a, 0x3e79c23a, 0x578edf08 }}} - }, { - {{{ 0x3ea01ea7, 0xb8f996f8, 0x7497bb15, 0xc0045d33, - 0x6205647c, 0xc4749dc9, 0x0efd22c9, 0xd8946054 }}}, - {{{ 0x12774ad5, 0x062dcb09, 0x8be06e3a, 0xcb13f310, - 0x235de1a9, 0xca281d35, 0x69c3645c, 0xaf8a7412 }}} - }, { - {{{ 0xbeb8b1e2, 0x8808ca5f, 0xea0dda76, 0x0262b204, - 0xddeb356b, 0xb6fffffc, 0xfbb83870, 0x52de253a }}}, - {{{ 0x8f8d21ea, 0x961f40c0, 0x002f03ed, 0x89686278, - 0x38e421ea, 0x0ff834d7, 0xd36fb8db, 0x3a270d6f }}} - } -}; - -static const ac precomputed_2E_KG[15] = { - { - {{{ 0x39a48db0, 0xefd7835b, 0x9b3c03bf, 0x9f1215a2, - 0x9b7bde45, 0x2791d0a0, 0x696e7167, 0x100f44da }}}, - {{{ 0x2bc65a09, 0x0fbd5cd6, 0xff5195ac, 0xb7ff4a18, - 0x0c090666, 0x2ec8f330, 0x92a00b77, 0xcdd9e131 }}} - }, { - {{{ 0x40fb27b6, 0x32427e28, 0xbe430576, 0xc76e3db2, - 0x61686aa5, 0x10f238ad, 0xbe778b1b, 0xfea74e3d }}}, - {{{ 0xf23cb96f, 0x701d3db7, 0x973f7b77, 0x126b596b, - 0xccb6af93, 0x7cf674de, 0x9b0b1329, 0x6e0568db }}} - }, { - {{{ 0x2c8118bc, 0x6cac5154, 0x399ddd98, 0x19bd4b34, - 0x2e9c8949, 0x47248a8d, 0x2cefa3b1, 0x734cb6a8 }}}, - {{{ 0x1e410fd5, 0xf1b340ad, 0xc4873539, 0xa2982bee, - 0xd4de4530, 0x7b5a3ea4, 0x42202574, 0xae46e10e }}} - }, { - {{{ 0xac1f98cd, 0xcbfc99c8, 0x4d7f0308, 0x52348905, - 0x1cc66021, 0xfaed8a9c, 0x4a474870, 0x9c3919a8 }}}, - {{{ 0xd4fc599d, 0xbe7e5e03, 0x6c64c8e6, 0x905326f7, - 0xf260e641, 0x584f044b, 0x4a4ddd57, 0xddb84f0f }}} - }, { - {{{ 0xed7cebed, 0xc4aacaa8, 0x4fae424e, 0xb75d2dce, - 0xba20735e, 0xa01585a2, 0xba122399, 0x3d75f24b }}}, - {{{ 0xd5570dce, 0xcbe4606f, 0x2da192c2, 0x9d00bfd7, - 0xa57b7265, 0x9c3ce86b, 0xec4edf5e, 0x987a22f1 }}} - }, { - {{{ 0x73ea0665, 0x211b9715, 0xf3a1abbb, 0x86f485d4, - 0xcd076f0e, 0xabd242d8, 0x0ba5dc88, 0x862332ab }}}, - {{{ 0x7b784911, 0x09af505c, 0xcaf4fae7, 0xc89544e8, - 0xae9a32eb, 0x256625f6, 0x606d1a3f, 0xe2532b72 }}} - }, { - {{{ 0x0deaf885, 0x79e9f313, 0x46df21c9, 0x938ff76e, - 0xa953bb2c, 0x1968f5fb, 0x29155f27, 0xdff538bf }}}, - {{{ 0x31d5d020, 0xf7bae0b1, 0x1a676a8d, 0x5afdc787, - 0xfa9d53ff, 0x11b4f032, 0xc5959167, 0x86ba433e }}} - }, { - {{{ 0x9475b7ba, 0x884fdff0, 0xe4918b3d, 0xe039e730, - 0xf5018cdb, 0x3d3e57ed, 0x1943785c, 0x95939698 }}}, - {{{ 0x7524f2fd, 0xe9b8abf8, 0xc8709385, 0x9c653f64, - 0x4b9cd684, 0x8ba0386a, 0x88c331dd, 0x2e7e5528 }}} - }, { - {{{ 0xeefe79e5, 0x940bef53, 0xbe9b87f3, 0xc518d286, - 0x7833042c, 0x9e0c7c76, 0x11fbe152, 0x104e2cb5 }}}, - {{{ 0x50bbec83, 0xc0d35e0f, 0x4acd0fcc, 0xee4879be, - 0x006085ee, 0xc8d80f5d, 0x72fe1ac1, 0x3c51bc1c }}} - }, { - {{{ 0xb2de976e, 0x06187f61, 0xf5e4b4b6, 0x52869e18, - 0x38d332ca, 0x74d4facd, 0xb3a2f8d9, 0x5c1c90b4 }}}, - {{{ 0xdaa37893, 0x98644d09, 0xabe39818, 0x682435a8, - 0x469c53a0, 0x17e46617, 0x77dc2e64, 0x642f9632 }}} - }, { - {{{ 0x222f6c54, 0xad2101c5, 0xfa74785e, 0xb05c7a58, - 0x489bcdaf, 0xce55fa79, 0xffe88d54, 0xc1f920fd }}}, - {{{ 0x9065e490, 0x32553ab0, 0x35329f74, 0x7611b9af, - 0xab7b24c0, 0x57df19ef, 0x6181c447, 0xb9a78749 }}} - }, { - {{{ 0xa80b7ea8, 0x392f156f, 0x8ae4a8bf, 0x57ab7ca0, - 0x50c4b178, 0xac320747, 0x0e781feb, 0x146041b9 }}}, - {{{ 0x845279b2, 0xd343f075, 0x7387afa5, 0x2d4fe757, - 0xa72f3c39, 0x151e0948, 0x550da168, 0x41a6d54e }}} - }, { - {{{ 0x075a0010, 0xb3134ed3, 0x7ae93e23, 0x9fa76f4b, - 0x7bb4daaa, 0xc0db256f, 0x464dd8a3, 0x7668dc27 }}}, - {{{ 0x9f5da977, 0x150063f5, 0x05efce00, 0x3acac5c8, - 0x884493fe, 0xc8e12ffc, 0x88f06bd2, 0x4ab936d8 }}} - }, { - {{{ 0x5d09ea98, 0x996fde77, 0x4145da58, 0x16ddf512, - 0xdc2fb225, 0xa97a6ca8, 0xfbdcdf5a, 0xc7331f30 }}}, - {{{ 0x86a86e52, 0x838f99e0, 0x77795edd, 0x68d39b29, - 0x9f412aaa, 0xe4e4f97e, 0x30d25352, 0xe5cc2c0a }}} - }, { - {{{ 0x9c21ff71, 0xb3d68650, 0xddbe3884, 0x11e7589d, - 0x423bac67, 0x7efd4055, 0x46957425, 0x587a7293 }}}, - {{{ 0x8f5a8fc6, 0x360adc2e, 0xbd69f12e, 0x6f8bbafb, - 0x0a3f3b4d, 0xf671f423, 0x59942dc3, 0xb49acb47 }}} - } -}; - -/* - * N: order of G - * 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - */ -static const bn256 N[1] = { - {{ 0xd0364141, 0xbfd25e8c, 0xaf48a03b, 0xbaaedce6, - 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff }} -}; - -/* - * MU = 2^512 / N - * MU = ( (1 << 256) | MU_lower ) - */ -static const bn256 MU_lower[1] = { - {{ 0x2fc9bec0, 0x402da173, 0x50b75fc4, 0x45512319, - 0x1, 0x0, 0x0, 0x0 }} -}; - - -#include "ecc.c" diff --git a/src/openpgp/ec_p256k1.h b/src/openpgp/ec_p256k1.h deleted file mode 100644 index ec0e213..0000000 --- a/src/openpgp/ec_p256k1.h +++ /dev/null @@ -1,4 +0,0 @@ -int compute_kP_p256k1 (ac *X, const bn256 *K, const ac *P); -int compute_kG_p256k1 (ac *X, const bn256 *K); -void ecdsa_p256k1 (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d); -int check_secret_p256k1 (const bn256 *q, bn256 *d1); diff --git a/src/openpgp/ecc-ed25519.c b/src/openpgp/ecc-ed25519.c deleted file mode 100644 index 0109855..0000000 --- a/src/openpgp/ecc-ed25519.c +++ /dev/null @@ -1,955 +0,0 @@ -/* -*- coding: utf-8 -*- - * ecc-ed25519.c - Elliptic curve computation for - * the twisted Edwards curve: -x^2 + y^2 = 1 + d*x^2*y^2 - * d = -121665/121666 - * - * Copyright (C) 2014, 2017 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include - -#include "bn.h" -#include "mod.h" -#include "mod25638.h" -#include "mbedtls/sha512.h" - -/* - * References: - * - * [1] Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter Schwabe, Bo-Yin Yang. - * High-speed high-security signatures. - * Journal of Cryptographic Engineering 2 (2012), 77--89. - * http://cr.yp.to/papers.html#ed25519 - * - * [2] Daniel J. Bernstein, Peter Birkner, Marc Joye, Tanja Lange, - * Christiane Peters. - * Twisted Edwards curves. - * Pages 389--405 in Progress in cryptology---AFRICACRYPT 2008. - * http://cr.yp.to/papers.html#twisted - */ - -/* - * IMPLEMENTATION NOTE - * - * (0) We assume that the processor has no cache, nor branch target - * prediction. Thus, we don't avoid indexing by secret value. - * We don't avoid conditional jump if both cases have same timing, - * either. - * - * (1) We use Radix-32 field arithmetic. It's a representation like - * 2^256-38, but it's more redundant. For example, "1" can be - * represented in three ways in 256-bit: 1, 2^255-18, and - * 2^256-37. - * - * (2) We use fixed base comb multiplication. Scalar is 252-bit. - * There are various possible choices for 252 = 2 * 2 * 3 * 3 * 7. - * Current choice of total size is 3KB. We use three tables, and - * a table has 16 points (3 * 1KB). - * - * Window size W = 4-bit, E = 21. - * <--21-bit- - * <---42-bit---------- - * [ ][########][////////][ ][########][////////] - * <-------63-bit---------------- - * <-----------84-bit---------------------- - * <--------------105-bit---------------------------- - * - * [ ][########][////////][ ][########][////////] - * <-126-bit- - * <-147-bit- - * <----168-bit-------- - * - * <-------189-bit--------------- - * <----------210-bit---------------------- - * <-------------231-bit----------------------------- - */ - -/* - * Identity element: (0,1) - * Negation: -(x,y) = (-x,y) - * - * d: -0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A - * order: - * 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED - * Gx: 0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A - * Gy: 0x6666666666666666666666666666666666666666666666666666666666666658 - */ - -/* d + 2^255 - 19 */ -static const bn256 coefficient_d[1] = { - {{ 0x135978a3, 0x75eb4dca, 0x4141d8ab, 0x00700a4d, - 0x7779e898, 0x8cc74079, 0x2b6ffe73, 0x52036cee }} }; - - -/** - * @brief Projective Twisted Coordinates - */ -typedef struct -{ - bn256 x[1]; - bn256 y[1]; - bn256 z[1]; -} ptc; - -#include "affine.h" - - -static int -mod25519_is_neg (const bn256 *a) -{ - return (a->word[0] & 1); -} - - -/** - * @brief X = 2 * A - * - * Compute (X3 : Y3 : Z3) = 2 * (X1 : Y1 : Z1) - */ -static void -point_double (ptc *X, const ptc *A) -{ - bn256 b[1], d[1], e[1]; - - /* Compute: B = (X1 + Y1)^2 */ - mod25638_add (b, A->x, A->y); - mod25638_sqr (b, b); - - /* Compute: C = X1^2 : E */ - mod25638_sqr (e, A->x); - - /* Compute: D = Y1^2 */ - mod25638_sqr (d, A->y); - - /* E = aC; where a = -1 */ - /* Compute: D - E = D + C : Y3_tmp */ - mod25638_add (X->y, e, d); - - /* Compute: -F = -(E + D) = C - D; where a = -1 : E */ - mod25638_sub (e, e, d); - - /* Compute: H = Z1^2 : D */ - mod25638_sqr (d, A->z); - - /* Compute: -J = 2*H - F : D */ - mod25638_add (d, d, d); - mod25638_add (d, d, e); - - /* Compute: X3 = (B-C-D)*J = -J*(C+D-B) = -J*(Y3_tmp-B) */ - mod25638_sub (X->x, X->y, b); - mod25638_mul (X->x, X->x, d); - - /* Compute: Y3 = -F*(D-E) = -F*Y3_tmp */ - mod25638_mul (X->y, X->y, e); - - /* Z3 = -F*-J */ - mod25638_mul (X->z, e, d); -} - - -/** - * @brief X = A + B - * - * @param X Destination PTC - * @param A PTC - * @param B AC - * - * Compute: (X3 : Y3 : Z3) = (X1 : Y1 : Z1) + (X2 : Y2 : 1) - */ -static void -point_add (ptc *X, const ptc *A, const ac *B) -{ - bn256 c[1], d[1], e[1], tmp[1]; - - /* Compute: C = X1 * X2 */ - mod25638_mul (c, A->x, B->x); - - /* Compute: D = Y1 * Y2 */ - mod25638_mul (d, A->y, B->y); - - /* Compute: E = d * C * D */ - mod25638_mul (e, c, d); - mod25638_mul (e, coefficient_d, e); - - /* Compute: C_1 = C + D */ - mod25638_add (c, c, d); - - /* Compute: D_1 = Z1^2 : B */ - mod25638_sqr (d, A->z); - - /* tmp = D_1 - E : F */ - mod25638_sub (tmp, d, e); - - /* D_2 = D_1 + E : G */ - mod25638_add (d, d, e); - - /* X3_final = Z1 * tmp * ((X1 + Y1) * (X2 + Y2) - C_1) */ - mod25638_add (X->x, A->x, A->y); - mod25638_add (e, B->x, B->y); - mod25638_mul (e, X->x, e); - mod25638_sub (e, e, c); - mod25638_mul (e, tmp, e); - mod25638_mul (X->x, A->z, e); - - /* Y3_final = Z1 * D_2 * C_1 */ - mod25638_mul (c, d, c); - mod25638_mul (X->y, A->z, c); - - /* Z3_final = tmp * D_2 */ - mod25638_mul (X->z, tmp, d); - - /* A = Z1 */ - /* B = A^2 */ - /* C = X1 * X2 */ - /* D = Y1 * Y2 */ - /* E = d * C * D */ - /* F = B - E */ - /* G = B + E */ - /* X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) */ - /* Y3 = A * G * (D - aC); where a = -1 */ - /* Z3 = F * G */ -} - - -/** - * @brief X = convert A - * - * @param X Destination AC - * @param A PTC - * - * (X1:Y1:Z1) represents the affine point (x=X1/Z1, y=Y1/Z1) - */ -static void -point_ptc_to_ac (ac *X, const ptc *A) -{ - bn256 z_inv[1]; - - /* - * A->z may be bigger than p25519, or two times bigger than p25519. - * But this is no problem for computation of mod_inv. - */ - mod_inv (z_inv, A->z, p25519); - - mod25638_mul (X->x, A->x, z_inv); - mod25519_reduce (X->x); - mod25638_mul (X->y, A->y, z_inv); - mod25519_reduce (X->y); -} - - -static const ac precomputed_KG[16] = { - { {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}}, - {{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} }, - { {{{ 0x8f25d51a, 0xc9562d60, 0x9525a7b2, 0x692cc760, - 0xfdd6dc5c, 0xc0a4e231, 0xcd6e53fe, 0x216936d3 }}}, - {{{ 0x66666658, 0x66666666, 0x66666666, 0x66666666, - 0x66666666, 0x66666666, 0x66666666, 0x66666666 }}} }, - { {{{ 0x3713af22, 0xac7137bd, 0xac634604, 0x25ed77a4, - 0xa815e038, 0xce0d0064, 0xbca90151, 0x041c030f }}}, - {{{ 0x0780f989, 0xe9b33fcf, 0x3d4445e7, 0xe4e97c2a, - 0x655e5c16, 0xc67dc71c, 0xee43fb7a, 0x72467625 }}} }, - { {{{ 0x3ee99893, 0x76a19171, 0x7ba9b065, 0xe647edd9, - 0x6aeae260, 0x31f39299, 0x5f4a9bb2, 0x6d9e4545 }}}, - {{{ 0x94cae280, 0xc41433da, 0x79061211, 0x8e842de8, - 0xa259dc8a, 0xaab95e0b, 0x99013cd0, 0x28bd5fc3 }}} }, - { {{{ 0x7d23ea24, 0x59e22c56, 0x0460850e, 0x1e745a88, - 0xda13ef4b, 0x4583ff4c, 0x95083f85, 0x1f13202c }}}, - {{{ 0x90275f48, 0xad42025c, 0xb55c4778, 0x0085087e, - 0xfdfd7ffa, 0xf21109e7, 0x6c381b7e, 0x66336d35 }}} }, - { {{{ 0xd00851f2, 0xaa9476ab, 0x4a61600b, 0xe7838534, - 0x1a52df87, 0x0de65625, 0xbd675870, 0x5f0dd494 }}}, - {{{ 0xe23493ba, 0xf20aec1b, 0x3414b0a8, 0x8f7f2741, - 0xa80e1eb6, 0x497e74bd, 0xe9365b15, 0x1648eaac }}} }, - { {{{ 0x04ac2b69, 0x5b78dcec, 0x32001a73, 0xecdb66ce, - 0xb34cf697, 0xb75832f4, 0x3a2bce94, 0x7aaf57c5 }}}, - {{{ 0x60fdfc6f, 0xb32ed2ce, 0x757924c6, 0x77bf20be, - 0x48742dd1, 0xaebd15dd, 0x55d38439, 0x6311bb16 }}} }, - { {{{ 0x42ff5c97, 0x139cdd73, 0xdbd82964, 0xee4c359e, - 0x70611a3f, 0x91c1cd94, 0x8075dbcb, 0x1d0c34f6 }}}, - {{{ 0x5f931219, 0x43eaa549, 0xa23d35a6, 0x3737aba7, - 0x46f167bb, 0x54b1992f, 0xb74a9944, 0x01a11f3c }}} }, - { {{{ 0xba46b161, 0x67a5310e, 0xd9d67f6c, 0x790f8527, - 0x2f6cc814, 0x359c5b5f, 0x7786383d, 0x7b6a5565 }}}, - {{{ 0x663ab0d3, 0xf1431b60, 0x09995826, 0x14a32d8f, - 0xeddb8571, 0x61d526f6, 0x0eac739a, 0x0cb7acea }}} }, - { {{{ 0x4a2d009f, 0x5eb1a697, 0xd8df987a, 0xdacb43b4, - 0x8397f958, 0x4870f214, 0x8a175fbb, 0x5aa0c67c }}}, - {{{ 0x78887db3, 0x27dbbd4c, 0x64e322ab, 0xe327b707, - 0x7cbe4e3b, 0x87e293fa, 0xbda72395, 0x17040799 }}} }, - { {{{ 0x99d1e696, 0xc833a5a2, 0x2d9d5877, 0x969bff8e, - 0x2216fa67, 0x383a533a, 0x684d3925, 0x338bbe0a }}}, - {{{ 0xd6cfb491, 0x35b5aae8, 0xaa12f3f8, 0x4a588279, - 0x2e30380e, 0xa7c2e708, 0x9e4b3d62, 0x69f13e09 }}} }, - { {{{ 0x27f1cd56, 0xec0dc2ef, 0xdb11cc97, 0x1af11548, - 0x9ebc7613, 0xb642f86a, 0xcb77c3b9, 0x5ce45e73 }}}, - {{{ 0x3eddd6de, 0x5d128786, 0x4859eab7, 0x16f9a6b4, - 0xd8782345, 0x55c53916, 0xdb7b202a, 0x6b1dfa87 }}} }, - { {{{ 0x19e30528, 0x2461a8ed, 0x665cfb1c, 0xaf756bf9, - 0x3a6e8673, 0x0fcafd1d, 0x45d10f48, 0x0d264435 }}}, - {{{ 0x5431db67, 0x543fd4c6, 0x60932432, 0xc153a5b3, - 0xd2119aa4, 0x41d5b8eb, 0x8b09b6a5, 0x36bd9ab4 }}} }, - { {{{ 0x21e06738, 0x6d39f935, 0x3765dd86, 0x4e6a7c59, - 0xa4730880, 0xefc0dd80, 0x4079fe2f, 0x40617e56 }}}, - {{{ 0x921439b9, 0xbc83cdff, 0x98833c09, 0xd5cccc06, - 0xda13cdcb, 0xe315c425, 0x67ff5370, 0x37bc6e84 }}} }, - { {{{ 0xf643b5f5, 0x65e7f028, 0x0ffbf5a8, 0x5b0d4831, - 0xf4085f62, 0x0f540498, 0x0db7bd1b, 0x6f0bb035 }}}, - {{{ 0x9733742c, 0x51f65571, 0xf513409f, 0x2fc047a0, - 0x355facf6, 0x07f45010, 0x3a989a9c, 0x5cd416a9 }}} }, - { {{{ 0x748f2a67, 0x0bdd7208, 0x415b7f7f, 0x0cf0b80b, - 0x57aa0119, 0x44afdd5f, 0x430dc946, 0x05d68802 }}}, - {{{ 0x1a60eeb2, 0x420c46e5, 0x665024f5, 0xc60a9b33, - 0x48c51347, 0x37520265, 0x00a21bfb, 0x6f4be0af }}} } -}; - -static const ac precomputed_2E_KG[16] = { - { {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}}, - {{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} }, - { {{{ 0x199c4f7d, 0xec314ac0, 0xb2ebaaf9, 0x66a39c16, - 0xedd4d15f, 0xab1c92b8, 0x57d9eada, 0x482a4cdf }}}, - {{{ 0x6e4eb04b, 0xbd513b11, 0x25e4fd6a, 0x3f115fa5, - 0x14519298, 0x0b3c5fc6, 0x81c2f7a8, 0x7391de43 }}} }, - { {{{ 0x1254fe02, 0xa57dca18, 0x6da34368, 0xa56a2a14, - 0x63e7328e, 0x44c6e34f, 0xca63ab3e, 0x3f748617 }}}, - {{{ 0x7dc1641e, 0x5a13dc52, 0xee4e9ca1, 0x4cbb2899, - 0x1ba9acee, 0x3938a289, 0x420fc47b, 0x0fed89e6 }}} }, - { {{{ 0x49cbad08, 0x3c193f32, 0x15e80ef5, 0xdda71ef1, - 0x9d128c33, 0xda44186c, 0xbf98c24f, 0x54183ede }}}, - {{{ 0x93d165c1, 0x2cb483f7, 0x177f44aa, 0x51762ace, - 0xb4ab035d, 0xb3fe651b, 0xa0b0d4e5, 0x426c99c3 }}} }, - { {{{ 0xef3f3fb1, 0xb3fcf4d8, 0x065060a0, 0x7052292b, - 0x24240b15, 0x18795ff8, 0x9989ffcc, 0x13aea184 }}}, - {{{ 0xc2b81f44, 0x1930c101, 0x10600555, 0x672d6ca4, - 0x1b25e570, 0xfbddbff2, 0x8ca12b70, 0x0884949c }}} }, - { {{{ 0x00564bbf, 0x9983a033, 0xde61b72d, 0x95587d25, - 0xeb17ad71, 0xb6719dfb, 0xc0bc3517, 0x46871ad0 }}}, - {{{ 0xe95a6693, 0xb034fb61, 0x76eabad9, 0x5b0d8d18, - 0x884785dc, 0xad295dd0, 0x74a1276a, 0x359debad }}} }, - { {{{ 0xe89fb5ca, 0x2e5a2686, 0x5656c6c5, 0xd3d200ba, - 0x9c969001, 0xef4c051e, 0x02cb45f4, 0x0d4ea946 }}}, - {{{ 0x76d6e506, 0xa6f8a422, 0x63209e23, 0x454c768f, - 0x2b372386, 0x5c12fd04, 0xdbfee11f, 0x1aedbd3e }}} }, - { {{{ 0x00dbf569, 0x700ab50f, 0xd335b313, 0x9553643c, - 0xa17dc97e, 0xeea9bddf, 0x3350a2bd, 0x0d12fe3d }}}, - {{{ 0xa16a3dee, 0xe5ac35fe, 0xf81950c3, 0x4ae4664a, - 0x3dbbf921, 0x75c63df4, 0x2958a5a6, 0x545b109c }}} }, - { {{{ 0x0a61b29c, 0xd7a52a98, 0x65aca9ee, 0xe21e0acb, - 0x5985dcbe, 0x57a69c0f, 0xeb87a534, 0x3c0c1e7b }}}, - {{{ 0x6384bd2f, 0xf0a0b50d, 0xc6939e4b, 0xff349a34, - 0x6e2f1973, 0x922c4554, 0xf1347631, 0x74e826b2 }}} }, - { {{{ 0xa655803c, 0xd7eaa066, 0x38292c5c, 0x09504e76, - 0x2c874953, 0xe298a02e, 0x8932b73f, 0x225093ed }}}, - {{{ 0xe69c3efd, 0xf93e2b4d, 0x8a87c799, 0xa2cbd5fc, - 0x85dba986, 0xdf41da94, 0xccee8edc, 0x36fe85e7 }}} }, - { {{{ 0x7d742813, 0x78df7dc5, 0x4a193e64, 0x333bcc6d, - 0x6a966d2d, 0x8242aa25, 0x4cd36d32, 0x03500a94 }}}, - {{{ 0x580505d7, 0xd5d110fc, 0xfa11e1e9, 0xb2f47e16, - 0x06eab6b4, 0xd0030f92, 0x62c91d46, 0x2dc80d5f }}} }, - { {{{ 0x2a75e492, 0x5788b01a, 0xbae31352, 0x992acf54, - 0x8159db27, 0x4591b980, 0xd3d84740, 0x36c6533c }}}, - {{{ 0x103883b5, 0xc44c7c00, 0x515d0820, 0x10329423, - 0x71b9dc16, 0xbd306903, 0xf88f8d32, 0x7edd5a95 }}} }, - { {{{ 0x005523d7, 0xfd63b1ac, 0xad70dd21, 0x74482e0d, - 0x02b56105, 0x67c9d9d0, 0x5971b456, 0x4d318012 }}}, - {{{ 0x841106df, 0xdc9a6f6d, 0xa326987f, 0x7c52ed9d, - 0x00607ea0, 0x4dbeaa6f, 0x6959e688, 0x115c221d }}} }, - { {{{ 0xc80f7c16, 0xf8718464, 0xe9930634, 0x05dc8f40, - 0xc2e9d5f4, 0xefa699bb, 0x021da209, 0x2469e813 }}}, - {{{ 0xc602a3c4, 0x75c02845, 0x0a200f9d, 0x49d1b2ce, - 0x2fb3ec8f, 0xd21b75e4, 0xd72a7545, 0x10dd726a }}} }, - { {{{ 0x63ef1a6c, 0xeda58527, 0x051705e0, 0xb3fc0e72, - 0x44f1161f, 0xbda6f3ee, 0xf339efe5, 0x7680aebf }}}, - {{{ 0xb1b070a7, 0xe8d3fd01, 0xdbfbaaa0, 0xc3ff7dbf, - 0xa320c916, 0xd81ef6f2, 0x62a3b54d, 0x3e22a1fb }}} }, - { {{{ 0xb1fa18c8, 0xcdbb9187, 0xcb483a17, 0x8ddb5f6b, - 0xea49af98, 0xc0a880b9, 0xf2dfddd0, 0x53bf600b }}}, - {{{ 0x9e25b164, 0x4217404c, 0xafb74aa7, 0xfabf06ee, - 0x2b9f233c, 0xb17712ae, 0xd0eb909e, 0x71f0b344 }}} } -}; - -static const ac precomputed_4E_KG[16] = { - { {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}}, - {{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} }, - { {{{ 0xe388a820, 0xbb6ec091, 0x5182278a, 0xa928b283, - 0xa9a6eb83, 0x2259174d, 0x45500054, 0x184b48cb }}}, - {{{ 0x26e77c33, 0xfe324dba, 0x83faf453, 0x6679a5e3, - 0x2380ef73, 0xdd60c268, 0x03dc33a9, 0x3ee0e07a }}} }, - { {{{ 0xce974493, 0x403aff28, 0x9bf6f5c4, 0x84076bf4, - 0xecd898fb, 0xec57038c, 0xb663ed49, 0x2898ffaa }}}, - {{{ 0xf335163d, 0xf4b3bc46, 0xfa4fb6c6, 0xe613a0f4, - 0xb9934557, 0xe759d6bc, 0xab6c9477, 0x094f3b96 }}} }, - { {{{ 0x6afffe9e, 0x168bb5a0, 0xee748c29, 0x950f7ad7, - 0xda17203d, 0xa4850a2b, 0x77289e0f, 0x0062f7a7 }}}, - {{{ 0x4b3829fa, 0x6265d4e9, 0xbdfcd386, 0x4f155ada, - 0x475795f6, 0x9f38bda4, 0xdece4a4c, 0x560ed4b3 }}} }, - { {{{ 0x141e648a, 0xdad4570a, 0x019b965c, 0x8bbf674c, - 0xdb08fe30, 0xd7a8d50d, 0xa2851109, 0x7efb45d3 }}}, - {{{ 0xd0c28cda, 0x52e818ac, 0xa321d436, 0x792257dd, - 0x9d71f8b7, 0x867091c6, 0x11a1bf56, 0x0fe1198b }}} }, - { {{{ 0x06137ab1, 0x4e848339, 0x3e6674cc, 0x5673e864, - 0x0140502b, 0xad882043, 0x6ea1e46a, 0x34b5c0cb }}}, - {{{ 0x1d70aa7c, 0x29786814, 0x8cdbb8aa, 0x840ae3f9, - 0xbd4801fb, 0x78b4d622, 0xcf18ae9a, 0x6cf4e146 }}} }, - { {{{ 0x36297168, 0x95c270ad, 0x942e7812, 0x2303ce80, - 0x0205cf0e, 0x71908cc2, 0x32bcd754, 0x0cc15edd }}}, - {{{ 0x2c7ded86, 0x1db94364, 0xf141b22c, 0xc694e39b, - 0x5e5a9312, 0xf22f64ef, 0x3c5e6155, 0x649b8859 }}} }, - { {{{ 0xb6417945, 0x0d5611c6, 0xac306c97, 0x9643fdbf, - 0x0df500ff, 0xe81faaa4, 0x6f50e615, 0x0792c79b }}}, - {{{ 0xd2af8c8d, 0xb45bbc49, 0x84f51bfe, 0x16c615ab, - 0xc1d02d32, 0xdc57c526, 0x3c8aaa55, 0x5fb9a9a6 }}} }, - { {{{ 0xdee40b98, 0x82faa8db, 0x6d520674, 0xff8a5208, - 0x446ac562, 0x1f8c510f, 0x2cc6b66e, 0x4676d381 }}}, - {{{ 0x2e7429f4, 0x8f1aa780, 0x8ed6bdf6, 0x2a95c1bf, - 0x457fa0eb, 0x051450a0, 0x744c57b1, 0x7d89e2b7 }}} }, - { {{{ 0x3f95ea15, 0xb6bdacd2, 0x2f1a5d69, 0xc9a9d1b1, - 0xf4d22d72, 0xd4c2f1a9, 0x4dc516b5, 0x73ecfdf1 }}}, - {{{ 0x05391e08, 0xa1ce93cd, 0x7b8aac17, 0x98f1e99e, - 0xa098cbb3, 0x9ba84f2e, 0xf9bdd37a, 0x1425aa8b }}} }, - { {{{ 0x966abfc0, 0x8a385bf4, 0xf081a640, 0x55e5e8bc, - 0xee26f5ff, 0x835dff85, 0xe509e1ea, 0x4927e622 }}}, - {{{ 0x352334b0, 0x164c8dbc, 0xa3fea31f, 0xcac1ad63, - 0x682fd457, 0x9b87a676, 0x1a53145f, 0x75f382ff }}} }, - { {{{ 0xc3efcb46, 0x16b944f5, 0x68cb184c, 0x1fb55714, - 0x9ccf2dc8, 0xf1c2b116, 0x808283d8, 0x7417e00f }}}, - {{{ 0x930199ba, 0x1ea67a22, 0x718990d8, 0x9fbaf765, - 0x8f3d5d57, 0x231fc664, 0xe5853194, 0x38141a19 }}} }, - { {{{ 0x2f81290d, 0xb9f00390, 0x04a9ca6c, 0x44877827, - 0xe1dbdd65, 0x65d7f9b9, 0xf7c6698a, 0x7133424c }}}, - {{{ 0xa7cd250f, 0x604cfb3c, 0x5acc18f3, 0x460c3c4b, - 0xb518e3eb, 0xa53e50e0, 0x98a40196, 0x2b4b9267 }}} }, - { {{{ 0xc5dbd06c, 0x591b0672, 0xaa1eeb65, 0x10d43dca, - 0xcd2517af, 0x420cdef8, 0x0b695a8a, 0x513a307e }}}, - {{{ 0x66503215, 0xee9d6a7b, 0x088fd9a4, 0xdea58720, - 0x973afe12, 0x8f3cbbea, 0x872f2538, 0x005c2350 }}} }, - { {{{ 0x35af3291, 0xe5024b70, 0x4f5e669a, 0x1d3eec2d, - 0x6e79d539, 0xc1f6d766, 0x795b5248, 0x34ec043f }}}, - {{{ 0x400960b6, 0xb2763511, 0x29e57df0, 0xff7a3d84, - 0x1666c1f1, 0xaeac7792, 0x66084bc0, 0x72426e97 }}} }, - { {{{ 0x44f826ca, 0x5b1c3199, 0x790aa408, 0x68b00b73, - 0x69e9b92b, 0xaf0984b4, 0x3ffe9093, 0x5fe6736f }}}, - {{{ 0xffd49312, 0xd67f2889, 0x5cb9ed21, 0x3520d747, - 0x3c65a606, 0x94f893b1, 0x2d65496f, 0x2fee5e8c }}} } -}; - -/** - * @brief X = k * G - * - * @param K scalar k - * - * Return -1 on error. - * Return 0 on success. - */ -static void -compute_kG_25519 (ac *X, const bn256 *K) -{ - ptc Q[1]; - int i; - - /* identity element */ - memset (Q, 0, sizeof (ptc)); - Q->y->word[0] = 1; - Q->z->word[0] = 1; - - for (i = 20; i >= 0; i--) - { - int k0, k1, k2; - - k0 = ((K->word[0] >> i) & 1) - | (i < 1 ? ((K->word[1] >> 30) & 2) - : (((K->word[2] >> (i-1)) & 1) << 1)) - | (i < 2 ? ((K->word[3] >> (i+28)) & 4) - : (((K->word[4] >> (i-2)) & 1) << 2)) - | (i < 3 ? ((K->word[5] >> (i+26)) & 8) - : (((K->word[6] >> (i-3)) & 1) << 3)); - - k1 = (i < 11 ? ((K->word[0] >> (i+21)) & 1) - : ((K->word[1] >> (i-11)) & 1)) - | (i < 12 ? ((K->word[2] >> (i+19)) & 2) - : (((K->word[3] >> (i-12)) & 1) << 1)) - | (i < 13 ? ((K->word[4] >> (i+17)) & 4) - : (((K->word[5] >> (i-13)) & 1) << 2)) - | (i < 14 ? ((K->word[6] >> (i+15)) & 8) - : (((K->word[7] >> (i-14)) & 1) << 3)); - - k2 = ((K->word[1] >> (i+10)) & 1) - | ((K->word[3] >> (i+8)) & 2) - | ((K->word[5] >> (i+6)) & 4) - | ((K->word[7] >> (i+4)) & 8); - - point_double (Q, Q); - point_add (Q, Q, &precomputed_KG[k0]); - point_add (Q, Q, &precomputed_2E_KG[k1]); - point_add (Q, Q, &precomputed_4E_KG[k2]); - } - - point_ptc_to_ac (X, Q); -} - - -#define BN416_WORDS 13 -#define BN128_WORDS 4 - -/* M: The order of the generator G. */ -static const bn256 M[1] = { - {{ 0x5CF5D3ED, 0x5812631A, 0xA2F79CD6, 0x14DEF9DE, - 0x00000000, 0x00000000, 0x00000000, 0x10000000 }} -}; - -#define C ((const uint32_t *)M) - -static void -bnX_mul_C (uint32_t *r, const uint32_t *q, int q_size) -{ - int i, j, k; - int i_beg, i_end; - uint32_t r0, r1, r2; - - r0 = r1 = r2 = 0; - for (k = 0; k <= q_size + BN128_WORDS - 2; k++) - { - if (q_size < BN128_WORDS) - if (k < q_size) - { - i_beg = 0; - i_end = k; - } - else - { - i_beg = k - q_size + 1; - i_end = k; - if (i_end > BN128_WORDS - 1) - i_end = BN128_WORDS - 1; - } - else - if (k < BN128_WORDS) - { - i_beg = 0; - i_end = k; - } - else - { - i_beg = k - BN128_WORDS + 1; - i_end = k; - if (i_end > q_size - 1) - i_end = q_size - 1; - } - - for (i = i_beg; i <= i_end; i++) - { - uint64_t uv; - uint32_t u, v; - uint32_t carry; - - j = k - i; - if (q_size < BN128_WORDS) - uv = ((uint64_t )q[j])*((uint64_t )C[i]); - else - uv = ((uint64_t )q[i])*((uint64_t )C[j]); - v = uv; - u = (uv >> 32); - r0 += v; - carry = (r0 < v); - r1 += carry; - carry = (r1 < carry); - r1 += u; - carry += (r1 < u); - r2 += carry; - } - - r[k] = r0; - r0 = r1; - r1 = r2; - r2 = 0; - } - - r[k] = r0; -} - -/** - * @brief R = A mod M (using M=2^252+C) (Barret reduction) - * - * See HAC 14.47 and 14.52. - */ -static void -mod_reduce_M (bn256 *R, const bn512 *A) -{ - uint32_t q[BN256_WORDS+1]; - uint32_t tmp[BN416_WORDS]; - bn256 r[1]; - uint32_t carry, next_carry; - int i; -#define borrow carry - - q[8] = A->word[15]>>28; - carry = A->word[15] & 0x0fffffff; - for (i = BN256_WORDS - 1; i >= 0; i--) - { - next_carry = A->word[i+7] & 0x0fffffff; - q[i] = (A->word[i+7] >> 28) | (carry << 4); - carry = next_carry; - } - memcpy (R, A, sizeof (bn256)); - R->word[7] &= 0x0fffffff; - - /* Q_size: 9 */ - bnX_mul_C (tmp, q, 9); /* TMP = Q*C */ - /* Q = tmp / 2^252 */ - carry = tmp[12] & 0x0fffffff; - for (i = 4; i >= 0; i--) - { - next_carry = tmp[i+7] & 0x0fffffff; - q[i] = (tmp[i+7] >> 28) | (carry << 4); - carry = next_carry; - } - /* R' = tmp % 2^252 */ - memcpy (r, tmp, sizeof (bn256)); - r->word[7] &= 0x0fffffff; - /* R -= R' */ - borrow = bn256_sub (R, R, r); - if (borrow) - bn256_add (R, R, M); - else - bn256_add ((bn256 *)tmp, R, M); - - /* Q_size: 5 */ - bnX_mul_C (tmp, q, 5); /* TMP = Q*C */ - carry = tmp[8] & 0x0fffffff; - q[0] = (tmp[7] >> 28) | (carry << 4); - /* R' = tmp % 2^252 */ - memcpy (r, tmp, sizeof (bn256)); - r->word[7] &= 0x0fffffff; - /* R += R' */ - bn256_add (R, R, r); - borrow = bn256_sub (R, R, M); - if (borrow) - bn256_add (R, R, M); - else - bn256_add ((bn256 *)tmp, R, M); - - /* Q_size: 1 */ - bnX_mul_C (tmp, q, 1); /* TMP = Q*C */ - /* R' = tmp % 2^252 */ - memset (((uint8_t *)r)+(sizeof (uint32_t)*5), 0, sizeof (uint32_t)*3); - memcpy (r, tmp, sizeof (uint32_t)*5); - /* R -= R' */ - borrow = bn256_sub (R, R, r); - if (borrow) - bn256_add (R, R, M); - else - bn256_add ((bn256 *)tmp, R, M); -#undef borrow -} - - -int -eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *out, - const bn256 *a, const uint8_t *seed, const bn256 *pk) -{ - bn256 *r, *s; - mbedtls_sha512_context ctx; - mbedtls_sha512_init(&ctx); - uint8_t hash[64]; - bn256 tmp[1]; - ac R[1]; - uint32_t carry, borrow; - - r = (bn256 *)out; - s = (bn256 *)(out+(32/4)); - - mbedtls_sha512_starts (&ctx, 0); - mbedtls_sha512_update (&ctx, seed, sizeof (bn256)); /* It's upper half of the hash */ - mbedtls_sha512_update (&ctx, input, ilen); - mbedtls_sha512_finish (&ctx, hash); - - mod_reduce_M (r, (bn512 *)hash); - compute_kG_25519 (R, r); - - /* EdDSA encoding. */ - memcpy (tmp, R->y, sizeof (bn256)); - tmp->word[7] ^= mod25519_is_neg (R->x) * 0x80000000; - - mbedtls_sha512_starts (&ctx, 0); - mbedtls_sha512_update (&ctx, (uint8_t *)tmp, sizeof (bn256)); - mbedtls_sha512_update (&ctx, (uint8_t *)pk, sizeof (bn256)); - mbedtls_sha512_update (&ctx, input, ilen); - mbedtls_sha512_finish (&ctx, (uint8_t *)hash); - - mod_reduce_M (s, (bn512 *)hash); - bn256_mul ((bn512 *)hash, s, a); - mod_reduce_M (s, (bn512 *)hash); - carry = bn256_add (s, s, r); - borrow = bn256_sub (s, s, M); - - memcpy (r, tmp, sizeof (bn256)); - - if ((borrow && !carry)) - bn256_add (s, s, M); - else - bn256_add (tmp, s, M); - - mbedtls_sha512_free (&ctx); - - return 0; -} - -static void -eddsa_public_key_25519 (bn256 *pk, const bn256 *a) -{ - ac R[1]; - ptc X[1]; - bn256 a0[1]; - - bn256_shift (a0, a, -3); - compute_kG_25519 (R, a0); - memcpy (X, R, sizeof (ac)); - memset (X->z, 0, sizeof (bn256)); - X->z->word[0] = 1; - point_double (X, X); - point_double (X, X); - point_double (X, X); - point_ptc_to_ac (R, X); - /* EdDSA encoding. */ - memcpy (pk, R->y, sizeof (bn256)); - pk->word[7] ^= mod25519_is_neg (R->x) * 0x80000000; -} - - -void -eddsa_compute_public_25519 (const uint8_t *kd, uint8_t *pubkey) -{ - eddsa_public_key_25519 ((bn256 *)pubkey, (const bn256 *)kd); -} - - -#if 0 -/** - * check if P is on the curve. - * - * Return -1 on error. - * Return 0 on success. - */ -static int -point_is_on_the_curve (const ac *P) -{ - bn256 s[1], t[1]; - - /* Twisted Edwards curve: a*x^2 + y^2 = 1 + d*x^2*y^2 */ -} - -int -compute_kP_25519 (ac *X, const bn256 *K, const ac *P); -#endif - -#ifdef PRINT_OUT_TABLE -static const ptc G[1] = {{ - {{{ 0x8f25d51a, 0xc9562d60, 0x9525a7b2, 0x692cc760, - 0xfdd6dc5c, 0xc0a4e231, 0xcd6e53fe, 0x216936d3 }}}, - {{{ 0x66666658, 0x66666666, 0x66666666, 0x66666666, - 0x66666666, 0x66666666, 0x66666666, 0x66666666 }}}, - {{{ 1, 0, 0, 0, 0, 0, 0, 0 }}}, -}}; - -#include - -#ifdef TESTING_EDDSA -static void -print_bn256 (const bn256 *X) -{ - int i; - - for (i = 7; i >= 0; i--) - printf ("%08x", X->word[i]); - puts (""); -} -#endif - -#if 0 -static void -print_point (const ac *X) -{ - int i; - -#ifdef PRINT_OUT_TABLE_AS_C - fputs (" { {{{ ", stdout); - for (i = 0; i < 4; i++) - printf ("0x%08x, ", X->x->word[i]); - fputs ("\n ", stdout); - for (; i < 7; i++) - printf ("0x%08x, ", X->x->word[i]); - printf ("0x%08x }}},\n", X->x->word[i]); - fputs (" {{{ ", stdout); - for (i = 0; i < 4; i++) - printf ("0x%08x, ", X->y->word[i]); - fputs ("\n ", stdout); - for (; i < 7; i++) - printf ("0x%08x, ", X->y->word[i]); - printf ("0x%08x }}} },\n", X->y->word[i]); -#else - puts ("--"); - for (i = 7; i >= 0; i--) - printf ("%08x", X->x->word[i]); - puts (""); - for (i = 7; i >= 0; i--) - printf ("%08x", X->y->word[i]); - puts (""); - puts ("--"); -#endif -} - -static void -print_point_ptc (const ptc *X) -{ - int i; - - puts ("---"); - for (i = 7; i >= 0; i--) - printf ("%08x", X->x->word[i]); - puts (""); - for (i = 7; i >= 0; i--) - printf ("%08x", X->y->word[i]); - puts (""); - for (i = 7; i >= 0; i--) - printf ("%08x", X->z->word[i]); - puts (""); - puts ("---"); -} -#endif - - -#ifndef TESTING_EDDSA -static void power_2 (ac *A, ptc *a, int N) -{ - int i; - - for (i = 0; i < N; i++) - ed_double_25638 (a, a); - ptc_to_ac_25519 (A, a); -} - -static void print_table (ac *a0001, ac *a0010, ac *a0100, ac *a1000) -{ - int i; - ptc a[1]; - ac x[1]; - - for (i = 1; i < 16; i++) - { - /* A := Identity Element */ - memset (a, 0, sizeof (ptc)); - a->y->word[0] = 1; - a->z->word[0] = 1; - - if ((i & 1)) - ed_add_25638 (a, a, a0001); - if ((i & 2)) - ed_add_25638 (a, a, a0010); - if ((i & 4)) - ed_add_25638 (a, a, a0100); - if ((i & 8)) - ed_add_25638 (a, a, a1000); - - ptc_to_ac_25519 (x, a); - print_point (x); - } - - fputs ("\n", stdout); -} - -static void compute_and_print_table (ac *a0001, ac *a0010, ac *a0100, ac *a1000) -{ - ptc a[1]; - - memcpy (a, a0001, sizeof (ac)); - memset (a->z, 0, sizeof (bn256)); - a->z->word[0] = 1; - power_2 (a0010, a, 63); - power_2 (a0100, a, 63); - power_2 (a1000, a, 63); - print_table (a0001, a0010, a0100, a1000); -} -#endif - -int -main (int argc, char *argv[]) -{ -#ifdef TESTING_EDDSA - uint8_t hash[64]; - bn256 a[1]; - uint8_t r_s[64]; - bn256 pk[1]; - bn256 *r, *s; - - const bn256 sk[1] = { - {{ 0x9db1619d, 0x605afdef, 0xf44a84ba, 0xc42cec92, - 0x69c54944, 0x1969327b, 0x03ac3b70, 0x607fae1c }} }; - - const bn256 r_expected[1] = { - {{ 0x004356e5, 0x72ac60c3, 0xcce28690, 0x8a826e80, - 0x1e7f8784, 0x74d9e5b8, 0x65e073d8, 0x55014922 }} }; - - const bn256 s_expected[1] = { - {{ 0x1582b85f, 0xac3ba390, 0x70391ec6, 0x6bb4f91c, - 0xf0f55bd2, 0x24be5b59, 0x43415165, 0x0b107a8e }} }; - - r = (bn256 *)r_s; - s = (bn256 *)(r_s+32); - - sha512 ((uint8_t *)sk, sizeof (bn256), hash); - hash[0] &= 248; - hash[31] &= 127; - hash[31] |= 64; - memcpy (a, hash, sizeof (bn256)); - - eddsa_public_key_25519 (pk, a); - eddsa_sign_25519 ((const uint8_t *)"", 0, r_s, a, hash+32, pk); - - if (memcmp (r, r_expected, sizeof (bn256)) != 0 - || memcmp (s, s_expected, sizeof (bn256)) != 0) - { - print_bn256 (r); - print_bn256 (s); - return 1; - } -#else - ac a0001[1], a0010[1], a0100[1], a1000[1]; - ptc a[1]; - - memcpy (a, G, sizeof (ptc)); - ptc_to_ac_25519 (a0001, a); - compute_and_print_table (a0001, a0010, a0100, a1000); - - memcpy (a, a0001, sizeof (ac)); - memset (a->z, 0, sizeof (bn256)); - a->z->word[0] = 1; - power_2 (a0001, a, 21); - compute_and_print_table (a0001, a0010, a0100, a1000); - - memcpy (a, a0001, sizeof (ac)); - memset (a->z, 0, sizeof (bn256)); - a->z->word[0] = 1; - power_2 (a0001, a, 21); - compute_and_print_table (a0001, a0010, a0100, a1000); -#endif - - return 0; -} -#endif diff --git a/src/openpgp/ecc-ed448.c b/src/openpgp/ecc-ed448.c deleted file mode 100644 index 70141c4..0000000 --- a/src/openpgp/ecc-ed448.c +++ /dev/null @@ -1,824 +0,0 @@ -/* -*- coding: utf-8 -*- - * ecc-ed448.c - Elliptic curve computation for - * the twisted Edwards curve: -x^2 + y^2 = 1 + d*x^2*y^2 - * d = -39081 - * - * Copyright (C) 2021 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -/* - * IMPLEMENTATION NOTE - * - * (0) We assume that the processor has no cache, nor branch target - * prediction. Thus, we don't avoid indexing by secret value. - * We don't avoid conditional jump if both cases have same timing, - * either. - * - * (1) We use fixed base comb multiplication. Scalar is 448-bit. - * We use two tables, and a table has 16 points. - * Window size W = 4-bit, E = 56. - * - */ - -#include -#include - -#include "p448.h" -#include "shake256.h" - - -#define C_WORDS 7 -#define BN448_WORDS 14 -#define BN690_WORDS 22 -#define BN896_WORDS 28 -#define BN912_WORDS 29 /* 28.5 */ - -typedef struct bn448 { - uint32_t word[ BN448_WORDS ]; /* Little endian */ -} bn448; - -typedef struct bn896 { - uint32_t word[ BN896_WORDS ]; /* Little endian */ -} bn896; - -typedef struct bn912 { - uint32_t word[ BN912_WORDS ]; /* Little endian */ -} bn912; - -static const bn448 M[1] = {{{ - 0xab5844f3, 0x2378c292, 0x8dc58f55, 0x216cc272, - 0xaed63690, 0xc44edb49, 0x7cca23e9, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x3fffffff -}}}; - -static const uint32_t C[C_WORDS] = { - 0x54a7bb0d, 0xdc873d6d, 0x723a70aa, 0xde933d8d, - 0x5129c96f, 0x3bb124b6, 0x8335dc16 -}; - - -static uint32_t -bn448_add (bn448 *X, const bn448 *A, const bn448 *B) -{ - int i; - uint32_t v; - uint32_t carry = 0; - uint32_t *px; - const uint32_t *pa, *pb; - - px = X->word; - pa = A->word; - pb = B->word; - - for (i = 0; i < BN448_WORDS; i++) - { - v = *pb; - *px = *pa + carry; - carry = (*px < carry); - *px += v; - carry += (*px < v); - px++; - pa++; - pb++; - } - - return carry; -} - -static uint32_t -bn448_sub (bn448 *X, const bn448 *A, const bn448 *B) -{ - int i; - uint32_t v; - uint32_t borrow = 0; - uint32_t *px; - const uint32_t *pa, *pb; - - px = X->word; - pa = A->word; - pb = B->word; - - for (i = 0; i < BN448_WORDS; i++) - { - uint32_t borrow0 = (*pa < borrow); - - v = *pb; - *px = *pa - borrow; - borrow = (*px < v) + borrow0; - *px -= v; - px++; - pa++; - pb++; - } - - return borrow; -} - - -static void -bnX_mul_C (uint32_t *r, const uint32_t *q, int q_size) -{ - int i, j, k; - int i_beg, i_end; - uint32_t r0, r1, r2; - - r0 = r1 = r2 = 0; - for (k = 0; k <= q_size + C_WORDS - 2; k++) - { - if (q_size < C_WORDS) - if (k < q_size) - { - i_beg = 0; - i_end = k; - } - else - { - i_beg = k - q_size + 1; - i_end = k; - if (i_end > C_WORDS - 1) - i_end = C_WORDS - 1; - } - else - if (k < C_WORDS) - { - i_beg = 0; - i_end = k; - } - else - { - i_beg = k - C_WORDS + 1; - i_end = k; - if (i_end > q_size - 1) - i_end = q_size - 1; - } - - for (i = i_beg; i <= i_end; i++) - { - uint64_t uv; - uint32_t u, v; - uint32_t carry; - - j = k - i; - if (q_size < C_WORDS) - uv = ((uint64_t)q[j])*((uint64_t)C[i]); - else - uv = ((uint64_t)q[i])*((uint64_t)C[j]); - v = uv; - u = (uv >> 32); - r0 += v; - carry = (r0 < v); - r1 += carry; - carry = (r1 < carry); - r1 += u; - carry += (r1 < u); - r2 += carry; - } - - r[k] = r0; - r0 = r1; - r1 = r2; - r2 = 0; - } - - r[k] = r0; -} - -/* X <= X + A when COND!=0 */ -/* X <= X when COND==0 */ -static void -bn448_add_cond (bn448 *X, const bn448 *A, int cond) -{ - int i; - uint32_t v; - uint32_t carry = 0; - uint32_t *px; - const uint32_t *pa; - uint32_t mask = -(!!cond); - - px = X->word; - pa = A->word; - - for (i = 0; i < BN448_WORDS; i++) - { - v = *px; - *px = (*pa & mask) + carry; - carry = (*px < carry); - *px += v; - carry += (*px < v); - px++; - pa++; - } -} - - -/* X <= X + A mod M */ -static void -bn448_addm (bn448 *X, const bn448 *A) -{ - uint32_t borrow; - - bn448_add (X, X, A); - borrow = bn448_sub (X, X, M); - bn448_add_cond (X, M, borrow); -} - -/** - * @brief R = A mod M (using M=2^446-C) (Barret reduction) - * - * See HAC 14.47. - */ -void -mod_reduce_M (bn448 *R, const bn912 *A) -{ - uint32_t q[BN448_WORDS+1]; - uint32_t tmp[BN690_WORDS]; - bn448 r[1]; - uint32_t carry, next_carry; - int i; - - /* Q = A / 2^446 *//* 466-bit */ - /* Upper half of A->word[28] must be zero. */ - q[14] = (A->word[28] << 2) | (A->word[27] >> 30); - carry = A->word[27] & 0x3fffffff; - for (i = BN448_WORDS - 1; i >= 0; i--) - { - next_carry = A->word[i+13] & 0x3fffffff; - q[i] = (A->word[i+13] >> 30) | (carry << 2); - carry = next_carry; - } - memcpy (R, A, sizeof (bn448)); - R->word[13] &= 0x3fffffff; - - /* Q_size: 15 *//* 466-bit */ - bnX_mul_C (tmp, q, 15); /* TMP = Q*C *//* 690-bit */ - /* Q = tmp / 2^446 *//* 244-bit */ - carry = tmp[21]; - for (i = 7; i >= 0; i--) - { - next_carry = tmp[i+13] & 0x3fffffff; - q[i] = (tmp[i+13] >> 30) | (carry << 2); - carry = next_carry; - } - /* R' = tmp % 2^446 */ - memcpy (r, tmp, sizeof (bn448)); - r->word[13] &= 0x3fffffff; - /* R += R' */ - bn448_addm (R, r); - - /* Q_size: 8 *//* 244-bit */ - bnX_mul_C (tmp, q, 8); /* TMP = Q*C *//* 468-bit */ - /* Q = tmp / 2^446 *//* 22-bit */ - carry = tmp[14]; - q[0] = (tmp[13] >> 30) | (carry << 2); - /* R' = tmp % 2^446 */ - memcpy (r, tmp, sizeof (bn448)); - r->word[13] &= 0x3fffffff; - /* R += R' */ - bn448_addm (R, r); - - /* Q_size: 1 */ - bnX_mul_C (tmp, q, 1); /* TMP = Q*C *//* 246-bit */ - /* R' = tmp % 2^446 */ - memset (((uint8_t *)r)+(sizeof (uint32_t)*8), 0, sizeof (uint32_t)*6); - memcpy (r, tmp, sizeof (uint32_t)*8); - /* R += R' */ - bn448_addm (R, r); -} - - -static void -bn448_mul (bn896 *X, const bn448 *A, const bn448 *B) -{ - int i, j, k; - int i_beg, i_end; - uint32_t r0, r1, r2; - - r0 = r1 = r2 = 0; - for (k = 0; k <= (BN448_WORDS - 1)*2; k++) - { - if (k < BN448_WORDS) - { - i_beg = 0; - i_end = k; - } - else - { - i_beg = k - BN448_WORDS + 1; - i_end = BN448_WORDS - 1; - } - - for (i = i_beg; i <= i_end; i++) - { - uint64_t uv; - uint32_t u, v; - uint32_t carry; - - j = k - i; - - uv = ((uint64_t )A->word[i])*((uint64_t )B->word[j]); - v = uv; - u = (uv >> 32); - r0 += v; - carry = (r0 < v); - r1 += carry; - carry = (r1 < carry); - r1 += u; - carry += (r1 < u); - r2 += carry; - } - - X->word[k] = r0; - r0 = r1; - r1 = r2; - r2 = 0; - } - - X->word[k] = r0; -} - -static const p448_t nGx0[16] = { - { { 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { { 0x070cc05e, 0x026a82bc, 0x00938e26, 0x080e18b0, - 0x0511433b, 0x0f72ab66, 0x0412ae1a, 0x0a3d3a46, - 0x0a6de324, 0x00f1767e, 0x04657047, 0x036da9e1, - 0x05a622bf, 0x0ed221d1, 0x066bed0d, 0x04f1970c } }, - { { 0x0464238e, 0x00079817, 0x00d381ca, 0x02110302, - 0x0d9f01b5, 0x01cc4c6e, 0x05a131b1, 0x05e35dc5, - 0x006944eb, 0x0b61848d, 0x029631a3, 0x083792a0, - 0x0afca0dd, 0x0be1017f, 0x0782fcbb, 0x070aaa01 } }, - { { 0x0e7661f9, 0x0b2f9f62, 0x009fae89, 0x03b99803, - 0x066014d2, 0x067900ef, 0x06556c10, 0x0c8eacf3, - 0x0ad4a82e, 0x020a44d0, 0x00572f1c, 0x0e7819e7, - 0x0fd08cdf, 0x0c0ed140, 0x09aee1da, 0x0a16934a } }, - { { 0x091780c7, 0x0a7ea989, 0x0d2476b6, 0x004e4ecc, - 0x0c494b68, 0x00af9f58, 0x0dee64fd, 0x0e0f269f, - 0x0021bd26, 0x085a61f6, 0x0b5d284b, 0x0c265c35, - 0x03775afd, 0x058755ea, 0x02ecf2c6, 0x0617f174 } }, - { { 0x067f4947, 0x0dbf4eb6, 0x0b8716d9, 0x02206a2a, - 0x0e7cad5a, 0x04a148b0, 0x0e483133, 0x0fbf12cd, - 0x0c6458f7, 0x0e022d5a, 0x01b7e39d, 0x0a60afe6, - 0x05a5208c, 0x0c62f458, 0x03311553, 0x0a08a4c3 } }, - { { 0x0054a90d, 0x0ad5dc54, 0x00ac9fd6, 0x097f2af4, - 0x0f4ddbc7, 0x01b0f7b3, 0x0324ce0b, 0x01d5d092, - 0x0cd2798f, 0x08cb96e2, 0x0957bc39, 0x0bd045b5, - 0x0f76fbfb, 0x046308a9, 0x0ef679ce, 0x0c86d628 } }, - { { 0x0d5d9262, 0x0f251539, 0x0711a956, 0x0240708f, - 0x04a0b0bc, 0x07f7e4dd, 0x055b70a8, 0x065dd24f, - 0x07ef8979, 0x0e83cec7, 0x09589db8, 0x0f1db2d1, - 0x09d93037, 0x0fcc7e8a, 0x04e0b8f4, 0x0cb99f0b } }, - { { 0x04acea57, 0x06f24100, 0x0da68597, 0x0dace1c6, - 0x050ce77f, 0x0ea7dd41, 0x01585884, 0x01aecb84, - 0x0ea4a85c, 0x092ff208, 0x088eebd2, 0x0de9433c, - 0x03f4d289, 0x053cd318, 0x026539af, 0x03970858 } }, - { { 0x0d229665, 0x06e9fd2b, 0x0878dd51, 0x049345aa, - 0x0f45bacf, 0x0ccde72a, 0x0be16b6f, 0x0bc249d1, - 0x0448a61d, 0x0a25bae9, 0x0d773878, 0x0c93b6ea, - 0x02cda508, 0x055f708a, 0x08cf49e6, 0x0fa56852 } }, - { { 0x093bfef9, 0x07bec8db, 0x0fafda3d, 0x0ce4dcdc, - 0x06f62ed7, 0x0a75c872, 0x07b3dadd, 0x0c39ac92, - 0x0f926d90, 0x0ae1b8d1, 0x048da0a9, 0x0d7dbeca, - 0x02a52b3b, 0x0ec13f74, 0x0d4c5ce2, 0x02071cee } }, - { { 0x05a644a6, 0x0e56b0a9, 0x0be6360b, 0x01ecf90e, - 0x023b73a8, 0x0c3bbcf7, 0x0292054b, 0x05417d25, - 0x07b91b46, 0x0ca1ea05, 0x07ea6c44, 0x01560b21, - 0x04f12989, 0x0463cd2a, 0x03d7e086, 0x0092781c } }, - { { 0x0d59796d, 0x0ce08d7e, 0x055bc822, 0x0e464443, - 0x0d243cc4, 0x0542002f, 0x098259b3, 0x044fc576, - 0x012781de, 0x08650550, 0x0055e6b4, 0x0137f762, - 0x0fbf007e, 0x0a391ccc, 0x039fe6f6, 0x0a9c9ad3 } }, - { { 0x01ca2765, 0x0ccddbb0, 0x0563b46c, 0x05d18f4c, - 0x0462647e, 0x02ff700d, 0x0822dc83, 0x0670b143, - 0x00013963, 0x01627d78, 0x055dbfb9, 0x0435f413, - 0x063d41e8, 0x066c95cd, 0x0c797bba, 0x08e27dfb } }, - { { 0x03da4531, 0x01ff4dd6, 0x0cd39a3c, 0x02d0de4c, - 0x0bc9da8d, 0x0003561e, 0x033e1e9a, 0x001eea00, - 0x078bf710, 0x05458c53, 0x0f56338e, 0x069043ab, - 0x061ffba0, 0x0637cf41, 0x039fb551, 0x0fc09757 } }, - { { 0x0256141f, 0x0f1e0e38, 0x00ab2673, 0x0efd5f47, - 0x0af4a4af, 0x0b749116, 0x0ac6540b, 0x04242f82, - 0x0abaf195, 0x0b26730c, 0x0d06842d, 0x076fbe60, - 0x0580cad8, 0x02613d91, 0x0b568ae0, 0x0c2e5b1d } } -}; - -static const p448_t nGy0[16] = { - { { 0x00000001, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { { 0x0230fa14, 0x008795bf, 0x07c8ad98, 0x0132c4ed, - 0x09c4fdbd, 0x01ce67c3, 0x073ad3ff, 0x005a0c2d, - 0x07789c1e, 0x0a398408, 0x0a73736c, 0x0c7624be, - 0x003756c9, 0x02488762, 0x016eb6bc, 0x0693f467 } }, - { { 0x099945e7, 0x0c63b7a0, 0x0c4486c1, 0x0e9164ec, - 0x0885f2c1, 0x0b133e35, 0x0c99ae02, 0x0186f0d3, - 0x02bf53e6, 0x02fca492, 0x048a02bc, 0x0f922aa2, - 0x00dd3dca, 0x04fe6490, 0x0f6a8207, 0x0e8c313f } }, - { { 0x0579a4e2, 0x0a1ffe8b, 0x0ce472b4, 0x01d006b3, - 0x089def96, 0x07c8f689, 0x0a32ae93, 0x079d7bd1, - 0x03a02760, 0x0ebb4776, 0x05b4c55e, 0x019b3c6c, - 0x07da436f, 0x066ff782, 0x0659536d, 0x0ee40076 } }, - { { 0x05ec556a, 0x050109e2, 0x0fd57e39, 0x0235366b, - 0x044b6b2e, 0x07b3c976, 0x0b2b7b9c, 0x0f7f9e82, - 0x00ec6409, 0x0b6196ab, 0x00a20d9e, 0x088f1d16, - 0x0586f761, 0x0e3be3b4, 0x0e26395d, 0x09983c26 } }, - { { 0x0fab8e56, 0x0ded288e, 0x057277e6, 0x0a4e6f4e, - 0x0e949681, 0x0a2a4c4f, 0x0721fdb3, 0x0508a46c, - 0x0fb44de2, 0x0f98049e, 0x02fb0f31, 0x071f3724, - 0x09067763, 0x0d3fbbb3, 0x0a83faaa, 0x0696ec4a } }, - { { 0x07a04bb0, 0x0f52ae70, 0x0ae14cdb, 0x0784d14b, - 0x034acc37, 0x09aa3869, 0x09703f7b, 0x08f79c87, - 0x0264026c, 0x0859cde5, 0x0486b035, 0x0b2a45f7, - 0x03d5144b, 0x0809740f, 0x0416dc87, 0x0dcf324d } }, - { { 0x0a0c8bc7, 0x04125cec, 0x0eac3f20, 0x0d30ff7e, - 0x029ad678, 0x06901f05, 0x04805ff1, 0x033c307d, - 0x049d6a79, 0x080f0710, 0x02dece6c, 0x0d1ba22b, - 0x0778cccb, 0x01692a0b, 0x02df78fb, 0x0f8c02d3 } }, - { { 0x0b827d87, 0x04b57599, 0x03d77638, 0x0dc82ac0, - 0x052f6e61, 0x06943366, 0x0ad5e8a6, 0x0b8fc4b0, - 0x0f388642, 0x01b6f7dc, 0x0a74dd57, 0x06f24533, - 0x041750cf, 0x0c669378, 0x028a37af, 0x006757eb } }, - { { 0x080128d5, 0x0ef186a8, 0x04a54843, 0x01ceb43b, - 0x045be148, 0x0c112a42, 0x01ac9412, 0x0621b93a, - 0x05e16552, 0x0a2ca24f, 0x086301c0, 0x0cf3fecf, - 0x05c2e2e0, 0x05108805, 0x09e9d8ab, 0x0d2ba341 } }, - { { 0x02138911, 0x0f0d3e4c, 0x0c1a371b, 0x062382ce, - 0x05b3a392, 0x09d954e7, 0x0517d2a1, 0x0047d71a, - 0x07f70073, 0x09cd1733, 0x0efc3aea, 0x0549d0d1, - 0x0df78457, 0x0666e074, 0x0a48e084, 0x0f67e924 } }, - { { 0x0b3114fe, 0x073bec50, 0x0e8b6172, 0x01c5e7b6, - 0x0e896bcc, 0x0a1c3ae1, 0x0bcd8cab, 0x0bb3f870, - 0x07e9fa9d, 0x0eea8546, 0x0042e2cf, 0x056431f0, - 0x0469e8d2, 0x08eb9b9c, 0x0a9adf2c, 0x06856458 } }, - { { 0x07b2cfdd, 0x01855530, 0x073bd43a, 0x01816246, - 0x08897062, 0x02f82d12, 0x03563816, 0x06517857, - 0x0394a8c7, 0x0529bf2e, 0x075a3141, 0x0660c4f2, - 0x018e5a16, 0x0787c8ad, 0x045b679e, 0x0abaec01 } }, - { { 0x06d87d9e, 0x07c9fabb, 0x03b2a99d, 0x0673b28a, - 0x068816ee, 0x0efb205e, 0x0dd5e3d5, 0x03d21920, - 0x07544f4d, 0x085f40c2, 0x06fb538d, 0x057d045b, - 0x05470e4e, 0x028a93c3, 0x063adfd4, 0x0d1cf7a5 } }, - { { 0x06699694, 0x0c83c837, 0x0386dade, 0x0621103f, - 0x0f247dc3, 0x06058f43, 0x0aec07c3, 0x0b1ac29a, - 0x0bde5d50, 0x06e35e33, 0x078fd31c, 0x0516263c, - 0x00a9d127, 0x04a13379, 0x078bec6e, 0x0f39316a } }, - { { 0x0e26ea19, 0x05ecf40e, 0x03bdf1b5, 0x07c284a0, - 0x06f461fa, 0x08393462, 0x064a69aa, 0x07d4f6a5, - 0x06e88ea4, 0x023059e9, 0x0f92bd0b, 0x0c4a8035, - 0x0c5c44a2, 0x0fccec22, 0x07f57ea1, 0x0598207c } } -}; - -static const p448_t nGx1[16] = { - { { 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { { 0x0528af6f, 0x078c6f13, 0x094b74d9, 0x00001fe2, - 0x001aab44, 0x0ae77425, 0x0ef0039c, 0x07cbe937, - 0x00fa2a67, 0x0af3e4f0, 0x0da1378e, 0x0e28175f, - 0x08ccd90e, 0x072adeed, 0x000af22f, 0x016a8ce1 } }, - { { 0x0fa0459e, 0x0f31f53f, 0x0315cd6b, 0x0f8742a1, - 0x0ae64e97, 0x0abe2f50, 0x09b9da48, 0x0bd78741, - 0x051e526e, 0x04521a33, 0x0e10ba45, 0x0fa05935, - 0x0e8f903c, 0x05c947e1, 0x05a754ee, 0x00aa47d1 } }, - { { 0x00d9a33b, 0x0284f76f, 0x0e4d41e7, 0x09461141, - 0x0cc79344, 0x015371b9, 0x03dd8bdd, 0x0173f667, - 0x053f866b, 0x0c0d0f83, 0x030b45ea, 0x08b7d59b, - 0x0044dc82, 0x02b4cdec, 0x094fa772, 0x0e245b21 } }, - { { 0x04ddc8a8, 0x02fe182d, 0x0ac056bf, 0x088d6e79, - 0x00e41e4e, 0x0c3ff2d1, 0x02c3679f, 0x032ec7f9, - 0x04e61051, 0x03561f09, 0x06c6250a, 0x04553f5a, - 0x0dd25c5b, 0x02b765ef, 0x06a1cd7f, 0x0e3a40a2 } }, - { { 0x05e1f4b2, 0x0e9485c4, 0x070a1e6b, 0x01d85e53, - 0x077730a7, 0x0db61fa9, 0x050d418e, 0x0201a6bd, - 0x02774433, 0x0e78a475, 0x0622ea3a, 0x016424e5, - 0x0d5b9631, 0x01c7734d, 0x0f5064f2, 0x0c7586d3 } }, - { { 0x0af6151d, 0x0c3ed603, 0x0aa19b93, 0x05a5e4a6, - 0x0536ff03, 0x07e465ce, 0x0b0be710, 0x0bbb36bf, - 0x09249bff, 0x0d15454d, 0x03736654, 0x0ba934d9, - 0x0370dc86, 0x0675c04e, 0x0d86eb3b, 0x06cd21cb } }, - { { 0x030c7ce7, 0x04217221, 0x0e9dba4d, 0x0ec314cd, - 0x05439062, 0x0d7196cd, 0x0dd96166, 0x0b8295cd, - 0x0c15796f, 0x0c767da7, 0x00ab2036, 0x059120e7, - 0x0b7d07ec, 0x0e1562a9, 0x0231cdd9, 0x07d5c89f } }, - { { 0x01a82a12, 0x091a5884, 0x080f3a62, 0x0a754175, - 0x0f73417a, 0x0399009f, 0x00a8c5cd, 0x02db1fb9, - 0x0c046d51, 0x082c8912, 0x08f18274, 0x00a3f577, - 0x026ccae2, 0x02ad0ede, 0x08a4e9c2, 0x07d6bd8b } }, - { { 0x0afd28b4, 0x02b7b7be, 0x0298d67e, 0x0e834401, - 0x04b11493, 0x0e070d60, 0x063ce6fb, 0x04b67725, - 0x0a0cfb04, 0x0d3a0f67, 0x0f08f1b2, 0x0debe82e, - 0x0b402b9e, 0x07114482, 0x0b307043, 0x0af532e6 } }, - { { 0x049ab457, 0x0f6483c2, 0x0818ac81, 0x05aced0a, - 0x0a900e3a, 0x080916bc, 0x02948675, 0x0145adb9, - 0x0d8b7821, 0x04fe2b0e, 0x0b1a62cc, 0x0a9e1bce, - 0x096c2408, 0x048f1f80, 0x0ac552fe, 0x0d17e7a0 } }, - { { 0x08ce3344, 0x0ea48915, 0x0434ae70, 0x0c6cf019, - 0x0c48f5d2, 0x089d3c0f, 0x0ca7aa7e, 0x0c550a00, - 0x017fb3ab, 0x09f8b49f, 0x024844a0, 0x0366a6d5, - 0x0ceb4a83, 0x0f1f5bf4, 0x03b782f0, 0x099fd2f7 } }, - { { 0x052daf76, 0x038fbbd7, 0x0bced01d, 0x0ffb0a8b, - 0x07c6bd6c, 0x0dc3b0ff, 0x041d595c, 0x03814ee7, - 0x01941d44, 0x0e1f8343, 0x0f89b18d, 0x0c083601, - 0x0e52ec62, 0x0fc338ff, 0x0e971788, 0x04601008 } }, - { { 0x0add862e, 0x0e8c3a8e, 0x033cea23, 0x06d00cf1, - 0x0cdc039a, 0x0d7bda40, 0x0e0a2ac3, 0x04750dcb, - 0x0bec4388, 0x0a1bb0bc, 0x0d20c0f9, 0x077a4a7b, - 0x0b9e1f0b, 0x02ff072d, 0x07bd3e06, 0x0bd796d7 } }, - { { 0x08e321b4, 0x08757de1, 0x0151699c, 0x06ba6bd4, - 0x0a156df0, 0x02ec93a1, 0x0dad4f9e, 0x04e547c5, - 0x0ee9310d, 0x01dcc8bf, 0x0f7b5016, 0x0355f710, - 0x0ce8f36d, 0x0389d7a9, 0x02b8056d, 0x0ff83804 } }, - { { 0x060f6dcf, 0x0dcaa234, 0x0285b23d, 0x0ec8d56f, - 0x083dac2b, 0x01042255, 0x08e1bed7, 0x0c3fe788, - 0x0832c0af, 0x07258b0e, 0x02b2affc, 0x0a901bdb, - 0x0038f36e, 0x01a28d5f, 0x0dbb618d, 0x080838af } } -}; - -static const p448_t nGy1[16] = { - { { 0x00000001, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { { 0x0cbf63dd, 0x069fae17, 0x09e39e26, 0x06786172, - 0x0f827a18, 0x0e92b3d5, 0x08403682, 0x04d75e41, - 0x09056a79, 0x001a4fd9, 0x020008f5, 0x089efb2d, - 0x0b78ff15, 0x0a2f6918, 0x0a3437f5, 0x0f41c870 } }, - { { 0x0d814825, 0x0b2849ef, 0x05c9968d, 0x09c2a5d2, - 0x004e634c, 0x024dbb26, 0x0db38194, 0x033f3a4c, - 0x0c8a2b6b, 0x0e04f609, 0x0abbbfdb, 0x0caefd8e, - 0x0404498b, 0x0683119a, 0x08b21cbd, 0x024ab7a9 } }, - { { 0x0ede77b3, 0x0043b728, 0x0a043f1d, 0x003cf736, - 0x0ab4e700, 0x0d95a612, 0x0c8fe17c, 0x05ccaac2, - 0x0177bd28, 0x0dc3bd14, 0x05360c86, 0x0b3d5c96, - 0x04ec7e48, 0x01880c26, 0x04bb47c6, 0x0fd5dba8 } }, - { { 0x05d821dd, 0x0b27309b, 0x0c2c17ca, 0x0950fb8d, - 0x08fb0d4c, 0x0feed015, 0x0f550179, 0x0762c479, - 0x0e095840, 0x0306cf44, 0x0d379e66, 0x084b413a, - 0x0bb2e4f1, 0x0d6e5d5a, 0x094b085d, 0x08bc12b7 } }, - { { 0x0b8a16f6, 0x0b4dacd9, 0x003afc96, 0x0000b9b9, - 0x03f19cbf, 0x0ab930b8, 0x0b077171, 0x0541f92e, - 0x019baa42, 0x08758d9c, 0x0fea31a2, 0x0299b935, - 0x081d9e24, 0x03bc7232, 0x09d91676, 0x0fc081c2 } }, - { { 0x02f05282, 0x04ca6fb6, 0x02e9801e, 0x051928b6, - 0x0b609dcb, 0x0c6f37b6, 0x06e32803, 0x06617fd7, - 0x0166f0bb, 0x07d1bffb, 0x0ac137d4, 0x0bfdebdd, - 0x0df8f3cb, 0x0d558ac9, 0x08fabbb4, 0x00217c7c } }, - { { 0x0f5d72ad, 0x04c71050, 0x008880dd, 0x093209a0, - 0x07c3fef0, 0x0e1857c5, 0x022b21d2, 0x07584709, - 0x0e52fe8a, 0x039aeffa, 0x0a384e66, 0x0bd7c58b, - 0x0bfbbfe2, 0x022fc035, 0x0506e447, 0x0bc96411 } }, - { { 0x04b3de44, 0x0aa0d797, 0x096ac9bb, 0x0f8658b9, - 0x05f6c334, 0x031e7be2, 0x04df12c9, 0x023836ce, - 0x059eb5c9, 0x0029027b, 0x05b8649d, 0x02f22531, - 0x0d907162, 0x0a0fdf03, 0x09e80226, 0x0101d9df } }, - { { 0x05237b19, 0x00d0c997, 0x04a2bcdb, 0x0692bae3, - 0x0805b9e0, 0x0a0d3a98, 0x08c7dd07, 0x0a253f11, - 0x0e19738e, 0x0c0794d0, 0x019812a1, 0x041a8569, - 0x025d360c, 0x078e4ebd, 0x07ee8567, 0x0f02e9d6 } }, - { { 0x00548584, 0x0bb1ee61, 0x0549030f, 0x0026e17a, - 0x0b4c52fb, 0x0a4e4e61, 0x0a1ca8f9, 0x0339754c, - 0x0ee8806f, 0x03d2a45e, 0x0e2028fa, 0x03c44782, - 0x0072e42b, 0x03328ae4, 0x0d21c91f, 0x07e98738 } }, - { { 0x0b9618ad, 0x07f781fa, 0x09cf7662, 0x0855bfab, - 0x0c316a14, 0x0d98f9ff, 0x07b3046a, 0x0109f273, - 0x042cecfe, 0x0cc21cdc, 0x05be5a36, 0x05236b10, - 0x058a0700, 0x0ff2cf95, 0x005ad57d, 0x09cbf152 } }, - { { 0x0ebe90d2, 0x049f0de4, 0x02243779, 0x0221424d, - 0x09051808, 0x0b52f44b, 0x0bb9c3fb, 0x0a5d64e3, - 0x07690354, 0x0d8bf65d, 0x0bc06e3f, 0x05d039f6, - 0x033a3443, 0x04e11c79, 0x04147a83, 0x06a7e42c } }, - { { 0x082e4773, 0x00d276be, 0x0e1b9057, 0x0e9dd324, - 0x0369bc97, 0x0b3181ef, 0x002f04fa, 0x01d08726, - 0x07c2c5d3, 0x0bf49cbf, 0x09ecb59b, 0x098eae7e, - 0x02e09293, 0x052e08b6, 0x0c40f3e6, 0x04096c37 } }, - { { 0x06074e1f, 0x07bc94ed, 0x0790175a, 0x040b2a81, - 0x0e307782, 0x0b7958e8, 0x089ff273, 0x07ed27c6, - 0x026db869, 0x0b6a32f8, 0x03d2e15c, 0x00446ef9, - 0x0777e1ac, 0x0492d2de, 0x01b69b63, 0x06b8dbab } }, - { { 0x07e98bea, 0x0e7c9e7a, 0x02e17335, 0x09302c64, - 0x0acc1e93, 0x05dcdcd8, 0x04d90baa, 0x05982bae, - 0x0c686ed6, 0x07c08c6c, 0x0fce2c72, 0x04dd3cce, - 0x01dc8f12, 0x029ca465, 0x0161cbd7, 0x09324c0a } } -}; - -static void -compute_kG_448 (uint8_t *out, const uint32_t k[16]) -{ - int i; - p448_t x0[1], y0[1], z0[1]; /* P0 */ - p448_t tmp0[1], tmp1[1]; - - /* P0 <= O */ - memset (x0, 0, sizeof (p448_t)); - memset (y0, 0, sizeof (p448_t)); - memset (z0, 0, sizeof (p448_t)); - y0->limb[0] = 1; - z0->limb[0] = 1; - - for (i = 0; i < 56; i++) - { - p448_t b[1], c[1], d[1]; - p448_t e[1], f[1], g[1], h[1]; - int index0, index1; - - if (i < 28) - { - int i0 = 28 - i - 1; - - index0 = ((k[1] >> i0) & 1) | (((k[5] >> i0) & 1)<<1) - | (((k[ 9] >> i0) & 1)<<2) | (((k[13] >> i0) & 1)<<3); - index1 = ((k[3] >> i0) & 1) | (((k[7] >> i0) & 1)<<1) - | (((k[11] >> i0) & 1)<<2) | (((k[15] >> i0) & 1)<<3); - } - else - { - int i0 = 56 - i - 1; - - index0 = ((k[0] >> i0) & 1) | (((k[4] >> i0) & 1)<<1) - | (((k[ 8] >> i0) & 1)<<2) | (((k[12] >> i0) & 1)<<3); - index1 = ((k[2] >> i0) & 1) | (((k[6] >> i0) & 1)<<1) - | (((k[10] >> i0) & 1)<<2) | (((k[14] >> i0) & 1)<<3); - } - - /* Point double P0' <= P0 + P0 */ - p448_add (tmp0, x0, y0); - p448_sqr (b, tmp0); - p448_sqr (c, x0); - p448_sqr (d, y0); - p448_add (e, c, d); - p448_sqr (h, z0); - p448_add (tmp0, h, h); - p448_sub (tmp1, e, tmp0); - p448_sub (tmp0, b, e); - p448_mul (x0, tmp0, tmp1); - p448_sub (tmp0, c, d); - p448_mul (y0, e, tmp0); - p448_mul (z0, e, tmp1); - /* - B = (X1+Y1)^2 - C = X1^2 - D = Y1^2 - E = C+D - H = Z1^2 - J = E-2*H - X3 = (B-E)*J - Y3 = E*(C-D) - Z3 = E*J - */ - - /* Point addition P0' <= P0 + [v0(index0)]G */ - p448_sqr (b, z0); - p448_mul (c, x0, &nGx0[index0]); - p448_mul (d, y0, &nGy0[index0]); - p448_mul (tmp0, c, d); - p448_mul_39081 (e, tmp0); - p448_add (f, b, e); - p448_sub (g, b, e); - p448_add (tmp0, x0, y0); - p448_add (tmp1, &nGx0[index0], &nGy0[index0]); - p448_mul (h, tmp0, tmp1); - p448_sub (tmp0, h, c); - p448_sub (tmp1, tmp0, d); - p448_mul (tmp0, f, tmp1); - p448_mul (x0, z0, tmp0); - p448_sub (tmp0, d, c); - p448_mul (tmp1, g, tmp0); - p448_mul (y0, z0, tmp1); - p448_mul (z0, f, g); - /* - A = Z1*Z2 - B = A^2 - C = X1*X2 - D = Y1*Y2 - E = d*C*D - F = B-E - G = B+E - H = (X1+Y1)*(X2+Y2) - X3 = A*F*(H-C-D) - Y3 = A*G*(D-C) - Z3 = F*G - */ - /* Point addition P0' <= P0 + [v1(index1)]G */ - p448_sqr (b, z0); - p448_mul (c, x0, &nGx1[index1]); - p448_mul (d, y0, &nGy1[index1]); - p448_mul (tmp0, c, d); - p448_mul_39081 (e, tmp0); - p448_add (f, b, e); - p448_sub (g, b, e); - p448_add (tmp0, x0, y0); - p448_add (tmp1, &nGx1[index1], &nGy1[index1]); - p448_mul (h, tmp0, tmp1); - p448_sub (tmp0, h, c); - p448_sub (tmp1, tmp0, d); - p448_mul (tmp0, f, tmp1); - p448_mul (x0, z0, tmp0); - p448_sub (tmp0, d, c); - p448_mul (tmp1, g, tmp0); - p448_mul (y0, z0, tmp1); - p448_mul (z0, f, g); - } - - /* Convert to affine coordinate. */ - p448_inv (tmp0, z0); - p448_mul (tmp1, x0, tmp0); - p448_serialize (out, tmp1); - /* EdDSA encoding. */ - out[56] = (out[0] & 1) << 7; - p448_mul (tmp1, y0, tmp0); - p448_serialize (out, tmp1); -} - - -#define SEED_SIZE 57 - -#define DOM448 (const uint8_t *)"SigEd448" -#define DOM448_LEN 8 - -int -ed448_sign (uint8_t *out, const uint8_t *input, unsigned int ilen, - const uint8_t *a_in, const uint8_t *seed, const uint8_t *pk) -{ - bn448 a[1], k[1], s[1]; - shake_context ctx; - const unsigned char x_olen[2] = { 0, 0 }; - uint32_t hash[BN912_WORDS]; - uint8_t r[57]; - uint32_t carry, borrow; - p448_t k_redundant[1]; - - memset (hash, 0, sizeof (hash)); - - memcpy (a, a_in, sizeof (bn448)); - a->word[13] |= 0x80000000; - a->word[0] &= ~3; - - shake256_start (&ctx); - shake256_update (&ctx, DOM448, DOM448_LEN); - shake256_update (&ctx, x_olen, 2); - shake256_update (&ctx, seed, 57); - shake256_update (&ctx, input, ilen); - shake256_finish (&ctx, (uint8_t *)hash, 2*57); - - mod_reduce_M (k, (const bn912 *)hash); - p448_deserialize (k_redundant, (uint8_t *)k); - compute_kG_448 (r, (uint32_t *)k_redundant); - - shake256_start (&ctx); - shake256_update (&ctx, DOM448, DOM448_LEN); - shake256_update (&ctx, x_olen, 2); - shake256_update (&ctx, r, 57); - shake256_update (&ctx, pk, 57); - shake256_update (&ctx, input, ilen); - shake256_finish (&ctx, (uint8_t *)hash, 2*57); - - mod_reduce_M (s, (const bn912 *)hash); - - memset (hash, 0, sizeof (hash)); - bn448_mul ((bn896 *)hash, s, a); - mod_reduce_M (s, (const bn912 *)hash); - - carry = bn448_add (s, s, k); - borrow = bn448_sub (s, s, M); - bn448_add_cond (s, M, (borrow && !carry)); - - memcpy (out, r, 57); - memcpy (out+57, s, 56); - out[114-1] = 0; - - return 0; -} - - -void -ed448_compute_public (uint8_t *pk, const uint8_t *a_in) -{ - p448_t a[1]; - - p448_deserialize (a, a_in); - a->limb[15] |= 0x08000000; - a->limb[0] &= ~3; - - compute_kG_448 (pk, (uint32_t *)a); -} diff --git a/src/openpgp/ecc-mont.c b/src/openpgp/ecc-mont.c deleted file mode 100644 index 68bd30a..0000000 --- a/src/openpgp/ecc-mont.c +++ /dev/null @@ -1,226 +0,0 @@ -/* -*- coding: utf-8 -*- - * ecc-mont.c - Elliptic curve computation for - * the Montgomery curve: y^2 = x^3 + 486662*x^2 + x. - * - * Copyright (C) 2014, 2015, 2017 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include -#include "bn.h" -#include "mod25638.h" -#include "mod.h" - -/* - * References: - * - * [1] D. J. Bernstein. Curve25519: new Diffie-Hellman speed records. - * Proceedings of PKC 2006, to appear. - * http://cr.yp.to/papers.html#curve25519. Date: 2006.02.09. - * - * [2] D. J. Bernstein. Can we avoid tests for zero in fast - * elliptic-curve arithmetic? - * http://cr.yp.to/papers.html#curvezero. Date: 2006.07.26. - * - */ - -/* - * IMPLEMENTATION NOTE - * - * (0) We assume that the processor has no cache, nor branch target - * prediction. Thus, we don't avoid indexing by secret value. - * We don't avoid conditional jump if both cases have same timing, - * either. - * - * (1) We use Radix-32 field arithmetic. It's a representation like - * 2^256-38, but it's more redundant. For example, "1" can be - * represented in three ways in 256-bit: 1, 2^255-18, and - * 2^256-37. - * - * (2) We use Montgomery double-and-add. - * - */ - -#ifndef BN256_C_IMPLEMENTATION -#define ASM_IMPLEMENTATION 0 -#endif -/* - * - * 121665 = 0x1db41 - * 1 1101 1011 0100 0001 - */ -static void -mod25638_mul_121665 (bn256 *x, const bn256 *a) -{ -#if ASM_IMPLEMENTATION -#include "muladd_256.h" - const uint32_t *s; - uint32_t *d; - uint32_t w; - uint32_t c; - - s = a->word; - d = x->word; - memset (d, 0, sizeof (bn256)); - w = 121665; - MULADD_256_ASM (s, d, w, c); -#else - uint32_t c, c1; - bn256 m[1]; - - c = c1 = bn256_shift (m, a, 6); c += bn256_add (x, a, m); - c1 <<= 2; c1 |= bn256_shift (m, m, 2); c = c + c1 + bn256_add (x, x, m); - c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m); - c1 <<= 2; c1 |= bn256_shift (m, m, 2); c = c + c1 + bn256_add (x, x, m); - c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m); - c1 <<= 2; c1 |= bn256_shift (m, m, 2); c = c + c1 + bn256_add (x, x, m); - c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m); - c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m); -#endif - c = bn256_add_uint (x, x, c*38); - x->word[0] += c * 38; -} - - -typedef struct -{ - bn256 x[1]; - bn256 z[1]; -} pt; - - -/** - * @brief Process Montgomery double-and-add - * - * With Q0, Q1, DIF (= Q0 - Q1), compute PRD = 2Q0, SUM = Q0 + Q1 - * Q0 and Q1 are clobbered. - * - */ -static void -mont_d_and_a (pt *prd, pt *sum, pt *q0, pt *q1, const bn256 *dif_x) -{ - mod25638_add (sum->x, q1->x, q1->z); - mod25638_sub (q1->z, q1->x, q1->z); - mod25638_add (prd->x, q0->x, q0->z); - mod25638_sub (q0->z, q0->x, q0->z); - mod25638_mul (q1->x, q0->z, sum->x); - mod25638_mul (q1->z, prd->x, q1->z); - mod25638_sqr (q0->x, prd->x); - mod25638_sqr (q0->z, q0->z); - mod25638_add (sum->x, q1->x, q1->z); - mod25638_sub (q1->z, q1->x, q1->z); - mod25638_mul (prd->x, q0->x, q0->z); - mod25638_sub (q0->z, q0->x, q0->z); - mod25638_sqr (sum->x, sum->x); - mod25638_sqr (sum->z, q1->z); - mod25638_mul_121665 (prd->z, q0->z); - mod25638_mul (sum->z, sum->z, dif_x); - mod25638_add (prd->z, q0->x, prd->z); - mod25638_mul (prd->z, prd->z, q0->z); -} - - -/** - * @brief RES = x-coordinate of [n]Q - * - * @param N Scalar N (three least significant bits are 000) - * @param Q_X x-coordinate of Q - * - */ -static void -compute_nQ (bn256 *res, const bn256 *n, const bn256 *q_x) -{ - int i, j; - pt p0[1], p1[1], p0_[1], p1_[1]; - - /* P0 = O = (1:0) */ - memset (p0->x, 0, sizeof (bn256)); - p0->x->word[0] = 1; - memset (p0->z, 0, sizeof (bn256)); - - /* P1 = (X:1) */ - memcpy (p1->x, q_x, sizeof (bn256)); - memset (p1->z, 0, sizeof (bn256)); - p1->z->word[0] = 1; - - for (i = 0; i < 8; i++) - { - uint32_t u = n->word[7-i]; - - for (j = 0; j < 16; j++) - { - pt *q0, *q1; - pt *sum_n, *prd_n; - - if ((u & 0x80000000)) - q0 = p1, q1 = p0, sum_n = p0_, prd_n = p1_; - else - q0 = p0, q1 = p1, sum_n = p1_, prd_n = p0_; - mont_d_and_a (prd_n, sum_n, q0, q1, q_x); - - if ((u & 0x40000000)) - q0 = p1_, q1 = p0_, sum_n = p0, prd_n = p1; - else - q0 = p0_, q1 = p1_, sum_n = p1, prd_n = p0; - mont_d_and_a (prd_n, sum_n, q0, q1, q_x); - - u <<= 2; - } - } - - /* We know the LSB of N is always 0. Thus, result is always in P0. */ - /* - * p0->z may be zero here, but our mod_inv doesn't raise error for 0, - * but returns 0 (like the implementation of z^(p-2)), thus, RES will - * be 0 in that case, which is correct value. - */ - mod_inv (res, p0->z, p25519); - mod25638_mul (res, res, p0->x); - mod25519_reduce (res); -} - - -void -ecdh_compute_public_25519 (const uint8_t *key_data, uint8_t *pubkey) -{ - bn256 gx[1]; - bn256 k[1]; - - memset (gx, 0, sizeof (bn256)); - gx[0].word[0] = 9; /* Gx = 9 */ - memcpy (k, key_data, sizeof (bn256)); - - compute_nQ ((bn256 *)pubkey, k, gx); -} - -int -ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output, - const uint8_t *key_data) -{ - bn256 q_x[1]; - bn256 k[1]; - bn256 shared[1]; - - memcpy (q_x, input, sizeof (bn256)); - memcpy (k, key_data, sizeof (bn256)); - compute_nQ (shared, k, q_x); - memcpy (output, shared, sizeof (bn256)); - return 0; -} diff --git a/src/openpgp/ecc-x448.c b/src/openpgp/ecc-x448.c deleted file mode 100644 index 7201501..0000000 --- a/src/openpgp/ecc-x448.c +++ /dev/null @@ -1,177 +0,0 @@ -/* -*- coding: utf-8 -*- - * ecc-x448.c - Elliptic curve computation for - * the Montgomery curve: y^2 = x^3 + 156326*x^2 + x - * - * Copyright (C) 2021 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -/* - * IMPLEMENTATION NOTE - * - * (0) We assume that the processor has no cache, nor branch target - * prediction. - * We don't avoid conditional jump if both cases have same timing, - * either. - * - */ - -#include -#include - -#include "p448.h" - -#define N_LIMBS 14 - -/** - * @brief Process Montgomery double-and-add - * - * With Q0, Q1, DIF (= Q0 - Q1), compute PRD = 2Q0 into Q0, - * and computute SUM = Q0 + Q1 into Q1 - * - */ -static void -mont_d_and_a (p448_t q0_x[1], p448_t q0_z[1], p448_t q1_x[1], p448_t q1_z[1], - const p448_t dif_x[1]) -{ - p448_t reg0[1], reg1[1]; -#define c reg0 -#define d reg1 -#define a q1_x -#define b q1_z -#define cb q0_x -#define da reg0 -#define aa reg1 -#define bb q0_z -#define da_plus_cb q1_z -#define da_minus_cb q1_x -#define e reg0 -#define dacb_2 q0_z -#define a24_e q1_x -#define aa_ aa /* override is allowed by p448_add */ - - p448_add (c, q1_x, q1_z); - p448_sub (d, q1_x, q1_z); - p448_add (a, q0_x, q0_z); - p448_sub (b, q0_x, q0_z); - p448_mul (cb, c, b); - p448_mul (da, d, a); - p448_sqr (aa, a); - p448_sqr (bb, b); - p448_add (da_plus_cb, da, cb); - p448_sub (da_minus_cb, da, cb); - p448_mul (q0_x, aa, bb); - p448_sub (e, aa, bb); - p448_sqr (dacb_2, da_minus_cb); - p448_mul_39081 (a24_e, e); - p448_add (aa_, aa, a24_e); - p448_sqr (q1_x, da_plus_cb); - p448_mul (q1_z, dacb_2, dif_x); - p448_mul (q0_z, e, aa_); -} - - -typedef struct -{ - p448_t x[1]; - p448_t z[1]; -} pt; - - -/** - * @brief RES = x-coordinate of [n]Q - * - * @param N Scalar N (three least significant bits are 00) - * @param Q_X x-coordinate of Q - * - */ -static void -compute_nQ (uint8_t *res, const uint32_t n[N_LIMBS], const p448_t q_x[1]) -{ - int i, j; - pt p0[1], p1[1]; -#define tmp0 p0->z -#define tmp1 p1->z - - /* P0 = O = (1:0) */ - memset (p0->x, 0, sizeof (p0->x)); - p0->x->limb[0] = 1; - memset (p0->z, 0, sizeof (p0->z)); - - /* P1 = (X:1) */ - memcpy (p1->x, q_x, N_REDUNDANT_LIMBS*4); - memset (p1->z, 0, sizeof (p1->z)); - p1->z->limb[0] = 1; - - for (i = 0; i < N_LIMBS; i++) - { - uint32_t u = n[N_LIMBS-i-1]; - - for (j = 0; j < 32; j++) - { - p448_t *q0_x, *q0_z, *q1_x, *q1_z; - - if ((u & 0x80000000)) - q0_x = p1->x, q0_z = p1->z, q1_x = p0->x, q1_z = p0->z; - else - q0_x = p0->x, q0_z = p0->z, q1_x = p1->x, q1_z = p1->z; - mont_d_and_a (q0_x, q0_z, q1_x, q1_z, q_x); - - u <<= 1; - } - } - - /* We know the LSB of N is always 0. Thus, result is always in P0. */ - /* - * p0->z may be zero here, but our inverse function doesn't raise - * error for 0, but returns 0, thus, RES will be 0 in that case, - * which is correct value. - */ - p448_inv (tmp1, p0->z); - p448_mul (tmp0, tmp1, p0->x); - p448_serialize (res, tmp0); -} - - -void -ecdh_compute_public_x448 (uint8_t *pubkey, const uint8_t *key_data) -{ - const p448_t gx[1] = { { { 5, 0, }, } }; - uint32_t k[N_LIMBS]; - - memcpy (k, key_data, N_LIMBS*4); - k[0] &= ~3; - k[N_LIMBS-1] |= 0x80000000; - compute_nQ (pubkey, k, gx); -} - -int -ecdh_decrypt_x448 (uint8_t *output, const uint8_t *input, - const uint8_t *key_data) -{ - p448_t q_x[1]; - uint32_t k[N_LIMBS]; - - p448_deserialize (q_x, input); - memcpy (k, key_data, N_LIMBS*4); - k[0] &= ~3; - k[N_LIMBS-1] |= 0x80000000; - compute_nQ (output, k, q_x); - return 0; -} diff --git a/src/openpgp/ecc.c b/src/openpgp/ecc.c deleted file mode 100644 index 2d637e9..0000000 --- a/src/openpgp/ecc.c +++ /dev/null @@ -1,398 +0,0 @@ -/* -*- coding: utf-8 -*- - * ecc.c - Elliptic curve over GF(prime) - * - * Copyright (C) 2011, 2013, 2014, 2015 - * Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -/* - * References: - * - * [1] Suite B Implementer's Guide to FIPS 186-3 (ECDSA), February 3, 2010. - * - * [2] Michael Brown, Darrel Hankerson, Julio López, and Alfred Menezes, - * Software Implementation of the NIST Elliptic Curves Over Prime Fields, - * Proceedings of the 2001 Conference on Topics in Cryptology: The - * Cryptographer's Track at RSA - * Pages 250-265, Springer-Verlag London, UK, 2001 - * ISBN:3-540-41898-9 - * - * [3] Mustapha Hedabou, Pierre Pinel, Lucien Bénéteau, - * A comb method to render ECC resistant against Side Channel Attacks, - * 2004 - */ - -#include "field-group-select.h" - -/* - * Coefficients - */ -/* - * static const bn256 *coefficient_a; - * static const bn256 *coefficient_b; - */ -/* - * N: order of G - */ -/* - * static const bn256 N[1]; - */ -/* - * MU = 2^512 / N - * MU = ( (1 << 256) | MU_lower ) - */ -/* - * static const bn256 MU_lower[1]; - */ - -/* - * w = 4 - * m = 256 - * d = 64 - * e = 32 - */ - -/* - * static const ac precomputed_KG[15]; - * static const ac precomputed_2E_KG[15]; - */ - -#if TEST -/* - * Generator of Elliptic curve over GF(p256) - */ -const ac *G = &precomputed_KG[0]; -#endif - - -static int -get_vk (const bn256 *K, int i) -{ - uint32_t w0, w1, w2, w3; - - if (i < 32) - { - w3 = K->word[6]; w2 = K->word[4]; w1 = K->word[2]; w0 = K->word[0]; - } - else - { - w3 = K->word[7]; w2 = K->word[5]; w1 = K->word[3]; w0 = K->word[1]; - i -= 32; - } - - w3 >>= i; w2 >>= i; w1 >>= i; w0 >>= i; - return ((w3 & 1) << 3) | ((w2 & 1) << 2) | ((w1 & 1) << 1) | (w0 & 1); -} - - -/** - * @brief X = k * G - * - * @param K scalar k - * - * Return -1 on error. - * Return 0 on success. - */ -int -FUNC(compute_kG) (ac *X, const bn256 *K) -{ - uint8_t index[64]; /* Lower 4-bit for index absolute value, msb is - for sign (encoded as: 0 means 1, 1 means -1). */ - bn256 K_dash[1]; - jpc Q[1], tmp[1], *dst; - int i; - int vk; - uint32_t k_is_even = bn256_is_even (K); - - bn256_sub_uint (K_dash, K, k_is_even); - /* It keeps the condition: 1 <= K' <= N - 2, and K' is odd. */ - - /* Fill index. */ - vk = get_vk (K_dash, 0); - for (i = 1; i < 64; i++) - { - int vk_next, is_zero; - - vk_next = get_vk (K_dash, i); - is_zero = (vk_next == 0); - index[i-1] = (vk - 1) | (is_zero << 7); - vk = (is_zero ? vk : vk_next); - } - index[63] = vk - 1; - - memset (Q->z, 0, sizeof (bn256)); /* infinity */ - for (i = 31; i >= 0; i--) - { - FUNC(jpc_double) (Q, Q); - FUNC(jpc_add_ac_signed) (Q, Q, &precomputed_2E_KG[index[i+32]&0x0f], - index[i+32] >> 7); - FUNC(jpc_add_ac_signed) (Q, Q, &precomputed_KG[index[i]&0x0f], - index[i] >> 7); - } - - dst = k_is_even ? Q : tmp; - FUNC(jpc_add_ac) (dst, Q, &precomputed_KG[0]); - - return FUNC(jpc_to_ac) (X, Q); -} - - - -/** - * check if P is on the curve. - * - * Return -1 on error. - * Return 0 on success. - */ -static int -point_is_on_the_curve (const ac *P) -{ - bn256 s[1], t[1]; - - /* Elliptic curve: y^2 = x^3 + a*x + b */ - MFNC(sqr) (s, P->x); - MFNC(mul) (s, s, P->x); - -#ifndef COEFFICIENT_A_IS_ZERO - MFNC(mul) (t, coefficient_a, P->x); - MFNC(add) (s, s, t); -#endif - MFNC(add) (s, s, coefficient_b); - - MFNC(sqr) (t, P->y); - if (bn256_cmp (s, t) == 0) - return 0; - else - return -1; -} - - -static int -get_vk_kP (const bn256 *K, int i) -{ - uint32_t w; - uint8_t blk = i/32; - uint8_t pos = i%32; - uint8_t col = 3*(pos % 11) + (pos >= 11) + (pos >= 22); - uint8_t word_index = (blk * 3) + (pos / 11); - - w = ((K->word[word_index] >> col) & 7); - if (word_index < 7 && (pos == 10 || pos == 21)) - { - uint8_t mask; - uint8_t shift; - - word_index++; - if (pos == 10) - { - shift = 2; - mask = 4; - } - else - { - shift = 1; - mask = 6; - } - - w |= ((K->word[word_index] << shift) & mask); - } - - return w; -} - -/** - * @brief X = k * P - * - * @param K scalar k - * @param P P in affine coordiate - * - * Return -1 on error. - * Return 0 on success. - * - * For the curve (cofactor is 1 and n is prime), possible error cases are: - * - * P is not on the curve. - * P = G, k = n - * Something wrong in the code. - * - * Mathmatically, k=1 and P=O is another possible case, but O cannot be - * represented by affine coordinate. - */ -int -FUNC(compute_kP) (ac *X, const bn256 *K, const ac *P) -{ - uint8_t index[86]; /* Lower 2-bit for index absolute value, msb is - for sign (encoded as: 0 means 1, 1 means -1). */ - bn256 K_dash[1]; - uint32_t k_is_even = bn256_is_even (K); - jpc Q[1], tmp[1], *dst; - int i; - int vk; - ac P3[1], P5[1], P7[1]; - const ac *p_Pi[4]; - - if (point_is_on_the_curve (P) < 0) - return -1; - - if (bn256_sub (K_dash, K, N) == 0) /* >= N, it's too big. */ - return -1; - - bn256_sub_uint (K_dash, K, k_is_even); - /* It keeps the condition: 1 <= K' <= N - 2, and K' is odd. */ - - p_Pi[0] = P; - p_Pi[1] = P3; - p_Pi[2] = P5; - p_Pi[3] = P7; - - { - jpc Q1[1]; - - memcpy (Q->x, P->x, sizeof (bn256)); - memcpy (Q->y, P->y, sizeof (bn256)); - memset (Q->z, 0, sizeof (bn256)); - Q->z->word[0] = 1; - - FUNC(jpc_double) (Q, Q); - FUNC(jpc_add_ac) (Q1, Q, P); - if (FUNC(jpc_to_ac) (P3, Q1) < 0) /* Never occurs, except coding errors. */ - return -1; - FUNC(jpc_double) (Q, Q); - FUNC(jpc_add_ac) (Q1, Q, P); - if (FUNC(jpc_to_ac) (P5, Q1) < 0) /* Never occurs, except coding errors. */ - return -1; - - memcpy (Q->x, P3->x, sizeof (bn256)); - memcpy (Q->y, P3->y, sizeof (bn256)); - memset (Q->z, 0, sizeof (bn256)); - Q->z->word[0] = 1; - FUNC(jpc_double) (Q, Q); - FUNC(jpc_add_ac) (Q1, Q, P); - if (FUNC(jpc_to_ac) (P7, Q1) < 0) /* Never occurs, except coding errors. */ - return -1; - } - - /* Fill index. */ - vk = get_vk_kP (K_dash, 0); - for (i = 1; i < 86; i++) - { - int vk_next, is_even; - - vk_next = get_vk_kP (K_dash, i); - is_even = ((vk_next & 1) == 0); - index[i-1] = (is_even << 7) | ((is_even?7-vk:vk-1) >> 1); - vk = vk_next + is_even; - } - index[85] = ((vk - 1) >> 1); - - memset (Q->z, 0, sizeof (bn256)); /* infinity */ - for (i = 85; i >= 0; i--) - { - FUNC(jpc_double) (Q, Q); - FUNC(jpc_double) (Q, Q); - FUNC(jpc_double) (Q, Q); - FUNC(jpc_add_ac_signed) (Q, Q, p_Pi[index[i]&0x03], index[i] >> 7); - } - - dst = k_is_even ? Q : tmp; - FUNC(jpc_add_ac) (dst, Q, P); - - return FUNC(jpc_to_ac) (X, Q); -} - - -/** - * @brief Compute signature (r,s) of hash string z with secret key d - */ -void -FUNC(ecdsa) (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d) -{ - bn256 k[1]; - ac KG[1]; - bn512 tmp[1]; - bn256 k_inv[1]; - uint32_t carry; -#define borrow carry -#define tmp_k k_inv - - do - { - do - { - bn256_random (k); - if (bn256_add_uint (k, k, 1)) - continue; - if (bn256_sub (tmp_k, k, N) == 0) /* >= N, it's too big. */ - continue; - /* 1 <= k <= N - 1 */ - FUNC(compute_kG) (KG, k); - borrow = bn256_sub (r, KG->x, N); - if (borrow) - memcpy (r, KG->x, sizeof (bn256)); - else - memcpy (KG->x, r, sizeof (bn256)); - } - while (bn256_is_zero (r)); - - mod_inv (k_inv, k, N); - bn256_mul (tmp, r, d); - mod_reduce (s, tmp, N, MU_lower); - carry = bn256_add (s, s, z); - if (carry) - bn256_sub (s, s, N); - else - bn256_sub ((bn256 *)tmp, s, N); - bn256_mul (tmp, s, k_inv); - mod_reduce (s, tmp, N, MU_lower); - } - while (bn256_is_zero (s)); - -#undef tmp_k -#undef borrow -} - - -/** - * @brief Check if a secret d0 is valid or not - * - * @param D0 scalar D0: secret - * @param D1 scalar D1: secret candidate N-D0 - * - * Return 0 on error. - * Return -1 when D1 should be used as the secret - * Return 1 when D0 should be used as the secret - */ -int -FUNC(check_secret) (const bn256 *d0, bn256 *d1) -{ - ac Q0[1], Q1[1]; - - if (bn256_is_zero (d0) || bn256_sub (d1, N, d0) != 0) - /* == 0 or >= N, it's not valid. */ - return 0; - - FUNC(compute_kG) (Q0, d0); - FUNC(compute_kG) (Q1, d1); - - /* - * Jivsov compliant key check - */ - return bn256_cmp (Q1[0].y, Q0[0].y); -} diff --git a/src/openpgp/field-group-select.h b/src/openpgp/field-group-select.h deleted file mode 100644 index 78cb6a5..0000000 --- a/src/openpgp/field-group-select.h +++ /dev/null @@ -1,7 +0,0 @@ -#define CONCAT0(a,b) a##b -#define CONCAT1(a,b) CONCAT0(a,b) -#define CONCAT2(a,b,c) CONCAT1(a,b##c) -#define CONCAT3(a,b,c) CONCAT2(a,b,c) - -#define FUNC(func) CONCAT1(func##_,FIELD) -#define MFNC(func) CONCAT3(mod,FIELD,_##func) diff --git a/src/openpgp/flash_openpgp.c b/src/openpgp/flash_openpgp.c deleted file mode 100644 index 65eef1a..0000000 --- a/src/openpgp/flash_openpgp.c +++ /dev/null @@ -1,763 +0,0 @@ -/* - * flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM - * - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 - * Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -/* - * We assume single DO size is less than 256. - * - * NOTE: "Card holder certificate" (which size is larger than 256) is - * not put into data pool, but is implemented by its own flash - * page(s). - */ - -#include -#include - -#include "config.h" - -#include "sys.h" -#include "gnuk.h" - -#include "pico/stdlib.h" -#include "hardware/flash.h" -#include "hsm2040.h" -#include "tusb.h" - -extern void low_flash_available(); - -/* - * Flash memory map - * - * _text - * .text - * .ctors - * .dtors - * _etext - * .data - * _bss_start - * .bss - * _end - * - * ch_certificate_startp - * <2048 bytes> - * _keystore_pool - * Three flash pages for keystore - * a page contains a key data of: - * For RSA-2048: 512-byte (p, q and N) - * For RSA-4096: 1024-byte (p, q and N) - * For ECDSA/ECDH and EdDSA, there are padding after public key - * _data_pool - * - */ - -#define FLASH_DATA_POOL_HEADER_SIZE 2 -#define FLASH_DATA_POOL_SIZE (2048*1024) - -static uint16_t flash_page_size; -static const uint8_t *data_pool; -static uint8_t *last_p; - -/* The first halfword is generation for the data page (little endian) */ -const uint8_t flash_data[4] __attribute__ ((section (".gnuk_data"))) = { - 0x00, 0x00, 0xff, 0xff -}; - -#define FLASH_TARGET_OFFSET (PICO_FLASH_SIZE_BYTES >> 1) // DATA starts at the mid of flash - - -const uint8_t *flash_addr_key_storage_start = (const uint8_t *) (XIP_BASE + FLASH_TARGET_OFFSET); -const uint8_t *flash_addr_data_storage_start = (const uint8_t *) (XIP_BASE + FLASH_TARGET_OFFSET + 2048 * 1024); // 2 MB -const uint8_t *ch_certificate_start = (const uint8_t *) (XIP_BASE + FLASH_TARGET_OFFSET - FLASH_SECTOR_SIZE); -#define FLASH_ADDR_KEY_STORAGE_START flash_addr_key_storage_start -#define FLASH_ADDR_DATA_STORAGE_START flash_addr_data_storage_start - -extern int flash_erase_page (uintptr_t addr); -extern int flash_program_halfword (uintptr_t addr, uint16_t data); -extern int flash_check_blank (const uint8_t *p_start, size_t size); -extern int flash_write (uintptr_t dst_addr, const uint8_t *src, size_t len); - -static int key_available_at (const uint8_t *k, int key_size) -{ - int i; - - for (i = 0; i < key_size; i++) - if (k[i]) - break; - if (i == key_size) /* It's ZERO. Released key. */ - return 0; - - for (i = 0; i < key_size; i++) - if (k[i] != 0xff) - break; - if (i == key_size) /* It's FULL. Unused key. */ - return 0; - - return 1; -} - -void -flash_do_storage_init (const uint8_t **p_do_start, const uint8_t **p_do_end) -{ - uint16_t gen0, gen1; - uint16_t *gen0_p = (uint16_t *)FLASH_ADDR_DATA_STORAGE_START; - uint16_t *gen1_p; - - flash_page_size = FLASH_SECTOR_SIZE * 8; // 32 KB - - gen1_p = (uint16_t *)(FLASH_ADDR_DATA_STORAGE_START + flash_page_size); - data_pool = FLASH_ADDR_DATA_STORAGE_START; - - /* Check data pool generation and choose the page */ - gen0 = *gen0_p; - gen1 = *gen1_p; - - if (gen0 == 0xffff && gen1 == 0xffff) - { - gen0 = 0x0000; - *gen0_p = gen0; - } - - if (gen0 == 0xffff) - /* Use another page if a page is erased. */ - data_pool = FLASH_ADDR_DATA_STORAGE_START + flash_page_size; - else if (gen1 == 0xffff) - /* Or use different page if another page is erased. */ - data_pool = FLASH_ADDR_DATA_STORAGE_START; - else if ((gen0 == 0xfffe && gen1 == 0) || gen1 > gen0) - /* When both pages have valid header, use newer page. */ - data_pool = FLASH_ADDR_DATA_STORAGE_START + flash_page_size; - - *p_do_start = data_pool + FLASH_DATA_POOL_HEADER_SIZE; - *p_do_end = data_pool + flash_page_size; -} - -static uint8_t *flash_key_getpage (enum kind_of_key kk); - -void -flash_terminate (void) -{ - int i; - - for (i = 0; i < 3; i++) - flash_erase_page ((uintptr_t)flash_key_getpage (i)); - flash_erase_page ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START); - flash_erase_page ((uintptr_t)(FLASH_ADDR_DATA_STORAGE_START + flash_page_size)); - data_pool = FLASH_ADDR_DATA_STORAGE_START; - last_p = (uint8_t *)FLASH_ADDR_DATA_STORAGE_START + FLASH_DATA_POOL_HEADER_SIZE; -#if defined(CERTDO_SUPPORT) - flash_erase_page ((uintptr_t)ch_certificate_start); - if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size) - flash_erase_page ((uintptr_t)(ch_certificate_start + flash_page_size)); -#endif -} - -void -flash_activate (void) -{ - flash_program_halfword ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START, 0); - low_flash_available(); -} - - -void -flash_key_storage_init (void) -{ - const uint8_t *p; - int i; - - /* For each key, find its address. */ - p = FLASH_ADDR_KEY_STORAGE_START; - for (i = 0; i < 3; i++) - { - const uint8_t *k; - int key_size = gpg_get_algo_attr_key_size (i, GPG_KEY_STORAGE); - - kd[i].pubkey = NULL; - for (k = p; k < p + flash_page_size; k += key_size) - if (key_available_at (k, key_size)) - { - int prv_len = gpg_get_algo_attr_key_size (i, GPG_KEY_PRIVATE); - - kd[i].pubkey = k + prv_len; - break; - } - - p += flash_page_size; - } -} - -/* - * Flash data pool managenent - * - * Flash data pool consists of two parts: - * 2-byte header - * contents - * - * Flash data pool objects: - * Data Object (DO) (of smart card) - * Internal objects: - * NONE (0x0000) - * 123-counter - * 14-bit counter - * bool object - * small enum - * - * Format of a Data Object: - * NR: 8-bit tag_number - * LEN: 8-bit length - * DATA: data * LEN - * PAD: optional byte for 16-bit alignment - */ - -void -flash_set_data_pool_last (const uint8_t *p) -{ - last_p = (uint8_t *)p; -} - -/* - * We use two pages - */ -static int -flash_copying_gc (void) -{ - uint8_t *src, *dst; - uint16_t generation; - - if (data_pool == FLASH_ADDR_DATA_STORAGE_START) - { - src = (uint8_t *)FLASH_ADDR_DATA_STORAGE_START; - dst = (uint8_t *)FLASH_ADDR_DATA_STORAGE_START + flash_page_size; - } - else - { - src = (uint8_t *)FLASH_ADDR_DATA_STORAGE_START + flash_page_size; - dst = (uint8_t *)FLASH_ADDR_DATA_STORAGE_START; - } - - generation = *(uint16_t *)src; - data_pool = dst; - gpg_data_copy (data_pool + FLASH_DATA_POOL_HEADER_SIZE); - if (generation == 0xfffe) - generation = 0; - else - generation++; - flash_program_halfword ((uintptr_t)dst, generation); - flash_erase_page ((uintptr_t)src); - low_flash_available(); - return 0; -} - -static int -is_data_pool_full (size_t size) -{ - return last_p + size > data_pool + flash_page_size; -} - -static uint8_t * -flash_data_pool_allocate (size_t size) -{ - uint8_t *p; - - size = (size + 1) & ~1; /* allocation unit is 1-halfword (2-byte) */ - - if (is_data_pool_full (size)) - if (flash_copying_gc () < 0 || /*still*/ is_data_pool_full (size)) - TU_LOG1 ("!!!! FATAL: %d\r\n",FATAL_FLASH); - - p = last_p; - last_p += size; - return p; -} - -void -flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len) -{ - uint16_t hw; - uintptr_t addr; - int i; - - addr = (uintptr_t)p; - hw = nr | (len << 8); - if (flash_program_halfword (addr, hw) != 0) - flash_warning ("DO WRITE ERROR"); - addr += 2; - - for (i = 0; i < len/2; i++) - { - hw = data[i*2] | (data[i*2+1]<<8); - if (flash_program_halfword (addr, hw) != 0) - flash_warning ("DO WRITE ERROR"); - addr += 2; - } - - if ((len & 1)) - { - hw = data[i*2] | 0xff00; - if (flash_program_halfword (addr, hw) != 0) - flash_warning ("DO WRITE ERROR"); - } - - low_flash_available(); -} - -const uint8_t * -flash_do_write (uint8_t nr, const uint8_t *data, int len) -{ - const uint8_t *p; - - DEBUG_INFO ("flash DO\r\n"); - - p = flash_data_pool_allocate (2 + len); - if (p == NULL) - { - DEBUG_INFO ("flash data pool allocation failure.\r\n"); - return NULL; - } - - flash_do_write_internal (p, nr, data, len); - DEBUG_INFO ("flash DO...done\r\n"); - return p + 1; -} - -void -flash_warning (const char *msg) -{ - (void)msg; - DEBUG_INFO ("FLASH: "); - DEBUG_INFO (msg); - DEBUG_INFO ("\r\n"); -} - -void -flash_do_release (const uint8_t *do_data) -{ - uintptr_t addr = (uintptr_t)do_data - 1; - uintptr_t addr_tag = addr; - int i; - int len = do_data[0]; - - /* Don't filling zero for data in code (such as ds_count_initial_value) */ - if (do_data < FLASH_ADDR_DATA_STORAGE_START - || do_data > FLASH_ADDR_DATA_STORAGE_START + FLASH_DATA_POOL_SIZE) - return; - - addr += 2; - - /* Fill zero for content and pad */ - for (i = 0; i < len/2; i ++) - { - if (flash_program_halfword (addr, 0) != 0) - flash_warning ("fill-zero failure"); - addr += 2; - } - - if ((len & 1)) - { - if (flash_program_halfword (addr, 0) != 0) - flash_warning ("fill-zero pad failure"); - } - - /* Fill 0x0000 for "tag_number and length" word */ - if (flash_program_halfword (addr_tag, 0) != 0) - flash_warning ("fill-zero tag_nr failure"); - - //CAUTION: flash_do_release is followed by a flash_write. Thus, we can avoid a single write - //low_flash_available(); -} - - -static uint8_t * -flash_key_getpage (enum kind_of_key kk) -{ - /* There is a page for each KK. */ - return (uint8_t *)FLASH_ADDR_KEY_STORAGE_START + (flash_page_size * kk); -} - -uint8_t * -flash_key_alloc (enum kind_of_key kk) -{ - uint8_t *k, *k0 = flash_key_getpage (kk); - int i; - int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE); - - /* Seek free space in the page. */ - for (k = k0; k < k0 + flash_page_size; k += key_size) - { - const uint32_t *p = (const uint32_t *)k; - - for (i = 0; i < key_size/4; i++) - if (p[i] != 0xffffffff) - break; - - if (i == key_size/4) /* Yes, it's empty. */ - return k; - } - - /* Should not happen as we have enough free space all time, but just - in case. */ - return NULL; -} - -int -flash_key_write (uint8_t *key_addr, - const uint8_t *key_data, int key_data_len, - const uint8_t *pubkey, int pubkey_len) -{ - uint16_t hw; - uintptr_t addr; - int i; - - addr = (uintptr_t)key_addr; - for (i = 0; i < key_data_len/2; i ++) - { - hw = key_data[i*2] | (key_data[i*2+1]<<8); - if (flash_program_halfword (addr, hw) != 0) - return -1; - addr += 2; - } - - for (i = 0; i < pubkey_len/2; i ++) - { - hw = pubkey[i*2] | (pubkey[i*2+1]<<8); - if (flash_program_halfword (addr, hw) != 0) - return -1; - addr += 2; - } - - low_flash_available(); - return 0; -} - -static int -flash_check_all_other_keys_released (const uint8_t *key_addr, int key_size) -{ - uintptr_t start = (uintptr_t)key_addr & ~(flash_page_size - 1); - const uint32_t *p = (const uint32_t *)start; - - while (p < (const uint32_t *)(start + flash_page_size)) - if (p == (const uint32_t *)key_addr) - p += key_size/4; - else - if (*p) - return 0; - else - p++; - - return 1; -} - -static void -flash_key_fill_zero_as_released (uint8_t *key_addr, int key_size) -{ - int i; - uintptr_t addr = (uintptr_t)key_addr; - - for (i = 0; i < key_size/2; i++) - flash_program_halfword (addr + i*2, 0); - - low_flash_available(); -} - -void -flash_key_release (uint8_t *key_addr, int key_size) -{ - if (flash_check_all_other_keys_released (key_addr, key_size)) - flash_erase_page (((uintptr_t)key_addr & ~(flash_page_size - 1))); - else - flash_key_fill_zero_as_released (key_addr, key_size); -} - -void -flash_key_release_page (enum kind_of_key kk) -{ - flash_erase_page ((uintptr_t)flash_key_getpage (kk)); -} - - -void -flash_clear_halfword (uintptr_t addr) -{ - flash_program_halfword (addr, 0); - low_flash_available(); -} - - -void -flash_put_data_internal (const uint8_t *p, uint16_t hw) -{ - flash_program_halfword ((uintptr_t)p, hw); - low_flash_available(); -} - -void -flash_put_data (uint16_t hw) -{ - uint8_t *p; - - p = flash_data_pool_allocate (2); - if (p == NULL) - { - DEBUG_INFO ("data allocation failure.\r\n"); - } - - flash_program_halfword ((uintptr_t)p, hw); - low_flash_available(); -} - - -void -flash_bool_clear (const uint8_t **addr_p) -{ - const uint8_t *p; - - if ((p = *addr_p) == NULL) - return; - - flash_program_halfword ((uintptr_t)p, 0); - *addr_p = NULL; - low_flash_available(); -} - -void -flash_bool_write_internal (const uint8_t *p, int nr) -{ - flash_program_halfword ((uintptr_t)p, nr); - low_flash_available(); -} - -const uint8_t * -flash_bool_write (uint8_t nr) -{ - uint8_t *p; - uint16_t hw = nr; - - p = flash_data_pool_allocate (2); - if (p == NULL) - { - DEBUG_INFO ("bool allocation failure.\r\n"); - return NULL; - } - - flash_program_halfword ((uintptr_t)p, hw); - low_flash_available(); - return p; -} - - -void -flash_enum_clear (const uint8_t **addr_p) -{ - flash_bool_clear (addr_p); -} - -void -flash_enum_write_internal (const uint8_t *p, int nr, uint8_t v) -{ - uint16_t hw = nr | (v << 8); - - flash_program_halfword ((uintptr_t)p, hw); - low_flash_available(); -} - -const uint8_t * -flash_enum_write (uint8_t nr, uint8_t v) -{ - uint8_t *p; - uint16_t hw = nr | (v << 8); - - p = flash_data_pool_allocate (2); - if (p == NULL) - { - DEBUG_INFO ("enum allocation failure.\r\n"); - return NULL; - } - - flash_program_halfword ((uintptr_t)p, hw); - low_flash_available(); - return p; -} - - -int -flash_cnt123_get_value (const uint8_t *p) -{ - if (p == NULL) - return 0; - else - { - uint8_t v = *p; - - /* - * After erase, a halfword in flash memory becomes 0xffff. - * The halfword can be programmed to any value. - * Then, the halfword can be programmed to zero. - * - * Thus, we can represent value 1, 2, and 3. - */ - if (v == 0xff) - return 1; - else if (v == 0x00) - return 3; - else - return 2; - } -} - -void -flash_cnt123_write_internal (const uint8_t *p, int which, int v) -{ - uint16_t hw; - - hw = NR_COUNTER_123 | (which << 8); - flash_program_halfword ((uintptr_t)p, hw); - - if (v == 1) - return; - else if (v == 2) - flash_program_halfword ((uintptr_t)p+2, 0xc3c3); - else /* v == 3 */ - flash_program_halfword ((uintptr_t)p+2, 0); - low_flash_available(); -} - -void -flash_cnt123_increment (uint8_t which, const uint8_t **addr_p) -{ - const uint8_t *p; - uint16_t hw; - - if ((p = *addr_p) == NULL) - { - p = flash_data_pool_allocate (4); - if (p == NULL) - { - DEBUG_INFO ("cnt123 allocation failure.\r\n"); - return; - } - hw = NR_COUNTER_123 | (which << 8); - flash_program_halfword ((uintptr_t)p, hw); - *addr_p = p + 2; - } - else - { - uint8_t v = *p; - - if (v == 0) - return; - - if (v == 0xff) - hw = 0xc3c3; - else - hw = 0; - - flash_program_halfword ((uintptr_t)p, hw); - } - low_flash_available(); -} - -void -flash_cnt123_clear (const uint8_t **addr_p) -{ - const uint8_t *p; - - if ((p = *addr_p) == NULL) - return; - - flash_program_halfword ((uintptr_t)p, 0); - p -= 2; - flash_program_halfword ((uintptr_t)p, 0); - *addr_p = NULL; - low_flash_available(); -} - - -#if defined(CERTDO_SUPPORT) -int -flash_erase_binary (uint8_t file_id) -{ - if (file_id == FILEID_CH_CERTIFICATE) - { - const uint8_t *p = ch_certificate_start; - if (flash_check_blank (p, FLASH_CH_CERTIFICATE_SIZE) == 0) - { - flash_erase_page ((uintptr_t)p); - if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size) - flash_erase_page ((uintptr_t)p + flash_page_size); - } - low_flash_available(); - - return 0; - } - - return -1; -} -#endif - - -int -flash_write_binary (uint8_t file_id, const uint8_t *data, - uint16_t len, uint16_t offset) -{ - uint16_t maxsize; - const uint8_t *p; - - if (file_id == FILEID_SERIAL_NO) - { - maxsize = 6; - p = &openpgpcard_aid[8]; - } -#if defined(CERTDO_SUPPORT) - else if (file_id == FILEID_CH_CERTIFICATE) - { - maxsize = FLASH_CH_CERTIFICATE_SIZE; - p = ch_certificate_start; - } -#endif - else - return -1; - - if (offset + len > maxsize || (offset&1) || (len&1)) - return -1; - else - { - uint16_t hw; - uintptr_t addr; - int i; - - if (flash_check_blank (p + offset, len) == 0) - return -1; - - addr = (uintptr_t)p + offset; - for (i = 0; i < len/2; i++) - { - hw = data[i*2] | (data[i*2+1]<<8); - if (flash_program_halfword (addr, hw) != 0) - flash_warning ("DO WRITE ERROR"); - addr += 2; - } - - low_flash_available(); - return 0; - } -} diff --git a/src/openpgp/gnuk.h b/src/openpgp/gnuk.h deleted file mode 100644 index b9a3a6f..0000000 --- a/src/openpgp/gnuk.h +++ /dev/null @@ -1,465 +0,0 @@ -#ifndef _GNUK_H_ -#define _GNUK_H_ - -#include "config.h" -/* - * Application layer <-> CCID layer data structure - */ - - -#define CARD_CHANGE_INSERT 0 -#define CARD_CHANGE_REMOVE 1 -#define CARD_CHANGE_TOGGLE 2 -void ccid_card_change_signal (int how); - -/* CCID thread */ -#define EV_CARD_CHANGE 1 -#define EV_TX_FINISHED 2 /* CCID Tx finished */ -#define EV_EXEC_ACK_REQUIRED 4 /* OpenPGPcard Execution ACK required */ -#define EV_EXEC_FINISHED 8 /* OpenPGPcard Execution finished */ -#define EV_RX_DATA_READY 16 /* USB Rx data available */ - -/* OpenPGPcard thread */ -#define EV_MODIFY_CMD_AVAILABLE 1 -#define EV_VERIFY_CMD_AVAILABLE 2 -#define EV_CMD_AVAILABLE 4 -#define EV_EXIT 8 -#define EV_PINPAD_INPUT_DONE 16 - -/* Maximum cmd apdu data is key import 24+4+256+256 (proc_key_import) */ -#define MAX_CMD_APDU_DATA_SIZE (24+4+256+256) /* without header */ -/* Maximum res apdu data is public key 5+9+512 (gpg_do_public_key) */ -#define MAX_RES_APDU_DATA_SIZE (5+9+512) /* without trailer */ - -#define CCID_MSG_HEADER_SIZE 10 - - - -/* USB buffer size of LL (Low-level): size of single Bulk transaction */ -#define USB_LL_BUF_SIZE 64 - -enum ccid_state { - CCID_STATE_NOCARD, /* No card available */ - CCID_STATE_START, /* Initial */ - CCID_STATE_WAIT, /* Waiting APDU */ - - CCID_STATE_EXECUTE, /* Executing command */ - CCID_STATE_ACK_REQUIRED_0, /* Ack required (executing)*/ - CCID_STATE_ACK_REQUIRED_1, /* Waiting user's ACK (execution finished) */ - - CCID_STATE_EXITED, /* CCID Thread Terminated */ - CCID_STATE_EXEC_REQUESTED, /* Exec requested */ -}; - - -enum ccid_state ccid_get_ccid_state (void); - -extern volatile uint8_t auth_status; -#define AC_NONE_AUTHORIZED 0x00 -#define AC_PSO_CDS_AUTHORIZED 0x01 /* PW1 with 0x81 verified */ -#define AC_OTHER_AUTHORIZED 0x02 /* PW1 with 0x82 verified */ -#define AC_ADMIN_AUTHORIZED 0x04 /* PW3 verified */ -#define AC_NEVER 0x80 -#define AC_ALWAYS 0xFF - -#define PW_ERR_PW1 0 -#define PW_ERR_RC 1 -#define PW_ERR_PW3 2 -int gpg_pw_get_retry_counter (int who); -int gpg_pw_locked (uint8_t which); -void gpg_pw_reset_err_counter (uint8_t which); -void gpg_pw_increment_err_counter (uint8_t which); - -int ac_check_status (uint8_t ac_flag); -int verify_pso_cds (const uint8_t *pw, int pw_len); -int verify_other (const uint8_t *pw, int pw_len); -int verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, - int pw_len_known, const uint8_t *ks_pw1, int saveks); -int verify_admin (const uint8_t *pw, int pw_len); -int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known, - const uint8_t *ks_pw3, int saveks); - -void ac_reset_pso_cds (void); -void ac_reset_other (void); -void ac_reset_admin (void); -void ac_fini (void); - - -extern uint8_t file_selection; -extern const uint8_t historical_bytes[]; -extern uint16_t data_objects_number_of_bytes; - -#define CHALLENGE_LEN 32 - -void gpg_data_scan (const uint8_t *start, const uint8_t *end); -void gpg_data_copy (const uint8_t *p); -void gpg_do_terminate (void); -void gpg_do_get_data (uint16_t tag, int with_tag); -void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len); -void gpg_do_public_key (uint8_t kk_byte); -void gpg_do_keygen (uint8_t *buf); - -const uint8_t *gpg_get_firmware_update_key (uint8_t keyno); - -/* Constants: algo+size */ -#define ALGO_RSA4K 0 -/* #define ALGO_NISTP256R1 1 */ -#define ALGO_SECP256K1 2 -#define ALGO_ED25519 3 -#define ALGO_CURVE25519 4 -#define ALGO_X448 5 -#define ALGO_ED448 6 -#define ALGO_RSA2K 255 - -enum kind_of_key { - GPG_KEY_FOR_SIGNING = 0, - GPG_KEY_FOR_DECRYPTION = 1, - GPG_KEY_FOR_AUTHENTICATION = 2, -}; - -enum size_of_key { - GPG_KEY_STORAGE = 0, /* PUBKEY + PRVKEY rounded to 2^N */ - GPG_KEY_PUBLIC, - GPG_KEY_PRIVATE, -}; - -int gpg_get_algo_attr (enum kind_of_key kk); -int gpg_get_algo_attr_key_size (enum kind_of_key kk, enum size_of_key s); - -void flash_do_storage_init (const uint8_t **, const uint8_t **); -void flash_terminate (void); -void flash_activate (void); -void flash_key_storage_init (void); -void flash_do_release (const uint8_t *); -const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len); -uint8_t *flash_key_alloc (enum kind_of_key); -void flash_key_release (uint8_t *, int); -void flash_key_release_page (enum kind_of_key); -int flash_key_write (uint8_t *key_addr, - const uint8_t *key_data, int key_data_len, - const uint8_t *pubkey, int pubkey_len); -void flash_set_data_pool_last (const uint8_t *p); -void flash_clear_halfword (uintptr_t addr); -void flash_increment_counter (uint8_t counter_tag_nr); -void flash_reset_counter (uint8_t counter_tag_nr); - -#define FILEID_SERIAL_NO 0 -#define FILEID_UPDATE_KEY_0 1 -#define FILEID_UPDATE_KEY_1 2 -#define FILEID_UPDATE_KEY_2 3 -#define FILEID_UPDATE_KEY_3 4 -#define FILEID_CH_CERTIFICATE 5 -int flash_erase_binary (uint8_t file_id); -int flash_write_binary (uint8_t file_id, const uint8_t *data, - uint16_t len, uint16_t offset); - -#define FLASH_CH_CERTIFICATE_SIZE 2048 - -extern const uint8_t *ch_certificate_start; - -#define FIRMWARE_UPDATE_KEY_CONTENT_LEN 256 /* RSA-2048 (p and q) */ - -#define INITIAL_VECTOR_SIZE 16 -#define DATA_ENCRYPTION_KEY_SIZE 16 - -#define MAX_PRVKEY_LEN 512 /* Maximum is the case for RSA 4096-bit. */ - -struct key_data { - const uint8_t *pubkey; /* Pointer to public key */ - uint8_t data[MAX_PRVKEY_LEN]; /* decrypted private key data content */ -}; - -struct prvkey_data { - /* - * IV: Initial Vector - */ - uint8_t iv[INITIAL_VECTOR_SIZE]; - /* - * Checksum - */ - uint8_t checksum_encrypted[DATA_ENCRYPTION_KEY_SIZE]; - /* - * DEK (Data Encryption Key) encrypted - */ - uint8_t dek_encrypted_1[DATA_ENCRYPTION_KEY_SIZE]; /* For user */ - uint8_t dek_encrypted_2[DATA_ENCRYPTION_KEY_SIZE]; /* For resetcode */ - uint8_t dek_encrypted_3[DATA_ENCRYPTION_KEY_SIZE]; /* For admin */ -}; - -#define BY_USER 1 -#define BY_RESETCODE 2 -#define BY_ADMIN 3 - -/* - * Maximum length of pass phrase is 127. - * We use the top bit (0x80) to encode if keystring is available within DO. - */ -#define PW_LEN_MAX 127 -#define PW_LEN_MASK 0x7f -#define PW_LEN_KEYSTRING_BIT 0x80 - -#define SALT_SIZE 8 - -void s2k (const unsigned char *salt, size_t slen, - const unsigned char *input, size_t ilen, unsigned char output[32]); - -#define KEYSTRING_PASSLEN_SIZE 1 -#define KEYSTRING_SALT_SIZE SALT_SIZE -#define KEYSTRING_MD_SIZE 32 -#define KEYSTRING_SIZE (KEYSTRING_PASSLEN_SIZE + KEYSTRING_SALT_SIZE \ - + KEYSTRING_MD_SIZE) -#define KS_META_SIZE (KEYSTRING_PASSLEN_SIZE + KEYSTRING_SALT_SIZE) -#define KS_GET_SALT(ks) (ks + KEYSTRING_PASSLEN_SIZE) -#define KS_GET_KEYSTRING(ks) (ks + KS_META_SIZE) - -void gpg_do_clear_prvkey (enum kind_of_key kk); -int gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring); -int gpg_do_chks_prvkey (enum kind_of_key kk, - int who_old, const uint8_t *old_ks, - int who_new, const uint8_t *new_ks); - -int gpg_change_keystring (int who_old, const uint8_t *old_ks, - int who_new, const uint8_t *new_ks); - -extern struct key_data kd[3]; - - -int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *, int); -int modulus_calc (const uint8_t *, int, uint8_t *); -int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *, - unsigned int *); -int rsa_verify (const uint8_t *, int, const uint8_t *, const uint8_t *); -int rsa_genkey (int, uint8_t *, uint8_t *); - -int ecdsa_sign_p256k1 (const uint8_t *hash, uint8_t *output, - const uint8_t *key_data); -int ecc_compute_public_p256k1 (const uint8_t *key_data, uint8_t *); -int ecc_check_secret_p256k1 (const uint8_t *d0, uint8_t *d1); -int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output, - const uint8_t *key_data); - -int eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *output, - const uint8_t *sk_a, const uint8_t *seed, - const uint8_t *pk); -void eddsa_compute_public_25519 (const uint8_t *a, uint8_t *); -void ecdh_compute_public_25519 (const uint8_t *a, uint8_t *); -int ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output, - const uint8_t *key_data); - -void ecdh_compute_public_x448 (uint8_t *pubkey, const uint8_t *key_data); -int ecdh_decrypt_x448 (uint8_t *output, const uint8_t *input, - const uint8_t *key_data); - -int ed448_sign (uint8_t *out, const uint8_t *input, unsigned int ilen, - const uint8_t *a_in, const uint8_t *seed, const uint8_t *pk); -void ed448_compute_public (uint8_t *pk, const uint8_t *a_in); - - -const uint8_t *gpg_do_read_simple (uint8_t); -void gpg_do_write_simple (uint8_t, const uint8_t *, int); -void gpg_increment_digital_signature_counter (void); -void gpg_do_get_initial_pw_setting (int is_pw3, int *r_len, - const uint8_t **r_p); -int gpg_do_kdf_check (int len, int how_many); -int gpg_do_get_uif (enum kind_of_key kk); - - -void fatal (uint8_t code) __attribute__ ((noreturn)); -#define FATAL_FLASH 1 -#define FATAL_RANDOM 2 -#define FATAL_HEAP 3 - -extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE]; -extern uint8_t admin_authorized; - -/*** Flash memory tag values ***/ -/* Data objects */ -/* - * Representation of data object: - * - * <-1 halfword-> <--len/2 halfwords-> - * <-tag-><-len-> <---data content---> - */ -#define NR_DO_SEX 0x00 -#define NR_DO_FP_SIG 0x01 -#define NR_DO_FP_DEC 0x02 -#define NR_DO_FP_AUT 0x03 -#define NR_DO_CAFP_1 0x04 -#define NR_DO_CAFP_2 0x05 -#define NR_DO_CAFP_3 0x06 -#define NR_DO_KGTIME_SIG 0x07 -#define NR_DO_KGTIME_DEC 0x08 -#define NR_DO_KGTIME_AUT 0x09 -#define NR_DO_LOGIN_DATA 0x0a -#define NR_DO_URL 0x0b -#define NR_DO_NAME 0x0c -#define NR_DO_LANGUAGE 0x0d -#define NR_DO_PRVKEY_SIG 0x0e -#define NR_DO_PRVKEY_DEC 0x0f -#define NR_DO_PRVKEY_AUT 0x10 -#define NR_DO_KEYSTRING_PW1 0x11 -#define NR_DO_KEYSTRING_RC 0x12 -#define NR_DO_KEYSTRING_PW3 0x13 -#define NR_DO_KDF 0x14 -#define NR_DO__LAST__ 21 /* == 0x15 */ -/* 14-bit counter for DS: Recorded in flash memory by 1-halfword (2-byte). */ -/* - * Representation of 14-bit counter: - * 0: 0x8000 - * 1: 0x8001 - * ... - * 16383: 0xbfff - */ -#define NR_COUNTER_DS 0x80 /* ..0xbf */ -/* 10-bit counter for DS: Recorded in flash memory by 1-halfword (2-byte). */ -/* - * Representation of 10-bit counter: - * 0: 0xc000 - * 1: 0xc001 - * ... - * 1023: 0xc3ff - */ -#define NR_COUNTER_DS_LSB 0xc0 /* ..0xc3 */ -/* - * Boolean object, small enum, or 8-bit integer: - * Recorded in flash memory by 1-halfword (2-byte) - */ -/* - * Representation of Boolean object: - * 0: No record in flash memory - * 1: 0xf000 - */ -#define NR_BOOL_PW1_LIFETIME 0xf0 -/* - * Representation of algorithm attribute object: - * RSA-2048: No record in flash memory - * RSA-4096: 0xf?00 - * ECC p256r1: 0xf?01 - * ECC p256k1: 0xf?02 - * ECC Ed25519: 0xf?03 - * ECC Curve25519: 0xf?04 - * where == 1 (signature), 2 (decryption) or 3 (authentication) - */ -#define NR_KEY_ALGO_ATTR_SIG 0xf1 -#define NR_KEY_ALGO_ATTR_DEC 0xf2 -#define NR_KEY_ALGO_ATTR_AUT 0xf3 -/* - * Representation of User Interaction Flag: - * 0 (UIF disabled): 0xf?00 or No record in flash memory - * 1 (UIF enabled): 0xf?01 - * 2 (UIF permanently enabled): 0xf?02 - * - */ -#define NR_DO_UIF_SIG 0xf6 -#define NR_DO_UIF_DEC 0xf7 -#define NR_DO_UIF_AUT 0xf8 -/* - * NR_UINT_SOMETHING could be here... Use 0xf[459abcd] - */ -/* 123-counters: Recorded in flash memory by 2-halfword (4-byte). */ -/* - * Representation of 123-counters: - * 0: No record in flash memory - * 1: 0xfe?? 0xffff - * 2: 0xfe?? 0xc3c3 - * 3: 0xfe?? 0x0000 - * where is placed at second byte - */ -#define NR_COUNTER_123 0xfe -#define NR_EMPTY 0xff - -#define SIZE_PW_STATUS_BYTES 7 - - -#define NUM_ALL_PRV_KEYS 3 /* SIG, DEC and AUT */ - -#if !defined(OPENPGP_CARD_INITIAL_PW1) -#define OPENPGP_CARD_INITIAL_PW1 "123456" -#endif - -#if !defined(OPENPGP_CARD_INITIAL_PW3) -#define OPENPGP_CARD_INITIAL_PW3 "12345678" -#endif - -extern const uint8_t openpgpcard_aid[]; - -void flash_bool_clear (const uint8_t **addr_p); -const uint8_t *flash_bool_write (uint8_t nr); -void flash_enum_clear (const uint8_t **addr_p); -const uint8_t *flash_enum_write (uint8_t nr, uint8_t v); -int flash_cnt123_get_value (const uint8_t *p); -void flash_cnt123_increment (uint8_t which, const uint8_t **addr_p); -void flash_cnt123_clear (const uint8_t **addr_p); -void flash_put_data (uint16_t hw); -void flash_warning (const char *msg); - -void flash_put_data_internal (const uint8_t *p, uint16_t hw); -void flash_bool_write_internal (const uint8_t *p, int nr); -void flash_enum_write_internal (const uint8_t *p, int nr, uint8_t v); -void flash_cnt123_write_internal (const uint8_t *p, int which, int v); -void flash_do_write_internal (const uint8_t *p, int nr, - const uint8_t *data, int len); - -extern const uint8_t gnuk_string_serial[]; - -#define LED_ONESHOT 1 -#define LED_TWOSHOTS 2 -#define LED_SHOW_STATUS 4 -#define LED_FATAL 8 -#define LED_SYNC 16 -#define LED_GNUK_EXEC 32 -#define LED_START_COMMAND 64 -#define LED_FINISH_COMMAND 128 -#define LED_WAIT_FOR_BUTTON 256 -#define LED_OFF LED_FINISH_COMMAND -void led_blink (int spec); - -#if defined(PINPAD_SUPPORT) -# if defined(PINPAD_CIR_SUPPORT) -void cir_init (void); -# elif defined(PINPAD_DIAL_SUPPORT) -void dial_sw_disable (void); -void dial_sw_enable (void); -# elif defined(PINPAD_DND_SUPPORT) -void msc_init (void); -void msc_media_insert_change (int available); -int msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size); -int msc_scsi_read (uint32_t lba, const uint8_t **sector_p); -void msc_scsi_stop (uint8_t code); -# endif -#define PIN_INPUT_CURRENT 1 -#define PIN_INPUT_NEW 2 -#define PIN_INPUT_CONFIRM 3 -#define MAX_PIN_CHARS 32 -extern uint8_t pin_input_buffer[MAX_PIN_CHARS]; -extern uint8_t pin_input_len; - -int pinpad_getline (int msg_code, uint32_t timeout_usec); - -#endif - - -extern uint8_t _regnual_start, __heap_end__[]; - -uint8_t * sram_address (uint32_t offset); - -static inline const uint8_t * -unique_device_id (void) -{ - /* - * STM32F103 has 96-bit unique device identifier. - * This routine mimics that. - */ - - static const uint8_t id[] = { /* My RSA fingerprint */ - 0x12, 0x41, 0x24, 0xBD, 0x3B, 0x48, 0x62, 0xAF, - 0x7A, 0x0A, 0x42, 0xF1, 0x00, 0xB4, 0x5E, 0xBD, - 0x4C, 0xA7, 0xBA, 0xBE - }; - - return id; -} - - - -#endif \ No newline at end of file diff --git a/src/openpgp/jpc-ac_p256k1.h b/src/openpgp/jpc-ac_p256k1.h deleted file mode 100644 index d8624bd..0000000 --- a/src/openpgp/jpc-ac_p256k1.h +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @brief Jacobian projective coordinates - */ -typedef struct -{ - bn256 x[1]; - bn256 y[1]; - bn256 z[1]; -} jpc; - -void jpc_double_p256k1 (jpc *X, const jpc *A); -void jpc_add_ac_p256k1 (jpc *X, const jpc *A, const ac *B); -void jpc_add_ac_signed_p256k1 (jpc *X, const jpc *A, const ac *B, int minus); -int jpc_to_ac_p256k1 (ac *X, const jpc *A); diff --git a/src/openpgp/jpc.c b/src/openpgp/jpc.c deleted file mode 100644 index e6a1f7d..0000000 --- a/src/openpgp/jpc.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * jpc.c -- arithmetic on Jacobian projective coordinates. - * - * Copyright (C) 2011, 2013 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include "field-group-select.h" - -/** - * @brief X = 2 * A - * - * @param X Destination JPC - * @param A JPC - */ -void -FUNC(jpc_double) (jpc *X, const jpc *A) -{ - bn256 a[1], b[1], c[1], tmp0[1]; - bn256 *d; - - if (bn256_is_zero (A->z)) /* A is infinite */ - return; - - d = X->x; - MFNC(sqr) (a, A->y); - memcpy (b, a, sizeof (bn256)); - MFNC(mul) (a, a, A->x); - MFNC(shift) (a, a, 2); - - MFNC(sqr) (b, b); - MFNC(shift) (b, b, 3); - -#if defined(COEFFICIENT_A_IS_MINUS_3) - MFNC(sqr) (tmp0, A->z); - MFNC(sub) (c, A->x, tmp0); - MFNC(add) (tmp0, tmp0, A->x); - MFNC(mul) (tmp0, tmp0, c); - MFNC(shift) (c, tmp0, 1); - MFNC(add) (c, c, tmp0); -#elif defined (COEFFICIENT_A_IS_ZERO) - MFNC(sqr) (tmp0, A->x); - MFNC(shift) (c, tmp0, 1); - MFNC(add) (c, c, tmp0); -#else -#error "not supported." -#endif - - MFNC(sqr) (d, c); - MFNC(shift) (tmp0, a, 1); - MFNC(sub) (d, d, tmp0); - - MFNC(mul) (X->z, A->y, A->z); - MFNC(shift) (X->z, X->z, 1); - - MFNC(sub) (tmp0, a, d); - MFNC(mul) (tmp0, c, tmp0); - MFNC(sub) (X->y, tmp0, b); -} - -/** - * @brief X = A + B - * - * @param X Destination JPC - * @param A JPC - * @param B AC - * @param MINUS if 1 subtraction, addition otherwise. - */ -void -FUNC(jpc_add_ac_signed) (jpc *X, const jpc *A, const ac *B, int minus) -{ - bn256 a[1], b[1], c[1], d[1], tmp[1]; -#define minus_B_y c -#define c_sqr a -#define c_cube b -#define x1_c_sqr c -#define x1_c_sqr_2 c -#define c_cube_plus_x1_c_sqr_2 c -#define x1_c_sqr_copy a -#define y3_tmp c -#define y1_c_cube a - - if (bn256_is_zero (A->z)) /* A is infinite */ - { - memcpy (X->x, B->x, sizeof (bn256)); - if (minus) - { - memcpy (tmp, B->y, sizeof (bn256)); - bn256_sub (X->y, CONST_P256, B->y); - } - else - { - memcpy (X->y, B->y, sizeof (bn256)); - bn256_sub (tmp, CONST_P256, B->y); - } - memset (X->z, 0, sizeof (bn256)); - X->z->word[0] = 1; - return; - } - - MFNC(sqr) (a, A->z); - memcpy (b, a, sizeof (bn256)); - MFNC(mul) (a, a, B->x); - - MFNC(mul) (b, b, A->z); - if (minus) - { - bn256_sub (minus_B_y, CONST_P256, B->y); - MFNC(mul) (b, b, minus_B_y); - } - else - { - bn256_sub (tmp, CONST_P256, B->y); - MFNC(mul) (b, b, B->y); - } - - if (bn256_cmp (A->x, a) == 0 && bn256_cmp (A->y, b) == 0) - { - FUNC(jpc_double) (X, A); - return; - } - - MFNC(sub) (c, a, A->x); - MFNC(sub) (d, b, A->y); - - MFNC(mul) (X->z, A->z, c); - - MFNC(sqr) (c_sqr, c); - MFNC(mul) (c_cube, c_sqr, c); - - MFNC(mul) (x1_c_sqr, A->x, c_sqr); - - MFNC(sqr) (X->x, d); - memcpy (x1_c_sqr_copy, x1_c_sqr, sizeof (bn256)); - MFNC(shift) (x1_c_sqr_2, x1_c_sqr, 1); - MFNC(add) (c_cube_plus_x1_c_sqr_2, x1_c_sqr_2, c_cube); - MFNC(sub) (X->x, X->x, c_cube_plus_x1_c_sqr_2); - - MFNC(sub) (y3_tmp, x1_c_sqr_copy, X->x); - MFNC(mul) (y3_tmp, y3_tmp, d); - MFNC(mul) (y1_c_cube, A->y, c_cube); - MFNC(sub) (X->y, y3_tmp, y1_c_cube); -} - -/** - * @brief X = A + B - * - * @param X Destination JPC - * @param A JPC - * @param B AC - */ -void -FUNC(jpc_add_ac) (jpc *X, const jpc *A, const ac *B) -{ - FUNC(jpc_add_ac_signed) (X, A, B, 0); -} - -/** - * @brief X = convert A - * - * @param X Destination AC - * @param A JPC - * - * Return -1 on error (infinite). - * Return 0 on success. - */ -int -FUNC(jpc_to_ac) (ac *X, const jpc *A) -{ - bn256 z_inv[1], z_inv_sqr[1]; - - if (bn256_is_zero (A->z)) - return -1; - - mod_inv (z_inv, A->z, CONST_P256); - - MFNC(sqr) (z_inv_sqr, z_inv); - MFNC(mul) (z_inv, z_inv, z_inv_sqr); - - MFNC(mul) (X->x, A->x, z_inv_sqr); - MFNC(mul) (X->y, A->y, z_inv); - return 0; -} diff --git a/src/openpgp/jpc_p256k1.c b/src/openpgp/jpc_p256k1.c deleted file mode 100644 index a903b12..0000000 --- a/src/openpgp/jpc_p256k1.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * jpc_p256k1.c -- arithmetic on Jacobian projective coordinates for p256k1. - * - * Copyright (C) 2014 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include -#include "bn.h" -#include "mod.h" -#include "modp256k1.h" -#include "affine.h" -#include "jpc-ac_p256k1.h" - -#define FIELD p256k1 -#define CONST_P256 P256K1 -#define COEFFICIENT_A_IS_ZERO 1 - -#include "jpc.c" diff --git a/src/openpgp/mod.c b/src/openpgp/mod.c deleted file mode 100644 index 340fc16..0000000 --- a/src/openpgp/mod.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * mod.c -- modulo arithmetic - * - * Copyright (C) 2011, 2014 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include -#include "bn.h" - -/** - * @brief X = A mod B (using MU=(1<<(256)+MU_lower)) (Barret reduction) - * - */ -void -mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower) -{ - bn256 q[1]; - bn512 q_big[1], tmp[1]; - uint32_t carry; -#define borrow carry - - memset (q, 0, sizeof (bn256)); - q->word[0] = A->word[15]; - bn256_mul (tmp, q, MU_lower); - tmp->word[8] += A->word[15]; - carry = (tmp->word[8] < A->word[15]); - tmp->word[9] += carry; - - q->word[7] = A->word[14]; - q->word[6] = A->word[13]; - q->word[5] = A->word[12]; - q->word[4] = A->word[11]; - q->word[3] = A->word[10]; - q->word[2] = A->word[9]; - q->word[1] = A->word[8]; - q->word[0] = A->word[7]; - bn256_mul (q_big, q, MU_lower); - bn256_add ((bn256 *)&q_big->word[8], (bn256 *)&q_big->word[8], q); - - q->word[0] = q_big->word[9] + tmp->word[1]; - carry = (q->word[0] < tmp->word[1]); - - q->word[1] = q_big->word[10] + carry; - carry = (q->word[1] < carry); - q->word[1] += tmp->word[2]; - carry += (q->word[1] < tmp->word[2]); - - q->word[2] = q_big->word[11] + carry; - carry = (q->word[2] < carry); - q->word[2] += tmp->word[3]; - carry += (q->word[2] < tmp->word[3]); - - q->word[3] = q_big->word[12] + carry; - carry = (q->word[3] < carry); - q->word[3] += tmp->word[4]; - carry += (q->word[3] < tmp->word[4]); - - q->word[4] = q_big->word[13] + carry; - carry = (q->word[4] < carry); - q->word[4] += tmp->word[5]; - carry += (q->word[4] < tmp->word[5]); - - q->word[5] = q_big->word[14] + carry; - carry = (q->word[5] < carry); - q->word[5] += tmp->word[6]; - carry += (q->word[5] < tmp->word[6]); - - q->word[6] = q_big->word[15] + carry; - carry = (q->word[6] < carry); - q->word[6] += tmp->word[7]; - carry += (q->word[6] < tmp->word[7]); - - q->word[7] = carry; - q->word[7] += tmp->word[8]; - carry = (q->word[7] < tmp->word[8]); - - memset (q_big, 0, sizeof (bn512)); - q_big->word[8] = A->word[8]; - q_big->word[7] = A->word[7]; - q_big->word[6] = A->word[6]; - q_big->word[5] = A->word[5]; - q_big->word[4] = A->word[4]; - q_big->word[3] = A->word[3]; - q_big->word[2] = A->word[2]; - q_big->word[1] = A->word[1]; - q_big->word[0] = A->word[0]; - - bn256_mul (tmp, q, B); - tmp->word[8] += carry * B->word[0]; - tmp->word[15] = tmp->word[14] = tmp->word[13] = tmp->word[12] - = tmp->word[11] = tmp->word[10] = tmp->word[9] = 0; - - borrow = bn256_sub (X, (bn256 *)&q_big->word[0], (bn256 *)&tmp->word[0]); - q_big->word[8] -= borrow; - q_big->word[8] -= tmp->word[8]; - - carry = q_big->word[8]; - if (carry) - carry -= bn256_sub (X, X, B); - else - bn256_sub (q, X, B); - - if (carry) - bn256_sub (X, X, B); - else - bn256_sub (q, X, B); - - borrow = bn256_sub (q, X, B); - if (borrow) - memcpy (q, X, sizeof (bn256)); - else - memcpy (X, q, sizeof (bn256)); -#undef borrow -} - -/* - * Reference: - * Donald E. Knuth, The Art of Computer Programming, Vol. 2: - * Seminumerical Algorithms, 3rd ed. Reading, MA: Addison-Wesley, 1998 - * - * Max loop: X=0x8000...0000 and N=0xffff...ffff - */ -#define MAX_GCD_STEPS_BN256 (3*256-2) - -/** - * @brief C = X^(-1) mod N - * - * Assume X and N are co-prime (or N is prime). - * NOTE: If X==0, it return 0. - * - */ -void -mod_inv (bn256 *C, const bn256 *X, const bn256 *N) -{ - bn256 u[1], v[1], tmp[1]; - bn256 A[1] = { { { 1, 0, 0, 0, 0, 0, 0, 0 } } }; - uint32_t carry; -#define borrow carry - int n = MAX_GCD_STEPS_BN256; - - memset (tmp, 0, sizeof (bn256)); - memset (C, 0, sizeof (bn256)); - memcpy (u, X, sizeof (bn256)); - memcpy (v, N, sizeof (bn256)); - - while (n--) - { - int c = (bn256_is_even (u) << 1) + bn256_is_even (v); - - switch (c) - { - case 3: - bn256_shift (u, u, -1); - if (bn256_is_even (A)) - { - bn256_add (tmp, A, N); - carry = 0; - } - else - carry = bn256_add (A, A, N); - - bn256_shift (A, A, -1); - A->word[7] |= carry * 0x80000000; - - bn256_shift (v, v, -1); - if (bn256_is_even (C)) - { - bn256_add (tmp, C, N); - carry = 0; - } - else - carry = bn256_add (C, C, N); - - bn256_shift (C, C, -1); - C->word[7] |= carry * 0x80000000; - - if (bn256_is_ge (tmp, tmp)) - { - bn256_sub (tmp, tmp, tmp); - borrow = bn256_sub (tmp, tmp, tmp); - if (borrow) - bn256_add (tmp, tmp, tmp); - else - bn256_add (tmp, A, N); - } - else - { - bn256_sub (tmp, tmp, tmp); - borrow = bn256_sub (tmp, tmp, tmp); - if (borrow) - bn256_add (tmp, tmp, tmp); - else - bn256_add (tmp, tmp, N); - } - break; - - case 1: - bn256_shift (tmp, tmp, -1); - if (bn256_is_even (tmp)) - { - bn256_add (tmp, tmp, N); - carry = 0; - } - else - carry = bn256_add (tmp, tmp, N); - - bn256_shift (tmp, tmp, -1); - tmp->word[7] |= carry * 0x80000000; - - bn256_shift (v, v, -1); - if (bn256_is_even (C)) - { - bn256_add (tmp, C, N); - carry = 0; - } - else - carry = bn256_add (C, C, N); - - bn256_shift (C, C, -1); - C->word[7] |= carry * 0x80000000; - - if (bn256_is_ge (tmp, tmp)) - { - bn256_sub (tmp, tmp, tmp); - borrow = bn256_sub (tmp, tmp, tmp); - if (borrow) - bn256_add (tmp, tmp, tmp); - else - bn256_add (tmp, A, N); - } - else - { - bn256_sub (tmp, tmp, tmp); - borrow = bn256_sub (tmp, tmp, tmp); - if (borrow) - bn256_add (tmp, tmp, tmp); - else - bn256_add (tmp, tmp, N); - } - break; - - case 2: - bn256_shift (u, u, -1); - if (bn256_is_even (A)) - { - bn256_add (tmp, A, N); - carry = 0; - } - else - carry = bn256_add (A, A, N); - - bn256_shift (A, A, -1); - A->word[7] |= carry * 0x80000000; - - bn256_shift (tmp, tmp, -1); - if (bn256_is_even (tmp)) - { - bn256_add (tmp, tmp, N); - carry = 0; - } - else - carry = bn256_add (tmp, tmp, N); - - bn256_shift (tmp, tmp, -1); - tmp->word[7] |= carry * 0x80000000; - - if (bn256_is_ge (tmp, tmp)) - { - bn256_sub (tmp, tmp, tmp); - borrow = bn256_sub (tmp, tmp, tmp); - if (borrow) - bn256_add (tmp, tmp, tmp); - else - bn256_add (tmp, A, N); - } - else - { - bn256_sub (tmp, tmp, tmp); - borrow = bn256_sub (tmp, tmp, tmp); - if (borrow) - bn256_add (tmp, tmp, tmp); - else - bn256_add (tmp, tmp, N); - } - break; - - case 0: - bn256_shift (tmp, tmp, -1); - if (bn256_is_even (tmp)) - { - bn256_add (tmp, tmp, N); - carry = 0; - } - else - carry = bn256_add (tmp, tmp, N); - - bn256_shift (tmp, tmp, -1); - tmp->word[7] |= carry * 0x80000000; - - bn256_shift (tmp, tmp, -1); - if (bn256_is_even (tmp)) - { - bn256_add (tmp, tmp, N); - carry = 0; - } - else - carry = bn256_add (tmp, tmp, N); - - bn256_shift (tmp, tmp, -1); - tmp->word[7] |= carry * 0x80000000; - - if (bn256_is_ge (u, v)) - { - bn256_sub (u, u, v); - borrow = bn256_sub (A, A, C); - if (borrow) - bn256_add (A, A, N); - else - bn256_add (tmp, A, N); - } - else - { - bn256_sub (v, v, u); - borrow = bn256_sub (C, C, A); - if (borrow) - bn256_add (C, C, N); - else - bn256_add (tmp, C, N); - } - break; - } - } -#undef borrow -} diff --git a/src/openpgp/mod.h b/src/openpgp/mod.h deleted file mode 100644 index 117bcc7..0000000 --- a/src/openpgp/mod.h +++ /dev/null @@ -1,3 +0,0 @@ -void mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, - const bn256 *MU_lower); -void mod_inv (bn256 *X, const bn256 *A, const bn256 *N); diff --git a/src/openpgp/mod25638.c b/src/openpgp/mod25638.c deleted file mode 100644 index 975a6b4..0000000 --- a/src/openpgp/mod25638.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * mod25638.c -- modulo arithmetic of 2^256-38 for 2^255-19 field - * - * Copyright (C) 2014 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -/* - * The field is \Z/(2^255-19) - * - * We use radix-32. During computation, it's not reduced to 2^255-19, - * but it is represented in 256-bit (it is redundant representation), - * that is, something like 2^256-38. - * - * The idea is, keeping within 256-bit until it will be converted to - * affine coordinates. - */ - -#include -#include - -#include "bn.h" -#include "mod25638.h" - -#ifndef BN256_C_IMPLEMENTATION -#define ASM_IMPLEMENTATION 0 -#endif - -#if ASM_IMPLEMENTATION -#include "muladd_256.h" -#define ADDWORD_256(d_,s_,w_,c_) \ - asm ( "ldmia %[s]!, { r4, r5, r6, r7 } \n\t" \ - "adds r4, r4, %[w] \n\t" \ - "adcs r5, r5, #0 \n\t" \ - "adcs r6, r6, #0 \n\t" \ - "adcs r7, r7, #0 \n\t" \ - "stmia %[d]!, { r4, r5, r6, r7 }\n\t" \ - "ldmia %[s]!, { r4, r5, r6, r7 } \n\t" \ - "adcs r4, r4, #0 \n\t" \ - "adcs r5, r5, #0 \n\t" \ - "adcs r6, r6, #0 \n\t" \ - "adcs r7, r7, #0 \n\t" \ - "stmia %[d]!, { r4, r5, r6, r7 }\n\t" \ - "mov %[c], #0 \n\t" \ - "adc %[c], %[c], #0" \ - : [s] "=&r" (s_), [d] "=&r" (d_), [c] "=&r" (c_) \ - : "[s]" (s_), "[d]" (d_), [w] "r" (w_) \ - : "r4", "r5", "r6", "r7", "memory", "cc" ) -#endif - -/* -256 224 192 160 128 96 64 32 0 -2^256 - 1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 -2^256 - 16 - 0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffff0 -2^256 - 16 - 2 - 0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffee -2^256 - 16 - 2 - 1 - 0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffed -*/ -const bn256 p25519[1] = { - {{ 0xffffffed, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff }} }; - - -/* - * Implementation Note. - * - * It's not always modulo n25638. The representation is redundant - * during computation. For example, when we add the number - 1 and 1, - * it won't overflow to 2^256, and the result is represented within - * 256-bit. - */ - - -/** - * @brief X = (A + B) mod 2^256-38 - */ -void -mod25638_add (bn256 *X, const bn256 *A, const bn256 *B) -{ - uint32_t carry; - - carry = bn256_add (X, A, B); - carry = bn256_add_uint (X, X, carry*38); - X->word[0] += carry * 38; -} - -/** - * @brief X = (A - B) mod 2^256-38 - */ -void -mod25638_sub (bn256 *X, const bn256 *A, const bn256 *B) -{ - uint32_t borrow; - - borrow = bn256_sub (X, A, B); - borrow = bn256_sub_uint (X, X, borrow*38); - X->word[0] -= borrow * 38; -} - - -/** - * @brief X = A mod 2^256-38 - * - * Note that the second argument is not "const bn512 *". - * A is modified during the computation of modulo. - * - * It's not precisely modulo 2^256-38 for all cases, - * but result may be redundant. - */ -static void -mod25638_reduce (bn256 *X, bn512 *A) -{ - const uint32_t *s; - uint32_t *d; - uint32_t w; - -#if ASM_IMPLEMENTATION - uint32_t c, c0; - - s = &A->word[8]; d = &A->word[0]; w = 38; MULADD_256 (s, d, w, c); - c0 = A->word[8] * 38; - d = &X->word[0]; - s = &A->word[0]; - ADDWORD_256 (d, s, c0, c); - X->word[0] += c * 38; -#else - s = &A->word[8]; d = &A->word[0]; w = 38; - { - int i; - uint64_t r; - uint32_t carry; - - r = 0; - for (i = 0; i < BN256_WORDS; i++) - { - uint64_t uv; - - r += d[i]; - carry = (r < d[i]); - - uv = ((uint64_t)s[i])*w; - r += uv; - carry += (r < uv); - - d[i] = (uint32_t)r; - r = ((r >> 32) | ((uint64_t)carry << 32)); - } - - carry = bn256_add_uint (X, (bn256 *)A, r * 38); - X->word[0] += carry * 38; - } -#endif -} - -/** - * @brief X = (A * B) mod 2^256-38 - */ -void -mod25638_mul (bn256 *X, const bn256 *A, const bn256 *B) -{ - bn512 tmp[1]; - - bn256_mul (tmp, A, B); - mod25638_reduce (X, tmp); -} - -/** - * @brief X = A * A mod 2^256-38 - */ -void -mod25638_sqr (bn256 *X, const bn256 *A) -{ - bn512 tmp[1]; - - bn256_sqr (tmp, A); - mod25638_reduce (X, tmp); -} - - -/** - * @brief X = (A << shift) mod 2^256-38 - * @note shift < 32 - */ -void -mod25638_shift (bn256 *X, const bn256 *A, int shift) -{ - uint32_t carry; - bn256 tmp[1]; - - carry = bn256_shift (X, A, shift); - if (shift < 0) - return; - - memset (tmp, 0, sizeof (bn256)); - tmp->word[0] = (carry << 1); - /* tmp->word[1] = (carry >> 31); always zero. */ - tmp->word[0] = tmp->word[0] + (carry << 2); - tmp->word[1] = (tmp->word[0] < (carry << 2)) + (carry >> 30); - tmp->word[0] = tmp->word[0] + (carry << 5); - tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 5)) + (carry >> 27); - - mod25638_add (X, X, tmp); -} - - -/* - * @brief X = A mod 2^255-19 - * - * It's precisely modulo 2^255-19 (unlike mod25638_reduce). - */ -void -mod25519_reduce (bn256 *X) -{ - uint32_t q; - bn256 r0[1], r1[1]; - int flag; - - memcpy (r0, X, sizeof (bn256)); - q = (r0->word[7] >> 31); - r0->word[7] &= 0x7fffffff; - if (q) - { - bn256_add_uint (r0, r0, 19); - q = (r0->word[7] >> 31); - r0->word[7] &= 0x7fffffff; - if (q) - { - bn256_add_uint (r1, r0, 19); - q = (r1->word[7] >> 31); - r1->word[7] &= 0x7fffffff; - flag = 0; - } - else - flag = 1; - } - else - { - bn256_add_uint (r1, r0, 19); - q = (r1->word[7] >> 31); /* dummy */ - r1->word[7] &= 0x7fffffff; /* dummy */ - if (q) - flag = 2; - else - flag = 3; - } - - if (flag) - { - bn256_add_uint (r1, r0, 19); - q = (r1->word[7] >> 31); - r1->word[7] &= 0x7fffffff; - if (q) - memcpy (X, r1, sizeof (bn256)); - else - memcpy (X, r0, sizeof (bn256)); - } - else - { - if (q) - { - asm volatile ("" : : "r" (q) : "memory"); - memcpy (X, r1, sizeof (bn256)); - asm volatile ("" : : "r" (q) : "memory"); - } - else - memcpy (X, r1, sizeof (bn256)); - } -} diff --git a/src/openpgp/mod25638.h b/src/openpgp/mod25638.h deleted file mode 100644 index 8773611..0000000 --- a/src/openpgp/mod25638.h +++ /dev/null @@ -1,7 +0,0 @@ -extern const bn256 p25519[1]; - -void mod25638_add (bn256 *X, const bn256 *A, const bn256 *B); -void mod25638_sub (bn256 *X, const bn256 *A, const bn256 *B); -void mod25638_mul (bn256 *X, const bn256 *A, const bn256 *B); -void mod25638_sqr (bn256 *X, const bn256 *A); -void mod25519_reduce (bn256 *X); diff --git a/src/openpgp/modp256k1.c b/src/openpgp/modp256k1.c deleted file mode 100644 index 299647b..0000000 --- a/src/openpgp/modp256k1.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * modp256k1.c -- modulo arithmetic for p256k1 - * - * Copyright (C) 2014, 2016, 2020 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -/* - * p256k1 = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 - */ -#include -#include - -#include "bn.h" -#include "modp256k1.h" - -/* -256 224 192 160 128 96 64 32 0 -2^256 - 1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 -2^256 - 2^32 - 0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff 00000000 -2^256 - 2^32 - 2^9 - 0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffe00 -2^256 - 2^32 - 2^9 - 2^8 - 0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffd00 -2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc80 -2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc40 -2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc30 -2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 - 0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f -*/ -const bn256 p256k1 = { {0xfffffc2f, 0xfffffffe, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } }; - -/* - * Implementation Note. - * - * It's always modulo p256k1. - * - * Once, I tried redundant representation which caused wrong - * calculation. Implementation could be correct with redundant - * representation, but it found that it's more expensive. - * - */ - -/** - * @brief X = (A + B) mod p256k1 - */ -void -modp256k1_add (bn256 *X, const bn256 *A, const bn256 *B) -{ - uint32_t cond; - bn256 tmp[1]; - bn256 dummy[1]; - - cond = (bn256_add (X, A, B) == 0); - cond &= bn256_sub (tmp, X, P256K1); - memcpy (cond?dummy:X, tmp, sizeof (bn256)); - asm ("" : "=m" (dummy) : "m" (dummy) : "memory"); -} - -/** - * @brief X = (A - B) mod p256 - */ -void -modp256k1_sub (bn256 *X, const bn256 *A, const bn256 *B) -{ - uint32_t borrow; - bn256 tmp[1]; - bn256 dummy[1]; - - borrow = bn256_sub (X, A, B); - bn256_add (tmp, X, P256K1); - memcpy (borrow?X:dummy, tmp, sizeof (bn256)); - asm ("" : "=m" (dummy) : "m" (dummy) : "memory"); -} - -/** - * @brief X = A mod p256k1 - */ -void -modp256k1_reduce (bn256 *X, const bn512 *A) -{ - bn256 tmp[1]; - uint32_t carry; -#define borrow carry - uint32_t s0, s1; -#define s00 tmp->word[0] -#define s01 tmp->word[1] -#define s02 tmp->word[2] - -#define W0 X -#define W1 tmp -#define W2 tmp -#define W3 tmp -#define W4 tmp -#define W5 tmp -#define W6 tmp -#define W7 tmp -#define S tmp - - /* - * Suppose: P256K1 = 2^256 - CONST - * Then, compute: W = A_low + A_high * CONST - * 256-bit W0 = W mod 2^256 - * 64-bit (S1, S0) = W / 2^256 - * where: CONST = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 - */ - - /* W0 = A_low */ - /* W7 = A_high */ - /* W0 += W7 */ - carry = bn256_add (W0, (const bn256 *)&A->word[8], (const bn256 *)A); - - /* W6 = W7 << 4 */ - /* W0 += W6 */ - bn256_shift (W6, (const bn256 *)&A->word[8], 4); - carry += bn256_add (W0, W0, W6); - - /* W5 = W6 << 2 */ - /* W0 += W5 */ - bn256_shift (W5, W6, 2); - carry += bn256_add (W0, W0, W5); - - /* W4 = W5 << 1 */ - /* W0 += W4 */ - bn256_shift (W4, W5, 1); - carry += bn256_add (W0, W0, W4); - - /* W3 = W4 << 1 */ - /* W0 += W3 */ - bn256_shift (W3, W4, 1); - carry += bn256_add (W0, W0, W3); - - /* W2 = W3 << 1 */ - /* W0 += W2 */ - bn256_shift (W2, W3, 1); - carry += bn256_add (W0, W0, W2); - - /* W1 = A_high << 32 */ - /* W0 += W1 */ - W1->word[7] = A->word[14]; - W1->word[6] = A->word[13]; - W1->word[5] = A->word[12]; - W1->word[4] = A->word[11]; - W1->word[3] = A->word[10]; - W1->word[2] = A->word[9]; - W1->word[1] = A->word[8]; - W1->word[0] = 0; - carry += bn256_add (W0, W0, W1); - - /* (S1, S0) = W / 2^256 */ - s0 = A->word[15]; - carry += (s0 >> 28) + (s0 >> 26) + (s0 >> 25) + (s0 >> 24) + (s0 >> 23); - carry += s0; - s1 = (carry < s0) ? 1 : 0; - s0 = carry; - - /* - * Compute: S:=(S02, S01, S00), S = (S1,S0)*CONST - */ - S->word[7] = S->word[6] = S->word[5] = S->word[4] = S->word[3] = 0; - - /* (S02, S01, S00) = (S1, S0) + (S1, S0)*2^32 */ - s00 = s0; - s01 = s0 + s1; - s02 = s1 + ((s01 < s0)? 1 : 0); - - /* (S02, S01, S00) += (S1, S0)*2^9 */ - carry = (s0 >> 23) + s01; - s02 += (s1 >> 23) + ((carry < s01)? 1 : 0); - s01 = (s1 << 9) + carry; - s02 += ((s01 < carry)? 1 : 0); - s00 += (s0 << 9); - carry = ((s00 < (s0 << 9))? 1 : 0); - s01 += carry; - s02 += ((s01 < carry)? 1 : 0); - - /* (S02, S01, S00) += (S1, S0)*2^8 */ - carry = (s0 >> 24) + s01; - s02 += (s1 >> 24) + ((carry < s01)? 1 : 0); - s01 = (s1 << 8) + carry; - s02 += ((s01 < carry)? 1 : 0); - s00 += (s0 << 8); - carry = ((s00 < (s0 << 8))? 1 : 0); - s01 += carry; - s02 += ((s01 < carry)? 1 : 0); - - /* (S02, S01, S00) += (S1, S0)*2^7 */ - carry = (s0 >> 25) + s01; - s02 += (s1 >> 25) + ((carry < s01)? 1 : 0); - s01 = (s1 << 7) + carry; - s02 += ((s01 < carry)? 1 : 0); - s00 += (s0 << 7); - carry = ((s00 < (s0 << 7))? 1 : 0); - s01 += carry; - s02 += ((s01 < carry)? 1 : 0); - - /* (S02, S01, S00) += (S1, S0)*2^6 */ - carry = (s0 >> 26) + s01; - s02 += (s1 >> 26) + ((carry < s01)? 1 : 0); - s01 = (s1 << 6) + carry; - s02 += ((s01 < carry)? 1 : 0); - s00 += (s0 << 6); - carry = ((s00 < (s0 << 6))? 1 : 0); - s01 += carry; - s02 += ((s01 < carry)? 1 : 0); - - /* (S02, S01, S00) += (S1, S0)*2^4 */ - carry = (s0 >> 28) + s01; - s02 += (s1 >> 28) + ((carry < s01)? 1 : 0); - s01 = (s1 << 4) + carry; - s02 += ((s01 < carry)? 1 : 0); - s00 += (s0 << 4); - carry = ((s00 < (s0 << 4))? 1 : 0); - s01 += carry; - s02 += ((s01 < carry)? 1 : 0); - - /* W0 += S */ - modp256k1_add (W0, W0, S); - - borrow = bn256_sub (tmp, W0, P256K1); - if (borrow) - memcpy (tmp, W0, sizeof (bn256)); - else - memcpy (W0, tmp, sizeof (bn256)); - -#undef W0 -#undef W1 -#undef W2 -#undef W3 -#undef W4 -#undef W5 -#undef W6 -#undef W7 -#undef S -#undef s00 -#undef s01 -#undef s02 -#undef borrow -} - -/** - * @brief X = (A * B) mod p256k1 - */ -void -modp256k1_mul (bn256 *X, const bn256 *A, const bn256 *B) -{ - bn512 AB[1]; - - bn256_mul (AB, A, B); - modp256k1_reduce (X, AB); -} - -/** - * @brief X = A * A mod p256k1 - */ -void -modp256k1_sqr (bn256 *X, const bn256 *A) -{ - bn512 AA[1]; - - bn256_sqr (AA, A); - modp256k1_reduce (X, AA); -} - - -/** - * @brief X = (A << shift) mod p256k1 - * @note shift < 32 - */ -void -modp256k1_shift (bn256 *X, const bn256 *A, int shift) -{ - uint32_t carry; - bn256 tmp[1]; - - carry = bn256_shift (X, A, shift); - if (shift < 0) - return; - - memset (tmp, 0, sizeof (bn256)); - tmp->word[0] = carry + (carry << 9); - tmp->word[1] = carry + (tmp->word[0] < (carry << 9)) + (carry >> 23); - tmp->word[0] = tmp->word[0] + (carry << 8); - tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 8)) + (carry >> 24); - tmp->word[0] = tmp->word[0] + (carry << 7); - tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 7)) + (carry >> 25); - tmp->word[0] = tmp->word[0] + (carry << 6); - tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 6)) + (carry >> 26); - tmp->word[0] = tmp->word[0] + (carry << 4); - tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 4)) + (carry >> 28); - - modp256k1_add (X, X, tmp); -} diff --git a/src/openpgp/modp256k1.h b/src/openpgp/modp256k1.h deleted file mode 100644 index 3e20ab5..0000000 --- a/src/openpgp/modp256k1.h +++ /dev/null @@ -1,9 +0,0 @@ -extern const bn256 p256k1; -#define P256K1 (&p256k1) - -void modp256k1_add (bn256 *X, const bn256 *A, const bn256 *B); -void modp256k1_sub (bn256 *X, const bn256 *A, const bn256 *B); -void modp256k1_reduce (bn256 *X, const bn512 *A); -void modp256k1_mul (bn256 *X, const bn256 *A, const bn256 *B); -void modp256k1_sqr (bn256 *X, const bn256 *A); -void modp256k1_shift (bn256 *X, const bn256 *A, int shift); diff --git a/src/openpgp/muladd_256.h b/src/openpgp/muladd_256.h deleted file mode 100644 index f37d976..0000000 --- a/src/openpgp/muladd_256.h +++ /dev/null @@ -1,50 +0,0 @@ -#define MULADD_256_ASM(s_,d_,w_,c_) \ - asm ( "ldmia %[s]!, { r8, r9, r10 } \n\t" \ - "ldmia %[d], { r5, r6, r7 } \n\t" \ - "umull r4, r8, %[w], r8 \n\t" \ - "adds r5, r5, r4 \n\t" \ - "adcs r6, r6, r8 \n\t" \ - "umull r4, r8, %[w], r9 \n\t" \ - "adc %[c], r8, #0 \n\t" \ - "adds r6, r6, r4 \n\t" \ - "adcs r7, r7, %[c] \n\t" \ - "umull r4, r8, %[w], r10 \n\t" \ - "adc %[c], r8, #0 \n\t" \ - "adds r7, r7, r4 \n\t" \ - "stmia %[d]!, { r5, r6, r7 } \n\t" \ - "ldmia %[s]!, { r8, r9, r10 } \n\t" \ - "ldmia %[d], { r5, r6, r7 } \n\t" \ - "adcs r5, r5, %[c] \n\t" \ - "umull r4, r8, %[w], r8 \n\t" \ - "adc %[c], r8, #0 \n\t" \ - "adds r5, r5, r4 \n\t" \ - "adcs r6, r6, %[c] \n\t" \ - "umull r4, r8, %[w], r9 \n\t" \ - "adc %[c], r8, #0 \n\t" \ - "adds r6, r6, r4 \n\t" \ - "adcs r7, r7, %[c] \n\t" \ - "umull r4, r8, %[w], r10 \n\t" \ - "adc %[c], r8, #0 \n\t" \ - "adds r7, r7, r4 \n\t" \ - "stmia %[d]!, { r5, r6, r7 } \n\t" \ - "ldmia %[s]!, { r8, r9 } \n\t" \ - "ldmia %[d], { r5, r6 } \n\t" \ - "adcs r5, r5, %[c] \n\t" \ - "umull r4, r8, %[w], r8 \n\t" \ - "adc %[c], r8, #0 \n\t" \ - "adds r5, r5, r4 \n\t" \ - "adcs r6, r6, %[c] \n\t" \ - "umull r4, r8, %[w], r9 \n\t" \ - "adc %[c], r8, #0 \n\t" \ - "adds r6, r6, r4 \n\t" \ - "adc %[c], %[c], #0 \n\t" \ - "stmia %[d]!, { r5, r6 }" \ - : [s] "=&r" (s_), [d] "=&r" (d_), [c] "=&r" (c_) \ - : "[s]" (s_), "[d]" (d_), [w] "r" (w_) \ - : "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "memory", "cc" ) - -#define MULADD_256(s__,d__,w__,c__) do { \ - MULADD_256_ASM(s__,d__,w__,c__); \ - *d__ = c__; \ -} while (0) diff --git a/src/openpgp/openpgp-do.c b/src/openpgp/openpgp-do.c deleted file mode 100644 index 925b763..0000000 --- a/src/openpgp/openpgp-do.c +++ /dev/null @@ -1,2656 +0,0 @@ -/* - * openpgp-do.c -- OpenPGP card Data Objects (DO) handling - * - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, - * 2020, 2021 - * Free Software Initiative of Japan1161 - - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include - -#include "config.h" - -#include "sys.h" -#include "gnuk.h" -#include "status-code.h" -#include "random.h" -#include "common.h" -#include "mbedtls/aes.h" -#include "mbedtls/sha512.h" -#include "shake256.h" -#include "hsm2040.h" - -/* Forward declaration */ -#define CLEAN_PAGE_FULL 1 -#define CLEAN_SINGLE 0 -static void gpg_do_delete_prvkey (enum kind_of_key kk, int clean_page_full); -static void gpg_reset_digital_signature_counter (void); - -#define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */ -static const uint8_t *pw_err_counter_p[3]; - -static int -gpg_pw_get_err_counter (uint8_t which) -{ - return flash_cnt123_get_value (pw_err_counter_p[which]); -} - -int -gpg_pw_get_retry_counter (int who) -{ - if (who == 0x81 || who == 0x82) - return PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_PW1); - else if (who == 0x83) - return PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_PW3); - else - return PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_RC); -} - -int -gpg_pw_locked (uint8_t which) -{ - if (gpg_pw_get_err_counter (which) >= PASSWORD_ERRORS_MAX) - return 1; - else - return 0; -} - -void -gpg_pw_reset_err_counter (uint8_t which) -{ - flash_cnt123_clear (&pw_err_counter_p[which]); - if (pw_err_counter_p[which] != NULL) - GPG_MEMORY_FAILURE (); -} - -void -gpg_pw_increment_err_counter (uint8_t which) -{ - flash_cnt123_increment (which, &pw_err_counter_p[which]); -} - - -uint16_t data_objects_number_of_bytes; - -/* - * Compile time vars: - * Historical Bytes, Extended Capabilities. - */ - -/* Historical Bytes */ -const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = { - 10, - 0x00, - 0x31, 0x84, /* Full DF name, GET DATA, MF */ - 0x73, - 0x80, 0x01, 0x80, /* Full DF name */ - /* 1-byte */ - /* Command chaining, No extended Lc and Le */ -#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT - 0x05, -#else - 0x00, -#endif - 0x90, 0x00 /* Status info */ -}; - -/* Extended Capabilities */ -static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = { - 10, - 0x75, /* - * No Secure Messaging supported - * GET CHALLENGE supported - * Key import supported - * PW status byte can be put - * No private_use_DO - * Algorithm attrs are changable - * No DEC with AES - * KDF-DO available - */ - 0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */ - 0x00, CHALLENGE_LEN, /* Max size of GET CHALLENGE */ -#ifdef CERTDO_SUPPORT - 0x08, 0x00, /* max. length of cardholder certificate (2KiB) */ -#else - 0x00, 0x00, -#endif - /* Max. length of command APDU data */ - 0x00, 0xff, - /* Max. length of response APDU data */ - 0x01, 0x00, -}; - -#ifdef ACKBTN_SUPPORT -/* General Feature Management */ -static const uint8_t feature_mngmnt[] __attribute__ ((aligned (1))) = { - 3, - 0x81, 0x01, 0x20, -}; -#endif - -/* Algorithm Attributes */ -#define OPENPGP_ALGO_RSA 0x01 -#define OPENPGP_ALGO_ECDH 0x12 -#define OPENPGP_ALGO_ECDSA 0x13 -#define OPENPGP_ALGO_EDDSA 0x16 /* It catches 22, finally. */ - -static const uint8_t algorithm_attr_ed448[] __attribute__ ((aligned (1))) = { - 4, - OPENPGP_ALGO_EDDSA, - /* OID of Ed448 */ - 0x2b, 0x65, 0x71 -}; - -static const uint8_t algorithm_attr_x448[] __attribute__ ((aligned (1))) = { - 4, - OPENPGP_ALGO_ECDH, - /* OID of X448 */ - 0x2b, 0x65, 0x6f -}; - -static const uint8_t algorithm_attr_rsa2k[] __attribute__ ((aligned (1))) = { - 6, - OPENPGP_ALGO_RSA, - 0x08, 0x00, /* Length modulus (in bit): 2048 */ - 0x00, 0x20, /* Length exponent (in bit): 32 */ - 0x00 /* 0: Acceptable format is: P and Q */ -}; - -static const uint8_t algorithm_attr_rsa4k[] __attribute__ ((aligned (1))) = { - 6, - OPENPGP_ALGO_RSA, - 0x10, 0x00, /* Length modulus (in bit): 4096 */ - 0x00, 0x20, /* Length exponent (in bit): 32 */ - 0x00 /* 0: Acceptable format is: P and Q */ -}; - -static const uint8_t algorithm_attr_p256k1[] __attribute__ ((aligned (1))) = { - 6, - OPENPGP_ALGO_ECDSA, - 0x2b, 0x81, 0x04, 0x00, 0x0a /* OID of curve secp256k1 */ -}; - -static const uint8_t algorithm_attr_ed25519[] __attribute__ ((aligned (1))) = { - 10, - OPENPGP_ALGO_EDDSA, - /* OID of the curve Ed25519 */ - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01 -}; - -static const uint8_t algorithm_attr_cv25519[] __attribute__ ((aligned (1))) = { - 11, - OPENPGP_ALGO_ECDH, - /* OID of the curve Curve25519 */ - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 -}; - - -/* - * Representation of PW1_LIFETIME: - * 0: PW1_LIEFTIME_P == NULL : PW1 is valid for single PSO:CDS command - * 1: PW1_LIEFTIME_P != NULL : PW1 is valid for several PSO:CDS commands - * - * The address in the variable PW1_LIEFTIME_P is used when filling zero - * in flash memory - */ -static const uint8_t *pw1_lifetime_p; - -static int -gpg_get_pw1_lifetime (void) -{ - if (pw1_lifetime_p == NULL) - return 0; - else - return 1; -} - - -/* - * Representation of algorithm attributes: - * 0: ALGO_ATTR_<>_P == NULL : RSA-2048 - * N: ALGO_ATTR_<>_P != NULL : - * - */ -static const uint8_t *algo_attr_sig_p; -static const uint8_t *algo_attr_dec_p; -static const uint8_t *algo_attr_aut_p; - -static const uint8_t ** -get_algo_attr_pointer (enum kind_of_key kk) -{ - if (kk == GPG_KEY_FOR_SIGNING) - return &algo_attr_sig_p; - else if (kk == GPG_KEY_FOR_DECRYPTION) - return &algo_attr_dec_p; - else - return &algo_attr_aut_p; -} - -static int -kk_to_nr (enum kind_of_key kk) -{ - int nr; - - if (kk == GPG_KEY_FOR_SIGNING) - nr = NR_KEY_ALGO_ATTR_SIG; - else if (kk == GPG_KEY_FOR_DECRYPTION) - nr = NR_KEY_ALGO_ATTR_DEC; - else - nr = NR_KEY_ALGO_ATTR_AUT; - - return nr; -} - -int -gpg_get_algo_attr (enum kind_of_key kk) -{ - const uint8_t *algo_attr_p = *get_algo_attr_pointer (kk); - - if (algo_attr_p == NULL) - return ALGO_RSA2K; - - return algo_attr_p[1]; -} - -static void -gpg_reset_algo_attr (enum kind_of_key kk) -{ - gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL); - if (kk == GPG_KEY_FOR_SIGNING) - { - gpg_reset_digital_signature_counter (); - gpg_do_write_simple (NR_DO_FP_SIG, NULL, 0); - gpg_do_write_simple (NR_DO_KGTIME_SIG, NULL, 0); - } - else if (kk == GPG_KEY_FOR_DECRYPTION) - { - gpg_do_write_simple (NR_DO_FP_DEC, NULL, 0); - gpg_do_write_simple (NR_DO_KGTIME_DEC, NULL, 0); - } - else - { - gpg_do_write_simple (NR_DO_FP_AUT, NULL, 0); - gpg_do_write_simple (NR_DO_KGTIME_AUT, NULL, 0); - } -} - -static const uint8_t * -get_algo_attr_data_object (enum kind_of_key kk) -{ - const uint8_t *algo_attr_p = *get_algo_attr_pointer (kk); - - if (algo_attr_p == NULL) - return algorithm_attr_rsa2k; - - switch (algo_attr_p[1]) - { - case ALGO_RSA4K: - return algorithm_attr_rsa4k; - case ALGO_SECP256K1: - return algorithm_attr_p256k1; - case ALGO_CURVE25519: - return algorithm_attr_cv25519; - case ALGO_ED25519: - return algorithm_attr_ed25519; - case ALGO_ED448: - return algorithm_attr_ed448; - case ALGO_X448: - return algorithm_attr_x448; - default: - return algorithm_attr_rsa2k; - } -} - -int -gpg_get_algo_attr_key_size (enum kind_of_key kk, enum size_of_key s) -{ - const uint8_t *algo_attr_p = *get_algo_attr_pointer (kk); - - if (algo_attr_p == NULL) /* RSA-2048 */ - goto rsa2k; - - switch (algo_attr_p[1]) - { - case ALGO_RSA4K: - if (s == GPG_KEY_STORAGE) - return 1024; - else - return 512; - case ALGO_SECP256K1: - if (s == GPG_KEY_STORAGE) - return 128; - else if (s == GPG_KEY_PUBLIC) - return 64; - else - return 32; - case ALGO_CURVE25519: - if (s == GPG_KEY_STORAGE) - return 64; - else - return 32; - case ALGO_ED25519: - if (s == GPG_KEY_STORAGE) - return 128; - else if (s == GPG_KEY_PUBLIC) - return 32; - else - return 64; - case ALGO_ED448: - if (s == GPG_KEY_STORAGE) - return 256; - else if (s == GPG_KEY_PUBLIC) - return 57; - else - return 128; - case ALGO_X448: - if (s == GPG_KEY_STORAGE) - return 112; - else - return 56; - default: - rsa2k: - if (s == GPG_KEY_STORAGE) - return 512; - else - return 256; - } -} - - -static uint32_t digital_signature_counter; - -static const uint8_t * -gpg_write_digital_signature_counter (const uint8_t *p, uint32_t dsc) -{ - uint16_t hw0, hw1; - - if ((dsc >> 10) == 0) - { /* no upper bits */ - hw1 = NR_COUNTER_DS_LSB | ((dsc & 0x0300) >> 8) | ((dsc & 0x00ff) << 8); - flash_put_data_internal (p, hw1); - return p+2; - } - else - { - hw0 = NR_COUNTER_DS | ((dsc & 0xfc0000) >> 18) | ((dsc & 0x03fc00) >> 2); - hw1 = NR_COUNTER_DS_LSB | ((dsc & 0x0300) >> 8) | ((dsc & 0x00ff) << 8); - flash_put_data_internal (p, hw0); - flash_put_data_internal (p+2, hw1); - return p+4; - } -} - -static void -gpg_reset_digital_signature_counter (void) -{ - if (digital_signature_counter != 0) - { - flash_put_data (NR_COUNTER_DS); - flash_put_data (NR_COUNTER_DS_LSB); - digital_signature_counter = 0; - } -} - -void -gpg_increment_digital_signature_counter (void) -{ - uint16_t hw0, hw1; - uint32_t dsc = (digital_signature_counter + 1) & 0x00ffffff; - - if ((dsc & 0x03ff) == 0) - { /* carry occurs from l10 to h14 */ - hw0 = NR_COUNTER_DS | ((dsc & 0xfc0000) >> 18) | ((dsc & 0x03fc00) >> 2); - hw1 = NR_COUNTER_DS_LSB; /* zero */ - flash_put_data (hw0); - flash_put_data (hw1); - } - else - { - hw1 = NR_COUNTER_DS_LSB | ((dsc & 0x0300) >> 8) | ((dsc & 0x00ff) << 8); - flash_put_data (hw1); - } - - digital_signature_counter = dsc; - - if (gpg_get_pw1_lifetime () == 0) - ac_reset_pso_cds (); -} - - -#define SIZE_FINGER_PRINT 20 -#define SIZE_KEYGEN_TIME 4 /* RFC4880 */ - -enum do_type { - DO_FIXED, - DO_VAR, - DO_CMP_READ, - DO_PROC_READ, - DO_PROC_WRITE, - DO_PROC_READWRITE, -}; - -struct do_table_entry { - uint16_t tag; - enum do_type do_type; - uint8_t ac_read; - uint8_t ac_write; - const void *obj; -}; - -static uint8_t *res_p; - -static void copy_do_1 (uint16_t tag, const uint8_t *do_data, int with_tag); -static const struct do_table_entry *get_do_entry (uint16_t tag); - -#define GPG_DO_AID 0x004f -#define GPG_DO_NAME 0x005b -#define GPG_DO_LOGIN_DATA 0x005e -#define GPG_DO_CH_DATA 0x0065 -#define GPG_DO_APP_DATA 0x006e -#define GPG_DO_DISCRETIONARY 0x0073 -#define GPG_DO_SS_TEMP 0x007a -#define GPG_DO_DS_COUNT 0x0093 -#define GPG_DO_EXTCAP 0x00c0 -#define GPG_DO_ALG_SIG 0x00c1 -#define GPG_DO_ALG_DEC 0x00c2 -#define GPG_DO_ALG_AUT 0x00c3 -#define GPG_DO_PW_STATUS 0x00c4 -#define GPG_DO_FP_ALL 0x00c5 -#define GPG_DO_CAFP_ALL 0x00c6 -#define GPG_DO_FP_SIG 0x00c7 -#define GPG_DO_FP_DEC 0x00c8 -#define GPG_DO_FP_AUT 0x00c9 -#define GPG_DO_CAFP_1 0x00ca -#define GPG_DO_CAFP_2 0x00cb -#define GPG_DO_CAFP_3 0x00cc -#define GPG_DO_KGTIME_ALL 0x00cd -#define GPG_DO_KGTIME_SIG 0x00ce -#define GPG_DO_KGTIME_DEC 0x00cf -#define GPG_DO_KGTIME_AUT 0x00d0 -#define GPG_DO_RESETTING_CODE 0x00d3 -#define GPG_DO_UIF_SIG 0x00d6 -#define GPG_DO_UIF_DEC 0x00d7 -#define GPG_DO_UIF_AUT 0x00d8 -#define GPG_DO_KDF 0x00f9 -#define GPG_DO_ALG_INFO 0x00fa -#define GPG_DO_KEY_IMPORT 0x3fff -#define GPG_DO_LANGUAGE 0x5f2d -#define GPG_DO_SEX 0x5f35 -#define GPG_DO_URL 0x5f50 -#define GPG_DO_HIST_BYTES 0x5f52 -#define GPG_DO_CH_CERTIFICATE 0x7f21 -#define GPG_DO_FEATURE_MNGMNT 0x7f74 - -static const uint8_t *do_ptr[NR_DO__LAST__]; - -static int -do_tag_to_nr (uint16_t tag) -{ - switch (tag) - { - case GPG_DO_SEX: - return NR_DO_SEX; - case GPG_DO_FP_SIG: - return NR_DO_FP_SIG; - case GPG_DO_FP_DEC: - return NR_DO_FP_DEC; - case GPG_DO_FP_AUT: - return NR_DO_FP_AUT; - case GPG_DO_CAFP_1: - return NR_DO_CAFP_1; - case GPG_DO_CAFP_2: - return NR_DO_CAFP_2; - case GPG_DO_CAFP_3: - return NR_DO_CAFP_3; - case GPG_DO_KGTIME_SIG: - return NR_DO_KGTIME_SIG; - case GPG_DO_KGTIME_DEC: - return NR_DO_KGTIME_DEC; - case GPG_DO_KGTIME_AUT: - return NR_DO_KGTIME_AUT; - case GPG_DO_LOGIN_DATA: - return NR_DO_LOGIN_DATA; - case GPG_DO_URL: - return NR_DO_URL; - case GPG_DO_NAME: - return NR_DO_NAME; - case GPG_DO_LANGUAGE: - return NR_DO_LANGUAGE; - case GPG_DO_KDF: - return NR_DO_KDF; - default: - return -1; - } -} - -static void -copy_tag (uint16_t tag) -{ - if (tag < 0x0100) - *res_p++ = (tag & 0xff); - else - { - *res_p++ = (tag >> 8); - *res_p++ = (tag & 0xff); - } -} - - -#define SIZE_FP 20 -#define SIZE_KGTIME 4 - -static void -do_fp_all (uint16_t tag, int with_tag) -{ - const uint8_t *data; - - if (with_tag) - { - copy_tag (tag); - *res_p++ = SIZE_FP*3; - } - - data = gpg_do_read_simple (NR_DO_FP_SIG); - if (data) - memcpy (res_p, data, SIZE_FP); - else - memset (res_p, 0, SIZE_FP); - res_p += SIZE_FP; - - data = gpg_do_read_simple (NR_DO_FP_DEC); - if (data) - memcpy (res_p, data, SIZE_FP); - else - memset (res_p, 0, SIZE_FP); - res_p += SIZE_FP; - - data = gpg_do_read_simple (NR_DO_FP_AUT); - if (data) - memcpy (res_p, data, SIZE_FP); - else - memset (res_p, 0, SIZE_FP); - res_p += SIZE_FP; -} - -static void -do_cafp_all (uint16_t tag, int with_tag) -{ - const uint8_t *data; - - if (with_tag) - { - copy_tag (tag); - *res_p++ = SIZE_FP*3; - } - - data = gpg_do_read_simple (NR_DO_CAFP_1); - if (data) - memcpy (res_p, data, SIZE_FP); - else - memset (res_p, 0, SIZE_FP); - res_p += SIZE_FP; - - data = gpg_do_read_simple (NR_DO_CAFP_2); - if (data) - memcpy (res_p, data, SIZE_FP); - else - memset (res_p, 0, SIZE_FP); - res_p += SIZE_FP; - - data = gpg_do_read_simple (NR_DO_CAFP_2); - if (data) - memcpy (res_p, data, SIZE_FP); - else - memset (res_p, 0, SIZE_FP); - res_p += SIZE_FP; -} - -static void -do_kgtime_all (uint16_t tag, int with_tag) -{ - const uint8_t *data; - - if (with_tag) - { - copy_tag (tag); - *res_p++ = SIZE_KGTIME*3; - } - - data = gpg_do_read_simple (NR_DO_KGTIME_SIG); - if (data) - memcpy (res_p, data, SIZE_KGTIME); - else - memset (res_p, 0, SIZE_KGTIME); - res_p += SIZE_KGTIME; - - data = gpg_do_read_simple (NR_DO_KGTIME_DEC); - if (data) - memcpy (res_p, data, SIZE_KGTIME); - else - memset (res_p, 0, SIZE_KGTIME); - res_p += SIZE_KGTIME; - - data = gpg_do_read_simple (NR_DO_KGTIME_AUT); - if (data) - memcpy (res_p, data, SIZE_KGTIME); - else - memset (res_p, 0, SIZE_KGTIME); - res_p += SIZE_KGTIME; -} - -const uint8_t openpgpcard_aid[] = { - 0xd2, 0x76, /* D: National, 276: DEU ISO 3166-1 */ - 0x00, 0x01, 0x24, /* Registered Application Provider Identifier */ - 0x01, /* Application: OpenPGPcard */ - 0x02, 0x00, /* Version 2.0 */ - /* v. id */ /* serial number */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* To be overwritten */ -}; - -static void -do_openpgpcard_aid (uint16_t tag, int with_tag) -{ - const volatile uint8_t *p = openpgpcard_aid; - uint16_t vid = (p[8] << 8) | p[9]; - - if (with_tag) - { - copy_tag (tag); - *res_p++ = 16; - } - - if (vid == 0xffff || vid == 0x0000) - { - const uint8_t *u = unique_device_id () + (MHZ < 96 ? 8: 0); - - memcpy (res_p, openpgpcard_aid, 8); - res_p += 8; - - /* vid == 0xfffe: serial number is four random bytes */ - *res_p++ = 0xff; - *res_p++ = 0xfe; - - *res_p++ = u[3]; - *res_p++ = u[2]; - *res_p++ = u[1]; - *res_p++ = u[0]; - } - else - { - memcpy (res_p, openpgpcard_aid, 14); - res_p += 14; - } - - *res_p++ = 0; - *res_p++ = 0; -} - -static void -do_ds_count (uint16_t tag, int with_tag) -{ - if (with_tag) - { - copy_tag (tag); - *res_p++ = 3; - } - - *res_p++ = (digital_signature_counter >> 16) & 0xff; - *res_p++ = (digital_signature_counter >> 8) & 0xff; - *res_p++ = digital_signature_counter & 0xff; -} - -static void -do_alg_info (uint16_t tag, int with_tag) -{ - uint8_t *len_p = NULL; - int i; - - if (with_tag) - { - copy_tag (tag); - len_p = res_p; - *res_p++ = 0; /* Filled later, assuming length is <= 127 */ - } - - for (i = 0; i < 3; i++) - { - uint16_t tag_algo = GPG_DO_ALG_SIG + i; - - copy_do_1 (tag_algo, algorithm_attr_rsa2k, 1); - copy_do_1 (tag_algo, algorithm_attr_rsa4k, 1); - copy_do_1 (tag_algo, algorithm_attr_p256k1, 1); - if (i == 0 || i == 2) - { - copy_do_1 (tag_algo, algorithm_attr_ed25519, 1); - copy_do_1 (tag_algo, algorithm_attr_ed448, 1); - } - if (i == 1) - { - copy_do_1 (tag_algo, algorithm_attr_cv25519, 1); - copy_do_1 (tag_algo, algorithm_attr_x448, 1); - } - }; - - if (len_p) - *len_p = res_p - len_p - 1; /* Actually, it's 127-byte long. */ -} - -static int -rw_pw_status (uint16_t tag, int with_tag, - const uint8_t *data, int len, int is_write) -{ - if (is_write) - { - if (len != 1) - return 0; /* Failure */ - - /* The first byte of DATA specifies the lifetime. */ - if (data[0] == 0 && pw1_lifetime_p != NULL) - { - flash_bool_clear (&pw1_lifetime_p); - if (pw1_lifetime_p != NULL) /* No change after update */ - return 0; - } - else if (pw1_lifetime_p == NULL) - { - pw1_lifetime_p = flash_bool_write (NR_BOOL_PW1_LIFETIME); - if (pw1_lifetime_p == NULL) /* No change after update */ - return 0; - } - - return 1; /* Success */ - } - else - { - if (with_tag) - { - copy_tag (tag); - *res_p++ = SIZE_PW_STATUS_BYTES; - } - - *res_p++ = gpg_get_pw1_lifetime (); - *res_p++ = PW_LEN_MAX; - *res_p++ = PW_LEN_MAX; - *res_p++ = PW_LEN_MAX; - *res_p++ = PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_PW1); - *res_p++ = PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_RC); - *res_p++ = PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_PW3); - return 1; - } -} - -static int -rw_algorithm_attr (uint16_t tag, int with_tag, - const uint8_t *data, int len, int is_write) -{ - enum kind_of_key kk; - - if (tag == GPG_DO_ALG_SIG) - kk = GPG_KEY_FOR_SIGNING; - else if (tag == GPG_DO_ALG_DEC) - kk = GPG_KEY_FOR_DECRYPTION; - else - kk = GPG_KEY_FOR_AUTHENTICATION; - - if (is_write) - { - int algo = -1; - const uint8_t **algo_attr_pp = get_algo_attr_pointer (kk); - - if (len == 4) - { - if (memcmp (data, algorithm_attr_ed448+1, 4) == 0) - algo = ALGO_ED448; - else if (memcmp (data, algorithm_attr_x448+1, 4) == 0) - algo = ALGO_X448; - } - if (len == 6) - { - if (memcmp (data, algorithm_attr_rsa2k+1, 6) == 0) - algo = ALGO_RSA2K; - else if (memcmp (data, algorithm_attr_rsa4k+1, 6) == 0) - algo = ALGO_RSA4K; - else if ((tag != GPG_DO_ALG_DEC - && memcmp (data, algorithm_attr_p256k1+1, 6) == 0) - || (tag == GPG_DO_ALG_DEC && data[0]==OPENPGP_ALGO_ECDH - && memcmp (data+1, algorithm_attr_p256k1+2, 5) == 0)) - algo = ALGO_SECP256K1; - } - else if (len == 10 && memcmp (data, algorithm_attr_ed25519+1, 10) == 0) - algo = ALGO_ED25519; - else if (len == 11 && memcmp (data, algorithm_attr_cv25519+1, 11) == 0) - algo = ALGO_CURVE25519; - - if (algo < 0) - return 0; /* Error. */ - else if (algo == ALGO_RSA2K && *algo_attr_pp != NULL) - { - gpg_reset_algo_attr (kk); - /* Read it again, since GC may occur. */ - algo_attr_pp = get_algo_attr_pointer (kk); - flash_enum_clear (algo_attr_pp); - if (*algo_attr_pp != NULL) - return 0; - } - else if ((algo != ALGO_RSA2K && *algo_attr_pp == NULL) || - (*algo_attr_pp != NULL && (*algo_attr_pp)[1] != algo)) - { - gpg_reset_algo_attr (kk); - /* Read it again, since GC may occur. */ - algo_attr_pp = get_algo_attr_pointer (kk); - if (*algo_attr_pp) - flash_enum_clear (algo_attr_pp); - *algo_attr_pp = flash_enum_write (kk_to_nr (kk), algo); - if (*algo_attr_pp == NULL) - return 0; - } - - return 1; - } - else - { - const uint8_t *algo_attr_do = get_algo_attr_data_object (kk); - - copy_do_1 (tag, algo_attr_do, with_tag); - /* Override the byte when GPG_DO_ALG_DEC. */ - if (tag == GPG_DO_ALG_DEC && algo_attr_do[1] == OPENPGP_ALGO_ECDSA) - *(res_p - algo_attr_do[0]) = OPENPGP_ALGO_ECDH; - return 1; - } -} - - -static uint8_t uif_flags; /* Six bits of flags */ - -#ifdef ACKBTN_SUPPORT -int -gpg_do_get_uif (enum kind_of_key kk) -{ - return ((uif_flags >> (kk * 2)) & 3) != 0; -} - -static int -rw_uif (uint16_t tag, int with_tag, const uint8_t *data, int len, int is_write) -{ - uint8_t nr; - int v; - - if (tag != GPG_DO_UIF_SIG && tag != GPG_DO_UIF_DEC && tag != GPG_DO_UIF_AUT) - return 0; /* Failure */ - - nr = (tag - GPG_DO_UIF_SIG) + NR_DO_UIF_SIG; - v = (uif_flags >> ((tag - GPG_DO_UIF_SIG) * 2)) & 3; - if (is_write) - { - const uint8_t *p; - - if (len != 2 || data[1] != 0x20) - return 0; - - if (v == 2) - return 0; - - if (data[0] != 0x00 && data[0] != 0x01 && data[0] != 0x02) - return 0; - - p = flash_enum_write (nr, data[0]); - if (p == NULL) - return 0; - - uif_flags &= ~(3 << ((nr - NR_DO_UIF_SIG) * 2)); - uif_flags |= (data[0] & 3) << ((nr - NR_DO_UIF_SIG) * 2); - return 1; - } - else - { - if (with_tag) - { - copy_tag (tag); - *res_p++ = 2; - } - - *res_p++ = v; - *res_p++ = 0x20; - return 1; - } -} -#endif - - -#define SIZE_OF_KDF_DO_MIN 90 -#define SIZE_OF_KDF_DO_MAX 110 -#define OPENPGP_KDF_ITERSALTED_S2K 3 -#define OPENPGP_SHA256 8 - -static int -rw_kdf (uint16_t tag, int with_tag, const uint8_t *data, int len, int is_write) -{ - if (tag != GPG_DO_KDF) - return 0; /* Failure */ - - if (is_write) - { - const uint8_t **do_data_p = (const uint8_t **)&do_ptr[NR_DO_KDF]; - - /* KDF DO can be changed only when no keys are registered. */ - if (do_ptr[NR_DO_PRVKEY_SIG] || do_ptr[NR_DO_PRVKEY_DEC] - || do_ptr[NR_DO_PRVKEY_AUT]) - return 0; - - /* The valid data format is: - Deleting: - nothing - Minimum (for admin-less): - 81 01 03 = KDF_ITERSALTED_S2K - 82 01 08 = SHA256 - 83 04 4-byte... = count - 84 08 8-byte... = salt - 87 20 32-byte user hash - 88 20 32-byte admin hash - Full: - 81 01 03 = KDF_ITERSALTED_S2K - 82 01 08 = SHA256 - 83 04 4-byte... = count - 84 08 8-byte... = salt user - 85 08 8-byte... = salt reset-code - 86 08 8-byte... = salt admin - 87 20 32-byte user hash - 88 20 32-byte admin hash - */ - if (!(len == 0 - || (len == SIZE_OF_KDF_DO_MIN && - (data[0] == 0x81 && data[3] == 0x82 && data[6] == 0x83 - && data[12] == 0x84 && data[22] == 0x87 && data[56] == 0x88)) - || (len == SIZE_OF_KDF_DO_MAX && - (data[0] == 0x81 && data[3] == 0x82 && data[6] == 0x83 - && data[12] == 0x84 && data[22] == 0x85 && data[32] == 0x86 - && data[42] == 0x87 && data[76] == 0x88)))) - return 0; - - if (*do_data_p) - flash_do_release (*do_data_p); - - /* Clear all keystrings and auth states */ - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0); - gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0); - gpg_do_write_simple (NR_DO_KEYSTRING_PW3, NULL, 0); - ac_reset_admin (); - ac_reset_pso_cds (); - ac_reset_other (); - - if (len == 0) - { - *do_data_p = NULL; - return 1; - } - else - { - *do_data_p = flash_do_write (NR_DO_KDF, data, len); - if (*do_data_p) - return 1; - else - return 0; - } - } - else - { - if (do_ptr[NR_DO_KDF]) - copy_do_1 (tag, do_ptr[NR_DO_KDF], with_tag); - else - return 0; - - return 1; - } -} - - -/* - * Check LEN is valid for HOW_MANY of passphrase string. - * - * HOW_MANY = 1: LEN is valid for a single passphrase string. - * HOW_MANY = 2: LEN is valid for two single passphrase strings. - * This is used to change passphrase. - * The second passphrase may be nothing. - * - * LEN = 0: Check if KDF-DO is available. - */ -int -gpg_do_kdf_check (int len, int how_many) -{ - const uint8_t *kdf_do = do_ptr[NR_DO_KDF]; - - if (len == 0) - return kdf_do != NULL; - - if (kdf_do) - { - const uint8_t *kdf_spec = kdf_do+1; - int kdf_do_len = kdf_do[0]; - int hash_len; - - if (kdf_do_len == SIZE_OF_KDF_DO_MIN) - hash_len = kdf_spec[23]; - else - hash_len = kdf_spec[43]; - - if ((hash_len * how_many) != len && hash_len != len) - return 0; - } - - return 1; -} - -void -gpg_do_get_initial_pw_setting (int is_pw3, int *r_len, const uint8_t **r_p) -{ - const uint8_t *kdf_do = do_ptr[NR_DO_KDF]; - - if (kdf_do) - { - int len = kdf_do[0]; - const uint8_t *kdf_spec = kdf_do+1; - - *r_len = 32; - - if (len == SIZE_OF_KDF_DO_MIN) - { - if (is_pw3) - *r_p = kdf_spec + 58; - else - *r_p = kdf_spec + 24; - } - else - { - if (is_pw3) - *r_p = kdf_spec + 78; - else - *r_p = kdf_spec + 44; - } - } - else - { - if (is_pw3) - { - *r_len = strlen (OPENPGP_CARD_INITIAL_PW3); - *r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW3; - } - else - { - *r_len = strlen (OPENPGP_CARD_INITIAL_PW1); - *r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1; - } - } -} - -static int -proc_resetting_code (const uint8_t *data, int len) -{ - const uint8_t *old_ks = keystring_md_pw3; - uint8_t new_ks0[KEYSTRING_SIZE]; - uint8_t *new_ks = KS_GET_KEYSTRING (new_ks0); - const uint8_t *newpw; - int newpw_len; - int r; - uint8_t *salt = KS_GET_SALT (new_ks0); - - DEBUG_INFO ("Resetting Code!\r\n"); - - if (len == 0) - { /* Removal of resetting code. */ - enum kind_of_key kk0; - - for (kk0 = 0; kk0 <= GPG_KEY_FOR_AUTHENTICATION; kk0++) - gpg_do_chks_prvkey (kk0, BY_RESETCODE, NULL, 0, NULL); - gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0); - } - else - { - if (gpg_do_kdf_check (len, 1) == 0) - return 0; - - newpw_len = len; - newpw = data; - new_ks0[0] = newpw_len; - random_get_salt (salt); - s2k (salt, SALT_SIZE, newpw, newpw_len, new_ks); - r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks); - if (r <= -2) - { - DEBUG_INFO ("memory error.\r\n"); - return 0; - } - else if (r < 0) - { - DEBUG_INFO ("security error.\r\n"); - return 0; - } - else if (r == 0) - { - DEBUG_INFO ("error (no prvkey).\r\n"); - return 0; - } - else - { - DEBUG_INFO ("done.\r\n"); - gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KS_META_SIZE); - } - } - - gpg_pw_reset_err_counter (PW_ERR_RC); - return 1; -} - -static void -encrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) -{ - mbedtls_aes_context aes; - uint8_t iv0[INITIAL_VECTOR_SIZE]; - size_t iv_offset; - - DEBUG_INFO ("ENC\r\n"); - DEBUG_BINARY (data, len); - - mbedtls_aes_setkey_enc (&aes, key, 128); - memcpy (iv0, iv, INITIAL_VECTOR_SIZE); - iv_offset = 0; - mbedtls_aes_crypt_cfb128 (&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, iv0, data, data); -} - -/* For three keys: Signing, Decryption, and Authentication */ -struct key_data kd[3]; - -static void -decrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) -{ - mbedtls_aes_context aes; - uint8_t iv0[INITIAL_VECTOR_SIZE]; - size_t iv_offset; - - mbedtls_aes_setkey_enc (&aes, key, 128); /* This is setkey_enc, because of CFB. */ - memcpy (iv0, iv, INITIAL_VECTOR_SIZE); - iv_offset = 0; - mbedtls_aes_crypt_cfb128 (&aes, MBEDTLS_AES_DECRYPT, len, &iv_offset, iv0, data, data); - - DEBUG_INFO ("DEC\r\n"); - DEBUG_BINARY (data, len); -} - -static void -encrypt_dek (const uint8_t *key_string, uint8_t *dek) -{ - mbedtls_aes_context aes; - - mbedtls_aes_setkey_enc (&aes, key_string, 128); - mbedtls_aes_crypt_ecb (&aes, MBEDTLS_AES_ENCRYPT, dek, dek); -} - -static void -decrypt_dek (const uint8_t *key_string, uint8_t *dek) -{ - mbedtls_aes_context aes; - - mbedtls_aes_setkey_dec (&aes, key_string, 128); - mbedtls_aes_crypt_ecb (&aes, MBEDTLS_AES_DECRYPT, dek, dek); -} - -static uint8_t -get_do_ptr_nr_for_kk (enum kind_of_key kk) -{ - switch (kk) - { - case GPG_KEY_FOR_SIGNING: - return NR_DO_PRVKEY_SIG; - case GPG_KEY_FOR_DECRYPTION: - return NR_DO_PRVKEY_DEC; - case GPG_KEY_FOR_AUTHENTICATION: - return NR_DO_PRVKEY_AUT; - } - return NR_DO_PRVKEY_SIG; -} - -void -gpg_do_clear_prvkey (enum kind_of_key kk) -{ - memset (kd[kk].data, 0, MAX_PRVKEY_LEN); -} - - -#define CHECKSUM_ADDR(kdi,prvkey_len) \ - (&(kdi).data[prvkey_len / sizeof (uint32_t)]) -#define kdi_len(prvkey_len) (prvkey_len+DATA_ENCRYPTION_KEY_SIZE) -struct key_data_internal { - uint32_t data[(MAX_PRVKEY_LEN+DATA_ENCRYPTION_KEY_SIZE) / sizeof (uint32_t)]; - /* - * Secret key data. - * RSA: p and q, ECDSA/ECDH: d, EdDSA: a+seed - */ - /* Checksum */ -}; - -#define CKDC_CALC 0 -#define CKDC_CHECK 1 -static int -compute_key_data_checksum (struct key_data_internal *kdi, int prvkey_len, - int check_or_calc) -{ - unsigned int i; - uint32_t d[4] = { 0, 0, 0, 0 }; - uint32_t *checksum = CHECKSUM_ADDR (*kdi, prvkey_len); - - for (i = 0; i < prvkey_len / sizeof (uint32_t); i++) - d[i&3] ^= kdi->data[i]; - - if (check_or_calc == CKDC_CALC) /* store */ - { - memcpy (checksum, d, DATA_ENCRYPTION_KEY_SIZE); - return 0; - } - else /* check */ - return memcmp (checksum, d, DATA_ENCRYPTION_KEY_SIZE) == 0; -} - -/* - * Return 1 on success, - * 0 if none, - * -1 on error, - */ -int -gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring) -{ - uint8_t nr = get_do_ptr_nr_for_kk (kk); - int prvkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PRIVATE); - const uint8_t *do_data = do_ptr[nr]; - const uint8_t *key_addr; - uint8_t dek[DATA_ENCRYPTION_KEY_SIZE]; - const uint8_t *iv; - struct key_data_internal kdi; - - DEBUG_INFO ("Loading private key: "); - DEBUG_BYTE (kk); - - if (do_data == NULL) - return 0; - - key_addr = kd[kk].pubkey - prvkey_len; - memcpy (kdi.data, key_addr, prvkey_len); - iv = &do_data[1]; - memcpy (CHECKSUM_ADDR (kdi, prvkey_len), - iv + INITIAL_VECTOR_SIZE, DATA_ENCRYPTION_KEY_SIZE); - - memcpy (dek, iv + DATA_ENCRYPTION_KEY_SIZE*(who+1), DATA_ENCRYPTION_KEY_SIZE); - decrypt_dek (keystring, dek); - - decrypt (dek, iv, (uint8_t *)&kdi, kdi_len (prvkey_len)); - memset (dek, 0, DATA_ENCRYPTION_KEY_SIZE); - if (!compute_key_data_checksum (&kdi, prvkey_len, CKDC_CHECK)) - { - DEBUG_INFO ("gpg_do_load_prvkey failed.\r\n"); - return -1; - } - - memcpy (kd[kk].data, kdi.data, prvkey_len); - DEBUG_BINARY (kd[kk].data, prvkey_len); - return 1; -} - - -static int8_t num_prv_keys; - -static void -gpg_do_delete_prvkey (enum kind_of_key kk, int clean_page_full) -{ - uint8_t nr = get_do_ptr_nr_for_kk (kk); - const uint8_t *do_data = do_ptr[nr]; - uint8_t *key_addr; - int prvkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PRIVATE); - int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE); - - if (do_data == NULL) - { - if (clean_page_full) - flash_key_release_page (kk); - return; - } - - do_ptr[nr] = NULL; - flash_do_release (do_data); - key_addr = (uint8_t *)kd[kk].pubkey - prvkey_len; - kd[kk].pubkey = NULL; - if (clean_page_full) - flash_key_release_page (kk); - else - flash_key_release (key_addr, key_size); - - if (admin_authorized == BY_ADMIN && kk == GPG_KEY_FOR_SIGNING) - { /* Recover admin keystring DO. */ - const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); - - if (ks_pw3 != NULL) - { - uint8_t ks0[KEYSTRING_SIZE]; - - ks0[0] = ks_pw3[0] | PW_LEN_KEYSTRING_BIT; - memcpy (KS_GET_SALT (ks0), KS_GET_SALT (ks_pw3), SALT_SIZE); - memcpy (KS_GET_KEYSTRING (ks0), keystring_md_pw3, KEYSTRING_MD_SIZE); - gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks0, KEYSTRING_SIZE); - } - } - - if (--num_prv_keys == 0) - { - /* Delete PW1 and RC if any. */ - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0); - gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0); - - ac_reset_pso_cds (); - ac_reset_other (); - if (admin_authorized == BY_USER) - ac_reset_admin (); - } -} - -void -gpg_do_terminate (void) -{ - int i; - - for (i = 0; i < 3; i++) - kd[i].pubkey = NULL; - - for (i = 0; i < NR_DO__LAST__; i++) - do_ptr[i] = NULL; - - num_prv_keys = 0; - data_objects_number_of_bytes = 0; - digital_signature_counter = 0; - - pw1_lifetime_p = NULL; - pw_err_counter_p[PW_ERR_PW1] = NULL; - pw_err_counter_p[PW_ERR_RC] = NULL; - pw_err_counter_p[PW_ERR_PW3] = NULL; - algo_attr_sig_p = algo_attr_dec_p = algo_attr_aut_p = NULL; -} - -static int -gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, - int prvkey_len, const uint8_t *keystring_admin, - const uint8_t *pubkey) -{ - uint8_t nr = get_do_ptr_nr_for_kk (kk); - int attr = gpg_get_algo_attr (kk);; - const uint8_t *p; - int r; - struct prvkey_data prv; - struct prvkey_data *pd = &prv; - uint8_t *key_addr; - const uint8_t *dek, *iv; - struct key_data_internal kdi; - int pubkey_len; - uint8_t ks[KEYSTRING_MD_SIZE]; - enum kind_of_key kk0; - int pw_len; - const uint8_t *initial_pw; - - DEBUG_INFO ("Key import\r\n"); - DEBUG_SHORT (prvkey_len); - - /* Delete it first, if any. */ - gpg_do_delete_prvkey (kk, CLEAN_SINGLE); - - if (attr == ALGO_SECP256K1) - { - pubkey_len = prvkey_len * 2; - if (prvkey_len != 32) - return -1; - } - else if (attr == ALGO_CURVE25519) - { - pubkey_len = prvkey_len; - if (prvkey_len != 32) - return -1; - } - else if (attr == ALGO_ED25519) - { - pubkey_len = prvkey_len / 2; - if (prvkey_len != 64) - return -1; - } - else if (attr == ALGO_ED448) - { - pubkey_len = 57 + 1; /* +1 to be even. */ - if (prvkey_len != 128) - return -1; - } - else if (attr == ALGO_X448) - { - pubkey_len = prvkey_len; - if (prvkey_len != 56) - return -1; - } - else /* RSA */ - { - int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE); - - pubkey_len = prvkey_len; - if (prvkey_len + pubkey_len != key_size) - return -1; - } - - DEBUG_INFO ("Getting keystore address...\r\n"); - key_addr = flash_key_alloc (kk); - if (key_addr == NULL) - return -1; - - kd[kk].pubkey = key_addr + prvkey_len; - - num_prv_keys++; - - DEBUG_INFO ("key_addr: "); - DEBUG_WORD ((uint32_t)key_addr); - - memcpy (kdi.data, key_data, prvkey_len); - memset ((uint8_t *)kdi.data + prvkey_len, 0, MAX_PRVKEY_LEN - prvkey_len); - - compute_key_data_checksum (&kdi, prvkey_len, CKDC_CALC); - - dek = random_bytes_get (32); /* 32-byte random bytes */ - iv = dek + DATA_ENCRYPTION_KEY_SIZE; - memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE); - memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE); - memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE); - - gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw); - s2k (NULL, 0, initial_pw, pw_len, ks); - - /* Handle existing keys and keystring DOs. */ - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0); - gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0); - for (kk0 = 0; kk0 <= GPG_KEY_FOR_AUTHENTICATION; kk0++) - if (kk0 != kk) - { - gpg_do_chks_prvkey (kk0, admin_authorized, keystring_md_pw3, - BY_USER, ks); - gpg_do_chks_prvkey (kk0, BY_RESETCODE, NULL, 0, NULL); - } - - encrypt (dek, iv, (uint8_t *)&kdi, kdi_len (prvkey_len)); - - r = flash_key_write (key_addr, (const uint8_t *)kdi.data, prvkey_len, - pubkey, pubkey_len); - if (r < 0) - { - random_bytes_free (dek); - memset (pd, 0, sizeof (struct prvkey_data)); - return r; - } - - memcpy (pd->iv, iv, INITIAL_VECTOR_SIZE); - memcpy (pd->checksum_encrypted, CHECKSUM_ADDR (kdi, prvkey_len), - DATA_ENCRYPTION_KEY_SIZE); - - encrypt_dek (ks, pd->dek_encrypted_1); - - memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE); - - if (keystring_admin) - encrypt_dek (keystring_admin, pd->dek_encrypted_3); - else - memset (pd->dek_encrypted_3, 0, DATA_ENCRYPTION_KEY_SIZE); - - p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data)); - do_ptr[nr] = p; - - random_bytes_free (dek); - memset (pd, 0, sizeof (struct prvkey_data)); - if (p == NULL) - return -1; - - if (keystring_admin && kk == GPG_KEY_FOR_SIGNING) - { - const uint8_t *ks_admin = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); - uint8_t ks_info[KS_META_SIZE]; - - if (ks_admin != NULL && (ks_admin[0] & PW_LEN_KEYSTRING_BIT)) - { - ks_info[0] = ks_admin[0] & PW_LEN_MASK; - memcpy (KS_GET_SALT (ks_info), KS_GET_SALT (ks_admin), SALT_SIZE); - gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks_info, KS_META_SIZE); - } - else - { - DEBUG_INFO ("No admin keystring!\r\n"); - } - } - - return 0; -} - -int -gpg_do_chks_prvkey (enum kind_of_key kk, - int who_old, const uint8_t *old_ks, - int who_new, const uint8_t *new_ks) -{ - uint8_t nr = get_do_ptr_nr_for_kk (kk); - const uint8_t *do_data = do_ptr[nr]; - uint8_t dek[DATA_ENCRYPTION_KEY_SIZE]; - struct prvkey_data prv; - struct prvkey_data *pd = &prv; - uint8_t *dek_p; - int update_needed = 0; - int r = 1; /* Success */ - - if (do_data == NULL) - return 0; /* No private key */ - - memcpy (pd, &do_data[1], sizeof (struct prvkey_data)); - - dek_p = ((uint8_t *)pd) + INITIAL_VECTOR_SIZE - + DATA_ENCRYPTION_KEY_SIZE * who_old; - memcpy (dek, dek_p, DATA_ENCRYPTION_KEY_SIZE); - if (who_new == 0) /* Remove */ - { - int i; - - for (i = 0; i < DATA_ENCRYPTION_KEY_SIZE; i++) - if (dek_p[i] != 0) - { - update_needed = 1; - dek_p[i] = 0; - } - } - else - { - decrypt_dek (old_ks, dek); - encrypt_dek (new_ks, dek); - dek_p += DATA_ENCRYPTION_KEY_SIZE * (who_new - who_old); - if (memcmp (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE) != 0) - { - memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE); - update_needed = 1; - } - } - - if (update_needed) - { - const uint8_t *p; - - flash_do_release (do_data); - do_ptr[nr] = NULL; - p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data)); - do_ptr[nr] = p; - if (p == NULL) - r = -1; - } - - memset (pd, 0, sizeof (struct prvkey_data)); - - return r; -} - - -static enum kind_of_key -kkb_to_kk (uint8_t kk_byte) -{ - enum kind_of_key kk; - - if (kk_byte == 0xb6) - kk = GPG_KEY_FOR_SIGNING; - else if (kk_byte == 0xb8) - kk = GPG_KEY_FOR_DECRYPTION; - else /* 0xa4 */ - kk = GPG_KEY_FOR_AUTHENTICATION; - return kk; -} - -/* - * RSA-2048: - * 4d, xx, xx, xx: Extended Header List - * b6 00 (SIG) / b8 00 (DEC) / a4 00 (AUT) - * 7f48, xx: cardholder private key template - * 91 L: 91=tag of E, L: length of E - * 92 Lh

Ll

: 92=tag of P, L

: length of P - * 93 Lh Ll: 93=tag of Q, L: length of Q - * 5f48, xx xx xx: cardholder private key - * , , - * - * RSA-4096: - * 4d, 82, 02, 18: Extended Header List - * b6 00 (SIG) / b8 00 (DEC) / a4 00 (AUT) - * 7f48, 0a: cardholder private key template - * 91 L: 91=tag of E, L: length of E - * 92 82 Lh

Ll

: 92=tag of P, L

: length of P - * 93 82 Lh Ll: 93=tag of Q, L: length of Q - * 5f48, 82 02 04: cardholder private key - * , , - * - * ECDSA / ECDH / EdDSA: - * 4d, 2a: Extended Header List - * b6 00 (SIG) / b8 00 (DEC) / a4 00 (AUT) - * 7f48, 02: cardholder private key template - * 9x LEN: 9x=tag of private key d, LEN=length of d - * 5f48, 20: cardholder private key - * - */ -static int -proc_key_import (const uint8_t *data, int len) -{ - int r = -1; - enum kind_of_key kk; - const uint8_t *keystring_admin; - int attr; - const uint8_t *p = data; - uint8_t pubkey[512]; - -#ifdef KDF_DO_REQUIRED - const uint8_t *kdf_do = do_ptr[NR_DO_KDF]; - - if (kdf_do == NULL) - return 0; /* Error. */ -#endif - - if (admin_authorized == BY_ADMIN) - keystring_admin = keystring_md_pw3; - else - keystring_admin = NULL; - - DEBUG_BINARY (data, len); - - if (*p++ != 0x4d) - return 0; - - /* length field */ - if (*p == 0x82) - p += 3; - else if (*p == 0x81) - p += 2; - else - p += 1; - - kk = kkb_to_kk (*p); - if (kk == GPG_KEY_FOR_SIGNING) - { - ac_reset_pso_cds (); - gpg_reset_digital_signature_counter (); - } - else - ac_reset_other (); - - attr = gpg_get_algo_attr (kk); - - if ((len <= 12 && (attr == ALGO_SECP256K1 || attr == ALGO_CURVE25519 - || attr == ALGO_ED25519 || attr == ALGO_ED448 - || attr == ALGO_X448)) - || (len <= 22 && attr == ALGO_RSA2K) || (len <= 24 && attr == ALGO_RSA4K)) - { /* Deletion of the key */ - gpg_do_delete_prvkey (kk, CLEAN_SINGLE); - return 1; - } - - if (attr == ALGO_RSA2K) - { - /* It should starts with 00 01 00 01 (E), skiping E (4-byte) */ - r = modulus_calc (&data[26], len - 26, pubkey); - if (r >= 0) - r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, - pubkey); - } - else if (attr == ALGO_RSA4K) - { - /* It should starts with 00 01 00 01 (E), skiping E (4-byte) */ - r = modulus_calc (&data[28], len - 28, pubkey); - if (r >= 0) - r = gpg_do_write_prvkey (kk, &data[28], len - 28, keystring_admin, - pubkey); - } - else if (attr == ALGO_SECP256K1) - { - r = ecc_compute_public_p256k1 (&data[12], pubkey); - if (r >= 0) - r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin, - pubkey); - } - else if (attr == ALGO_CURVE25519) - { - uint8_t priv[32]; - int i; - - if (len - 12 != 32) - return 0; /* Error. */ - - for (i = 0; i < 32; i++) - priv[31-i] = data[12+i]; - ecdh_compute_public_25519 (priv, pubkey); - r = gpg_do_write_prvkey (kk, priv, 32, keystring_admin, pubkey); - } - else if (attr == ALGO_ED25519) - { - uint8_t hash[64]; - - if (len - 12 != 32) - return 0; /* Error. */ - mbedtls_sha512_context ctx; - mbedtls_sha512_init(&ctx); - - mbedtls_sha512_starts (&ctx, 0); - mbedtls_sha512_update (&ctx, &data[12], 32); - mbedtls_sha512_finish (&ctx, hash); - mbedtls_sha512_free (&ctx); - - hash[0] &= 248; - hash[31] &= 127; - hash[31] |= 64; - eddsa_compute_public_25519 (hash, pubkey); - r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, pubkey); - } - else if (attr == ALGO_ED448) - { - shake_context ctx; - uint8_t hash[128]; - - if (len - 12 != 57) - return 0; /* Error. */ - - shake256_start (&ctx); - shake256_update (&ctx, &data[12], 57); - shake256_finish (&ctx, hash, 2*57); - memset (hash+114, 0, 128-114); - ed448_compute_public (pubkey, hash); - pubkey[57] = 0; - r = gpg_do_write_prvkey (kk, hash, 128, keystring_admin, pubkey); - } - else if (attr == ALGO_X448) - { - uint8_t priv[56]; - - if (len - 12 != 56) - return 0; /* Error. */ - - memcpy (priv, data+12, 56); - ecdh_compute_public_x448 (pubkey, priv); - r = gpg_do_write_prvkey (kk, priv, 56, keystring_admin, pubkey); - } - - if (r < 0) - return 0; - else - return 1; -} - -static const uint16_t cmp_ch_data[] = { - 3, - GPG_DO_NAME, - GPG_DO_LANGUAGE, - GPG_DO_SEX, -}; - -static const uint16_t cmp_app_data[] = { -#ifdef ACKBTN_SUPPORT - 4, -#else - 3, -#endif - GPG_DO_AID, - GPG_DO_HIST_BYTES, - GPG_DO_DISCRETIONARY, -#ifdef ACKBTN_SUPPORT - GPG_DO_FEATURE_MNGMNT, -#endif -}; - -static const uint16_t cmp_discretionary[] = { -#ifdef ACKBTN_SUPPORT - 11, -#else - 8, -#endif - GPG_DO_EXTCAP, - GPG_DO_ALG_SIG, GPG_DO_ALG_DEC, GPG_DO_ALG_AUT, - GPG_DO_PW_STATUS, - GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL, -#ifdef ACKBTN_SUPPORT - GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT -#endif -}; - -static const uint16_t cmp_ss_temp[] = { 1, GPG_DO_DS_COUNT }; - -static const struct do_table_entry -gpg_do_table[] = { - /* Variables: Fixed size */ - { GPG_DO_SEX, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[0] }, - { GPG_DO_FP_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[1] }, - { GPG_DO_FP_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[2] }, - { GPG_DO_FP_AUT, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[3] }, - { GPG_DO_CAFP_1, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[4] }, - { GPG_DO_CAFP_2, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[5] }, - { GPG_DO_CAFP_3, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[6] }, - { GPG_DO_KGTIME_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[7] }, - { GPG_DO_KGTIME_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[8] }, - { GPG_DO_KGTIME_AUT, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[9] }, - /* Variables: Variable size */ - { GPG_DO_LOGIN_DATA, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[10] }, - { GPG_DO_URL, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[11] }, - { GPG_DO_NAME, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[12] }, - { GPG_DO_LANGUAGE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[13] }, - /* Pseudo DO READ: calculated */ - { GPG_DO_FP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_fp_all }, - { GPG_DO_CAFP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_cafp_all }, - { GPG_DO_KGTIME_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_kgtime_all }, - /* Pseudo DO READ: calculated, not changeable by user */ - { GPG_DO_DS_COUNT, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_ds_count }, - { GPG_DO_AID, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_openpgpcard_aid }, - { GPG_DO_ALG_INFO, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_alg_info }, - /* Pseudo DO READ/WRITE: calculated */ - { GPG_DO_PW_STATUS, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, - rw_pw_status }, - { GPG_DO_ALG_SIG, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, - rw_algorithm_attr }, - { GPG_DO_ALG_DEC, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, - rw_algorithm_attr }, - { GPG_DO_ALG_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, - rw_algorithm_attr }, -#ifdef ACKBTN_SUPPORT - { GPG_DO_UIF_SIG, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif }, - { GPG_DO_UIF_DEC, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif }, - { GPG_DO_UIF_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif }, -#endif - { GPG_DO_KDF, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, - rw_kdf }, - /* Fixed data */ - { GPG_DO_HIST_BYTES, DO_FIXED, AC_ALWAYS, AC_NEVER, historical_bytes }, - { GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities }, -#ifdef ACKBTN_SUPPORT - { GPG_DO_FEATURE_MNGMNT, DO_FIXED, AC_ALWAYS, AC_NEVER, feature_mngmnt }, -#endif - /* Compound data: Read access only */ - { GPG_DO_CH_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ch_data }, - { GPG_DO_APP_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_app_data }, - { GPG_DO_DISCRETIONARY, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_discretionary }, - { GPG_DO_SS_TEMP, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ss_temp }, - /* Simple data: write access only */ - { GPG_DO_RESETTING_CODE, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED, - proc_resetting_code }, - /* Compound data: Write access only */ - { GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED, - proc_key_import }, -#if 0 - /* Card holder certificate is handled in special way, as its size is big */ - { GPG_DO_CH_CERTIFICATE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, -#endif -}; - -#define NUM_DO_ENTRIES (int)(sizeof (gpg_do_table) \ - / sizeof (struct do_table_entry)) - -/* - * Reading data from Flash ROM, initialize DO_PTR, PW_ERR_COUNTERS, etc. - */ -void -gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end) -{ - const uint8_t *p; - int i; - const uint8_t *dsc_h14_p, *dsc_l10_p; - int dsc_h14, dsc_l10; - - dsc_h14_p = dsc_l10_p = NULL; - pw1_lifetime_p = NULL; - pw_err_counter_p[PW_ERR_PW1] = NULL; - pw_err_counter_p[PW_ERR_RC] = NULL; - pw_err_counter_p[PW_ERR_PW3] = NULL; - algo_attr_sig_p = algo_attr_dec_p = algo_attr_aut_p = NULL; - digital_signature_counter = 0; - uif_flags = 0; - - /* Clear all data objects. */ - for (i = 0; i < NR_DO__LAST__; i++) - do_ptr[i] = NULL; - - /* When the card is terminated no data objects are valid. */ - if (do_start == NULL) - return; - - /* Traverse DO, counters, etc. in DATA pool */ - p = do_start; - while (p < do_end && *p != NR_EMPTY) - { - uint8_t nr = *p++; - uint8_t second_byte = *p; - - if (nr == 0x00 && second_byte == 0x00) - p++; /* Skip released word */ - else - { - if (nr < 0x80) - { - /* It's Data Object */ - if (nr < NR_DO__LAST__) - do_ptr[nr] = p; - - p += second_byte + 1; /* second_byte has length */ - - if (((uintptr_t)p & 1)) - p++; - } - else if (nr >= 0x80 && nr <= 0xbf) - /* Encoded data of Digital Signature Counter: upper 14-bit */ - { - dsc_h14_p = p - 1; - p++; - } - else if (nr >= 0xc0 && nr <= 0xc3) - /* Encoded data of Digital Signature Counter: lower 10-bit */ - { - dsc_l10_p = p - 1; - p++; - } - else - switch (nr) - { - case NR_BOOL_PW1_LIFETIME: - pw1_lifetime_p = p - 1; - p++; - break; - case NR_KEY_ALGO_ATTR_SIG: - algo_attr_sig_p = p - 1; - p++; - break; - case NR_KEY_ALGO_ATTR_DEC: - algo_attr_dec_p = p - 1; - p++; - break; - case NR_KEY_ALGO_ATTR_AUT: - algo_attr_aut_p = p - 1; - p++; - break; - case NR_DO_UIF_SIG: - case NR_DO_UIF_DEC: - case NR_DO_UIF_AUT: - uif_flags &= ~(3 << ((nr - NR_DO_UIF_SIG) * 2)); - uif_flags |= (second_byte & 3) << ((nr - NR_DO_UIF_SIG) * 2); - p++; - break; - case NR_COUNTER_123: - p++; - if (second_byte <= PW_ERR_PW3) - pw_err_counter_p[second_byte] = p; - p += 2; - break; - default: - /* Something going wrong. ignore this word. */ - p++; - break; - } - } - } - - flash_set_data_pool_last (p); - - num_prv_keys = 0; - if (do_ptr[NR_DO_PRVKEY_SIG] != NULL) - num_prv_keys++; - if (do_ptr[NR_DO_PRVKEY_DEC] != NULL) - num_prv_keys++; - if (do_ptr[NR_DO_PRVKEY_AUT] != NULL) - num_prv_keys++; - - data_objects_number_of_bytes = 0; - for (i = 0; i < NR_DO__LAST__; i++) - if (do_ptr[i] != NULL) - data_objects_number_of_bytes += *do_ptr[i]; - - if (dsc_l10_p == NULL) - dsc_l10 = 0; - else - dsc_l10 = ((*dsc_l10_p - 0xc0) << 8) | *(dsc_l10_p + 1); - - if (dsc_h14_p == NULL) - dsc_h14 = 0; - else - { - dsc_h14 = ((*dsc_h14_p - 0x80) << 8) | *(dsc_h14_p + 1); - if (dsc_l10_p == NULL) - DEBUG_INFO ("something wrong in DSC\r\n"); /* weird??? */ - else if (dsc_l10_p < dsc_h14_p) - /* Possibly, power off during writing dsc_l10 */ - dsc_l10 = 0; - } - - digital_signature_counter = (dsc_h14 << 10) | dsc_l10; -} - -/* - * Write all data to newly allocated Flash ROM page (from P_START), - * updating PW1_LIFETIME_P, PW_ERR_COUNTER_P, and DO_PTR. - * Called by flash_copying_gc. - */ -void -gpg_data_copy (const uint8_t *p_start) -{ - const uint8_t *p; - int i; - int v; - - p = gpg_write_digital_signature_counter (p_start, digital_signature_counter); - - if (pw1_lifetime_p != NULL) - { - flash_bool_write_internal (p, NR_BOOL_PW1_LIFETIME); - pw1_lifetime_p = p; - p += 2; - } - - if (algo_attr_sig_p != NULL) - { - flash_enum_write_internal (p, NR_KEY_ALGO_ATTR_SIG, algo_attr_sig_p[1]); - algo_attr_sig_p = p; - p += 2; - } - - if (algo_attr_dec_p != NULL) - { - flash_enum_write_internal (p, NR_KEY_ALGO_ATTR_DEC, algo_attr_dec_p[1]); - algo_attr_dec_p = p; - p += 2; - } - - if (algo_attr_aut_p != NULL) - { - flash_enum_write_internal (p, NR_KEY_ALGO_ATTR_AUT, algo_attr_aut_p[1]); - algo_attr_aut_p = p; - p += 2; - } - - for (i = 0; i < 3; i++) - if ((v = flash_cnt123_get_value (pw_err_counter_p[i])) != 0) - { - flash_cnt123_write_internal (p, i, v); - pw_err_counter_p[i] = p + 2; - p += 4; - } - - for (i = 0; i < 3; i++) - if ((v = (uif_flags >> (i * 2)) & 3)) - { - flash_enum_write_internal (p, NR_DO_UIF_SIG + i, v); - p += 2; - } - - data_objects_number_of_bytes = 0; - for (i = 0; i < NR_DO__LAST__; i++) - if (do_ptr[i] != NULL) - { - const uint8_t *do_data = do_ptr[i]; - int len = do_data[0]; - - flash_do_write_internal (p, i, &do_data[1], len); - do_ptr[i] = p + 1; - p += 2 + ((len + 1) & ~1); - data_objects_number_of_bytes += len; - } - - flash_set_data_pool_last (p); -} - -static const struct do_table_entry * -get_do_entry (uint16_t tag) -{ - int i; - - for (i = 0; i < NUM_DO_ENTRIES; i++) - if (gpg_do_table[i].tag == tag) - return &gpg_do_table[i]; - - return NULL; -} - -static void -copy_do_1 (uint16_t tag, const uint8_t *do_data, int with_tag) -{ - int len; - - if (with_tag) - { - copy_tag (tag); - - if (do_data[0] >= 128) - *res_p++ = 0x81; - - len = do_data[0] + 1; - } - else - { - len = do_data[0]; - do_data++; - } - - memcpy (res_p, do_data, len); - res_p += len; -} - -static int -copy_do (const struct do_table_entry *do_p, int with_tag) -{ - if (do_p == NULL) - return 0; - - if (!ac_check_status (do_p->ac_read)) - return -1; - - switch (do_p->do_type) - { - case DO_FIXED: - { - const uint8_t *do_data = (const uint8_t *)do_p->obj; - if (do_data == NULL) - return 0; - else - copy_do_1 (do_p->tag, do_data, with_tag); - break; - } - case DO_VAR: - { - const uint8_t *do_data = *(const uint8_t **)do_p->obj; - if (do_data == NULL) - return 0; - else - copy_do_1 (do_p->tag, do_data, with_tag); - break; - } - case DO_CMP_READ: - { - int i; - const uint16_t *cmp_data = (const uint16_t *)do_p->obj; - int num_components = cmp_data[0]; - uint8_t *len_p = NULL; - - if (with_tag) - { - copy_tag (do_p->tag); - *res_p++ = 0x81; /* Assume it's less than 256 */ - len_p = res_p; - *res_p++ = 0; /* for now */ - } - - for (i = 0; i < num_components; i++) - { - uint16_t tag0; - const struct do_table_entry *do0_p; - - tag0 = cmp_data[i+1]; - do0_p = get_do_entry (tag0); - if (copy_do (do0_p, 1) < 0) - return -1; - } - - if (len_p) - *len_p = res_p - len_p - 1; - break; - } - case DO_PROC_READ: - { - void (*do_func)(uint16_t, int) = (void (*)(uint16_t, int))do_p->obj; - - do_func (do_p->tag, with_tag); - return 1; - } - case DO_PROC_READWRITE: - { - int (*rw_func)(uint16_t, int, const uint8_t *, int, int) - = (int (*)(uint16_t, int, const uint8_t *, int, int))do_p->obj; - - return rw_func (do_p->tag, with_tag, NULL, 0, 0); - } - case DO_PROC_WRITE: - return -1; - } - - return 1; -} - -/* - * Process GET_DATA request on Data Object specified by TAG - * Call write_res_adpu to fill data returned - */ -void -gpg_do_get_data (uint16_t tag, int with_tag) -{ -#if defined(CERTDO_SUPPORT) - if (tag == GPG_DO_CH_CERTIFICATE) - { - apdu.res_apdu_data = (uint8_t *)ch_certificate_start; - apdu.res_apdu_data_len = ((apdu.res_apdu_data[2] << 8) | apdu.res_apdu_data[3]); - if (apdu.res_apdu_data_len == 0xffff) - { - apdu.res_apdu_data_len = 0; - GPG_NO_RECORD (); - } - else - /* Add length of (tag+len) */ - apdu.res_apdu_data_len += 4; - } - else -#endif - { - const struct do_table_entry *do_p = get_do_entry (tag); - - res_p = res_APDU; - - DEBUG_INFO (" "); - DEBUG_SHORT (tag); - - if (do_p) - { - if (copy_do (do_p, with_tag) < 0) - /* Overwriting partially written result */ - GPG_SECURITY_FAILURE (); - else - { - res_APDU_size = res_p - res_APDU; - GPG_SUCCESS (); - } - } - else - GPG_NO_RECORD (); - } -} - -void -gpg_do_put_data (uint16_t tag, const uint8_t *data, int len) -{ - const struct do_table_entry *do_p = get_do_entry (tag); - - DEBUG_INFO (" "); - DEBUG_SHORT (tag); - - if (do_p) - { - if (!ac_check_status (do_p->ac_write)) - { - GPG_SECURITY_FAILURE (); - return; - } - - switch (do_p->do_type) - { - case DO_FIXED: - case DO_CMP_READ: - case DO_PROC_READ: - GPG_SECURITY_FAILURE (); - break; - case DO_VAR: - { - const uint8_t **do_data_p = (const uint8_t **)do_p->obj; - - if (*do_data_p) - flash_do_release (*do_data_p); - - if (len == 0) - { - /* make DO empty */ - *do_data_p = NULL; - GPG_SUCCESS (); - } - else if (len > 255) - GPG_MEMORY_FAILURE (); - else - { - int nr = do_tag_to_nr (tag); - - if (nr < 0) - GPG_MEMORY_FAILURE (); - else - { - *do_data_p = NULL; - *do_data_p = flash_do_write (nr, data, len); - if (*do_data_p) - GPG_SUCCESS (); - else - GPG_MEMORY_FAILURE (); - } - } - break; - } - case DO_PROC_READWRITE: - { - int (*rw_func)(uint16_t, int, const uint8_t *, int, int) - = (int (*)(uint16_t, int, const uint8_t *, int, int))do_p->obj; - - if (rw_func (tag, 0, data, len, 1)) - GPG_SUCCESS (); - else - GPG_ERROR (); - break; - } - case DO_PROC_WRITE: - { - int (*proc_func)(const uint8_t *, int) - = (int (*)(const uint8_t *, int))do_p->obj; - - if (proc_func (data, len)) - GPG_SUCCESS (); - else - GPG_ERROR (); - break; - } - } - } - else - GPG_NO_RECORD (); -} - -void -gpg_do_public_key (uint8_t kk_byte) -{ - enum kind_of_key kk = kkb_to_kk (kk_byte); - int attr = gpg_get_algo_attr (kk); - int pubkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PUBLIC); - const uint8_t *pubkey = kd[kk].pubkey; - - DEBUG_INFO ("Public key\r\n"); - DEBUG_BYTE (kk_byte); - - if (pubkey == NULL) - { - DEBUG_INFO ("none.\r\n"); - GPG_NO_RECORD (); - return; - } - - res_p = res_APDU; - - /* TAG */ - *res_p++ = 0x7f; *res_p++ = 0x49; - - if (attr == ALGO_SECP256K1) - { /* ECDSA or ECDH */ - /* LEN */ - *res_p++ = 2 + 1 + 64; - { - /*TAG*/ /* LEN = 1+64 */ - *res_p++ = 0x86; *res_p++ = 0x41; - *res_p++ = 0x04; /* No compression of EC point. */ - /* 64-byte binary (big endian): X || Y */ - memcpy (res_p, pubkey, 64); - res_p += 64; - } - } - else if (attr == ALGO_ED25519 || attr == ALGO_CURVE25519) - { /* EdDSA or ECDH on curve25519 */ - /* LEN */ - *res_p++ = 2 + 32; - { - /*TAG*/ /* LEN = 32 */ - *res_p++ = 0x86; *res_p++ = 0x20; - /* 32-byte binary (little endian): Y with parity or X */ - memcpy (res_p, pubkey, 32); - res_p += 32; - } - } - else if (attr == ALGO_ED448) - { /* EdDSA using Ed448 */ - /* LEN */ - *res_p++ = 2 + 57; - { - /*TAG*/ /* LEN = 57 */ - *res_p++ = 0x86; *res_p++ = 0x39; - /* 57-byte binary (little endian): X */ - memcpy (res_p, pubkey, 57); - res_p += 57; - } - } - else if (attr == ALGO_X448) - { /* ECDH using X448 */ - /* LEN */ - *res_p++ = 2 + 56; - { - /*TAG*/ /* LEN = 56 */ - *res_p++ = 0x86; *res_p++ = 0x38; - /* 56-byte binary (little endian): X */ - memcpy (res_p, pubkey, 56); - res_p += 56; - } - } - else - { /* RSA */ - /* LEN = 9+256or512 */ - *res_p++ = 0x82; *res_p++ = pubkey_len > 256? 0x02: 0x01; *res_p++ = 0x09; - - { - /*TAG*/ /* LEN = 256or512 */ - *res_p++ = 0x81; - *res_p++ = 0x82; *res_p++ = pubkey_len > 256? 0x02: 0x01;*res_p++ = 0x00; - /* PUBKEY_LEN-byte binary (big endian) */ - memcpy (res_p, pubkey, pubkey_len); - res_p += pubkey_len; - } - { - /*TAG*/ /* LEN= 3 */ - *res_p++ = 0x82; *res_p++ = 3; - /* 3-byte E=0x10001 (big endian) */ - *res_p++ = 0x01; *res_p++ = 0x00; *res_p++ = 0x01; - } - } - - /* Success */ - res_APDU_size = res_p - res_APDU; - GPG_SUCCESS (); - - DEBUG_INFO ("done.\r\n"); - return; -} - -const uint8_t * -gpg_do_read_simple (uint8_t nr) -{ - const uint8_t *do_data; - - do_data = do_ptr[nr]; - if (do_data == NULL) - return NULL; - - return do_data+1; -} - -void -gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size) -{ - const uint8_t **do_data_p; - - do_data_p = (const uint8_t **)&do_ptr[nr]; - if (*do_data_p) - flash_do_release (*do_data_p); - - if (data != NULL) - { - *do_data_p = NULL; - *do_data_p = flash_do_write (nr, data, size); - if (*do_data_p == NULL) - flash_warning ("DO WRITE ERROR"); - } - else - *do_data_p = NULL; -} - -#include "hsm2040.h" -#include "tusb.h" - -void -gpg_do_keygen (uint8_t *buf) -{ - uint8_t kk_byte = buf[0]; - enum kind_of_key kk = kkb_to_kk (kk_byte); - int attr = gpg_get_algo_attr (kk);; - int prvkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PRIVATE); - const uint8_t *prv; - const uint8_t *rnd; - int r = 0; -#define p_q (&buf[3]) -#define d (&buf[3]) -#define d1 (&buf[3+64]) -#define pubkey (&buf[3+256]) - - DEBUG_INFO ("Keygen\r\n"); - DEBUG_BYTE (kk_byte); - - if (attr == ALGO_RSA2K || attr == ALGO_RSA4K) - { - if (rsa_genkey (prvkey_len, pubkey, p_q) < 0) - { - GPG_MEMORY_FAILURE (); - return; - } - - prv = p_q; - } - else if (attr == ALGO_SECP256K1) - { - const uint8_t *p; - int i; - - rnd = NULL; - do - { - if (rnd) - random_bytes_free (rnd); - rnd = random_bytes_get (32); - r = ecc_check_secret_p256k1 (rnd, d1); - } - while (r == 0); - - /* Convert it to big endian */ - - if (r < 0) - p = (const uint8_t *)d1; - else - p = rnd; - for (i = 0; i < 32; i++) - d[32 - i - 1] = p[i]; - - random_bytes_free (rnd); - - prv = d; - r = ecc_compute_public_p256k1 (prv, pubkey); - } - else if (attr == ALGO_CURVE25519) - { - rnd = random_bytes_get (32); - memcpy (d, rnd, 32); - random_bytes_free (rnd); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - prv = d; - ecdh_compute_public_25519 (prv, pubkey); - } - else if (attr == ALGO_ED25519) - { - rnd = random_bytes_get (32); - - mbedtls_sha512_context ctx; - mbedtls_sha512_init(&ctx); - - mbedtls_sha512_starts (&ctx, 0); - mbedtls_sha512_update (&ctx, rnd, 32); - mbedtls_sha512_finish (&ctx, d); - mbedtls_sha512_free (&ctx); - - random_bytes_free (rnd); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - prv = d; - eddsa_compute_public_25519 (d, pubkey); - } - else if (attr == ALGO_ED448) - { - shake_context ctx; - rnd = random_bytes_get (32); - shake256_start (&ctx); - shake256_update (&ctx, rnd, 32); - random_bytes_free (rnd); - rnd = random_bytes_get (32); - shake256_update (&ctx, rnd, 25); - shake256_finish (&ctx, d, 2*57); - random_bytes_free (rnd); - prv = d; - ed448_compute_public (pubkey, prv); - pubkey[57] = 0; - } - else if (attr == ALGO_X448) - { - rnd = random_bytes_get (32); - memcpy (d, rnd, 32); - random_bytes_free (rnd); - rnd = random_bytes_get (32); - memcpy (d+32, rnd, 24); - prv = d; - ecdh_compute_public_x448 (pubkey, prv); - } - else - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - if (r >= 0) - { - const uint8_t *keystring_admin; - - if (admin_authorized == BY_ADMIN) - keystring_admin = keystring_md_pw3; - else - keystring_admin = NULL; - - r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey); - } - - /* Clear private key data in the buffer. */ - memset (buf, 0, 256); - - if (r < 0) - { - GPG_ERROR (); - return; - } - - DEBUG_INFO ("Calling gpg_do_public_key...\r\n"); - - if (kk == GPG_KEY_FOR_SIGNING) - { - int pw_len; - const uint8_t *initial_pw; - uint8_t keystring[KEYSTRING_MD_SIZE]; - - /* GnuPG expects it's ready for signing. */ - /* Don't call ac_reset_pso_cds here, but load the private key */ - - gpg_reset_digital_signature_counter (); - gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw); - s2k (NULL, 0, initial_pw, pw_len, keystring); - gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring); - } - else - ac_reset_other (); - - gpg_do_public_key (kk_byte); -} diff --git a/src/openpgp/openpgp.c b/src/openpgp/openpgp.c deleted file mode 100644 index e09749a..0000000 --- a/src/openpgp/openpgp.c +++ /dev/null @@ -1,1610 +0,0 @@ -/* - * openpgp.c -- OpenPGP card protocol support - * - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 - * 2019, 2021 - * Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include - -#include "config.h" - -#include "gnuk.h" -//#include "sys.h" -#include "status-code.h" -#include "mbedtls/sha256.h" -#include "random.h" -#include "pico/util/queue.h" -#include "pico/multicore.h" -#include "hsm2040.h" -#include "tusb.h" -#include "file.h" -#include "libopensc/card-sc-hsm.h" - -extern const uint8_t openpgpcard_aid[]; -static int openpgp_process_apdu(); -static int gpg_fini(); - -app_t *openpgp_select_aid(app_t *a) { - if (!memcmp(apdu.cmd_apdu_data, openpgpcard_aid+1, MIN(apdu.cmd_apdu_data_len,openpgpcard_aid[0]))) { - a->aid = openpgpcard_aid; - a->process_apdu = openpgp_process_apdu; - a->unload = gpg_fini; - return a; - } - return NULL; -} - -void __attribute__ ((constructor)) openpgp_ctor() { - register_app(openpgp_select_aid); -} - - -#define USER_PASSWD_MINLEN 6 -#define ADMIN_PASSWD_MINLEN 8 - -#define INS_VERIFY 0x20 -#define INS_CHANGE_REFERENCE_DATA 0x24 -#define INS_PSO 0x2a -#define INS_RESET_RETRY_COUNTER 0x2c -#define INS_ACTIVATE_FILE 0x44 -#define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR 0x47 -#define INS_EXTERNAL_AUTHENTICATE 0x82 -#define INS_GET_CHALLENGE 0x84 -#define INS_INTERNAL_AUTHENTICATE 0x88 -#define INS_SELECT_FILE 0xa4 -#define INS_READ_BINARY 0xb0 -#define INS_READ_BINARY_ODD 0xb1 -#define INS_GET_DATA 0xca -#define INS_WRITE_BINARY 0xd0 -#define INS_UPDATE_BINARY 0xd6 -#define INS_PUT_DATA 0xda -#define INS_PUT_DATA_ODD 0xdb /* For key import */ -#define INS_TERMINATE_DF 0xe6 - -static const uint8_t *challenge; /* Random bytes */ - -static const uint8_t -select_file_TOP_result[] __attribute__ ((aligned (1))) = { - 0x00, 0x00, /* unused */ - 0x00, 0x00, /* number of bytes in this directory: to be filled */ - 0x3f, 0x00, /* field of selected file: MF, 3f00 */ - 0x38, /* it's DF */ - 0xff, /* unused */ - 0xff, 0x44, 0x44, /* access conditions */ - 0x01, /* status of the selected file (OK, unblocked) */ - 0x05, /* number of bytes of data follow */ - 0x03, /* Features: unused */ - 0x01, /* number of subdirectories (OpenPGP) */ - 0x01, /* number of elementary files (SerialNo) */ - 0x00, /* number of secret codes */ - 0x00, /* Unused */ - 0x00, 0x00 /* PIN status: OK, PIN blocked?: No */ -}; - - -#define FILE_NONE 0 -#define FILE_DF_OPENPGP 1 -#define FILE_MF 2 -#define FILE_EF_DIR 3 -#define FILE_EF_SERIAL_NO 4 -#define FILE_EF_UPDATE_KEY_0 5 -#define FILE_EF_UPDATE_KEY_1 6 -#define FILE_EF_UPDATE_KEY_2 7 -#define FILE_EF_UPDATE_KEY_3 8 -#define FILE_EF_CH_CERTIFICATE 9 -#define FILE_DF_SC_HSM 10 -#define FILE_CARD_TERMINATED 255 - -uint8_t file_selection; - -static void -gpg_init (void) -{ - const uint8_t *flash_do_start; - const uint8_t *flash_do_end; - - flash_do_storage_init (&flash_do_start, &flash_do_end); - - if (flash_do_start == NULL) - file_selection = FILE_CARD_TERMINATED; - else - file_selection = FILE_NONE; - - gpg_data_scan (flash_do_start, flash_do_end); - flash_key_storage_init (); - multicore_lockout_victim_init(); -} - -static int -gpg_fini (void) -{ - ac_fini (); - return 0; -} - -#if defined(PINPAD_SUPPORT) -/* - * Let user input PIN string. - * Return length of the string. - * The string itself is in PIN_INPUT_BUFFER. - */ -static int -get_pinpad_input (int msg_code) -{ - int r; - - led_blink (LED_START_COMMAND); - r = pinpad_getline (msg_code, 8000000); - led_blink (LED_FINISH_COMMAND); - return r; -} -#endif - -static void cmd_verify (queue_t *ccid_comm) -{ - int len; - uint8_t p1 = P1 (apdu); - uint8_t p2 = P2 (apdu); - int r; - const uint8_t *pw; - - (void)ccid_comm; - DEBUG_INFO (" - VERIFY\r\n"); - DEBUG_BYTE (p2); - - len = apdu.cmd_apdu_data_len; - pw = apdu.cmd_apdu_data; - - if (len == 0) - { - if (p1 == 0) - { /* This is to examine status. */ - if (p2 == 0x81) - r = ac_check_status (AC_PSO_CDS_AUTHORIZED); - else if (p2 == 0x82) - r = ac_check_status (AC_OTHER_AUTHORIZED); - else - r = ac_check_status (AC_ADMIN_AUTHORIZED); - - if (r) - /* If authentication done already, return success. */ - GPG_SUCCESS (); - else - { /* If not, return retry counter, encoded. */ - r = gpg_pw_get_retry_counter (p2); - set_res_sw (0x63, 0xc0 | (r&0x0f)); - } - } - else if (p1 == 0xff) - { /* Reset the status. */ - if (p2 == 0x81) - ac_reset_pso_cds (); - else if (p2 == 0x82) - ac_reset_other (); - else - ac_reset_admin (); - GPG_SUCCESS (); - } - else - GPG_BAD_P1_P2 (); - return; - } - - if (gpg_do_kdf_check (len, 1) == 0) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - /* This is real authentication. */ - if (p2 == 0x81) - r = verify_pso_cds (pw, len); - else if (p2 == 0x82) - r = verify_other (pw, len); - else - r = verify_admin (pw, len); - - if (r < 0) - { - DEBUG_INFO ("failed\r\n"); - GPG_SECURITY_FAILURE (); - } - else if (r == 0) - { - DEBUG_INFO ("blocked\r\n"); - GPG_SECURITY_AUTH_BLOCKED (); - } - else - { - DEBUG_INFO ("good\r\n"); - GPG_SUCCESS (); - } -} - -int -gpg_change_keystring (int who_old, const uint8_t *old_ks, - int who_new, const uint8_t *new_ks) -{ - int r; - int prv_keys_exist = 0; - - r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, who_old, old_ks); - if (r < 0) - return r; - - if (r > 0) - prv_keys_exist++; - - r = gpg_do_chks_prvkey (GPG_KEY_FOR_SIGNING, who_old, old_ks, - who_new, new_ks); - if (r < 0) - return -2; - - r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, who_old, old_ks); - if (r < 0) - return r; - - if (r > 0) - prv_keys_exist++; - - r = gpg_do_chks_prvkey (GPG_KEY_FOR_DECRYPTION, who_old, old_ks, - who_new, new_ks); - if (r < 0) - return -2; - - r = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, who_old, old_ks); - if (r < 0) - return r; - - if (r > 0) - prv_keys_exist++; - - r = gpg_do_chks_prvkey (GPG_KEY_FOR_AUTHENTICATION, who_old, old_ks, - who_new, new_ks); - if (r < 0) - return -2; - - if (prv_keys_exist) - return 1; - else - return 0; -} - -static void -cmd_change_password (queue_t *ccid_comm) -{ - uint8_t old_ks[KEYSTRING_MD_SIZE]; - uint8_t new_ks0[KEYSTRING_SIZE]; - uint8_t *new_salt = KS_GET_SALT (new_ks0); - int newsalt_len = SALT_SIZE; - uint8_t *new_ks = KS_GET_KEYSTRING (new_ks0); - uint8_t p1 = P1 (apdu); /* 0: change (old+new), 1: exchange (new) */ - uint8_t p2 = P2 (apdu); - int len; - uint8_t *pw, *newpw; - int pw_len, newpw_len; - int who = p2 - 0x80; - int who_old; - int r; - int pw3_null = 0; - const uint8_t *salt; - int salt_len; - const uint8_t *ks_pw3; - - (void)ccid_comm; - DEBUG_INFO ("Change PW\r\n"); - DEBUG_BYTE (who); - - len = apdu.cmd_apdu_data_len; - pw = apdu.cmd_apdu_data; - - if (p1 != 0) - { - GPG_FUNCTION_NOT_SUPPORTED (); - return; - } - - if (gpg_do_kdf_check (len, 2) == 0) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - if (who == BY_USER) /* PW1 */ - { - const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - - who_old = who; - pw_len = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, len, -1, ks_pw1, 0); - - if (ks_pw1 == NULL) - { - salt = NULL; - salt_len = 0; - } - else - { - salt = KS_GET_SALT (ks_pw1); - salt_len = SALT_SIZE; - } - - if (pw_len < 0) - { - DEBUG_INFO ("permission denied.\r\n"); - GPG_SECURITY_FAILURE (); - return; - } - else if (pw_len == 0) - { - DEBUG_INFO ("blocked.\r\n"); - GPG_SECURITY_AUTH_BLOCKED (); - return; - } - else - { - newpw = pw + pw_len; - newpw_len = len - pw_len; - ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); - - /* Check length of password */ - if ((ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN) - || newpw_len < USER_PASSWD_MINLEN) - { - DEBUG_INFO ("new password length is too short."); - GPG_CONDITION_NOT_SATISFIED (); - return; - } - } - } - else /* PW3 (0x83) */ - { - ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); - pw_len = verify_admin_0 (pw, len, -1, ks_pw3, 0); - - if (ks_pw3 == NULL) - { - if (admin_authorized == BY_USER) - { - const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - - if (ks_pw1 == NULL) - { - GPG_SECURITY_FAILURE (); - return; - } - - salt = KS_GET_SALT (ks_pw1); - salt_len = SALT_SIZE; - } - else - { - salt = NULL; - salt_len = 0; - } - } - else - { - salt = KS_GET_SALT (ks_pw3); - salt_len = SALT_SIZE; - } - - if (pw_len < 0) - { - DEBUG_INFO ("permission denied.\r\n"); - GPG_SECURITY_FAILURE (); - return; - } - else if (pw_len == 0) - { - DEBUG_INFO ("blocked.\r\n"); - GPG_SECURITY_AUTH_BLOCKED (); - return; - } - else - { - newpw = pw + pw_len; - newpw_len = len - pw_len; - - if (newpw_len == 0 && admin_authorized == BY_ADMIN) - { - const uint8_t *initial_pw; - - gpg_do_get_initial_pw_setting (1, &newpw_len, &initial_pw); - memcpy (newpw, initial_pw, newpw_len); - newsalt_len = 0; - pw3_null = 1; - } - else if (newpw_len < ADMIN_PASSWD_MINLEN) - { - DEBUG_INFO ("new password length is too short."); - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - who_old = admin_authorized; - } - } - - if (newsalt_len != 0) - random_get_salt (new_salt); - s2k (salt, salt_len, pw, pw_len, old_ks); - s2k (new_salt, newsalt_len, newpw, newpw_len, new_ks); - new_ks0[0] = newpw_len; - - r = gpg_change_keystring (who_old, old_ks, who, new_ks); - if (r <= -2) - { - DEBUG_INFO ("memory error.\r\n"); - GPG_MEMORY_FAILURE (); - } - else if (r < 0) - { - DEBUG_INFO ("security error.\r\n"); - GPG_SECURITY_FAILURE (); - } - else if (r == 0 && who == BY_USER) /* no prvkey */ - { - DEBUG_INFO ("user pass change not supported with no keys.\r\n"); - GPG_CONDITION_NOT_SATISFIED (); - } - else if (r > 0 && who == BY_USER) - { - /* When it was already admin-less mode, admin_authorized is - * BY_USER. If no PW3 keystring, it's becoming admin-less mode, - * now. For these two cases, we need to reset admin - * authorization status. */ - if (admin_authorized == BY_USER) - ac_reset_admin (); - else if (ks_pw3 == NULL) - { - enum kind_of_key kk0; - - /* Remove keystrings for BY_ADMIN. */ - for (kk0 = 0; kk0 <= GPG_KEY_FOR_AUTHENTICATION; kk0++) - gpg_do_chks_prvkey (kk0, BY_ADMIN, NULL, 0, NULL); - - ac_reset_admin (); - } - - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KS_META_SIZE); - ac_reset_pso_cds (); - ac_reset_other (); - DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n"); - GPG_SUCCESS (); - } - else if (r > 0 && who == BY_ADMIN) - { - if (pw3_null) - gpg_do_write_simple (NR_DO_KEYSTRING_PW3, NULL, 0); - else - gpg_do_write_simple (NR_DO_KEYSTRING_PW3, new_ks0, KS_META_SIZE); - - ac_reset_admin (); - DEBUG_INFO ("Changed length of DO_KEYSTRING_PW3.\r\n"); - GPG_SUCCESS (); - } - else /* r == 0 && who == BY_ADMIN */ /* no prvkey */ - { - if (pw3_null) - gpg_do_write_simple (NR_DO_KEYSTRING_PW3, NULL, 0); - else - { - new_ks0[0] |= PW_LEN_KEYSTRING_BIT; - gpg_do_write_simple (NR_DO_KEYSTRING_PW3, new_ks0, KEYSTRING_SIZE); - } - DEBUG_INFO ("Changed DO_KEYSTRING_PW3.\r\n"); - ac_reset_admin (); - GPG_SUCCESS (); - } -} - - -#ifndef S2KCOUNT -/* - * OpenPGP uses the value 65535 for the key on disk. - * Given the condition that the access to flash ROM is harder than disk, - * that is, the threat model is different, we chose the default value 192. - */ -#define S2KCOUNT 192 -#endif -void -s2k (const unsigned char *salt, size_t slen, - const unsigned char *input, size_t ilen, unsigned char output[32]) -{ - mbedtls_sha256_context ctx; - mbedtls_sha256_init(&ctx); - size_t count = S2KCOUNT; - const uint8_t *unique = unique_device_id (); - - mbedtls_sha256_starts (&ctx, 0); - - mbedtls_sha256_update (&ctx, unique, 12); - - while (count > slen + ilen) - { - if (slen) - mbedtls_sha256_update (&ctx, salt, slen); - mbedtls_sha256_update (&ctx, input, ilen); - count -= slen + ilen; - } - - if (count <= slen) - mbedtls_sha256_update (&ctx, salt, count); - else - { - if (slen) - { - mbedtls_sha256_update (&ctx, salt, slen); - count -= slen; - } - mbedtls_sha256_update (&ctx, input, count); - } - - mbedtls_sha256_finish (&ctx, output); - mbedtls_sha256_free (&ctx); -} - - -static void -cmd_reset_user_password (queue_t *ccid_comm) -{ - uint8_t p1 = P1 (apdu); - int len; - const uint8_t *pw; - const uint8_t *newpw; - int pw_len, newpw_len; - int r; - uint8_t new_ks0[KEYSTRING_SIZE]; - uint8_t *new_ks = KS_GET_KEYSTRING (new_ks0); - uint8_t *new_salt = KS_GET_SALT (new_ks0); - const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); - const uint8_t *salt; - int salt_len; - - (void)ccid_comm; - DEBUG_INFO ("Reset PW1\r\n"); - DEBUG_BYTE (p1); - - len = apdu.cmd_apdu_data_len; - pw = apdu.cmd_apdu_data; - - if (p1 == 0x00) /* by User with Reseting Code */ - { - const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC); - uint8_t old_ks[KEYSTRING_MD_SIZE]; - - if (gpg_do_kdf_check (len, 2) == 0) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - if (gpg_pw_locked (PW_ERR_RC)) - { - DEBUG_INFO ("blocked.\r\n"); - GPG_SECURITY_AUTH_BLOCKED (); - return; - } - - if (ks_rc == NULL) - { - DEBUG_INFO ("security error.\r\n"); - GPG_SECURITY_FAILURE (); - return; - } - - pw_len = ks_rc[0] & PW_LEN_MASK; - salt = KS_GET_SALT (ks_rc); - salt_len = SALT_SIZE; - newpw = pw + pw_len; - newpw_len = len - pw_len; - - /* Check length of new password */ - if ((ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN) - || newpw_len < USER_PASSWD_MINLEN) - { - DEBUG_INFO ("new password length is too short."); - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - random_get_salt (new_salt); - s2k (salt, salt_len, pw, pw_len, old_ks); - s2k (new_salt, SALT_SIZE, newpw, newpw_len, new_ks); - new_ks0[0] = newpw_len; - r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks); - if (r <= -2) - { - DEBUG_INFO ("memory error.\r\n"); - GPG_MEMORY_FAILURE (); - } - else if (r < 0) - { - DEBUG_INFO ("failed.\r\n"); - gpg_pw_increment_err_counter (PW_ERR_RC); - GPG_SECURITY_FAILURE (); - } - else if (r == 0) - { - DEBUG_INFO ("user pass change not supported with no keys.\r\n"); - GPG_CONDITION_NOT_SATISFIED (); - } - else - { - DEBUG_INFO ("done.\r\n"); - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KS_META_SIZE); - ac_reset_pso_cds (); - ac_reset_other (); - if (admin_authorized == BY_USER) - ac_reset_admin (); - gpg_pw_reset_err_counter (PW_ERR_RC); - gpg_pw_reset_err_counter (PW_ERR_PW1); - GPG_SUCCESS (); - } - } - else /* by Admin (p1 == 0x02) */ - { - const uint8_t *old_ks = keystring_md_pw3; - - if (!ac_check_status (AC_ADMIN_AUTHORIZED)) - { - DEBUG_INFO ("permission denied.\r\n"); - GPG_SECURITY_FAILURE (); - return; - } - - if (gpg_do_kdf_check (len, 1) == 0) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - newpw_len = len; - newpw = pw; - - /* Check length of new password */ - if ((ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN) - || newpw_len < USER_PASSWD_MINLEN) - { - DEBUG_INFO ("new password length is too short."); - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - random_get_salt (new_salt); - s2k (new_salt, SALT_SIZE, newpw, newpw_len, new_ks); - new_ks0[0] = newpw_len; - r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks); - if (r <= -2) - { - DEBUG_INFO ("memory error.\r\n"); - GPG_MEMORY_FAILURE (); - } - else if (r < 0) - { - DEBUG_INFO ("security error.\r\n"); - GPG_SECURITY_FAILURE (); - } - else if (r == 0) - { - DEBUG_INFO ("user pass change not supported with no keys.\r\n"); - GPG_CONDITION_NOT_SATISFIED (); - } - else - { - DEBUG_INFO ("done.\r\n"); - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KS_META_SIZE); - ac_reset_pso_cds (); - ac_reset_other (); - if (admin_authorized == BY_USER) - ac_reset_admin (); - gpg_pw_reset_err_counter (PW_ERR_PW1); - GPG_SUCCESS (); - } - } -} - -static void -cmd_put_data (queue_t *ccid_comm) -{ - uint8_t *data; - uint16_t tag; - int len; - - (void)ccid_comm; - DEBUG_INFO (" - PUT DATA\r\n"); - - tag = ((P1 (apdu)<<8) | P2 (apdu)); - len = apdu.cmd_apdu_data_len; - data = apdu.cmd_apdu_data; - gpg_do_put_data (tag, data, len); -} - -static void -cmd_pgp_gakp (queue_t *ccid_comm) -{ - (void)ccid_comm; - DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n"); - DEBUG_BYTE (P1 (apdu)); - - if (P1 (apdu) == 0x81) - /* Get public key */ - gpg_do_public_key (apdu.cmd_apdu_data[0]); - else - { - if (!ac_check_status (AC_ADMIN_AUTHORIZED)) - GPG_SECURITY_FAILURE (); -#ifdef KDF_DO_REQUIRED - else if (!gpg_do_kdf_check (0, 0)) - GPG_CONDITION_NOT_SATISFIED (); -#endif - else - gpg_do_keygen (&apdu.cmd_apdu_data[0]); - } -} - -#ifdef FLASH_UPGRADE_SUPPORT -const uint8_t * -gpg_get_firmware_update_key (uint8_t keyno) -{ - extern uint8_t _updatekey_store[1024]; - const uint8_t *p; - - p = _updatekey_store + keyno * FIRMWARE_UPDATE_KEY_CONTENT_LEN; - return p; -} -#endif - -#ifdef CERTDO_SUPPORT -#define FILEID_CH_CERTIFICATE_IS_VALID 1 -#else -#define FILEID_CH_CERTIFICATE_IS_VALID 0 -#endif - -static void -cmd_read_binary (queue_t *ccid_comm) -{ - int is_short_EF = (P1 (apdu) & 0x80) != 0; - uint8_t file_id; - uint16_t offset; - - (void)ccid_comm; - DEBUG_INFO (" - Read binary\r\n"); - - if (is_short_EF) - file_id = (P1 (apdu) & 0x1f); - else - file_id = file_selection - FILE_EF_SERIAL_NO + FILEID_SERIAL_NO; - - if (is_short_EF) - { - file_selection = file_id - FILEID_SERIAL_NO + FILE_EF_SERIAL_NO; - offset = P2 (apdu); - } - else - offset = (P1 (apdu) << 8) | P2 (apdu); - - if (file_id == FILEID_SERIAL_NO) - { - if (offset != 0) - GPG_BAD_P1_P2 (); - else - { - gpg_do_get_data (0x004f, 1); /* Get AID... */ - res_APDU[0] = 0x5a; /* ... and overwrite the first byte of data. */ - } - return; - } -#ifdef FLASH_UPGRADE_SUPPORT - else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3) - { - if (offset != 0) - GPG_MEMORY_FAILURE (); - else - { - const uint8_t *p; - - p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0); - res_APDU_size = FIRMWARE_UPDATE_KEY_CONTENT_LEN; - memcpy (res_APDU, p, FIRMWARE_UPDATE_KEY_CONTENT_LEN); - GPG_SUCCESS (); - } - } -#endif -#if defined(CERTDO_SUPPORT) - else if (file_id == FILEID_CH_CERTIFICATE) - { - const uint8_t *p; - uint16_t len = 256; - - p = ch_certificate_start; - if (offset >= FLASH_CH_CERTIFICATE_SIZE) - GPG_MEMORY_FAILURE (); - else - { - if (offset + len >= FLASH_CH_CERTIFICATE_SIZE) - len = FLASH_CH_CERTIFICATE_SIZE - offset; - - res_APDU_size = len; - memcpy (res_APDU, p + offset, len); - GPG_SUCCESS (); - } - } -#endif - else - { - GPG_NO_FILE (); - return; - } -} - -static void -cmd_select_file (queue_t *ccid_comm) -{ - (void)ccid_comm; - if (P1 (apdu) == 4) /* Selection by DF name */ - { - DEBUG_INFO (" - select DF by name\r\n"); - - /* name = D2 76 00 01 24 01 */ - if (apdu.cmd_apdu_data_len != 6 - || memcmp (openpgpcard_aid, apdu.cmd_apdu_data, 6) != 0) - { - DEBUG_SHORT (apdu.cmd_apdu_data_len); - DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); - - GPG_NO_FILE (); - return; - } - - if (file_selection == FILE_CARD_TERMINATED) - { - GPG_APPLICATION_TERMINATED (); - return; - } - - file_selection = FILE_DF_OPENPGP; - - /* Behave just like original OpenPGP card. */ - GPG_SUCCESS (); - } - else if (apdu.cmd_apdu_data_len == 2 - && apdu.cmd_apdu_data[0] == 0x2f && apdu.cmd_apdu_data[1] == 0x02) - { - DEBUG_INFO (" - select 0x2f02 EF\r\n"); - /* - * MF.EF-GDO -- Serial number of the card and name of the owner - */ - GPG_SUCCESS (); - file_selection = FILE_EF_SERIAL_NO; - } - else if (apdu.cmd_apdu_data_len == 2 - && apdu.cmd_apdu_data[0] == 0x3f && apdu.cmd_apdu_data[1] == 0x00) - { - DEBUG_INFO (" - select ROOT MF\r\n"); - if (P2 (apdu) == 0x0c) - { - GPG_SUCCESS (); - } - else - { - int len = sizeof (select_file_TOP_result); - - res_APDU_size = len; - memcpy (res_APDU, select_file_TOP_result, len); - res_APDU[2] = (data_objects_number_of_bytes & 0xff); - res_APDU[3] = (data_objects_number_of_bytes >> 8); - GPG_SUCCESS (); - } - - file_selection = FILE_MF; - ac_fini (); /* Reset authentication */ - } - else - { - DEBUG_INFO (" - select ?? \r\n"); - - file_selection = FILE_NONE; - GPG_NO_FILE (); - } -} - -static void -cmd_get_data (queue_t *ccid_comm) -{ - uint16_t tag = ((P1 (apdu)<<8) | P2 (apdu)); - - (void)ccid_comm; - DEBUG_INFO (" - Get Data\r\n"); - - gpg_do_get_data (tag, 0); -} - -#define ECDSA_HASH_LEN 32 -#define ECDSA_SIGNATURE_LENGTH 64 - -#define EDDSA_HASH_LEN_MAX 256 -#define ED25519_SIGNATURE_LENGTH 64 -#define ED448_SIGNATURE_LENGTH 114 - -#define ECC_CIPHER_DO_HEADER_SIZE 7 - -static void -cmd_pso (queue_t *ccid_comm) -{ - int len = apdu.cmd_apdu_data_len; - int r = -1; - int attr; - int pubkey_len; - unsigned int result_len = 0; - int cs; - - DEBUG_INFO (" - PSO: "); - DEBUG_WORD ((uint32_t)&r); - DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); - DEBUG_SHORT (len); - - if (P1 (apdu) == 0x9e && P2 (apdu) == 0x9a) - { - attr = gpg_get_algo_attr (GPG_KEY_FOR_SIGNING); - pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_SIGNING, - GPG_KEY_PUBLIC); - - if (!ac_check_status (AC_PSO_CDS_AUTHORIZED)) - { - DEBUG_INFO ("security error."); - GPG_SECURITY_FAILURE (); - return; - } - -#ifdef ACKBTN_SUPPORT - if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING)) - eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED); -#endif - - if (attr == ALGO_RSA2K || attr == ALGO_RSA4K) - { - /* Check size of digestInfo */ - if (len != 34 /* MD5 */ - && len != 35 /* SHA1 / RIPEMD-160 */ - && len != 47 /* SHA224 */ - && len != 51 /* SHA256 */ - && len != 67 /* SHA384 */ - && len != 83) /* SHA512 */ - { - DEBUG_INFO (" wrong length"); - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - DEBUG_BINARY (kd[GPG_KEY_FOR_SIGNING].data, pubkey_len); - - result_len = pubkey_len; - r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len, - &kd[GPG_KEY_FOR_SIGNING], pubkey_len); - } - else if (attr == ALGO_SECP256K1) - { - /* ECDSA with p256r1/p256k1 for signature */ - if (len != ECDSA_HASH_LEN) - { - DEBUG_INFO (" wrong length"); - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - //cs = chopstx_setcancelstate (0); - result_len = ECDSA_SIGNATURE_LENGTH; - r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU, - kd[GPG_KEY_FOR_SIGNING].data); - //chopstx_setcancelstate (cs); - } - else if (attr == ALGO_ED25519) - { - uint32_t output[ED25519_SIGNATURE_LENGTH/4]; /* Require 4-byte alignment. */ - - //cs = chopstx_setcancelstate (0); - result_len = ED25519_SIGNATURE_LENGTH; - r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output, - kd[GPG_KEY_FOR_SIGNING].data, - kd[GPG_KEY_FOR_SIGNING].data+32, - kd[GPG_KEY_FOR_SIGNING].pubkey); - //chopstx_setcancelstate (cs); - memcpy (res_APDU, output, ED25519_SIGNATURE_LENGTH); - } - else if (attr == ALGO_ED448) - { - //cs = chopstx_setcancelstate (0); - result_len = ED448_SIGNATURE_LENGTH; - r = ed448_sign (res_APDU, apdu.cmd_apdu_data, len, - kd[GPG_KEY_FOR_SIGNING].data, - kd[GPG_KEY_FOR_SIGNING].data+57, - kd[GPG_KEY_FOR_SIGNING].pubkey); - //chopstx_setcancelstate (cs); - } - else - { - DEBUG_INFO ("unknown algo."); - GPG_FUNCTION_NOT_SUPPORTED (); - return; - } - - if (r == 0) - { - res_APDU_size = result_len; - gpg_increment_digital_signature_counter (); - } - else /* Failure */ - ac_reset_pso_cds (); - } - else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86) - { - attr = gpg_get_algo_attr (GPG_KEY_FOR_DECRYPTION); - pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_DECRYPTION, - GPG_KEY_PUBLIC); - - DEBUG_BINARY (kd[GPG_KEY_FOR_DECRYPTION].data, pubkey_len); - - if (!ac_check_status (AC_OTHER_AUTHORIZED)) - { - DEBUG_INFO ("security error."); - GPG_SECURITY_FAILURE (); - return; - } - -#ifdef ACKBTN_SUPPORT - if (gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION)) - eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED); -#else - (void)ccid_comm; -#endif - - if (attr == ALGO_RSA2K || attr == ALGO_RSA4K) - { - /* Skip padding 0x00 */ - len--; - if (len != pubkey_len) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len, - &kd[GPG_KEY_FOR_DECRYPTION], &result_len); - } - else if (attr == ALGO_SECP256K1) - { - int header = ECC_CIPHER_DO_HEADER_SIZE; - - /* Format is in big endian MPI: 04 || x || y */ - if (len != 65 + ECC_CIPHER_DO_HEADER_SIZE - || apdu.cmd_apdu_data[header] != 0x04) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - //cs = chopstx_setcancelstate (0); - result_len = 65; - r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data + header, res_APDU, - kd[GPG_KEY_FOR_DECRYPTION].data); - //chopstx_setcancelstate (cs); - } - else if (attr == ALGO_CURVE25519) - { - int header = ECC_CIPHER_DO_HEADER_SIZE; - - if (len != 32 + ECC_CIPHER_DO_HEADER_SIZE) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - //cs = chopstx_setcancelstate (0); - result_len = 32; - r = ecdh_decrypt_curve25519 (apdu.cmd_apdu_data + header, res_APDU, - kd[GPG_KEY_FOR_DECRYPTION].data); - //chopstx_setcancelstate (cs); - } - else if (attr == ALGO_X448) - { - int header = ECC_CIPHER_DO_HEADER_SIZE; - - if (len != 56 + ECC_CIPHER_DO_HEADER_SIZE) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - //cs = chopstx_setcancelstate (0); - result_len = 56; - r = ecdh_decrypt_x448 (res_APDU, apdu.cmd_apdu_data + header, - kd[GPG_KEY_FOR_DECRYPTION].data); - //chopstx_setcancelstate (cs); - } - else - { - DEBUG_INFO ("unknown algo."); - GPG_FUNCTION_NOT_SUPPORTED (); - return; - } - - if (r == 0) - res_APDU_size = result_len; - } - - if (r < 0) - { - DEBUG_INFO (" - ??"); - DEBUG_BYTE (P1 (apdu)); - DEBUG_INFO (" - ??"); - DEBUG_BYTE (P2 (apdu)); - GPG_ERROR (); - } - - DEBUG_INFO ("PSO done.\r\n"); -} - - -#define MAX_RSA_DIGEST_INFO_LEN 102 /* 40% */ -static void -cmd_internal_authenticate (queue_t *ccid_comm) -{ - int attr = gpg_get_algo_attr (GPG_KEY_FOR_AUTHENTICATION); - int pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_AUTHENTICATION, - GPG_KEY_PUBLIC); - int len = apdu.cmd_apdu_data_len; - int r = -1; - unsigned int result_len = 0; - int cs; - - DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n"); - - if (P1 (apdu) != 0x00 || P2 (apdu) != 0x00) - { - DEBUG_INFO (" - ??"); - DEBUG_BYTE (P1 (apdu)); - DEBUG_INFO (" - ??"); - DEBUG_BYTE (P2 (apdu)); - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - DEBUG_SHORT (len); - if (!ac_check_status (AC_OTHER_AUTHORIZED)) - { - DEBUG_INFO ("security error."); - GPG_SECURITY_FAILURE (); - return; - } - -#ifdef ACKBTN_SUPPORT - if (gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION)) - eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED); -#else - (void)ccid_comm; -#endif - - if (attr == ALGO_RSA2K || attr == ALGO_RSA4K) - { - if (len > MAX_RSA_DIGEST_INFO_LEN) - { - DEBUG_INFO ("input is too long."); - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - result_len = pubkey_len; - r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len, - &kd[GPG_KEY_FOR_AUTHENTICATION], pubkey_len); - } - else if (attr == ALGO_SECP256K1) - { - if (len != ECDSA_HASH_LEN) - { - DEBUG_INFO ("wrong hash length."); - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - //cs = chopstx_setcancelstate (0); - result_len = ECDSA_SIGNATURE_LENGTH; - r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU, - kd[GPG_KEY_FOR_AUTHENTICATION].data); - //chopstx_setcancelstate (cs); - } - else if (attr == ALGO_ED25519) - { - uint32_t output[ED25519_SIGNATURE_LENGTH/4]; /* Require 4-byte alignment. */ - - //cs = chopstx_setcancelstate (0); - result_len = ED25519_SIGNATURE_LENGTH; - r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output, - kd[GPG_KEY_FOR_AUTHENTICATION].data, - kd[GPG_KEY_FOR_AUTHENTICATION].data+32, - kd[GPG_KEY_FOR_AUTHENTICATION].pubkey); - //chopstx_setcancelstate (cs); - memcpy (res_APDU, output, ED25519_SIGNATURE_LENGTH); - } - else if (attr == ALGO_ED448) - { - //cs = chopstx_setcancelstate (0); - result_len = ED448_SIGNATURE_LENGTH; - r = ed448_sign (res_APDU, apdu.cmd_apdu_data, len, - kd[GPG_KEY_FOR_AUTHENTICATION].data, - kd[GPG_KEY_FOR_AUTHENTICATION].data+57, - kd[GPG_KEY_FOR_AUTHENTICATION].pubkey); - //chopstx_setcancelstate (cs); - } - - if (r == 0) - res_APDU_size = result_len; - else - GPG_ERROR (); - - DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n"); -} - - -#define MBD_OPRATION_WRITE 0 -#define MBD_OPRATION_UPDATE 1 - -static void -modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len) -{ - uint8_t file_id; - uint16_t offset; - int is_short_EF = (p1 & 0x80) != 0; - int r; - - if (!ac_check_status (AC_ADMIN_AUTHORIZED)) - { - DEBUG_INFO ("security error."); - GPG_SECURITY_FAILURE (); - return; - } - - if (is_short_EF) - file_id = (p1 & 0x1f); - else - file_id = file_selection - FILE_EF_SERIAL_NO + FILEID_SERIAL_NO; - - if (!FILEID_CH_CERTIFICATE_IS_VALID && file_id == FILEID_CH_CERTIFICATE) - { - GPG_NO_FILE (); - return; - } - - if (op == MBD_OPRATION_UPDATE && file_id != FILEID_CH_CERTIFICATE) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - if (file_id > FILEID_CH_CERTIFICATE) - { - GPG_NO_FILE (); - return; - } - - if (is_short_EF) - { - file_selection = file_id - FILEID_SERIAL_NO + FILE_EF_SERIAL_NO; - offset = p2; - - if (op == MBD_OPRATION_UPDATE) - { - r = flash_erase_binary (file_id); - if (r < 0) - { - DEBUG_INFO ("memory error.\r\n"); - GPG_MEMORY_FAILURE (); - return; - } - } - } - else - offset = (p1 << 8) | p2; - - DEBUG_SHORT (len); - DEBUG_SHORT (offset); - - if (file_id == FILEID_CH_CERTIFICATE && (len&1)) - /* It's OK the size of last write is odd. */ - apdu.cmd_apdu_data[len++] = 0xff; - - r = flash_write_binary (file_id, apdu.cmd_apdu_data, len, offset); - if (r < 0) - { - DEBUG_INFO ("memory error.\r\n"); - GPG_MEMORY_FAILURE (); - return; - } - -#ifdef FLASH_UPGRADE_SUPPORT - if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3 - && len == 0 && offset == 0) - { - int i; - const uint8_t *p; - - for (i = 0; i < 4; i++) - { - p = gpg_get_firmware_update_key (i); - if (p[0] != 0x00 || p[1] != 0x00) /* still valid */ - break; - } - - if (i == 4) /* all update keys are removed */ - { - p = gpg_get_firmware_update_key (0); - flash_erase_page ((uintptr_t)p); - } - } -#endif - - GPG_SUCCESS (); -} - - - -#if defined(CERTDO_SUPPORT) -static void -cmd_update_binary (queue_t *ccid_comm) -{ - int len = apdu.cmd_apdu_data_len; - - (void)ccid_comm; - DEBUG_INFO (" - UPDATE BINARY\r\n"); - modify_binary (MBD_OPRATION_UPDATE, P1 (apdu), P2 (apdu), len); - DEBUG_INFO ("UPDATE BINARY done.\r\n"); -} -#endif - - -static void -cmd_write_binary (queue_t *ccid_comm) -{ - int len = apdu.cmd_apdu_data_len; - - (void)ccid_comm; - DEBUG_INFO (" - WRITE BINARY\r\n"); - modify_binary (MBD_OPRATION_WRITE, P1 (apdu), P2 (apdu), len); - DEBUG_INFO ("WRITE BINARY done.\r\n"); -} - - -#ifdef FLASH_UPGRADE_SUPPORT -static void -cmd_external_authenticate (queue_t *ccid_comm) -{ - const uint8_t *pubkey; - const uint8_t *signature = apdu.cmd_apdu_data; - int len = apdu.cmd_apdu_data_len; - uint8_t keyno = P2 (apdu); - int r; - - (void)ccid_comm; - DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n"); - - if (keyno >= 4) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - pubkey = gpg_get_firmware_update_key (keyno); - if (len != 256 - || (pubkey[0] == 0xff && pubkey[1] == 0xff) /* not registered */ - || (pubkey[0] == 0x00 && pubkey[1] == 0x00) /* removed */) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - r = rsa_verify (pubkey, FIRMWARE_UPDATE_KEY_CONTENT_LEN, - challenge, signature); - random_bytes_free (challenge); - challenge = NULL; - - if (r < 0) - { - GPG_SECURITY_FAILURE (); - return; - } - - //eventflag_signal (openpgp_comm, EV_EXIT); /* signal to self. */ - set_res_sw (0xff, 0xff); - DEBUG_INFO ("EXTERNAL AUTHENTICATE done.\r\n"); -} -#endif - -static void -cmd_get_challenge (queue_t *ccid_comm) -{ - int len = apdu.expected_res_size; - - (void)ccid_comm; - DEBUG_INFO (" - GET CHALLENGE\r\n"); - - if (len > CHALLENGE_LEN) - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - else if (len == 0) - /* Le is not specified. Return full-sized challenge by GET_RESPONSE. */ - len = CHALLENGE_LEN; - - if (challenge) - random_bytes_free (challenge); - -#ifdef ACKBTN_SUPPORT - if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING) - || gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION) - || gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION)) - eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED); -#endif - - challenge = random_bytes_get (32); - memcpy (res_APDU, challenge, len); - res_APDU_size = len; - GPG_SUCCESS (); - DEBUG_INFO ("GET CHALLENGE done.\r\n"); -} - - -#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT -static void -cmd_activate_file (queue_t *ccid_comm) -{ - (void)ccid_comm; - if (file_selection != FILE_CARD_TERMINATED) - { - GPG_NO_RECORD (); - return; - } - - flash_activate (); - file_selection = FILE_DF_OPENPGP; - GPG_SUCCESS (); -} - -static void -cmd_terminate_df (queue_t *ccid_comm) -{ - const uint8_t *ks_pw3; - uint8_t p1 = P1 (apdu); - uint8_t p2 = P2 (apdu); - - (void)ccid_comm; - if (file_selection != FILE_DF_OPENPGP) - { - GPG_NO_RECORD (); - return; - } - - if (p1 != 0 || p2 != 0) - { - GPG_BAD_P1_P2(); - return; - } - - if (apdu.cmd_apdu_data_len != 0) - { - GPG_WRONG_LENGTH(); - return; - } - - ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); - - if (!ac_check_status (AC_ADMIN_AUTHORIZED) - && !((ks_pw3 && gpg_pw_locked (PW_ERR_PW3)) - || (ks_pw3 == NULL && gpg_pw_locked (PW_ERR_PW1)))) - { - /* Only allow the case admin authorized, or, admin pass is locked. */ - GPG_SECURITY_FAILURE(); - return; - } - - ac_reset_admin (); - ac_reset_pso_cds (); - ac_reset_other (); - gpg_do_terminate (); - flash_terminate (); - file_selection = FILE_CARD_TERMINATED; - GPG_SUCCESS (); -} -#endif - - -struct command -{ - uint8_t command; - void (*cmd_handler) (); -}; - -const struct command cmds[] = { - { INS_VERIFY, cmd_verify }, - { INS_CHANGE_REFERENCE_DATA, cmd_change_password }, - { INS_PSO, cmd_pso }, - { INS_RESET_RETRY_COUNTER, cmd_reset_user_password }, - #ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT - { INS_ACTIVATE_FILE, cmd_activate_file }, - #endif - { INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR, cmd_pgp_gakp }, - #ifdef FLASH_UPGRADE_SUPPORT - { INS_EXTERNAL_AUTHENTICATE, /* Not in OpenPGP card protocol */ - cmd_external_authenticate }, - #endif - { INS_GET_CHALLENGE, cmd_get_challenge }, /* Not in OpenPGP card protocol */ - { INS_INTERNAL_AUTHENTICATE, cmd_internal_authenticate }, - { INS_SELECT_FILE, cmd_select_file }, - { INS_READ_BINARY, cmd_read_binary }, /* Not in OpenPGP card protocol */ - { INS_READ_BINARY_ODD, cmd_read_binary }, /* Not in OpenPGP card protocol */ - { INS_GET_DATA, cmd_get_data }, - { INS_WRITE_BINARY, cmd_write_binary}, /* Not in OpenPGP card protocol */ - #if defined(CERTDO_SUPPORT) - { INS_UPDATE_BINARY, cmd_update_binary }, /* Not in OpenPGP card protocol */ - #endif - { INS_PUT_DATA, cmd_put_data }, - { INS_PUT_DATA_ODD, cmd_put_data }, - #ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT - { INS_TERMINATE_DF, cmd_terminate_df}, - #endif -}; -#define NUM_CMDS ((int)(sizeof (cmds) / sizeof (struct command))) - -int openpgp_process_apdu() -{ - int i; - uint8_t cmd = INS (apdu); - - for (i = 0; i < NUM_CMDS; i++) - if (cmds[i].command == cmd) - break; - - if (i < NUM_CMDS) - { - if (file_selection == FILE_CARD_TERMINATED - && cmd != INS_SELECT_FILE && cmd != INS_ACTIVATE_FILE - && cmd != INS_GET_CHALLENGE && cmd != INS_EXTERNAL_AUTHENTICATE) - GPG_APPLICATION_TERMINATED (); - else if (selected_applet == NULL - && cmd != INS_SELECT_FILE && cmd != INS_ACTIVATE_FILE - && cmd != INS_GET_CHALLENGE && cmd != INS_EXTERNAL_AUTHENTICATE - && cmd != INS_WRITE_BINARY && cmd != INS_UPDATE_BINARY - && cmd != INS_READ_BINARY && cmd != INS_READ_BINARY_ODD) - GPG_NO_RECORD (); - else - { - cmds[i].cmd_handler (); - } - } - else - { - DEBUG_INFO (" - ??"); - DEBUG_BYTE (cmd); - GPG_NO_INS (); - } -} - diff --git a/src/openpgp/p448.c b/src/openpgp/p448.c deleted file mode 100644 index 2ce7a37..0000000 --- a/src/openpgp/p448.c +++ /dev/null @@ -1,666 +0,0 @@ -/* -*- coding: utf-8 -*- - * p448.c - Modular calculation with p448: 2^448 - 2^224 - 1 - * - * Copyright (C) 2021 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -#include -#include "p448.h" - -#define MASK_28BITS 0x0fffffff - -static void -p448_add_raw (p448_t *x, const p448_t *a, const p448_t *b) -{ - int i; - - for (i = 0; i < N_REDUNDANT_LIMBS; i++) - x->limb[i] = a->limb[i] + b->limb[i]; -} - -static void -p448_sub_raw (p448_t *x, const p448_t *a, const p448_t *b) -{ - int i; - - for (i = 0; i < N_REDUNDANT_LIMBS; i++) - x->limb[i] = a->limb[i] - b->limb[i]; -} - -static uint64_t -mul64_32x32 (const uint32_t a, const uint32_t b) -{ - return ((uint64_t)a) * b; -} - -/** - * Compute X = A * B mod p448 - */ -/* - * When we set phi = 2^224, p448 can be expressed as: - * - * p448 = phi^2 - phy - 1 - * - * Here, using the right hand side and make a fomula - * - * phi^2 - phy - 1 = 0 - * - * it is the fomula where it's solution is golden ratio. - * - * By analogy, so, p448 is called "golden-ratio prime". - * - * When we set phi = 2^224, Karatsuba multiplication goes like: - * - * (p + q * phi) * (r + s * phi) - * = pr + (ps + qr)*phy + qs*phi^2 - * == (pr + qs) + (ps + qr + qs) * phy (mod p448) - * = (pr + qs) + ((p + q)*(r + s) - pr) * phy - * - * That is, it can be done by three times of 224-bit multiplications - * (instead of four). - * - * Let us see more detail. - * - * The formula above is calculated to: - * = lower224(pr + qs) + upper224(pr + qs)*phy - * + lower224((p + q)*(r + s) - pr)*phy - * + upper224((p + q)*(r + s) - pr)*phy^2 (mod p448) - * == lower224(pr + qs) - * + upper224((p + q)*(r + s) - pr) - * + (upper224(pr + qs) - * + lower224((p + q)*(r + s) - pr) - * + upper224((p + q)*(r + s) - pr))*phy (mod p448) - * = lower224(pr + qs) - * + upper224((p + q)*(r + s) - pr) - * + (lower224((p + q)*(r + s) - pr) - * + upper224((p + q)*(r + s) + qs)) * phy - * - */ -/* - -Here is a figure of: multiplication by 8-limb * 8-limb - - a b c d e f g h - * i j k l m n o p ---------------------------------------------- - ap bp cp dp ep fp gp hp - ao bo co do eo fo go ho - an bn cn dn en fn gn hn - am bm cm dm em fm gm hm - al bl cl dl el fl gl hl - ak bk ck dk ek fk gk hk - aj bj cj dj ej fj gj hj -ai bi ci di ei fi gi hi - -Considering lower224, it's: - ap bp cp dp ep fp gp hp - bo co do eo fo go ho - cn dn en fn gn hn - dm em fm gm hm - el fl gl hl - fk gk hk - gj hj - hi - -Considering upper224, it's: - ao - an bn - am bm cm - al bl cl dl - ak bk ck dk ek - aj bj cj dj ej fj - ai bi ci di ei fi gi -*/ -void -p448_mul (p448_t *__restrict__ x, const p448_t *a, const p448_t *b) -{ - int i, j; - uint64_t v64_0, v64_1, v64_2; - uint32_t p_q[8], r_s[8]; - uint32_t *px; - const uint32_t *pa, *pb; - - px = x->limb; - pa = a->limb; - pb = b->limb; - - /* Firstly, we do Karatsuba preparation. */ - for (i = 0; i < 8; i++) - { - p_q[i] = pa[i] + pa[i+8]; - r_s[i] = pb[i] + pb[i+8]; - } - - v64_0 = v64_1 = 0; - - for (j = 0; j < 8; j++) - { - v64_2 = 0; - - /* Compute lower half of limbs (lower224) */ - /* __ <-- j - * | / | - * |/ v i - * - */ - for (i = 0; i <= j; i++) - { - v64_0 += mul64_32x32 (pa[8+j-i], pb[8+i]);/* accumulating q*s */ - v64_1 += mul64_32x32 (p_q[j-i], r_s[i]); /* accumulating p_q*r_s */ - v64_2 += mul64_32x32 (pa[j-i], pb[i]); /* accumulating p*r */ - } - - v64_0 += v64_2; /* Compute pr+qs. */ - v64_1 -= v64_2; /* Compute p_q*r_s - pr. */ - - v64_2 = 0; - - /* Compute upper half of limbs (upper224) */ - /* <-- j - * /| | - * /_| v i - * - */ - for (; i < 8; i++) - { - v64_0 -= mul64_32x32 (pa[8+j-i], pb[i]); /* accumulating -p*r */ - v64_1 += mul64_32x32 (pa[16+j-i], pb[8+i]);/* accumulating q*s */ - v64_2 += mul64_32x32 (p_q[8+j-i], r_s[i]); /* accumulating p_q*r_s */ - } - - v64_0 += v64_2; /* Compute p_q*r_s - pr. */ - v64_1 += v64_2; /* Compute p_q*r_s + qs. */ - - px[j] = v64_0 & MASK_28BITS; - px[j+8] = v64_1 & MASK_28BITS; - - v64_0 >>= 28; - v64_1 >>= 28; - } - - /* "Carry" remains as: 2^448 * v64_1 + 2^224 * v64_0 */ - /* - * Subtract p448 times v64_1 to clear msbs, meaning, clear those - * bits and adding v64_1 to px[0] and px[8] (in mod p448 - * calculation). - */ - v64_0 += v64_1; - v64_0 += px[8]; - v64_1 += px[0]; - px[8] = v64_0 & MASK_28BITS; - px[0] = v64_1 & MASK_28BITS; - - /* Still, it carries to... */ - v64_0 >>= 28; - v64_1 >>= 28; - px[9] += v64_0; - px[1] += v64_1; - /* DONE. */ -} - - -/** - * Compute X = A * 39081 - */ -void -p448_mul_39081 (p448_t *x, const p448_t *a) -{ - int i; - const uint32_t w = 39081; - uint32_t *px; - const uint32_t *pa; - uint64_t v64; - uint32_t carry; - - px = x->limb; - pa = a->limb; - - v64 = 0; - for (i = 0; i < N_REDUNDANT_LIMBS; i++) - { - v64 += mul64_32x32 (w, pa[i]); - px[i] = v64 & MASK_28BITS; - v64 >>= 28; - } - - carry = v64; - carry += px[0]; - px[0] = carry & MASK_28BITS; - px[1] += carry >> 28; - - carry = v64; - carry += px[8]; - px[8] = carry & MASK_28BITS; - px[9] += carry >> 28; -} - -/* - ah bh ch dh eh fh gh HH - bg cg dg eg fg GG - cf df ef FF - de EE - DD - CC dc ec - BB cb db eb fb - AA ba ca da ea fa ga - - */ -/** - * Compute X = A^2 mod p448 - */ -void -p448_sqr (p448_t *__restrict__ x, const p448_t *a) -{ - int i, j; - uint64_t v64_0, v64_1, v64_2, v64_3; - uint32_t p_q[8]; - uint32_t *px; - const uint32_t *pa; - - px = x->limb; - pa = a->limb; - - /* Firstly, we do Karatsuba preparation. */ - for (i = 0; i < 8; i++) - p_q[i] = pa[i] + pa[i+8]; - - v64_0 = v64_1 = 0; - - for (j = 0; j < 8; j++) - { - v64_2 = 0; - - /* Compute lower half of limbs (lower224) */ - /* __ <-- j - * | / | - * |/ v i - * - */ - for (i = 0; i <= j/2; i++) - { - int cond = ((j & 1) || i != j/2); - - v64_3 = mul64_32x32 (pa[8+j-i], pa[8+i]);/* accumulating q*q */ - v64_0 += (v64_3 << cond); - v64_3 = mul64_32x32 (p_q[j-i], p_q[i]); /* accumulating p_q^2 */ - v64_1 += (v64_3 << cond); - v64_3 = mul64_32x32 (pa[j-i], pa[i]); /* accumulating p*p */ - v64_2 += (v64_3 << cond); - } - - v64_0 += v64_2; /* Compute pp+qq. */ - v64_1 -= v64_2; /* Compute p_q^2 - pp. */ - - v64_2 = 0; - /* Compute upper half of limbs (upper224) */ - /* <-- j - * /| | - * /_| v i - * - */ - if (!(j & 1)) - { - v64_0 -= mul64_32x32 (pa[4+i-1], pa[4+i-1]); /* accumulating -p*p */ - v64_1 += mul64_32x32 (pa[12+i-1], pa[12+i-1]);/* accumulating q*q */ - v64_2 += mul64_32x32 (p_q[4+i-1], p_q[4+i-1]);/* accumulating p_q^2 */ - } - - for (; i < 4; i++) - { - v64_3 = mul64_32x32 (pa[4+j-i], pa[4+i]); - v64_0 -= (v64_3 << 1); /* accumulating -p*p */ - v64_3 = mul64_32x32 (pa[12+j-i], pa[12+i]); - v64_1 += (v64_3 << 1); /* accumulating q*q */ - v64_3 = mul64_32x32 (p_q[4+j-i], p_q[4+i]); - v64_2 += (v64_3 << 1); /* accumulating p_q^2 */ - } - - v64_0 += v64_2; /* Compute p_q^2 - p^2. */ - v64_1 += v64_2; /* Compute p_q^2 + q^2. */ - - px[j] = v64_0 & MASK_28BITS; - px[j+8] = v64_1 & MASK_28BITS; - - v64_0 >>= 28; - v64_1 >>= 28; - } - - /* "Carry" remains as: 2^448 * v64_1 + 2^224 * v64_0 */ - /* - * Subtract p448 times v64_1 to clear msbs, meaning, clear those - * bits and adding v64_1 to px[0] and px[8] (in mod p448 - * calculation). - */ - v64_0 += v64_1; - v64_0 += px[8]; - v64_1 += px[0]; - px[8] = v64_0 & MASK_28BITS; - px[0] = v64_1 & MASK_28BITS; - - /* Still, it carries to... */ - v64_0 >>= 28; - v64_1 >>= 28; - px[9] += v64_0; - px[1] += v64_1; - /* DONE. */ -} - -/** - * Weak reduce - Make each limb of redundunt representation smaller. - * Do our best weakly to zeroing most significant 4-bit. - * - * Note that: p448 = 2^448 - 2^224 - 1 - * - * Subtracting p448 means that subtracting 2^448 then adding 2^224 + 1. - */ -void -p448_weak_reduce (p448_t *a) -{ - int i; - uint32_t tmp = a->limb[15] >> 28; - - a->limb[8] += tmp; /* Adding TMP * 2^224 (28 * 8 = 224) */ - - /* Compute top to bottom. */ - for (i = 0; i < N_REDUNDANT_LIMBS - 1; i++) - a->limb[N_REDUNDANT_LIMBS - i - 1] = - (a->limb[N_REDUNDANT_LIMBS - i - 1] & MASK_28BITS) - + (a->limb[N_REDUNDANT_LIMBS - i - 2] >> 28); - - a->limb[0] = (a->limb[0] & MASK_28BITS) + tmp; -} - -static const p448_t p448[1] = { - { - { - 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, - 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, - 0x0ffffffe, 0x0fffffff, 0x0fffffff, 0x0fffffff, - 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff - } - } -}; - - -static uint32_t -p448_add_carry_cond (p448_t *x, const p448_t *a, const p448_t *b, - uint32_t cond) -{ - int i; - uint32_t v; - uint32_t carry = 0; - uint32_t *px; - const uint32_t *pa, *pb; - - cond = cond * MASK_28BITS; - - px = x->limb; - pa = a->limb; - pb = b->limb; - - for (i = 0; i < N_REDUNDANT_LIMBS; i++) - { - v = *pb & cond; - *px = *pa + carry; - carry = (*px < carry); - *px = (*px + v) & MASK_28BITS; - carry += (*px < v); - px++; - pa++; - pb++; - } - - return carry; -} - - -static uint32_t -p448_sub_borrow (p448_t *x, const p448_t *a, const p448_t *b) -{ - int i; - uint32_t v; - uint32_t borrow = 0; - uint32_t *px; - const uint32_t *pa, *pb; - - px = x->limb; - pa = a->limb; - pb = b->limb; - - for (i = 0; i < N_REDUNDANT_LIMBS; i++) - { - uint32_t borrow0 = (*pa < borrow); - - v = *pb; - *px = *pa - borrow; - borrow = (*px < v) + borrow0; - *px = (*px - v) & MASK_28BITS; - px++; - pa++; - pb++; - } - - return borrow; -} - -/** - * Strong reduce - Make sure that each limb of redundunt - * representation has zeros of significant 4-bit. - */ -void -p448_strong_reduce (p448_t *a) -{ - uint32_t tmp; - uint32_t is_negative; - - /* - * Clear the 4-bit of the last (top) limb. As stated in the comment - * of weak_reduce, subtracting p448 means that subtracting 2^448 - * then adding 2^224 + 1. - */ - tmp = a->limb[15] >> 28; - a->limb[8] += tmp; - a->limb[0] += tmp; - a->limb[15] &= MASK_28BITS; - - /* - * Here, it's: 0 <= v < 2*p448 - * - * When v > p448, subtract p448 from v, then it becomes strongly reduced. - * Otherwise, it's already strongly reduced. - */ - - /* Subtract p448 */ - is_negative = p448_sub_borrow (a, a, p448); - - /* Add p448 conditionally, when it becomes negative. */ - p448_add_carry_cond (a, a, p448, is_negative); -} - -/** - * Convert to wire-format from internal redundant representation. - */ -void -p448_serialize (uint8_t serial[56], const struct p448_t *x) -{ - int i; - p448_t tmp[1]; - uint8_t *p = serial; - - *tmp = *x; - p448_strong_reduce (tmp); - - for (i = 0; i < 8; i++) - { - uint32_t limb0 = tmp->limb[2*i]; - uint32_t limb1 = tmp->limb[2*i+1]; - - *p++ = limb0; - *p++ = (limb0 >> 8); - *p++ = (limb0 >> 16); - *p++ = ((limb0 >> 24) & 0x0f) | ((limb1 & 0x0f )<< 4); - *p++ = (limb1 >> 4); - *p++ = (limb1 >> 12); - *p++ = (limb1 >> 20); - } -} - -/** - * Convert from wire-format to internal redundant representation. - */ -void -p448_deserialize (p448_t *x, const uint8_t serial[56]) -{ - int i; - const uint8_t *p = serial + 56; - - for (i = 0; i < 8; i++) - { - uint32_t v; - - v = *--p; - v <<= 8; - v |= *--p; - v <<= 8; - v |= *--p; - v <<= 8; - v |= *--p; - - x->limb[N_REDUNDANT_LIMBS-2*i-1] = (v >> 4); - - v = (v & 0x0f); - v <<= 8; - v |= *--p; - v <<= 8; - v |= *--p; - v <<= 8; - v |= *--p; - - x->limb[N_REDUNDANT_LIMBS-2*i-2] = v & MASK_28BITS; - } -} - - -/* X = A^(2*N) */ -static void -p448_sqrn (p448_t *__restrict__ x, const p448_t *a, int n) -{ - p448_t tmp[1]; - - if ((n&1)) - { - p448_sqr (x, a); - n--; - } - else - { - p448_sqr (tmp, a); - p448_sqr (x, tmp); - n -= 2; - } - - for (; n; n -= 2) - { - p448_sqr (tmp, x); - p448_sqr (x, tmp); - } -} - -/** - * Compute X = A^(-1) mod p448 (if A=0, return X = 0) - * - * Internally, do A^(p448 - 2) to get A^(-1). - */ -void -p448_inv (p448_t *__restrict__ x, const p448_t *a) -{ - p448_t t[1], u[1]; - - /* - * Bit pattern of p448-2: 1{223} 0 1{222}01 - * - * 222-bit can be composed by 3-bit three times to get 9-bit, 9-bit - * two times to get 18-bit, 18-bit two times plus 1-bit to get 37-bit. - * 37-bit three times to get 111-bit, and lastly 111-bit two times. - * 222 = 111*2 = 37*3*2 = (18*2+1)*3*2 = (9*2*2+1)*3*2 = (3*3*2*2+1)*3*2 - */ - p448_sqr ( x, a ); /* 10 */ - p448_mul ( t, a, x ); /* 11 */ - p448_sqr ( x, t ); /* 110 */ - p448_mul ( t, a, x ); /* 111 */ - p448_sqrn ( x, t, 3 ); /* 111000 */ - p448_mul ( u, t, x ); /* 111111 */ - p448_sqrn ( x, u, 3 ); /* 111111000 */ - p448_mul ( u, t, x ); /* 111111111 */ - p448_sqrn ( t, u, 9 ); /* 1{9} 0{9} */ - p448_mul ( x, u, t ); /* 1{18} */ - p448_sqr ( t, x ); /* 1{18} 0 */ - p448_mul ( u, a, t ); /* 1{19} */ - p448_sqrn ( t, u, 18 ); /* 1{19} 0{18} */ - p448_mul ( u, x, t ); /* 1{37} */ - p448_sqrn ( t, u, 37 ); /* 1{37} 0{37} */ - p448_mul ( x, u, t ); /* 1{74} */ - p448_sqrn ( t, x, 37 ); /* 1{74} 0{37} */ - p448_mul ( x, u, t ); /* 1{111} */ - p448_sqrn ( t, x, 111 ); /* 1{111} 0{111} */ - p448_mul ( u, x, t ); /* 1{222} */ - p448_sqr ( t, u ); /* 1{222} 0 */ - p448_mul ( x, a, t ); /* 1{223} */ - p448_sqrn ( u, x, 224 ); /* 1{223} 0{224} */ - p448_mul ( x, u, t ); /* 1{223} 0 1{222}0 */ - p448_sqr ( t, x ); /* 1{223} 0 1{222}00 */ - p448_mul ( x, a, t ); /* 1{223} 0 1{222}01 */ -} - -static const p448_t p448_times_2[1] = { - { - { - 0x1ffffffe, 0x1ffffffe, 0x1ffffffe, 0x1ffffffe, - 0x1ffffffe, 0x1ffffffe, 0x1ffffffe, 0x1ffffffe, - 0x1ffffffc, 0x1ffffffe, 0x1ffffffe, 0x1ffffffe, - 0x1ffffffe, 0x1ffffffe, 0x1ffffffe, 0x1ffffffe - } - } -}; - -/** - * Compute X = A + B mod p448, result is weakly reduced. - * - */ -void -p448_add (p448_t *x, const p448_t *a, const p448_t *b) -{ - p448_add_raw (x, a, b); - p448_weak_reduce (x); -} - -/** - * Compute X = A - B mod p448, result is weakly reduced. - * - */ -void -p448_sub (p448_t *x, const p448_t *a, const p448_t *b) -{ - p448_t tmp[1]; - - p448_sub_raw (tmp, a, b); - p448_add_raw (x, p448_times_2, tmp); - p448_weak_reduce (x); -} diff --git a/src/openpgp/p448.h b/src/openpgp/p448.h deleted file mode 100644 index 5261c6b..0000000 --- a/src/openpgp/p448.h +++ /dev/null @@ -1,15 +0,0 @@ -#define N_REDUNDANT_LIMBS 16 -typedef struct p448_t -{ - uint32_t limb[N_REDUNDANT_LIMBS]; -} p448_t; - -void p448_add (p448_t *x, const p448_t *a, const p448_t *b); -void p448_sub (p448_t *x, const p448_t *a, const p448_t *b); -void p448_mul (p448_t *__restrict__ x, const p448_t *a, const p448_t *b); -void p448_mul_39081 (p448_t *x, const p448_t *a); -void p448_sqr (p448_t *__restrict__ c, const p448_t *a); -void p448_inv (p448_t *__restrict__ x, const p448_t *a); -void p448_serialize (uint8_t serial[56], const p448_t *x); -void p448_deserialize (p448_t *x, const uint8_t serial[56]); -void p448_strong_reduce (p448_t *a); diff --git a/src/openpgp/shake256.c b/src/openpgp/shake256.c deleted file mode 100644 index c1cfa60..0000000 --- a/src/openpgp/shake256.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * shake256.c -- Compute SHAKE hash. - * - * Copyright (C) 2021 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk 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, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk 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 . - * - */ - -/* - * Reference: - * - * [1] FIPS PUB 202: SHA-3 Standard: - * Permutation-Based Hash and Extendable-Output Functions, - * August 2015. - */ - -#define SHAKE_BITS 256 -#define SHAKE_INDEX_MAX (200 - (SHAKE_BITS >> 2)) - -/* - * b=1600 - * nr = 24 iterations - * l = 6 - * - * state: 25x64-bit == 5 x 5 x 64 - * row column bit - */ - -#include -#include -#include "shake256.h" - -/* Round constants in iota step. */ -static const uint64_t rc[24] = { - UINT64_C (0x0000000000000001), UINT64_C (0x0000000000008082), - UINT64_C (0x800000000000808a), UINT64_C (0x8000000080008000), - UINT64_C (0x000000000000808b), UINT64_C (0x0000000080000001), - UINT64_C (0x8000000080008081), UINT64_C (0x8000000000008009), - UINT64_C (0x000000000000008a), UINT64_C (0x0000000000000088), - UINT64_C (0x0000000080008009), UINT64_C (0x000000008000000a), - UINT64_C (0x000000008000808b), UINT64_C (0x800000000000008b), - UINT64_C (0x8000000000008089), UINT64_C (0x8000000000008003), - UINT64_C (0x8000000000008002), UINT64_C (0x8000000000000080), - UINT64_C (0x000000000000800a), UINT64_C (0x800000008000000a), - UINT64_C (0x8000000080008081), UINT64_C (0x8000000000008080), - UINT64_C (0x0000000080000001), UINT64_C (0x8000000080008008), -}; - -static const uint8_t rho[25-1] = { - 1, 62, 28, 27, - 36, 44, 6, 55, 20, - 3, 10, 43, 25, 39, - 41, 45, 15, 21, 8, - 18, 2, 61, 56, 14 -}; - -static const uint8_t pi[24] = { - 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, -}; - -static uint64_t -rotl64 (uint64_t x, uint64_t y) -{ - return (x << y) | (x >> (64U - y)); -} - -static void -absorb (uint64_t *dst, uint8_t index, uint8_t v) -{ - dst[index >> 3] ^= ((uint64_t)v) << ((index & 7) << 3); -} - -static uint8_t -squeeze (const uint64_t *src, uint8_t index) -{ - return src[index >> 3] >> ((index & 7) << 3); -} - -/* The permutation function. */ -static void -keccak_f1600 (uint64_t s[25]) -{ - uint64_t lane[5]; - int i, j, round; - - for (round = 0; round < 24; round++) - { - uint64_t t; - - /* STEP: theta */ - for (i = 0; i < 5; i++) - lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; - - for (i = 0; i < 5; i++) - { - t = lane[(i + 4) % 5] ^ rotl64 (lane[(i + 1) % 5], 1); - for (j = 0; j < 25; j += 5) - s[j + i] ^= t; - } - - /* STEP: rho */ - for (i = 1; i < 25; i++) - s[i] = rotl64(s[i], rho[i-1]); - - /* STEP: pi */ - t = s[1]; - for (i = 0; i < 25-1; i++) - { - uint64_t tmp; - - j = pi[i]; - tmp = s[j]; - s[j] = t; - t = tmp; - } - - /* STEP: chi */ - for (i = 0; i < 25; i += 5) - { - for (j = 0; j < 5; j++) - lane[j] = s[i + j]; - for (j = 0; j < 5; j++) - s[i + j] ^= (~lane[(j + 1) % 5]) & lane[(j + 2) % 5]; - } - - /* STEP: iota */ - s[0] ^= rc[round]; - } -} - -void -shake256_start (struct shake_context *shake) -{ - memset (shake, 0, sizeof (shake_context)); -} - -void -shake256_update (struct shake_context *shake, - const unsigned char *src, unsigned int size) -{ - if (size == 0) - return; - - while (1) - { - absorb (shake->state, shake->index, *src++); - if (++shake->index == SHAKE_INDEX_MAX) - { - keccak_f1600 (shake->state); - shake->index = 0; - } - if (--size == 0) - break; - } -} - -void -shake256_finish (struct shake_context *shake, - unsigned char *dst, unsigned int size) -{ - if (size == 0) - return; - - /* - * SHAKE is defined appending 11 at the end to RawSHAKE, - * RawSHAKE is defined adding 11 at the end to KECCAK, - * and KECCACK uses pad10*1 at the end. - * This means adding 111110*1 at the end. - */ - absorb (shake->state, shake->index, 0x1F); - absorb (shake->state, SHAKE_INDEX_MAX - 1, 0x80); - keccak_f1600 (shake->state); - shake->index = 0; - - while (1) - { - *dst++ = squeeze (shake->state, shake->index); - if (--size == 0) - break; - if (++shake->index == SHAKE_INDEX_MAX) - { - keccak_f1600 (shake->state); - shake->index = 0; - } - } -} diff --git a/src/openpgp/shake256.h b/src/openpgp/shake256.h deleted file mode 100644 index 4a4a210..0000000 --- a/src/openpgp/shake256.h +++ /dev/null @@ -1,13 +0,0 @@ -#include - -struct shake_context { - uint64_t state[25]; - uint32_t index; -}; -typedef struct shake_context shake_context; - -void shake256_start (struct shake_context *shake); -void shake256_update (struct shake_context *shake, - const unsigned char *src, unsigned int size); -void shake256_finish (struct shake_context *shake, - unsigned char *dst, unsigned int size); diff --git a/src/openpgp/status-code.h b/src/openpgp/status-code.h deleted file mode 100644 index 79e9ec1..0000000 --- a/src/openpgp/status-code.h +++ /dev/null @@ -1,14 +0,0 @@ -#define GPG_APPLICATION_TERMINATED() set_res_sw (0x62, 0x85) -#define GPG_MEMORY_FAILURE() set_res_sw (0x65, 0x81) -#define GPG_WRONG_LENGTH() set_res_sw (0x67, 0x00) -#define GPG_SECURITY_FAILURE() set_res_sw (0x69, 0x82) -#define GPG_SECURITY_AUTH_BLOCKED() set_res_sw (0x69, 0x83) -#define GPG_CONDITION_NOT_SATISFIED() set_res_sw (0x69, 0x85) -#define GPG_COMMAND_NOT_ALLOWED() set_res_sw (0x69, 0x86) -#define GPG_FUNCTION_NOT_SUPPORTED() set_res_sw (0x6a, 0x81) -#define GPG_NO_FILE() set_res_sw (0x6a, 0x82) -#define GPG_NO_RECORD() set_res_sw (0x6a, 0x88) -#define GPG_BAD_P1_P2() set_res_sw (0x6b, 0x00) -#define GPG_NO_INS() set_res_sw (0x6d, 0x00) -#define GPG_ERROR() set_res_sw (0x6f, 0x00) -#define GPG_SUCCESS() set_res_sw (0x90, 0x00) \ No newline at end of file