Support modifiable key algo attrs and divert on runtime
This commit is contained in:
19
ChangeLog
19
ChangeLog
@@ -1,3 +1,22 @@
|
||||
2014-11-21 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (ALGO_RSA4K, ALGO_NISTP256R1, ALGO_SECP256K1)
|
||||
(ALGO_ED25519, ALGO_RSA2K): New.
|
||||
(struct key_data_internal): Move to ...
|
||||
* src/openpgp-do.c (struct key_data_internal): ... here.
|
||||
(CHECKSUM_ADDR, kdi_len): New.
|
||||
(CKDC_CALC, CKDC_CHECK): New.
|
||||
(compute_key_data_checksum): Add arg PRVKEY_LEN.
|
||||
(gpg_do_load_prvkey, gpg_do_delete_prvkey): Support modifiable key
|
||||
algo attributes.
|
||||
(gpg_do_write_prvkey, gpg_do_public_key, gpg_do_keygen): Likewise.
|
||||
(gpg_do_clear_prvkey): Use MAX_PRVKEY_LEN.
|
||||
|
||||
* src/openpgp.c (gpg_init): Call flash_init_keys after
|
||||
gpg_data_scan.
|
||||
(cmd_pso): Support modifiable key algo attributes.
|
||||
(cmd_internal_authenticate): Likewise.
|
||||
|
||||
2014-11-21 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (algorithm_attr_rsa2k): Rename from *_rsa.
|
||||
|
||||
27
src/gnuk.h
27
src/gnuk.h
@@ -109,6 +109,12 @@ void gpg_do_keygen (uint8_t kk_byte);
|
||||
|
||||
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_RSA2K 255
|
||||
|
||||
enum kind_of_key {
|
||||
GPG_KEY_FOR_SIGNING = 0,
|
||||
@@ -122,6 +128,9 @@ enum size_of_key {
|
||||
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);
|
||||
|
||||
const uint8_t *flash_init (void);
|
||||
void flash_init_keys (void);
|
||||
void flash_do_release (const uint8_t *);
|
||||
@@ -160,18 +169,10 @@ extern uint8_t random_bits_start;
|
||||
#define MAX_PRVKEY_LEN 512 /* Maximum is the case for RSA 4096-bit. */
|
||||
|
||||
struct key_data {
|
||||
const uint8_t *pubkey; /* Pointer to public key*/
|
||||
const uint8_t *pubkey; /* Pointer to public key */
|
||||
uint8_t data[MAX_PRVKEY_LEN]; /* decrypted private key data content */
|
||||
};
|
||||
|
||||
struct key_data_internal {
|
||||
uint32_t data[KEY_CONTENT_LEN/4]; /*
|
||||
* Secret key data.
|
||||
* RSA: p and q, ECDSA: d, EdDSA: a+seed
|
||||
*/
|
||||
uint32_t checksum[DATA_ENCRYPTION_KEY_SIZE/4];
|
||||
};
|
||||
|
||||
struct prvkey_data {
|
||||
/*
|
||||
* IV: Initial Vector
|
||||
@@ -260,11 +261,15 @@ uint8_t *rsa_genkey (int);
|
||||
|
||||
int ecdsa_sign_p256r1 (const uint8_t *hash, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
uint8_t *ecdsa_compute_public_p256r1 (const uint8_t *key_data);
|
||||
uint8_t *ecc_compute_public_p256r1 (const uint8_t *key_data);
|
||||
int ecdh_decrypt_p256r1 (const uint8_t *input, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
|
||||
int ecdsa_sign_p256k1 (const uint8_t *hash, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
uint8_t *ecdsa_compute_public_p256k1 (const uint8_t *key_data);
|
||||
uint8_t *ecc_compute_public_p256k1 (const uint8_t *key_data);
|
||||
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,
|
||||
|
||||
254
src/openpgp-do.c
254
src/openpgp-do.c
@@ -861,26 +861,42 @@ get_do_ptr_nr_for_kk (enum kind_of_key kk)
|
||||
void
|
||||
gpg_do_clear_prvkey (enum kind_of_key kk)
|
||||
{
|
||||
memset (kd[kk].data, 0, KEY_CONTENT_LEN);
|
||||
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 check_or_calc)
|
||||
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 < KEY_CONTENT_LEN / sizeof (uint32_t); i++)
|
||||
for (i = 0; i < prvkey_len / sizeof (uint32_t); i++)
|
||||
d[i&3] ^= kdi->data[i];
|
||||
|
||||
if (check_or_calc == 0) /* store */
|
||||
if (check_or_calc == CKDC_CALC) /* store */
|
||||
{
|
||||
memcpy (kdi->checksum, d, DATA_ENCRYPTION_KEY_SIZE);
|
||||
memcpy (checksum, d, DATA_ENCRYPTION_KEY_SIZE);
|
||||
return 0;
|
||||
}
|
||||
else /* check */
|
||||
return memcmp (kdi->checksum, d, DATA_ENCRYPTION_KEY_SIZE) == 0;
|
||||
return memcmp (checksum, d, DATA_ENCRYPTION_KEY_SIZE) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -892,6 +908,7 @@ 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];
|
||||
@@ -904,24 +921,25 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
|
||||
if (do_data == NULL)
|
||||
return 0;
|
||||
|
||||
key_addr = kd[kk].key_addr;
|
||||
memcpy (kdi.data, key_addr, KEY_CONTENT_LEN);
|
||||
key_addr = kd[kk].pubkey - prvkey_len;
|
||||
memcpy (kdi.data, key_addr, prvkey_len);
|
||||
iv = &do_data[1];
|
||||
memcpy (kdi.checksum, iv + INITIAL_VECTOR_SIZE, DATA_ENCRYPTION_KEY_SIZE);
|
||||
memcpy (CHECKSUM_ADDR (kdi, prvkey_len),
|
||||
iv + INITIAL_VECTOR_SIZE, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
memcpy (dek, iv+16*(who+1), 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, sizeof (struct key_data_internal));
|
||||
decrypt (dek, iv, (uint8_t *)&kdi, kdi_len (prvkey_len));
|
||||
memset (dek, 0, DATA_ENCRYPTION_KEY_SIZE);
|
||||
if (!compute_key_data_checksum (&kdi, 1))
|
||||
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, KEY_CONTENT_LEN);
|
||||
DEBUG_BINARY (kd[kk].data, KEY_CONTENT_LEN);
|
||||
memcpy (kd[kk].data, kdi.data, prvkey_len);
|
||||
DEBUG_BINARY (kd[kk].data, prvkey_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -934,15 +952,17 @@ gpg_do_delete_prvkey (enum kind_of_key kk)
|
||||
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)
|
||||
return;
|
||||
|
||||
do_ptr[nr] = NULL;
|
||||
flash_do_release (do_data);
|
||||
key_addr = kd[kk].key_addr;
|
||||
kd[kk].key_addr = NULL;
|
||||
flash_key_release (key_addr);
|
||||
key_addr = (uint8_t *)kd[kk].pubkey - prvkey_len;
|
||||
kd[kk].pubkey = NULL;
|
||||
flash_key_release (key_addr, key_size);
|
||||
|
||||
if (admin_authorized == BY_ADMIN && kk == GPG_KEY_FOR_SIGNING)
|
||||
{ /* Recover admin keystring DO. */
|
||||
@@ -973,10 +993,12 @@ gpg_do_delete_prvkey (enum kind_of_key kk)
|
||||
}
|
||||
|
||||
static int
|
||||
gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
const uint8_t *keystring_admin, const uint8_t *pubkey)
|
||||
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 *pd;
|
||||
@@ -984,86 +1006,52 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
const uint8_t *dek, *iv;
|
||||
struct key_data_internal kdi;
|
||||
uint8_t *pubkey_allocated_here = NULL;
|
||||
int pubkey_len = KEY_CONTENT_LEN;
|
||||
int pubkey_len;
|
||||
uint8_t ks[KEYSTRING_MD_SIZE];
|
||||
enum kind_of_key kk0;
|
||||
|
||||
DEBUG_INFO ("Key import\r\n");
|
||||
DEBUG_SHORT (key_len);
|
||||
DEBUG_SHORT (prvkey_len);
|
||||
|
||||
/* Delete it first, if any. */
|
||||
gpg_do_delete_prvkey (kk);
|
||||
|
||||
#if defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
if (key_len != KEY_CONTENT_LEN)
|
||||
return -1;
|
||||
#elif defined(RSA_AUTH) && !defined(RSA_SIG)
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (kk != GPG_KEY_FOR_SIGNING && key_len != KEY_CONTENT_LEN)
|
||||
return -1;
|
||||
if (kk == GPG_KEY_FOR_SIGNING)
|
||||
{
|
||||
pubkey_len = key_len * 2;
|
||||
if (key_len != 32)
|
||||
return -1;
|
||||
}
|
||||
#elif !defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
#if defined(ECDSA_AUTH)
|
||||
/* ECDSA with p256r1 for authentication */
|
||||
if (kk != GPG_KEY_FOR_AUTHENTICATION && key_len != KEY_CONTENT_LEN)
|
||||
return -1;
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
{
|
||||
pubkey_len = key_len * 2;
|
||||
if (key_len != 32)
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
/* EdDSA with Ed25519 for authentication */
|
||||
if (kk != GPG_KEY_FOR_AUTHENTICATION && key_len != KEY_CONTENT_LEN)
|
||||
return -1;
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
{
|
||||
pubkey_len = key_len / 2;
|
||||
if (key_len != 64)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
|
||||
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
|
||||
if (pd == NULL)
|
||||
return -1;
|
||||
|
||||
if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
{
|
||||
pubkey_len = prvkey_len * 2;
|
||||
if (prvkey_len != 32)
|
||||
return -1;
|
||||
}
|
||||
else if (attr == ALGO_ED25519)
|
||||
{
|
||||
pubkey_len = prvkey_len / 2;
|
||||
if (prvkey_len != 64)
|
||||
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;
|
||||
}
|
||||
|
||||
if (pubkey == NULL)
|
||||
{
|
||||
#if defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
pubkey_allocated_here = modulus_calc (key_data, key_len);
|
||||
#elif defined(RSA_AUTH) && !defined(RSA_SIG)
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (kk == GPG_KEY_FOR_SIGNING)
|
||||
pubkey_allocated_here = ecdsa_compute_public_p256k1 (key_data);
|
||||
else
|
||||
pubkey_allocated_here = modulus_calc (key_data, key_len);
|
||||
#elif !defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
#if defined(ECDSA_AUTH)
|
||||
/* ECDSA with p256r1 for authentication */
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
pubkey_allocated_here = ecdsa_compute_public_p256r1 (key_data);
|
||||
else
|
||||
pubkey_allocated_here = modulus_calc (key_data, key_len);
|
||||
#else
|
||||
/* EdDSA with Ed25519 for authentication */
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
if (attr == ALGO_SECP256K1)
|
||||
pubkey_allocated_here = ecc_compute_public_p256k1 (key_data);
|
||||
else if (attr == ALGO_NISTP256R1)
|
||||
pubkey_allocated_here = ecc_compute_public_p256r1 (key_data);
|
||||
else if (attr == ALGO_ED25519)
|
||||
pubkey_allocated_here = eddsa_compute_public_25519 (key_data);
|
||||
else
|
||||
pubkey_allocated_here = modulus_calc (key_data, key_len);
|
||||
#endif
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
else /* RSA */
|
||||
pubkey_allocated_here = modulus_calc (key_data, prvkey_len);
|
||||
|
||||
if (pubkey_allocated_here == NULL)
|
||||
{
|
||||
free (pd);
|
||||
@@ -1083,38 +1071,17 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
free (pd);
|
||||
return -1;
|
||||
}
|
||||
kd[kk].key_addr = key_addr;
|
||||
kd[kk].pubkey = key_addr + prvkey_len;
|
||||
|
||||
num_prv_keys++;
|
||||
|
||||
DEBUG_INFO ("key_addr: ");
|
||||
DEBUG_WORD ((uint32_t)key_addr);
|
||||
|
||||
#if defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
memcpy (kdi.data, key_data, KEY_CONTENT_LEN);
|
||||
#elif defined(RSA_AUTH) && !defined(RSA_SIG)
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (kk == GPG_KEY_FOR_SIGNING)
|
||||
{
|
||||
memcpy (kdi.data, key_data, key_len);
|
||||
memset ((uint8_t *)kdi.data + key_len, 0, KEY_CONTENT_LEN - key_len);
|
||||
}
|
||||
else
|
||||
memcpy (kdi.data, key_data, KEY_CONTENT_LEN);
|
||||
#elif !defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
/* ECDSA with p256r1 for authentication */
|
||||
/* EdDSA with Ed25519 for authentication */
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
{
|
||||
memcpy (kdi.data, key_data, key_len);
|
||||
memset ((uint8_t *)kdi.data + key_len, 0, KEY_CONTENT_LEN - key_len);
|
||||
}
|
||||
else
|
||||
memcpy (kdi.data, key_data, KEY_CONTENT_LEN);
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
compute_key_data_checksum (&kdi, 0);
|
||||
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-byte random bytes */
|
||||
iv = dek + DATA_ENCRYPTION_KEY_SIZE;
|
||||
@@ -1136,9 +1103,9 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
gpg_do_chks_prvkey (kk0, BY_RESETCODE, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
encrypt (dek, iv, (uint8_t *)&kdi, sizeof (struct key_data_internal));
|
||||
encrypt (dek, iv, (uint8_t *)&kdi, kdi_len (prvkey_len));
|
||||
|
||||
r = flash_key_write (key_addr, (const uint8_t *)kdi.data,
|
||||
r = flash_key_write (key_addr, (const uint8_t *)kdi.data, prvkey_len,
|
||||
pubkey_allocated_here? pubkey_allocated_here: pubkey,
|
||||
pubkey_len);
|
||||
if (pubkey_allocated_here)
|
||||
@@ -1156,7 +1123,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
}
|
||||
|
||||
memcpy (pd->iv, iv, INITIAL_VECTOR_SIZE);
|
||||
memcpy (pd->checksum_encrypted, kdi.checksum, DATA_ENCRYPTION_KEY_SIZE);
|
||||
memcpy (pd->checksum_encrypted, CHECKSUM_ADDR (kdi, prvkey_len),
|
||||
DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
encrypt_dek (ks, pd->dek_encrypted_1);
|
||||
|
||||
@@ -1916,15 +1884,15 @@ gpg_do_put_data (uint16_t tag, const uint8_t *data, int len)
|
||||
void
|
||||
gpg_do_public_key (uint8_t kk_byte)
|
||||
{
|
||||
const uint8_t *key_addr;
|
||||
enum kind_of_key kk;
|
||||
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);
|
||||
|
||||
kk = kkb_to_kk (kk_byte);
|
||||
key_addr = kd[kk].key_addr;
|
||||
if (key_addr == NULL)
|
||||
if (pubkey == NULL)
|
||||
{
|
||||
DEBUG_INFO ("none.\r\n");
|
||||
GPG_NO_RECORD ();
|
||||
@@ -1936,20 +1904,8 @@ gpg_do_public_key (uint8_t kk_byte)
|
||||
/* TAG */
|
||||
*res_p++ = 0x7f; *res_p++ = 0x49;
|
||||
|
||||
#if defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
if (0)
|
||||
#elif defined(RSA_AUTH) && !defined(RSA_SIG)
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (kk_byte == 0xb6)
|
||||
#elif !defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
/* ECDSA with p256r1 for authentication */
|
||||
/* EdDSA with Ed25519 for authentication */
|
||||
if (kk_byte == 0xa4)
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
#if defined(ECDSA_AUTH)
|
||||
{ /* ECDSA */
|
||||
if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
{ /* ECDSA or ECDH */
|
||||
/* LEN */
|
||||
*res_p++ = 2 + 1 + 64;
|
||||
{
|
||||
@@ -1957,11 +1913,11 @@ gpg_do_public_key (uint8_t kk_byte)
|
||||
*res_p++ = 0x86; *res_p++ = 0x41;
|
||||
*res_p++ = 0x04; /* No compression of EC point. */
|
||||
/* 64-byte binary (big endian): X || Y */
|
||||
memcpy (res_p, key_addr + KEY_CONTENT_LEN, 64);
|
||||
memcpy (res_p, pubkey, 64);
|
||||
res_p += 64;
|
||||
}
|
||||
}
|
||||
#else /* EDDSA_AUTH */
|
||||
else if (attr == ALGO_ED25519)
|
||||
{ /* EdDSA */
|
||||
/* LEN */
|
||||
*res_p++ = 2 + 32;
|
||||
@@ -1969,22 +1925,22 @@ gpg_do_public_key (uint8_t kk_byte)
|
||||
/*TAG*/ /* LEN = 32 */
|
||||
*res_p++ = 0x86; *res_p++ = 0x20;
|
||||
/* 32-byte binary (little endian): Y with parity */
|
||||
memcpy (res_p, key_addr + KEY_CONTENT_LEN, 32);
|
||||
memcpy (res_p, pubkey, 32);
|
||||
res_p += 32;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{ /* RSA */
|
||||
/* LEN = 9+256 */
|
||||
*res_p++ = 0x82; *res_p++ = 0x01; *res_p++ = 0x09;
|
||||
/* LEN = 9+256or512 */
|
||||
*res_p++ = 0x82; *res_p++ = pubkey_len > 256? 0x02: 0x01; *res_p++ = 0x09;
|
||||
|
||||
{
|
||||
/*TAG*/ /* LEN = 256 */
|
||||
*res_p++ = 0x81; *res_p++ = 0x82; *res_p++ = 0x01; *res_p++ = 0x00;
|
||||
/* 256-byte binary (big endian) */
|
||||
memcpy (res_p, key_addr + KEY_CONTENT_LEN, KEY_CONTENT_LEN);
|
||||
res_p += 256;
|
||||
/*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 */
|
||||
@@ -2038,7 +1994,8 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
|
||||
void
|
||||
gpg_do_keygen (uint8_t kk_byte)
|
||||
{
|
||||
enum kind_of_key kk;
|
||||
enum kind_of_key kk = kkb_to_kk (kk_byte);
|
||||
int pubkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PUBLIC);
|
||||
const uint8_t *keystring_admin;
|
||||
uint8_t *p_q_modulus;
|
||||
const uint8_t *p_q;
|
||||
@@ -2048,13 +2005,12 @@ gpg_do_keygen (uint8_t kk_byte)
|
||||
DEBUG_INFO ("Keygen\r\n");
|
||||
DEBUG_BYTE (kk_byte);
|
||||
|
||||
kk = kkb_to_kk (kk_byte);
|
||||
if (admin_authorized == BY_ADMIN)
|
||||
keystring_admin = keystring_md_pw3;
|
||||
else
|
||||
keystring_admin = NULL;
|
||||
|
||||
p_q_modulus = rsa_genkey ();
|
||||
p_q_modulus = rsa_genkey (pubkey_len);
|
||||
if (p_q_modulus == NULL)
|
||||
{
|
||||
GPG_MEMORY_FAILURE ();
|
||||
@@ -2062,10 +2018,10 @@ gpg_do_keygen (uint8_t kk_byte)
|
||||
}
|
||||
|
||||
p_q = p_q_modulus;
|
||||
modulus = p_q_modulus + KEY_CONTENT_LEN;
|
||||
modulus = p_q_modulus + pubkey_len;
|
||||
|
||||
r = gpg_do_write_prvkey (kk, p_q, KEY_CONTENT_LEN, keystring_admin, modulus);
|
||||
memset (p_q_modulus, 0, KEY_CONTENT_LEN*2);
|
||||
r = gpg_do_write_prvkey (kk, p_q, pubkey_len, keystring_admin, modulus);
|
||||
memset (p_q_modulus, 0, pubkey_len * 2);
|
||||
free (p_q_modulus);
|
||||
if (r < 0)
|
||||
{
|
||||
|
||||
285
src/openpgp.c
285
src/openpgp.c
@@ -107,6 +107,7 @@ gpg_init (void)
|
||||
file_selection = FILE_NONE;
|
||||
flash_data_start = flash_init ();
|
||||
gpg_data_scan (flash_data_start);
|
||||
flash_init_keys ();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -815,14 +816,21 @@ static void
|
||||
cmd_pso (void)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r;
|
||||
int r = -1;
|
||||
int attr;
|
||||
int pubkey_len;
|
||||
|
||||
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.");
|
||||
@@ -830,64 +838,81 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef RSA_SIG
|
||||
/* 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 */
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
DEBUG_INFO (" wrong length: ");
|
||||
DEBUG_SHORT (len);
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_BINARY (kd[GPG_KEY_FOR_SIGNING].data, KEY_CONTENT_LEN);
|
||||
/* 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);
|
||||
|
||||
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_SIGNING]);
|
||||
&kd[GPG_KEY_FOR_SIGNING], pubkey_len);
|
||||
if (r < 0)
|
||||
{
|
||||
ac_reset_pso_cds ();
|
||||
GPG_ERROR ();
|
||||
}
|
||||
ac_reset_pso_cds ();
|
||||
else
|
||||
/* Success */
|
||||
gpg_increment_digital_signature_counter ();
|
||||
}
|
||||
#else
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
{
|
||||
DEBUG_INFO (" wrong length: ");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
/* ECDSA with p256r1/p256k1 for signature */
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
{
|
||||
DEBUG_INFO (" wrong length");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
res_APDU_size = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_SIGNING].data);
|
||||
if (attr == ALGO_NISTP256R1)
|
||||
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_SIGNING].data);
|
||||
else /* ALGO_SECP256K1 */
|
||||
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_SIGNING].data);
|
||||
if (r < 0)
|
||||
{
|
||||
ac_reset_pso_cds ();
|
||||
GPG_ERROR ();
|
||||
}
|
||||
ac_reset_pso_cds ();
|
||||
else
|
||||
/* Success */
|
||||
gpg_increment_digital_signature_counter ();
|
||||
{ /* Success */
|
||||
gpg_increment_digital_signature_counter ();
|
||||
res_APDU_size = ECDSA_SIGNATURE_LENGTH;
|
||||
}
|
||||
}
|
||||
else if (attr == ALGO_ED25519)
|
||||
{
|
||||
uint32_t output[64/4]; /* Require 4-byte alignment. */
|
||||
|
||||
if (len > EDDSA_HASH_LEN_MAX)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
res_APDU_size = EDDSA_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);
|
||||
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86)
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_BINARY (kd[GPG_KEY_FOR_DECRYPTION].data, KEY_CONTENT_LEN);
|
||||
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))
|
||||
{
|
||||
@@ -896,19 +921,40 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Skip padding 0x00 */
|
||||
len--;
|
||||
if (len != KEY_CONTENT_LEN)
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
else
|
||||
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]);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
{
|
||||
/* Format is in big endian MPI: 04 || x || y */
|
||||
if (len != 65 || apdu.cmd_apdu_data[0] != 4)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (attr == ALGO_NISTP256R1)
|
||||
r = ecdh_decrypt_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_DECRYPTION].data);
|
||||
else
|
||||
r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_DECRYPTION].data);
|
||||
|
||||
if (r == 0)
|
||||
res_APDU_size = 65;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (r < 0)
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
@@ -921,28 +967,39 @@ cmd_pso (void)
|
||||
}
|
||||
|
||||
|
||||
#if defined(RSA_AUTH)
|
||||
#define MAX_DIGEST_INFO_LEN 102 /* 40% */
|
||||
#define MAX_RSA_DIGEST_INFO_LEN 102 /* 40% */
|
||||
static void
|
||||
cmd_internal_authenticate (void)
|
||||
{
|
||||
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;
|
||||
int r = -1;
|
||||
|
||||
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
if (P1 (apdu) == 0x00 && P2 (apdu) == 0x00)
|
||||
if (P1 (apdu) != 0x00 || P2 (apdu) != 0x00)
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P2 (apdu));
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
DEBUG_SHORT (len);
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > MAX_DIGEST_INFO_LEN)
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
if (len > MAX_RSA_DIGEST_INFO_LEN)
|
||||
{
|
||||
DEBUG_INFO ("input is too long.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
@@ -950,41 +1007,10 @@ cmd_internal_authenticate (void)
|
||||
}
|
||||
|
||||
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_AUTHENTICATION]);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
&kd[GPG_KEY_FOR_AUTHENTICATION], pubkey_len);
|
||||
}
|
||||
else if (attr == ALGO_NISTP256R1)
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P2 (apdu));
|
||||
GPG_ERROR ();
|
||||
}
|
||||
|
||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
#elif defined(ECDSA_AUTH)
|
||||
static void
|
||||
cmd_internal_authenticate (void)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r;
|
||||
|
||||
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
if (P1 (apdu) == 0x00 && P2 (apdu) == 0x00)
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
@@ -995,42 +1021,24 @@ cmd_internal_authenticate (void)
|
||||
res_APDU_size = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
else if (attr == ALGO_SECP256K1)
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P2 (apdu));
|
||||
GPG_ERROR ();
|
||||
}
|
||||
|
||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
#elif defined(EDDSA_AUTH)
|
||||
static void
|
||||
cmd_internal_authenticate (void)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r;
|
||||
|
||||
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
if (P1 (apdu) == 0x00 && P2 (apdu) == 0x00)
|
||||
{
|
||||
uint32_t output[64/4]; /* Require 4-byte alignment. */
|
||||
|
||||
DEBUG_SHORT (len);
|
||||
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
res_APDU_size = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data);
|
||||
}
|
||||
else if (attr == ALGO_ED25519)
|
||||
{
|
||||
uint32_t output[64/4]; /* Require 4-byte alignment. */
|
||||
|
||||
if (len > EDDSA_HASH_LEN_MAX)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
@@ -1040,27 +1048,18 @@ cmd_internal_authenticate (void)
|
||||
|
||||
res_APDU_size = EDDSA_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].key_addr + KEY_CONTENT_LEN);
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data+32,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].pubkey);
|
||||
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P2 (apdu));
|
||||
GPG_ERROR ();
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
|
||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
#else
|
||||
#error "Authentication not defined."
|
||||
#endif
|
||||
|
||||
|
||||
#define MBD_OPRATION_WRITE 0
|
||||
#define MBD_OPRATION_UPDATE 1
|
||||
|
||||
Reference in New Issue
Block a user