Merge rsa-removal branch.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2022-04-25 14:29:27 +09:00
parent 3b2540bbf6
commit cd082d4823
19 changed files with 2931 additions and 3717 deletions

2864
ChangeLog

File diff suppressed because it is too large Load Diff

2823
ChangeLog-1_2 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -105,8 +105,8 @@ itself is needed before compiling reGNUal.
upgrade_by_passwd.py
--------------------
In the source code distribution of 1.0.4 (or current development
version) of Gnuk, there is a tool named 'upgrade_by_passwd.py'.
Since the source code distribution of 1.0.4 of Gnuk, there is a tool
named 'upgrade_by_passwd.py'.
This is an easy tool to hide lengthy steps from user and to allow user
firmware upgrade only by password of Gnuk Token.
@ -122,15 +122,11 @@ your environment for Gnuk Token.
How to run the script: ::
$ cd tool
$ ./upgrade_by_passwd.py ../regnual/regnual.bin ../src/build/gnuk.bin
$ ./upgrade_by_passwd.py
Then, the script on your host PC invoke the steps described above, and
you will get new version of Gnuk installed.
You can also specify -f option to skip entering your password (it
assumes the factory setting).
If you already have configured another upgrade key installed, you can
specify different slot by -k ``<slot_no>`` option. SLOT_NO can be 0
to 3.
--

View File

@ -5,7 +5,7 @@ PROJECT = gnuk
CHOPSTX = ../chopstx
CSRC = main.c call-rsa.c \
CSRC = main.c \
usb_desc.c usb_ctrl.c \
usb-ccid.c openpgp.c ac.c openpgp-do.c flash.c \
bn.c mod.c \
@ -20,7 +20,7 @@ INCDIR =
CRYPTDIR = ../polarssl
CRYPTSRCDIR = $(CRYPTDIR)/library
CRYPTINCDIR = $(CRYPTDIR)/include
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/aes.c
CRYPTSRC = $(CRYPTSRCDIR)/aes.c
CSRC += $(CRYPTSRC)
INCDIR += $(CRYPTINCDIR)

View File

@ -1,274 +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 <gniibe@fsij.org>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include <stdint.h>
#include <string.h>
#include <chopstx.h>
#include "config.h"
#include "gnuk.h"
#include "status-code.h"
#include "random.h"
#include "polarssl/config.h"
#include "polarssl/rsa.h"
static rsa_context rsa_ctx;
static struct chx_cleanup clp;
static void
rsa_cleanup (void *arg)
{
(void)arg;
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)
{
mpi P1, Q1, H;
int ret = 0;
unsigned char temp[pubkey_len];
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
mpi_init (&P1); mpi_init (&Q1); mpi_init (&H);
rsa_ctx.len = pubkey_len;
MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], pubkey_len / 2) );
MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[pubkey_len / 2],
pubkey_len / 2) );
#if 0
MPI_CHK( mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q) );
#endif
MPI_CHK( mpi_sub_int (&P1, &rsa_ctx.P, 1) );
MPI_CHK( mpi_sub_int (&Q1, &rsa_ctx.Q, 1) );
MPI_CHK( mpi_mul_mpi (&H, &P1, &Q1) );
MPI_CHK( mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H) );
MPI_CHK( mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1) );
MPI_CHK( mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1) );
MPI_CHK( mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P) );
cleanup:
mpi_free (&P1); mpi_free (&Q1); 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 = rsa_rsassa_pkcs1_v15_sign (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, SIG_RSA_RAW,
msg_len, raw_message, temp);
memcpy (output, temp, pubkey_len);
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
}
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)
{
mpi P, Q, N;
int ret;
mpi_init (&P); mpi_init (&Q); mpi_init (&N);
MPI_CHK( mpi_read_binary (&P, p, len / 2) );
MPI_CHK( mpi_read_binary (&Q, p + len / 2, len / 2) );
MPI_CHK( mpi_mul_mpi (&N, &P, &Q) );
MPI_CHK( mpi_write_binary (&N, pubkey, len) );
cleanup:
mpi_free (&P); mpi_free (&Q); 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)
{
mpi P1, Q1, H;
int ret;
#ifdef GNU_LINUX_EMULATION
size_t output_len;
#endif
DEBUG_INFO ("RSA decrypt:");
DEBUG_WORD ((uint32_t)&ret);
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
mpi_init (&P1); mpi_init (&Q1); mpi_init (&H);
rsa_ctx.len = msg_len;
DEBUG_WORD (msg_len);
MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], msg_len / 2) );
MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[msg_len / 2], msg_len / 2) );
#if 0
MPI_CHK( mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q) );
#endif
MPI_CHK( mpi_sub_int (&P1, &rsa_ctx.P, 1) );
MPI_CHK( mpi_sub_int (&Q1, &rsa_ctx.Q, 1) );
MPI_CHK( mpi_mul_mpi (&H, &P1, &Q1) );
MPI_CHK( mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H) );
MPI_CHK( mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1) );
MPI_CHK( mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1) );
MPI_CHK( mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P) );
cleanup:
mpi_free (&P1); mpi_free (&Q1); 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. */
#ifdef GNU_LINUX_EMULATION
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, &output_len, input,
output, MAX_RES_APDU_DATA_SIZE);
*output_len_p = (unsigned int)output_len;
#else
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, output_len_p, input,
output, MAX_RES_APDU_DATA_SIZE);
#endif
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
}
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;
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
rsa_ctx.len = pubkey_len;
MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
MPI_CHK( mpi_read_binary (&rsa_ctx.N, pubkey, pubkey_len) );
DEBUG_INFO ("RSA verify...");
MPI_CHK( rsa_rsassa_pkcs1_v15_verify (&rsa_ctx, NULL, NULL,
RSA_PUBLIC, SIG_RSA_SHA256, 32,
hash, sig) );
cleanup:
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
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 int prng_seed (int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
extern void neug_flush (void);
neug_flush ();
prng_seed (random_gen, &index);
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
clp.next = NULL;
clp.routine = rsa_cleanup;
clp.arg = NULL;
chopstx_cleanup_push (&clp);
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8,
RSA_EXPONENT) );
MPI_CHK( mpi_write_binary (&rsa_ctx.P, p, pubkey_len / 2) );
MPI_CHK( mpi_write_binary (&rsa_ctx.Q, q, pubkey_len / 2) );
MPI_CHK( mpi_write_binary (&rsa_ctx.N, pubkey, pubkey_len) );
cleanup:
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (1);
if (ret != 0)
return -1;
else
return 0;
}

View File

@ -1,6 +1,5 @@
CRYPTDIR = ../polarssl
CRYPTSRCDIR = $(CRYPTDIR)/library
CRYPTINCDIR = $(CRYPTDIR)/include
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c \
$(CRYPTSRCDIR)/aes.c \
sha256.c call-rsa.c
CRYPTSRC = $(CRYPTSRCDIR)/aes.c \
sha256.c

View File

@ -57,8 +57,6 @@
* _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
* <two pages>
@ -158,12 +156,6 @@ flash_terminate (void)
{
int i;
#ifdef FLASH_UPGRADE_SUPPORT
const uint8_t *p;
p = gpg_get_firmware_update_key (0);
flash_erase_page ((uintptr_t)p);
#endif
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);
@ -711,19 +703,6 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
maxsize = 6;
p = &openpgpcard_aid[8];
}
#ifdef FLASH_UPGRADE_SUPPORT
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
{
maxsize = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
if (len == 0 && offset == 0)
{ /* This means removal of update key. */
if (flash_program_halfword ((uintptr_t)p, 0) != 0)
flash_warning ("DO WRITE ERROR");
return 0;
}
}
#endif
#if defined(CERTDO_SUPPORT)
else if (file_id == FILEID_CH_CERTIFICATE)
{

View File

@ -1,16 +0,0 @@
/*
* Gnuk uses its own malloc functions.
*
* The intention is no-dependency to C library. But, we provide
* malloc and free here, since RSA routines uses malloc/free
* internally.
*
*/
#include <stddef.h> /* NULL and size_t */
#define malloc(size) gnuk_malloc (size)
#define free(p) gnuk_free (p)
void *gnuk_malloc (size_t);
void gnuk_free (void *);

View File

@ -112,8 +112,6 @@ 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 */
@ -157,10 +155,6 @@ 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,
@ -171,8 +165,6 @@ int flash_write_binary (uint8_t file_id, const uint8_t *data,
/* Linker set these two symbols */
extern 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
@ -264,13 +256,6 @@ void put_binary (const char *s, int len);
#define DEBUG_BINARY(s,len)
#endif
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 *);

View File

@ -141,9 +141,6 @@ SECTIONS
. = ALIGN(@FLASH_PAGE_SIZE@);
. += 1024;
. = ALIGN(@FLASH_PAGE_SIZE@);
_updatekey_store = .;
. += 1024;
. = ALIGN(@FLASH_PAGE_SIZE@);
_data_pool = .;
KEEP(*(.gnuk_data))
. = ALIGN(@FLASH_PAGE_SIZE@);

View File

@ -294,9 +294,6 @@ calculate_regnual_entry_address (const uint8_t *addr)
extern void *ccid_thread (void *arg);
static void gnuk_malloc_init (void);
extern uint32_t bDeviceState;
/*
@ -318,8 +315,6 @@ main (int argc, const char *argv[])
chopstx_conf_idle (1);
gnuk_malloc_init ();
#ifdef GNU_LINUX_EMULATION
#define FLASH_IMAGE_NAME ".gnuk-flash-image"
@ -538,189 +533,3 @@ fatal (uint8_t code)
_write ("fatal\r\n", 7);
for (;;);
}
/*
* Malloc for Gnuk.
*
* Each memory chunk has header with size information.
* The size of chunk is at least 16.
*
* Free memory is managed by FREE_LIST.
*
* When it is managed in FREE_LIST, three pointers, ->NEXT, ->PREV,
* and ->NEIGHBOR is used. NEXT and PREV is to implement doubly
* linked list. NEIGHBOR is to link adjacent memory chunk to be
* reclaimed to system.
*/
#ifdef GNU_LINUX_EMULATION
#define HEAP_SIZE (32*1024)
uint8_t __heap_base__[HEAP_SIZE];
#define HEAP_START __heap_base__
#define HEAP_END (__heap_base__ + HEAP_SIZE)
#define HEAP_ALIGNMENT 32
#else
extern uint8_t __heap_base__[];
extern uint8_t __heap_end__[];
#define HEAP_START __heap_base__
#define HEAP_END (__heap_end__)
#define HEAP_ALIGNMENT 16
#define HEAP_SIZE ((uintptr_t)__heap_end__ - (uintptr_t)__heap_base__)
#endif
#define HEAP_ALIGN(n) (((n) + HEAP_ALIGNMENT - 1) & ~(HEAP_ALIGNMENT - 1))
static uint8_t *heap_p;
static chopstx_mutex_t malloc_mtx;
struct mem_head {
uintptr_t size;
/**/
struct mem_head *next, *prev; /* free list chain */
struct mem_head *neighbor; /* backlink to neighbor */
};
#define MEM_HEAD_IS_CORRUPT(x) \
((x)->size != HEAP_ALIGN((x)->size) || (x)->size > HEAP_SIZE)
#define MEM_HEAD_CHECK(x) if (MEM_HEAD_IS_CORRUPT(x)) fatal (FATAL_HEAP)
static struct mem_head *free_list;
static void
gnuk_malloc_init (void)
{
chopstx_mutex_init (&malloc_mtx);
heap_p = HEAP_START;
free_list = NULL;
}
static void *
gnuk_sbrk (intptr_t size)
{
void *p = (void *)heap_p;
if ((HEAP_END - heap_p) < size)
return NULL;
heap_p += size;
return p;
}
static void
remove_from_free_list (struct mem_head *m)
{
if (m->prev)
m->prev->next = m->next;
else
free_list = m->next;
if (m->next)
m->next->prev = m->prev;
}
void *
gnuk_malloc (size_t size)
{
struct mem_head *m;
struct mem_head *m0;
size = HEAP_ALIGN (size + sizeof (uintptr_t));
chopstx_mutex_lock (&malloc_mtx);
DEBUG_INFO ("malloc: ");
DEBUG_SHORT (size);
m = free_list;
while (1)
{
if (m == NULL)
{
m = (struct mem_head *)gnuk_sbrk (size);
if (m)
m->size = size;
break;
}
MEM_HEAD_CHECK (m);
if (m->size == size)
{
remove_from_free_list (m);
m0 = free_list;
while (m0)
if (m0->neighbor == m)
m0->neighbor = NULL;
else
m0 = m0->next;
break;
}
m = m->next;
}
chopstx_mutex_unlock (&malloc_mtx);
if (m == NULL)
{
DEBUG_WORD (0);
return m;
}
else
{
DEBUG_WORD ((uintptr_t)m + sizeof (uintptr_t));
return (void *)m + sizeof (uintptr_t);
}
}
void
gnuk_free (void *p)
{
struct mem_head *m = (struct mem_head *)((void *)p - sizeof (uintptr_t));
struct mem_head *m0;
if (p == NULL)
return;
chopstx_mutex_lock (&malloc_mtx);
m0 = free_list;
DEBUG_INFO ("free: ");
DEBUG_SHORT (m->size);
DEBUG_WORD ((uintptr_t)p);
MEM_HEAD_CHECK (m);
m->neighbor = NULL;
while (m0)
{
MEM_HEAD_CHECK (m0);
if ((void *)m + m->size == (void *)m0)
m0->neighbor = m;
else if ((void *)m0 + m0->size == (void *)m)
m->neighbor = m0;
m0 = m0->next;
}
if ((void *)m + m->size == heap_p)
{
struct mem_head *mn = m->neighbor;
heap_p -= m->size;
while (mn)
{
MEM_HEAD_CHECK (mn);
heap_p -= mn->size;
remove_from_free_list (mn);
mn = mn->neighbor;
}
}
else
{
m->next = free_list;
m->prev = NULL;
if (free_list)
free_list->prev = m;
free_list = m;
}
chopstx_mutex_unlock (&malloc_mtx);
}

View File

@ -2,7 +2,7 @@
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
* 2020, 2021
* 2020, 2021, 2022
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@ -146,7 +146,6 @@ static const uint8_t feature_mngmnt[] __attribute__ ((aligned (1))) = {
#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. */
@ -165,22 +164,6 @@ static const uint8_t algorithm_attr_x448[] __attribute__ ((aligned (1))) = {
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,
@ -264,7 +247,12 @@ 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;
{
if (kk == GPG_KEY_FOR_DECRYPTION)
return ALGO_CURVE25519;
else
return ALGO_ED25519;
}
return algo_attr_p[1];
}
@ -297,12 +285,15 @@ 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;
{
if (kk == GPG_KEY_FOR_DECRYPTION)
return algorithm_attr_cv25519;
else
return algorithm_attr_ed25519;
}
switch (algo_attr_p[1])
{
case ALGO_RSA4K:
return algorithm_attr_rsa4k;
case ALGO_SECP256K1:
return algorithm_attr_p256k1;
case ALGO_CURVE25519:
@ -314,7 +305,7 @@ get_algo_attr_data_object (enum kind_of_key kk)
case ALGO_X448:
return algorithm_attr_x448;
default:
return algorithm_attr_rsa2k;
return algorithm_attr_ed25519;
}
}
@ -323,16 +314,16 @@ 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;
if (algo_attr_p == NULL)
{
if (kk == GPG_KEY_FOR_DECRYPTION)
goto cv25519;
else
goto ed25519;
}
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;
@ -340,18 +331,12 @@ gpg_get_algo_attr_key_size (enum kind_of_key kk, enum size_of_key s)
return 64;
else
return 32;
cv25519:
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;
@ -364,12 +349,15 @@ gpg_get_algo_attr_key_size (enum kind_of_key kk, enum size_of_key s)
return 112;
else
return 56;
ed25519:
default:
rsa2k:
case ALGO_ED25519:
if (s == GPG_KEY_STORAGE)
return 512;
return 128;
else if (s == GPG_KEY_PUBLIC)
return 32;
else
return 256;
return 64;
}
}
@ -733,8 +721,6 @@ do_alg_info (uint16_t tag, int with_tag)
{
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)
{
@ -823,11 +809,7 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
}
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
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))
@ -840,7 +822,7 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
if (algo < 0)
return 0; /* Error. */
else if (algo == ALGO_RSA2K && *algo_attr_pp != NULL)
else if (algo == ALGO_ED25519 && *algo_attr_pp != NULL)
{
gpg_reset_algo_attr (kk);
/* Read it again, since GC may occur. */
@ -849,7 +831,7 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
if (*algo_attr_pp != NULL)
return 0;
}
else if ((algo != ALGO_RSA2K && *algo_attr_pp == NULL) ||
else if ((algo != ALGO_ED25519 && *algo_attr_pp == NULL) ||
(*algo_attr_pp != NULL && (*algo_attr_pp)[1] != algo))
{
gpg_reset_algo_attr (kk);
@ -1239,7 +1221,7 @@ 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
* ECDSA/ECDH: d, EdDSA: a+seed
*/
/* Checksum */
};
@ -1444,14 +1426,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
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;
}
else
return -1;
DEBUG_INFO ("Getting keystore address...\r\n");
key_addr = flash_key_alloc (kk);
@ -1620,26 +1596,6 @@ kkb_to_kk (uint8_t kk_byte)
}
/*
* 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<E>: 91=tag of E, L<E>: length of E
* 92 Lh<P> Ll<P>: 92=tag of P, L<P>: length of P
* 93 Lh<Q> Ll<Q>: 93=tag of Q, L<Q>: length of Q
* 5f48, xx xx xx: cardholder private key
* <E: 4-byte>, <P: 128-byte>, <Q: 128-byte>
*
* 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<E>: 91=tag of E, L<E>: length of E
* 92 82 Lh<P> Ll<P>: 92=tag of P, L<P>: length of P
* 93 82 Lh<Q> Ll<Q>: 93=tag of Q, L<Q>: length of Q
* 5f48, 82 02 04: cardholder private key
* <E: 4-byte>, <P: 256-byte>, <Q: 256-byte>
*
* ECDSA / ECDH / EdDSA:
* 4d, 2a: Extended Header List
* b6 00 (SIG) / b8 00 (DEC) / a4 00 (AUT)
@ -1696,30 +1652,13 @@ proc_key_import (const uint8_t *data, int len)
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))
|| attr == ALGO_X448)))
{ /* 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)
if (attr == ALGO_SECP256K1)
{
r = ecc_compute_public_p256k1 (&data[12], pubkey);
if (r >= 0)
@ -2355,7 +2294,6 @@ 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");
@ -2423,24 +2361,9 @@ gpg_do_public_key (uint8_t kk_byte)
}
}
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;
}
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
/* Success */
@ -2501,17 +2424,7 @@ gpg_do_keygen (uint8_t *buf)
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)
if (attr == ALGO_SECP256K1)
{
const uint8_t *p;
int i;

View File

@ -2,7 +2,7 @@
* openpgp.c -- OpenPGP card protocol support
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* 2019, 2021
* 2019, 2021, 2022
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@ -64,8 +64,6 @@ static struct eventflag *openpgp_comm;
#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 */
@ -747,18 +745,6 @@ cmd_pgp_gakp (struct eventflag *ccid_comm)
}
}
#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
@ -799,22 +785,6 @@ cmd_read_binary (struct eventflag *ccid_comm)
}
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)
{
@ -939,7 +909,6 @@ cmd_pso (struct eventflag *ccid_comm)
int len = apdu.cmd_apdu_data_len;
int r = -1;
int attr;
int pubkey_len;
unsigned int result_len = 0;
int cs;
@ -951,9 +920,6 @@ cmd_pso (struct eventflag *ccid_comm)
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.");
@ -966,28 +932,7 @@ cmd_pso (struct eventflag *ccid_comm)
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)
if (attr == ALGO_SECP256K1)
{
/* ECDSA with p256r1/p256k1 for signature */
if (len != ECDSA_HASH_LEN)
@ -1044,11 +989,6 @@ cmd_pso (struct eventflag *ccid_comm)
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.");
@ -1063,19 +1003,7 @@ cmd_pso (struct eventflag *ccid_comm)
(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)
if (attr == ALGO_SECP256K1)
{
int header = ECC_CIPHER_DO_HEADER_SIZE;
@ -1149,13 +1077,10 @@ cmd_pso (struct eventflag *ccid_comm)
}
#define MAX_RSA_DIGEST_INFO_LEN 102 /* 40% */
static void
cmd_internal_authenticate (struct eventflag *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;
@ -1188,20 +1113,7 @@ cmd_internal_authenticate (struct eventflag *ccid_comm)
(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 (attr == ALGO_SECP256K1)
{
if (len != ECDSA_HASH_LEN)
{
@ -1324,28 +1236,6 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
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 ();
}
@ -1380,36 +1270,10 @@ cmd_write_binary (struct eventflag *ccid_comm)
static void
cmd_external_authenticate (struct eventflag *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)
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
{
GPG_SECURITY_FAILURE ();
return;
@ -1425,6 +1289,7 @@ static void
cmd_get_challenge (struct eventflag *ccid_comm)
{
int len = apdu.expected_res_size;
const uint8_t *challenge;
(void)ccid_comm;
DEBUG_INFO (" - GET CHALLENGE\r\n");
@ -1438,9 +1303,6 @@ cmd_get_challenge (struct eventflag *ccid_comm)
/* 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)
@ -1450,6 +1312,7 @@ cmd_get_challenge (struct eventflag *ccid_comm)
challenge = random_bytes_get ();
memcpy (res_APDU, challenge, len);
random_bytes_free (challenge);
res_APDU_size = len;
GPG_SUCCESS ();
DEBUG_INFO ("GET CHALLENGE done.\r\n");
@ -1488,13 +1351,13 @@ cmd_terminate_df (struct eventflag *ccid_comm)
if (p1 != 0 || p2 != 0)
{
GPG_BAD_P1_P2();
GPG_BAD_P1_P2 ();
return;
}
if (apdu.cmd_apdu_data_len != 0)
{
GPG_WRONG_LENGTH();
GPG_WRONG_LENGTH ();
return;
}
@ -1505,7 +1368,7 @@ cmd_terminate_df (struct eventflag *ccid_comm)
|| (ks_pw3 == NULL && gpg_pw_locked (PW_ERR_PW1))))
{
/* Only allow the case admin authorized, or, admin pass is locked. */
GPG_SECURITY_FAILURE();
GPG_SECURITY_FAILURE ();
return;
}

View File

@ -1,4 +0,0 @@
9cf7192b51a574d1ad3ccb08ba09b87f228573893eee355529ff243e90fd4b86f79a82097cc7922c0485bed1616b1656a9b0b19ef78ea8ec34c384019adc5d5bf4db2d2a0a2d9cf14277bdcb7056f48b81214e3f7f7742231e29673966f9b1106862112cc798dba8d4a138bb5abfc6d4c12d53a5d39b2f783da916da20852ee139bbafda61d429caf2a4f30847ce7e7ae32ab4061e27dd9e4d00d60910249db8d8559dd85f7ca59659ef400c8f6318700f4e97f0c6f4165de80641490433c88da8682befe68eb311f54af2b07d97ac74edb5399cf054764211694fbb8d1d333f3269f235abe025067f811ff83a2224826219b309ea3e6c968f42b3e52f245dc9
010001
b5ab7b159220b18e363258f61ebde08bae83d6ce2dbfe4adc143628c527887acde9de09bf9b49f438019004d71855f30c2d69b6c29bb9882ab641b3387409fe9199464a7faa4b5230c56d9e17cd9ed074bc00180ebed62bae3af28e6ff2ac2654ad968834c5d5c88f8d9d3cc5e167b10453b049d4e454a5761fb0ac717185907
dd2fffa9814296156a6926cd17b65564187e424dcadce9b032246ad7e46448bb0f9e0ff3c64f987424b1a40bc694e2e9ac4fb1930d163582d7acf20653a1c44b97846c1c5fd8a7b19bb225fb39c30e25410483deaf8c2538d222b748c4d8103b11cec04f666a5c0dbcbf5d5f625f158f65746c3fafe6418145f7cffa5fadeeaf

View File

@ -1,4 +0,0 @@
d392714c29738aac6372f2c8654a08c25a1299fed7004bd512cd2452b503ebad6301130816ac525ba528dc155be6347a5c70407fb4fbdaed751dfc0a7cd5e3910272ff236c4ed1ce5de6620b191a172e5b247347b8cab73a43d79221708755c959a2f83f486439da30917384554331532aabc8326db48866f8c91198834a86ab94679f6175db737bdf399e3f0b737dcb1f4208279d3e1cc694e78686785e4f363a377dec912b7c2f757b1422d866fb9fa85c96b83adfd6a223989a9a02988bdee81ad17eff6385e7b38cec8611fdf367ba4ac8e90d5f48ac7715c5f47aea06a4a37cdaa3029ce59d29bc66853bf6758ef4a7da5a5953f5e557a5a22f67c368c3
010001
dae085952c5beee38f25f09bc37a4ca2434c31f78055469d0d5f0bf3337e3a70ba6c91734f195b742e211a5fe283befdf66820008e6ef2c8ca54a91922838fce07d9e33a331ce20dac36803e777d5ee2195ed28d6a4045e28623a6a60b0661e45f7c4f84ae2b1dfad0cf1ec30605158323382a819e730c09a33fad704dd67501
f774be43ea198aa2f089274e4fffd7d0092ee7b35a1d2f854cdb166f698caab72fdeb099e690e78438b2e043e452d4d2f19d7f44ba6b286642f0ce5204966ff98ecd9e3b448877324631365dc860797429b9414a21a7e166d504cace156588b9a145657eeb1afb43b8ff65d8d6d93cea2ba4ef8aab047885c4de64ffef0b49c3

View File

@ -1,4 +0,0 @@
c6c877dfd3b441f8fb1b8dc504093a51c2efe4883fe0a6379205acc6e673709905e4d767ddf46143c535cc6d7f10b616f520d8346320ef69ff4a2c4f4a148edc65f7ad24ed7d4fe23bb862a0ae71f4f7904abac0397abf3213df91326b1a25554b3b18cf54584d8bf220169fc92b2aa511e8313983e72b4c9110b3a1aea087aebef95873865608e8faea9ef10e7f7f3a66ca8def2d499c3149c127491e0e4339fd6abe10bfc6c13e43d522004f1485767328eabe35d6ffa8df4c15f0fbcd4eb1c07cc6d85e275139ac69e2962273ae987236926dd6c1144fce3e7ae567fa58ea60620dfafc52f95299fea601739fce27ee71eea978d0074f21e7086f60ba8331
010001
cc365b5702714bf203e8c49b0b8afa8dad586e929cf5edca38ad07fa45efd5c2d89022d29f40283a57e50ca24c5f28c8e911a74faaf796f112e7e48195956f9a4df7668a5342523b27179cec958f363211ee11d0ec0e0e1b92ca007a61e8c9ac14e00229b9a7624850199e6667afa1a44db8f3c5de0a8eef0e6de050ac0ac633
f931a3c12f0e3a5276f712b7706590ba02e14a97ff9b8ce3152af0fc4d9cdc690ea9bc4c82cb16c7d23136cbdab58fbec69880a88bca85c4214df01045082cbe9f4192e3e39c79896533c37dad9eb9e73c2643b9c0a704a4f93d81573537963d6b6e5140a24c702d9f26e06a2095de906daa8824172a6b39f563b7153907050b

View File

@ -468,14 +468,8 @@ class gnuk_token(object):
raise ValueError("%02x%02x" % (sw[0], sw[1]))
return self.cmd_get_response(sw[1])
def cmd_external_authenticate(self, keyno, signed):
cmd_data = iso7816_compose(0x82, 0x00, keyno, signed[0:128], cls=0x10)
sw = self.icc_send_cmd(cmd_data)
if len(sw) != 2:
raise ValueError(sw)
if not (sw[0] == 0x90 and sw[1] == 0x00):
raise ValueError("%02x%02x" % (sw[0], sw[1]))
cmd_data = iso7816_compose(0x82, 0x00, keyno, signed[128:])
def cmd_external_authenticate(self):
cmd_data = iso7816_compose(0x82, 0x00, 0x00, b"", cls=0x10)
sw = self.icc_send_cmd(cmd_data)
if len(sw) != 2:
raise ValueError(sw)

View File

@ -3,7 +3,8 @@
"""
gnuk_upgrade.py - a tool to upgrade firmware of Gnuk Token
Copyright (C) 2012, 2015, 2021 Free Software Initiative of Japan
Copyright (C) 2012, 2015, 2021, 2022
Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@ -35,42 +36,7 @@ from gnuk_token import *
from subprocess import check_output
SHA256_OID_PREFIX="3031300d060960864801650304020105000420"
# When user specify KEYGRIP, use it. Or else, connect to SCD directly.
def gpg_sign(keygrip, hash):
if keygrip:
result = check_output(["gpg-connect-agent",
"SIGKEY %s" % keygrip,
"SETHASH --hash=sha256 %s" % hash,
"PKSIGN --hash=sha256", "/bye"])
else:
result = check_output(["gpg-connect-agent",
"SCD SETDATA " + SHA256_OID_PREFIX + hash,
"SCD PKAUTH OPENPGP.3",
"/bye"])
signed = ""
while True:
i = result.find('%')
if i < 0:
signed += result
break
hex_str = result[i+1:i+3]
signed += result[0:i]
signed += chr(int(hex_str,16))
result = result[i+3:]
if keygrip:
pos = signed.index("D (7:sig-val(3:rsa(1:s256:") + 26
signed = signed[pos:-7]
else:
pos = signed.index("D ") + 2
signed = signed[pos:-4] # \nOK\n
if len(signed) != 256:
raise ValueError(binascii.hexlify(signed))
return signed
def main(keyno, keygrip, data_regnual, data_upgrade):
def main(data_regnual, data_upgrade):
l = len(data_regnual)
if (l & 0x03) != 0:
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), b'\x00')
@ -91,9 +57,7 @@ def main(keyno, keygrip, data_regnual, data_upgrade):
elif icc.icc_get_status() == 1:
icc.icc_power_on()
icc.cmd_select_openpgp()
challenge = icc.cmd_get_challenge().tobytes()
signed = gpg_sign(keygrip, binascii.hexlify(challenge))
icc.cmd_external_authenticate(keyno, signed)
icc.cmd_external_authenticate()
icc.stop_gnuk()
mem_info = icc.mem_info()
print("%08x:%08x" % mem_info)
@ -131,12 +95,6 @@ def main(keyno, keygrip, data_regnual, data_upgrade):
if __name__ == '__main__':
keyno = 0
keygrip = None
if sys.argv[1] == '-k':
sys.argv.pop(1)
keygrip = sys.argv[1]
sys.argv.pop(1)
filename_regnual = sys.argv[1]
filename_upgrade = sys.argv[2]
f = open(filename_regnual, "rb")
@ -147,4 +105,4 @@ if __name__ == '__main__':
data_upgrade = f.read()
f.close()
print("%s: %d" % (filename_upgrade, len(data_upgrade)))
main(keyno, keygrip, data_regnual, data_upgrade[4096:])
main(data_regnual, data_upgrade[4096:])

View File

@ -4,7 +4,7 @@
upgrade_by_passwd.py - a tool to install another firmware for Gnuk Token
which is just shipped from factory
Copyright (C) 2012, 2013, 2015, 2018, 2021
Copyright (C) 2012, 2013, 2015, 2018, 2021, 2022
Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
@ -29,15 +29,12 @@ from gnuk_token import get_gnuk_device, gnuk_devices_by_vidpid, \
from kdf_calc import kdf_calc
import sys, binascii, time, os
import rsa
from struct import pack
DEFAULT_PW3 = "12345678"
BY_ADMIN = 3
KEYNO_FOR_AUTH=2
def main(wait_e, keyno, passwd, data_regnual, data_upgrade):
def main(wait_e, passwd, data_regnual, data_upgrade):
l = len(data_regnual)
if (l & 0x03) != 0:
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0))
@ -45,9 +42,6 @@ def main(wait_e, keyno, passwd, data_regnual, data_upgrade):
print("CRC32: %04x\n" % crc32code)
data_regnual += pack('<I', crc32code)
rsa_key = rsa.read_key_from_file('rsa_example.key')
rsa_raw_pubkey = rsa.get_raw_pubkey(rsa_key)
gnuk = get_gnuk_device()
gnuk.cmd_select_openpgp()
# Compute passwd data
@ -67,14 +61,9 @@ def main(wait_e, keyno, passwd, data_regnual, data_upgrade):
passwd_data = kdf_calc(passwd, salt, iters)
# And authenticate with the passwd data
gnuk.cmd_verify(BY_ADMIN, passwd_data)
gnuk.cmd_write_binary(1+keyno, rsa_raw_pubkey, False)
gnuk.cmd_select_openpgp()
challenge = gnuk.cmd_get_challenge().tobytes()
digestinfo = binascii.unhexlify(SHA256_OID_PREFIX) + challenge
signed = rsa.compute_signature(rsa_key, digestinfo)
signed_bytes = rsa.integer_to_bytes_256(signed)
gnuk.cmd_external_authenticate(keyno, signed_bytes)
gnuk.cmd_external_authenticate()
gnuk.stop_gnuk()
mem_info = gnuk.mem_info()
print("%08x:%08x" % mem_info)
@ -125,7 +114,6 @@ if __name__ == '__main__':
print("Please change working directory to: %s" % os.path.dirname(os.path.abspath(__file__)))
exit(1)
keyno = 0
passwd = None
wait_e = DEFAULT_WAIT_FOR_REENUMERATION
skip_check = False
@ -138,10 +126,6 @@ if __name__ == '__main__':
sys.argv.pop(1)
wait_e = int(sys.argv[1])
sys.argv.pop(1)
elif option == '-k': # K for Key number
sys.argv.pop(1)
keyno = int(sys.argv[1])
sys.argv.pop(1)
elif option == '-s': # S for skip the check of target
sys.argv.pop(1)
skip_check = True
@ -184,4 +168,4 @@ if __name__ == '__main__':
f.close()
print("%s: %d" % (filename_upgrade, len(data_upgrade)))
# First 4096-byte in data_upgrade is SYS, so, skip it.
main(wait_e, keyno, passwd, data_regnual, data_upgrade[4096:])
main(wait_e, passwd, data_regnual, data_upgrade[4096:])