works again
This commit is contained in:
138
README
138
README
@@ -1,33 +1,49 @@
|
||||
Gnuk - A USB Token software implementation
|
||||
Gnuk - software for GPG USB Token
|
||||
|
||||
Version 0.0 2010-09-01
|
||||
Version 0.0 2010-09-05
|
||||
Niibe Yutaka
|
||||
|
||||
What's Gnuk
|
||||
===========
|
||||
|
||||
Gnuk is a USB token software implementation to use with GNU privacy
|
||||
guard. Gnuk supports OpenPGP card protocol version 2, and it runs on
|
||||
Olimex STM32-H103 board.
|
||||
Gnuk is software implementation of a USB token for GNU privacy guard.
|
||||
Gnuk supports OpenPGP card protocol version 2, and it runs on STM32
|
||||
processor.
|
||||
|
||||
|
||||
Release notes
|
||||
=============
|
||||
|
||||
Initially, the development was started with a copy of the files in
|
||||
ChibiOS_2.0.2/demos/ARMCM3-STM32F103-GCC/*, Makefile, linker script,
|
||||
and header files (chconf.h, halconf.h, and mcuconf.h).
|
||||
This is initial release of Gnuk, and it is experimental yet.
|
||||
It is not yet daily use.
|
||||
|
||||
Since this is the initial release, some garbages still remain.
|
||||
Supported and tested features are:
|
||||
|
||||
* Personalization of the card
|
||||
|
||||
* Changing Login name, URL, Name, Sex, Language, etc.
|
||||
|
||||
* Password handling (PW1, RC, PW3)
|
||||
|
||||
* Single key import
|
||||
|
||||
* PSO: Digital Signature
|
||||
|
||||
|
||||
Target
|
||||
======
|
||||
It is known not-working:
|
||||
|
||||
* Multiple key import
|
||||
|
||||
* PSO: Decipher
|
||||
|
||||
|
||||
Targets
|
||||
=======
|
||||
|
||||
We use Olimex STM32-H103 board.
|
||||
|
||||
I think that it runs on Olimex STM32-P103 too. We are porting to
|
||||
STM32 Primer 2.
|
||||
I think that it runs on Olimex STM32-P103, STBee, or STBee mini too.
|
||||
Besides, we are porting it to STM32 Primer 2.
|
||||
|
||||
|
||||
Souce code
|
||||
@@ -49,35 +65,46 @@ External source code
|
||||
Gnuk is distributed with external source code.
|
||||
|
||||
* ChibiOS_2.0.2/ -- ChibiOS/RT 2.0.2
|
||||
Taken from http://chibios.sourceforge.net/
|
||||
Note that CRLF is converted to LF in this repository.
|
||||
We use ChibiOS/RT as the kernel for Gnuk.
|
||||
|
||||
Taken from http://chibios.sourceforge.net/
|
||||
Note that CRLF is converted to LF in this repository.
|
||||
We use ChibiOS/RT as the kernel for Gnuk.
|
||||
|
||||
* polarssl-0.14.0/ -- PolarSSL 0.14.0
|
||||
Taken from http://polarssl.org/
|
||||
We use PolarSSL for RSA computation.
|
||||
|
||||
Taken from http://polarssl.org/
|
||||
We use PolarSSL for RSA computation.
|
||||
|
||||
* STM32_USB-FS-Device_Driver/ -- a part of USB-FS-Device_Lib
|
||||
* Virtual_COM_Port/ -- a part of USB-FS-Device_Lib
|
||||
|
||||
STM32F10x USB Full Speed Device Library (USB-FS-Device_Lib)
|
||||
is a STM32F10x library for USB functionality.
|
||||
STM32F10x USB Full Speed Device Library (USB-FS-Device_Lib)
|
||||
is a STM32F10x library for USB functionality.
|
||||
|
||||
I took Libraries/STM32_USB-FS-Device_Driver and a part of
|
||||
Project/ in STM32_USB-FS-Device_Lib distribution.
|
||||
See http://www.st.com for detail.
|
||||
I took Libraries/STM32_USB-FS-Device_Driver and a part of
|
||||
Project/ in STM32_USB-FS-Device_Lib distribution.
|
||||
See http://www.st.com for detail.
|
||||
|
||||
|
||||
How to compile
|
||||
==============
|
||||
|
||||
You need GNU Toolchain and newlib for 'arm-none-eabi' target.
|
||||
You need GNU toolchain and newlib for 'arm-none-eabi' target.
|
||||
|
||||
See http://github.com/esden/summon-arm-toolchain/ for preparation of
|
||||
GNU Toolchain for 'arm-none-eabi' target.
|
||||
|
||||
$ cd gnuk-VERSION/src
|
||||
|
||||
Edit the Makefile. Comment out the line:
|
||||
----------------
|
||||
ENABLE_DEBUG=1
|
||||
----------------
|
||||
|
||||
if you don't want to debug Gnuk.
|
||||
|
||||
Type:
|
||||
|
||||
$ make
|
||||
|
||||
Then, we will have "gnuk.elf".
|
||||
@@ -99,6 +126,54 @@ Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
|
||||
> exit
|
||||
$
|
||||
|
||||
If you compiled with ENABLE_DEBUG=1, Gnuk has two interfaces
|
||||
(one is CCID/ICCD device and another is virtual COM port). Open
|
||||
virtual COM port by:
|
||||
|
||||
$ cu -l /dev/ttyACM0
|
||||
|
||||
and you will see debug output of Gnuk.
|
||||
|
||||
|
||||
For libccid, we need following change:
|
||||
|
||||
--- /etc/libccid_Info.plist.dpkg-dist 2009-07-29 06:50:20.000000000 +0900
|
||||
+++ /etc/libccid_Info.plist 2010-09-05 09:09:49.000000000 +0900
|
||||
@@ -104,6 +104,7 @@
|
||||
|
||||
<key>ifdVendorID</key>
|
||||
<array>
|
||||
+ <string>0x234B</string>
|
||||
<string>0x08E6</string>
|
||||
<string>0x08E6</string>
|
||||
<string>0x08E6</string>
|
||||
@@ -237,6 +238,7 @@
|
||||
|
||||
<key>ifdProductID</key>
|
||||
<array>
|
||||
+ <string>0x0000</string>
|
||||
<string>0x2202</string>
|
||||
<string>0x3437</string>
|
||||
<string>0x3438</string>
|
||||
@@ -370,6 +372,7 @@
|
||||
|
||||
<key>ifdFriendlyName</key>
|
||||
<array>
|
||||
+ <string>FSIJ USB Token</string>
|
||||
<string>Gemplus Gem e-Seal Pro</string>
|
||||
<string>Gemplus GemPC Twin</string>
|
||||
<string>Gemplus GemPC Key</string>
|
||||
------------------
|
||||
|
||||
|
||||
Then, try following to see Gnuk runs:
|
||||
|
||||
$ gpg --card-status
|
||||
|
||||
|
||||
For more, see doc/HOWTO_GNUK.
|
||||
|
||||
|
||||
|
||||
How to debug
|
||||
============
|
||||
@@ -107,4 +182,19 @@ We can use GDB.
|
||||
|
||||
$ arm-none-eabi-gdb gnuk.elf
|
||||
|
||||
|
||||
Inside GDB, we can connect OpenOCD by:
|
||||
|
||||
(gdb) target remote localhost:3333
|
||||
|
||||
|
||||
|
||||
Development history
|
||||
===================
|
||||
|
||||
Initially, the development was started with a copy of the files in
|
||||
ChibiOS_2.0.2/demos/ARMCM3-STM32F103-GCC/*, Makefile, linker script,
|
||||
and header files (chconf.h, halconf.h, and mcuconf.h).
|
||||
|
||||
Since this is the initial release, some garbages may still remain.
|
||||
--
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# Makefile for Gnuk
|
||||
|
||||
#
|
||||
#
|
||||
ENABLE_DEBUG=1
|
||||
|
||||
@@ -88,10 +87,14 @@ CSRC = $(PORTSRC) \
|
||||
$(STMUSBSRC) \
|
||||
$(VCOMSRC) \
|
||||
$(CRYPTSRC) \
|
||||
main.c debug.c usb_lld.c \
|
||||
main.c usb_lld.c \
|
||||
hw_config.c usb_desc.c usb_prop.c \
|
||||
usb-icc.c openpgp.c ac.c openpgp-do.c flash.c hardclock.c random.c
|
||||
|
||||
ifneq ($(ENABLE_DEBUG),)
|
||||
CSRC += debug.c
|
||||
endif
|
||||
|
||||
# List ASM source files here
|
||||
ASMSRC = $(PORTASM) \
|
||||
$(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s
|
||||
|
||||
22
src/ac.c
22
src/ac.c
@@ -26,7 +26,7 @@ int
|
||||
verify_pso_cds (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
int r;
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
||||
uint8_t keystring[KEYSTRING_SIZE_PW1];
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
@@ -40,13 +40,13 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
|
||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNATURE, 1, keystring+1)) < 0)
|
||||
{
|
||||
pwsb[PW_STATUS_PW1]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
pwsb[PW_STATUS_PW1] = 3;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
|
||||
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
||||
@@ -63,7 +63,7 @@ int
|
||||
verify_pso_other (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
int r;
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
||||
uint8_t keystring[KEYSTRING_SIZE_PW1];
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
@@ -77,13 +77,13 @@ verify_pso_other (const uint8_t *pw, int pw_len)
|
||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPT, 1, keystring+1)) < 0)
|
||||
{
|
||||
pwsb[PW_STATUS_PW1]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
pwsb[PW_STATUS_PW1] = 3;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
|
||||
auth_status |= AC_PSO_OTHER_AUTHORIZED;
|
||||
@@ -131,14 +131,14 @@ int
|
||||
verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
||||
{
|
||||
const uint8_t *pw3_keystring;
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
||||
int pw_len;
|
||||
|
||||
if (pw_status_bytes == NULL
|
||||
|| pw_status_bytes[PW_STATUS_PW3] == 0) /* locked */
|
||||
return 0;
|
||||
|
||||
pw3_keystring = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW3);
|
||||
pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
|
||||
if (pw3_keystring != NULL)
|
||||
{
|
||||
int count;
|
||||
@@ -159,13 +159,13 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
||||
{
|
||||
failure:
|
||||
pwsb[PW_STATUS_PW3]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{ /* OK, the user is now authenticated */
|
||||
pwsb[PW_STATUS_PW3] = 3;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -196,7 +196,7 @@ gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
|
||||
ks[9] = 0x60; /* 65536 iterations */
|
||||
|
||||
calc_md (65536, &ks[1], newpw, newpw_len, &ks[10]);
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
|
||||
}
|
||||
|
||||
uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
|
||||
164
src/call-rsa.c
Normal file
164
src/call-rsa.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
|
||||
*
|
||||
* Copyright (C) 2010 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 "config.h"
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/rsa.h"
|
||||
|
||||
static rsa_context rsa_ctx;
|
||||
|
||||
int
|
||||
rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len)
|
||||
{
|
||||
mpi P1, Q1, H;
|
||||
int r;
|
||||
|
||||
mpi_init (&P1, &Q1, &H, NULL);
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
|
||||
rsa_ctx.len = 2048 / 8;
|
||||
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
||||
mpi_read_binary (&rsa_ctx.P, &kd.data[0], rsa_ctx.len / 2);
|
||||
mpi_read_binary (&rsa_ctx.Q, &kd.data[128], rsa_ctx.len / 2);
|
||||
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
||||
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
||||
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
||||
mpi_mul_mpi (&H, &P1, &Q1);
|
||||
mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H);
|
||||
mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1);
|
||||
mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1);
|
||||
mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P);
|
||||
mpi_free (&P1, &Q1, &H, NULL);
|
||||
|
||||
DEBUG_INFO ("RSA...");
|
||||
|
||||
if ((r = rsa_check_privkey (&rsa_ctx)) == 0)
|
||||
DEBUG_INFO ("ok...");
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("failed.\r\n");
|
||||
DEBUG_SHORT (r);
|
||||
rsa_free (&rsa_ctx);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rsa_pkcs1_sign (&rsa_ctx, RSA_PRIVATE, SIG_RSA_RAW,
|
||||
msg_len, raw_message, output);
|
||||
rsa_free (&rsa_ctx);
|
||||
if (r < 0)
|
||||
{
|
||||
DEBUG_INFO ("fail:");
|
||||
DEBUG_SHORT (r);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
modulus_calc (const uint8_t *p, int len)
|
||||
{
|
||||
mpi P, Q, N;
|
||||
uint8_t *modulus;
|
||||
|
||||
(void)len; /* 2048-bit assumed */
|
||||
modulus = malloc (2048 / 8);
|
||||
if (modulus == NULL)
|
||||
return NULL;
|
||||
|
||||
mpi_init (&P, &Q, &N, NULL);
|
||||
mpi_read_binary (&P, p, 2048 / 8 / 2);
|
||||
mpi_read_binary (&Q, p + 128, 2048 / 8 / 2);
|
||||
mpi_mul_mpi (&N, &P, &Q);
|
||||
|
||||
mpi_write_binary (&N, modulus, 2048 / 8);
|
||||
mpi_free (&P, &Q, &N, NULL);
|
||||
return modulus;
|
||||
}
|
||||
|
||||
void
|
||||
modulus_free (const uint8_t *p)
|
||||
{
|
||||
free ((void *)p);
|
||||
}
|
||||
|
||||
int
|
||||
rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len)
|
||||
{
|
||||
mpi P1, Q1, H;
|
||||
int r;
|
||||
int output_len;
|
||||
|
||||
mpi_init (&P1, &Q1, &H, NULL);
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
|
||||
rsa_ctx.len = msg_len;
|
||||
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
||||
mpi_read_binary (&rsa_ctx.P, &kd.data[0], 2048 / 8 / 2);
|
||||
mpi_read_binary (&rsa_ctx.Q, &kd.data[128], 2048 / 8 / 2);
|
||||
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
||||
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
||||
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
||||
mpi_mul_mpi (&H, &P1, &Q1);
|
||||
mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H);
|
||||
mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1);
|
||||
mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1);
|
||||
mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P);
|
||||
mpi_free (&P1, &Q1, &H, NULL);
|
||||
|
||||
DEBUG_INFO ("RSA...");
|
||||
|
||||
if ((r = rsa_check_privkey (&rsa_ctx)) == 0)
|
||||
DEBUG_INFO ("ok...");
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("failed.\r\n");
|
||||
DEBUG_SHORT (r);
|
||||
rsa_free (&rsa_ctx);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len,
|
||||
input, output, MAX_RES_APDU_SIZE - 2);
|
||||
rsa_free (&rsa_ctx);
|
||||
if (r < 0)
|
||||
{
|
||||
DEBUG_INFO ("fail:");
|
||||
DEBUG_SHORT (r);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
res_APDU[output_len] = 0x90;
|
||||
res_APDU[output_len+1] = 0x00;
|
||||
res_APDU_size = output_len + 2;
|
||||
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -18,14 +18,14 @@
|
||||
#define CH_USE_CONDVARS_TIMEOUT TRUE
|
||||
#define CH_USE_EVENTS TRUE /* We use this! */
|
||||
#define CH_USE_EVENTS_TIMEOUT TRUE /* We use this! */
|
||||
#define CH_USE_MESSAGES TRUE
|
||||
#define CH_USE_MESSAGES FALSE
|
||||
#define CH_USE_MESSAGES_PRIORITY FALSE
|
||||
#define CH_USE_MAILBOXES FALSE
|
||||
#define CH_USE_QUEUES FALSE
|
||||
#define CH_USE_MEMCORE TRUE
|
||||
#define CH_USE_HEAP TRUE
|
||||
#define CH_USE_MALLOC_HEAP FALSE
|
||||
#define CH_USE_MEMPOOLS TRUE
|
||||
#define CH_USE_MEMPOOLS FALSE
|
||||
#define CH_USE_DYNAMIC FALSE
|
||||
|
||||
/* Debug options */
|
||||
|
||||
@@ -3,4 +3,4 @@ CRYPTSRCDIR = $(CRYPTDIR)/library
|
||||
CRYPTINCDIR = $(CRYPTDIR)/include
|
||||
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/sha1.c \
|
||||
$(CRYPTSRCDIR)/aes.c \
|
||||
rsa-sign.c
|
||||
call-rsa.c
|
||||
|
||||
14
src/debug.c
14
src/debug.c
@@ -64,6 +64,20 @@ put_short (uint16_t x)
|
||||
_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);
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
|
||||
void
|
||||
put_binary (const char *s, int len)
|
||||
{
|
||||
|
||||
282
src/flash.c
282
src/flash.c
@@ -22,90 +22,288 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Writing to Flash ROM is NOT YET IMPLEMENTED, just API only
|
||||
* Note: Garbage collection and page management with flash erase
|
||||
* is *NOT YET* implemented
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
static uint8_t do_pool[256];
|
||||
static uint8_t *last_p = do_pool;
|
||||
#define FLASH_KEY1 0x45670123UL
|
||||
#define FLASH_KEY2 0xCDEF89ABUL
|
||||
|
||||
enum flash_status
|
||||
{
|
||||
FLASH_BUSY = 1,
|
||||
FLASH_ERROR_PG,
|
||||
FLASH_ERROR_WRP,
|
||||
FLASH_COMPLETE,
|
||||
FLASH_TIMEOUT
|
||||
};
|
||||
|
||||
static void
|
||||
flash_unlock (void)
|
||||
{
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
FLASH->KEYR = FLASH_KEY2;
|
||||
}
|
||||
|
||||
static int
|
||||
flash_get_status (void)
|
||||
{
|
||||
int status;
|
||||
|
||||
if ((FLASH->SR & FLASH_SR_BSY) != 0)
|
||||
status = FLASH_BUSY;
|
||||
else if ((FLASH->SR & FLASH_SR_PGERR) != 0)
|
||||
status = FLASH_ERROR_PG;
|
||||
else if((FLASH->SR & FLASH_SR_WRPRTERR) != 0 )
|
||||
status = FLASH_ERROR_WRP;
|
||||
else
|
||||
status = FLASH_COMPLETE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
flash_wait_for_last_operation (uint32_t timeout)
|
||||
{
|
||||
int status;
|
||||
|
||||
do
|
||||
if (--timeout == 0)
|
||||
return FLASH_TIMEOUT;
|
||||
else
|
||||
status = flash_get_status ();
|
||||
while (status == FLASH_BUSY);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#define FLASH_PROGRAM_TIMEOUT 0x10000
|
||||
|
||||
static int
|
||||
flash_program_halfword (uint32_t addr, uint16_t data)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT);
|
||||
|
||||
chSysLock ();
|
||||
if (status == FLASH_COMPLETE)
|
||||
{
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
|
||||
*(volatile uint16_t *)addr = data;
|
||||
|
||||
status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT);
|
||||
if (status != FLASH_TIMEOUT)
|
||||
FLASH->CR &= ~FLASH_CR_PG;
|
||||
}
|
||||
chSysUnlock ();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* TLV (Tag, Length, and Value)
|
||||
* Flash memory map
|
||||
*
|
||||
* _text
|
||||
* .text
|
||||
* .ctors
|
||||
* .dtors
|
||||
* _etext
|
||||
* .data
|
||||
* ...
|
||||
* _etext + (_edata - _data)
|
||||
*
|
||||
* 1-KiB align padding
|
||||
*
|
||||
* 1-KiB DO pool * 3
|
||||
*
|
||||
* 3-KiB Key store (512-byte (p, q and N) key-store * 6)
|
||||
*/
|
||||
|
||||
static const uint8_t *do_pool;
|
||||
static const uint8_t *keystore_pool;
|
||||
|
||||
static const uint8_t *last_p;
|
||||
static const uint8_t *keystore;
|
||||
|
||||
const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
||||
0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
void
|
||||
flash_init (void)
|
||||
{
|
||||
const uint8_t *p;
|
||||
extern uint8_t _do_pool;
|
||||
extern uint8_t _keystore_pool;
|
||||
|
||||
do_pool = &_do_pool;
|
||||
keystore_pool = &_keystore_pool;
|
||||
|
||||
/* Seek empty keystore */
|
||||
p = keystore_pool;
|
||||
while (*p != 0xff || *(p+1) != 0xff)
|
||||
p += 512;
|
||||
|
||||
keystore = p;
|
||||
|
||||
flash_unlock ();
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
flash_do_write (uint16_t tag, const uint8_t *data, int len)
|
||||
flash_do_pool (void)
|
||||
{
|
||||
return do_pool;
|
||||
}
|
||||
|
||||
void
|
||||
flash_set_do_pool_last (const uint8_t *p)
|
||||
{
|
||||
last_p = p;
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
flash_do_write (uint8_t nr, const uint8_t *data, int len)
|
||||
{
|
||||
const uint8_t *p = last_p;
|
||||
uint16_t hw;
|
||||
uint32_t addr;
|
||||
int state = 0;
|
||||
int i;
|
||||
|
||||
if (last_p - do_pool + len + 2 + 3 > 1024)
|
||||
if (last_p - do_pool + len + 2 + 3 > 1024*3)
|
||||
return NULL;
|
||||
|
||||
*last_p++ = (tag >> 8);
|
||||
*last_p++ = (tag & 0xff);
|
||||
DEBUG_INFO ("flash DO\r\n");
|
||||
|
||||
addr = (uint32_t)last_p;
|
||||
hw = nr | (0xff << 8);
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return NULL;
|
||||
addr += 2;
|
||||
|
||||
if (len < 128)
|
||||
*last_p++ = len;
|
||||
{
|
||||
hw = len;
|
||||
state = 1;
|
||||
}
|
||||
else if (len < 256)
|
||||
{
|
||||
*last_p++ = 0x81;
|
||||
*last_p++ = len;
|
||||
hw = 0x81 | (len << 8);
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return NULL;
|
||||
addr += 2;
|
||||
state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*last_p++ = 0x82;
|
||||
*last_p++ = (len >> 8);
|
||||
*last_p++ = (len & 0xff);
|
||||
hw = 0x82 | ((len >> 8) << 8);
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return NULL;
|
||||
addr += 2;
|
||||
hw = (len & 0xff);
|
||||
state = 1;
|
||||
}
|
||||
memcpy (last_p, data, len);
|
||||
last_p += len;
|
||||
|
||||
if (state == 0)
|
||||
{
|
||||
for (i = 0; i < len/2; i ++)
|
||||
{
|
||||
hw = data[i*2] | (data[i*2+1]<<8);
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return NULL;
|
||||
addr += 2;
|
||||
}
|
||||
|
||||
if ((len & 1))
|
||||
{
|
||||
hw = data[i*2] | 0xff00;
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return NULL;
|
||||
addr += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hw |= data[0]<<8;
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return NULL;
|
||||
addr += 2;
|
||||
|
||||
for (i = 0; i < (len - 1)/2; i ++)
|
||||
{
|
||||
hw = data[i*2+1] | (data[i*2+2]<<8);
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return NULL;
|
||||
addr += 2;
|
||||
}
|
||||
|
||||
if (((len - 1) & 1))
|
||||
{
|
||||
hw = data[i*2+1] | 0xff00;
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return NULL;
|
||||
addr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
last_p = (const uint8_t *)addr;
|
||||
|
||||
DEBUG_INFO ("flash DO...done\r\n");
|
||||
return p + 2;
|
||||
}
|
||||
|
||||
void
|
||||
flash_do_release (const uint8_t *data)
|
||||
flash_do_release (const uint8_t *data_p)
|
||||
{
|
||||
(void)data;/*XXX*/
|
||||
(void)data_p;
|
||||
}
|
||||
|
||||
static uint8_t k1[KEY_CONTENT_LEN*2]; /* p, q and N */
|
||||
#if 0
|
||||
static uint8_t k2[KEY_CONTENT_LEN*2];
|
||||
static uint8_t k3[KEY_CONTENT_LEN*2];
|
||||
#endif
|
||||
|
||||
uint8_t *
|
||||
flash_key_alloc (enum kind_of_key kk)
|
||||
flash_key_alloc (void)
|
||||
{
|
||||
switch (kk)
|
||||
{
|
||||
case GPG_KEY_FOR_SIGNATURE:
|
||||
return k1;
|
||||
#if 0
|
||||
case GPG_KEY_FOR_DECRYPT:
|
||||
return k2;
|
||||
case GPG_KEY_FOR_AUTHENTICATION:
|
||||
return k3;
|
||||
#else
|
||||
default:
|
||||
return k1;
|
||||
#endif
|
||||
}
|
||||
uint8_t *k = (uint8_t *)keystore;
|
||||
|
||||
keystore += 512;
|
||||
return k;
|
||||
}
|
||||
|
||||
int
|
||||
flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
|
||||
const uint8_t *modulus)
|
||||
{
|
||||
memcpy (key_addr, key_data, KEY_CONTENT_LEN);
|
||||
memcpy (key_addr+KEY_CONTENT_LEN, modulus, KEY_CONTENT_LEN);
|
||||
uint16_t hw;
|
||||
uint32_t addr;
|
||||
int i;
|
||||
|
||||
addr = (uint32_t)key_addr;
|
||||
for (i = 0; i < KEY_CONTENT_LEN/2; i ++)
|
||||
{
|
||||
hw = key_data[i*2] | (key_data[i*2+1]<<8);
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return -1;
|
||||
addr += 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < KEY_CONTENT_LEN/2; i ++)
|
||||
{
|
||||
hw = modulus[i*2] | (modulus[i*2+1]<<8);
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return -1;
|
||||
addr += 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
flash_key_release (const uint8_t *key_addr)
|
||||
{
|
||||
(void)key_addr; /*XXX*/
|
||||
(void)key_addr;
|
||||
}
|
||||
|
||||
57
src/gnuk.h
57
src/gnuk.h
@@ -3,11 +3,16 @@ extern Thread *blinker_thread;
|
||||
extern void put_byte (uint8_t b);
|
||||
extern void put_byte_with_no_nl (uint8_t b);
|
||||
extern void put_short (uint16_t x);
|
||||
extern void put_word (uint32_t x);
|
||||
extern void put_string (const char *s);
|
||||
extern void put_binary (const char *s, int len);
|
||||
|
||||
extern void _write (const char *, int);
|
||||
|
||||
/*
|
||||
* We declare some of libc functions here, because we will
|
||||
* remove dependency on libc in future.
|
||||
*/
|
||||
extern size_t strlen (const char *s);
|
||||
extern int strncmp(const char *s1, const char *s2, size_t n);
|
||||
extern void *memcpy (void *dest, const void *src, size_t n);
|
||||
@@ -68,10 +73,13 @@ enum kind_of_key {
|
||||
GPG_KEY_FOR_AUTHENTICATION,
|
||||
};
|
||||
|
||||
extern void flash_init (void);
|
||||
extern void flash_do_release (const uint8_t *);
|
||||
extern const uint8_t *flash_do_write (uint16_t tag, const uint8_t *data, int len);
|
||||
extern uint8_t *flash_key_alloc (enum kind_of_key);
|
||||
extern const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
|
||||
extern uint8_t *flash_key_alloc (void);
|
||||
extern void flash_key_release (const uint8_t *);
|
||||
extern const uint8_t *flash_do_pool (void);
|
||||
extern void flash_set_do_pool_last (const uint8_t *p);
|
||||
|
||||
#define KEY_MAGIC_LEN 8
|
||||
#define KEY_CONTENT_LEN 256 /* p and q */
|
||||
@@ -118,11 +126,13 @@ extern struct key_data kd;
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_INFO(msg) put_string (msg)
|
||||
#define DEBUG_WORD(w) put_word (w)
|
||||
#define DEBUG_SHORT(h) put_short (h)
|
||||
#define DEBUG_BYTE(b) put_byte (b)
|
||||
#define DEBUG_BINARY(s,len) put_binary ((const char *)s,len)
|
||||
#else
|
||||
#define DEBUG_INFO(msg)
|
||||
#define DEBUG_WORD(w)
|
||||
#define DEBUG_SHORT(h)
|
||||
#define DEBUG_BYTE(b)
|
||||
#define DEBUG_BINARY(s,len)
|
||||
@@ -131,11 +141,12 @@ extern struct key_data kd;
|
||||
extern int rsa_sign (const uint8_t *, uint8_t *, int);
|
||||
extern const uint8_t *modulus_calc (const uint8_t *, int);
|
||||
extern void modulus_free (const uint8_t *);
|
||||
extern int rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len);
|
||||
|
||||
extern int gpg_do_write_privkey (enum kind_of_key kk, const uint8_t *key_data, int key_len);
|
||||
extern int gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, const uint8_t *keystring);
|
||||
|
||||
extern const uint8_t *gpg_do_read_simple (uint16_t);
|
||||
extern void gpg_do_write_simple (uint16_t, const uint8_t *, int);
|
||||
extern const uint8_t *gpg_do_read_simple (uint8_t);
|
||||
extern void gpg_do_write_simple (uint8_t, const uint8_t *, int);
|
||||
extern void gpg_do_increment_digital_signature_counter (void);
|
||||
|
||||
#define PW_STATUS_PW1 4
|
||||
@@ -144,21 +155,37 @@ extern void gpg_do_increment_digital_signature_counter (void);
|
||||
|
||||
|
||||
extern void gpg_set_pw3 (const uint8_t *newpw, int newpw_len);
|
||||
extern void fatal (void);
|
||||
extern void fatal (void) __attribute__ ((noreturn));
|
||||
|
||||
extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
|
||||
#define GNUK_DO_PRVKEY_SIG 0xff01
|
||||
#define GNUK_DO_PRVKEY_DEC 0xff02
|
||||
#define GNUK_DO_PRVKEY_AUT 0xff03
|
||||
#define GNUK_DO_KEYSTRING_PW1 0xff04
|
||||
#define GNUK_DO_KEYSTRING_RC 0xff05
|
||||
#define GNUK_DO_KEYSTRING_PW3 0xff06
|
||||
#define GNUK_DO_PW_STATUS 0xff07
|
||||
#define NR_DO_PRVKEY_SIG 0
|
||||
#define NR_DO_PRVKEY_DEC 1
|
||||
#define NR_DO_PRVKEY_AUT 2
|
||||
#define NR_DO_KEYSTRING_PW1 3
|
||||
#define NR_DO_KEYSTRING_RC 4
|
||||
#define NR_DO_KEYSTRING_PW3 5
|
||||
#define NR_DO_PW_STATUS 6
|
||||
#define NR_DO_DS_COUNT 7
|
||||
#define NR_DO_SEX 8
|
||||
#define NR_DO_FP_SIG 9
|
||||
#define NR_DO_FP_DEC 10
|
||||
#define NR_DO_FP_AUT 11
|
||||
#define NR_DO_CAFP_1 12
|
||||
#define NR_DO_CAFP_2 13
|
||||
#define NR_DO_CAFP_3 14
|
||||
#define NR_DO_KGTIME_SIG 15
|
||||
#define NR_DO_KGTIME_DEC 16
|
||||
#define NR_DO_KGTIME_AUT 17
|
||||
#define NR_DO_LOGIN_DATA 18
|
||||
#define NR_DO_URL 19
|
||||
#define NR_DO_NAME 20
|
||||
#define NR_DO_LANGUAGE 21
|
||||
#define NR_DO_CH_CERTIFICATE 22
|
||||
|
||||
#define SIZE_PW_STATUS_BYTES 7
|
||||
|
||||
/* 16-byte random bytes */
|
||||
extern uint8_t *get_data_encryption_key (void);
|
||||
extern uint8_t *get_data_encryption_key (void); /* 16-byte random bytes */
|
||||
extern void dek_free (uint8_t *);
|
||||
extern uint32_t get_random (void);
|
||||
extern void random_init (void);
|
||||
|
||||
20
src/gnuk.ld
20
src/gnuk.ld
@@ -110,11 +110,23 @@ SECTIONS
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_bss_end = .;
|
||||
} > ram
|
||||
}
|
||||
} > ram
|
||||
|
||||
PROVIDE(end = .);
|
||||
_end = .;
|
||||
PROVIDE(end = .);
|
||||
_end = .;
|
||||
|
||||
.gnuk_flash : ALIGN (1024)
|
||||
{
|
||||
_do_pool = .;
|
||||
KEEP(*(.gnuk_data))
|
||||
FILL(0xffffffff);
|
||||
. = ALIGN(1024);
|
||||
. += 1024*2;
|
||||
_keystore_pool = .;
|
||||
FILL(0xffffffff);
|
||||
. += 1024*3;
|
||||
} > flash
|
||||
}
|
||||
|
||||
__heap_base__ = _end;
|
||||
__heap_end__ = __ram_end__ - __stacks_total_size__;
|
||||
|
||||
10
src/main.c
10
src/main.c
@@ -173,12 +173,14 @@ main (int argc, char **argv)
|
||||
{
|
||||
eventmask_t m;
|
||||
int count = 0;
|
||||
uint8_t once = 0;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
blinker_thread = chThdSelf ();
|
||||
|
||||
flash_init ();
|
||||
gpg_do_table_init ();
|
||||
|
||||
usb_lld_init ();
|
||||
@@ -198,7 +200,8 @@ main (int argc, char **argv)
|
||||
|
||||
while (1)
|
||||
{
|
||||
uint8_t once = 0;
|
||||
uint32_t r;
|
||||
|
||||
#if 0
|
||||
if (palReadPad(IOPORT1, GPIOA_BUTTON))
|
||||
palSetPad (IOPORT3, GPIOC_LED);
|
||||
@@ -212,14 +215,15 @@ main (int argc, char **argv)
|
||||
{
|
||||
random_init ();
|
||||
once = 1;
|
||||
r = get_random ();
|
||||
DEBUG_WORD (r);
|
||||
}
|
||||
|
||||
if (bDeviceState == CONFIGURED && (count % 100) == 0)
|
||||
{
|
||||
uint32_t r;
|
||||
r = get_random ();
|
||||
|
||||
DEBUG_SHORT (r);
|
||||
DEBUG_WORD (r);
|
||||
_write ("\r\nThis is ChibiOS 2.0.2 on Olimex STM32-H103.\r\n"
|
||||
"Testing USB driver.\n\n"
|
||||
"Hello world\r\n\r\n", 47+21+15);
|
||||
|
||||
228
src/openpgp-do.c
228
src/openpgp-do.c
@@ -124,6 +124,13 @@ static int with_tag;
|
||||
static void copy_do_1 (uint16_t tag, const uint8_t *do_data);
|
||||
static const struct do_table_entry *get_do_entry (uint16_t tag);
|
||||
|
||||
#define GNUK_DO_PRVKEY_SIG 0xff01
|
||||
#define GNUK_DO_PRVKEY_DEC 0xff02
|
||||
#define GNUK_DO_PRVKEY_AUT 0xff03
|
||||
#define GNUK_DO_KEYSTRING_PW1 0xff04
|
||||
#define GNUK_DO_KEYSTRING_RC 0xff05
|
||||
#define GNUK_DO_KEYSTRING_PW3 0xff06
|
||||
#define GNUK_DO_PW_STATUS 0xff07
|
||||
#define GPG_DO_AID 0x004f
|
||||
#define GPG_DO_NAME 0x005b
|
||||
#define GPG_DO_LOGIN_DATA 0x005e
|
||||
@@ -159,29 +166,62 @@ static const struct do_table_entry *get_do_entry (uint16_t tag);
|
||||
|
||||
#define NUM_DO_OBJS 23
|
||||
static const uint8_t *do_ptr[NUM_DO_OBJS];
|
||||
#define NR_DO_PRVKEY_SIG 0
|
||||
#define NR_DO_PRVKEY_DEC 1
|
||||
#define NR_DO_PRVKEY_AUT 2
|
||||
#define NR_DO_KEYSTRING_PW1 3
|
||||
#define NR_DO_KEYSTRING_RC 4
|
||||
#define NR_DO_KEYSTRING_PW3 5
|
||||
#define NR_DO_PW_STATUS 6
|
||||
#define NR_DO_DS_COUNT 7
|
||||
#define NR_DO_SEX 8
|
||||
#define NR_DO_FP_SIG 9
|
||||
#define NR_DO_FP_DEC 10
|
||||
#define NR_DO_FP_AUT 11
|
||||
#define NR_DO_CAFP_1 12
|
||||
#define NR_DO_CAFP_2 13
|
||||
#define NR_DO_CAFP_3 14
|
||||
#define NR_DO_KGTIME_SIG 15
|
||||
#define NR_DO_KGTIME_DEC 16
|
||||
#define NR_DO_KGTIME_AUT 17
|
||||
#define NR_DO_LOGIN_DATA 18
|
||||
#define NR_DO_URL 19
|
||||
#define NR_DO_NAME 20
|
||||
#define NR_DO_LANGUAGE 21
|
||||
#define NR_DO_CH_CERTIFICATE 22
|
||||
|
||||
static uint8_t
|
||||
do_tag_to_nr (uint16_t tag)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case GNUK_DO_PRVKEY_SIG:
|
||||
return NR_DO_PRVKEY_SIG;
|
||||
case GNUK_DO_PRVKEY_DEC:
|
||||
return NR_DO_PRVKEY_DEC;
|
||||
case GNUK_DO_PRVKEY_AUT:
|
||||
return NR_DO_PRVKEY_AUT;
|
||||
case GNUK_DO_KEYSTRING_PW1:
|
||||
return NR_DO_KEYSTRING_PW1;
|
||||
case GNUK_DO_KEYSTRING_RC:
|
||||
return NR_DO_KEYSTRING_RC;
|
||||
case GNUK_DO_KEYSTRING_PW3:
|
||||
return NR_DO_KEYSTRING_PW3;
|
||||
case GNUK_DO_PW_STATUS:
|
||||
return NR_DO_PW_STATUS;
|
||||
case GPG_DO_DS_COUNT:
|
||||
return NR_DO_DS_COUNT;
|
||||
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_CH_CERTIFICATE:
|
||||
return NR_DO_CH_CERTIFICATE;
|
||||
default:
|
||||
fatal ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copy_tag (uint16_t tag)
|
||||
@@ -218,21 +258,21 @@ do_fp_all (uint16_t tag)
|
||||
*res_p++ = SIZE_FP*3;
|
||||
}
|
||||
|
||||
data = gpg_do_read_simple (GPG_DO_FP_SIG);
|
||||
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 (GPG_DO_FP_DEC);
|
||||
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 (GPG_DO_FP_AUT);
|
||||
data = gpg_do_read_simple (NR_DO_FP_AUT);
|
||||
if (data)
|
||||
memcpy (res_p, data, SIZE_FP);
|
||||
else
|
||||
@@ -253,21 +293,21 @@ do_cafp_all (uint16_t tag)
|
||||
*res_p++ = SIZE_FP*3;
|
||||
}
|
||||
|
||||
data = gpg_do_read_simple (GPG_DO_CAFP_1);
|
||||
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 (GPG_DO_CAFP_2);
|
||||
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 (GPG_DO_CAFP_2);
|
||||
data = gpg_do_read_simple (NR_DO_CAFP_2);
|
||||
if (data)
|
||||
memcpy (res_p, data, SIZE_FP);
|
||||
else
|
||||
@@ -288,21 +328,21 @@ do_kgtime_all (uint16_t tag)
|
||||
*res_p++ = SIZE_KGTIME*3;
|
||||
}
|
||||
|
||||
data = gpg_do_read_simple (GPG_DO_KGTIME_SIG);
|
||||
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 (GPG_DO_KGTIME_DEC);
|
||||
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 (GPG_DO_KGTIME_AUT);
|
||||
data = gpg_do_read_simple (NR_DO_KGTIME_AUT);
|
||||
if (data)
|
||||
memcpy (res_p, data, SIZE_KGTIME);
|
||||
else
|
||||
@@ -331,7 +371,7 @@ rw_pw_status (uint16_t tag, const uint8_t *data, int len, int is_write)
|
||||
|
||||
pwsb[0] = data[0];
|
||||
do_ptr[NR_DO_PW_STATUS]
|
||||
= flash_do_write (tag, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
= flash_do_write (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
if (do_ptr[NR_DO_PW_STATUS])
|
||||
GPG_SUCCESS ();
|
||||
else
|
||||
@@ -372,6 +412,8 @@ proc_resetting_code (const uint8_t *data, int len)
|
||||
int newpw_len;
|
||||
int r;
|
||||
|
||||
DEBUG_INFO ("Resetting Code!\r\n");
|
||||
|
||||
newpw_len = len;
|
||||
newpw = data;
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
@@ -379,18 +421,27 @@ proc_resetting_code (const uint8_t *data, int len)
|
||||
r = gpg_change_keystring (3, old_ks, 2, new_ks);
|
||||
if (r < -2)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
GPG_MEMORY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
else if (r < 0)
|
||||
{
|
||||
DEBUG_INFO ("security error.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
else if (r == 0)
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_RC, new_ks0, KEYSTRING_SIZE_RC);
|
||||
{
|
||||
DEBUG_INFO ("done (no prvkey).\r\n");
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KEYSTRING_SIZE_RC);
|
||||
}
|
||||
else
|
||||
GPG_SUCCESS ();
|
||||
{
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, 1);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
|
||||
/* Reset RC counter in GNUK_DO_PW_STATUS */
|
||||
gpg_do_reset_pw_counter (PW_STATUS_RC);
|
||||
@@ -422,21 +473,6 @@ decrypt (const uint8_t *key_str, uint8_t *data, int len)
|
||||
DEBUG_BINARY (data, len);
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
get_tag_for_kk (enum kind_of_key kk)
|
||||
{
|
||||
switch (kk)
|
||||
{
|
||||
case GPG_KEY_FOR_SIGNATURE:
|
||||
return GNUK_DO_PRVKEY_SIG;
|
||||
case GPG_KEY_FOR_DECRYPT:
|
||||
return GNUK_DO_PRVKEY_DEC;
|
||||
case GPG_KEY_FOR_AUTHENTICATION:
|
||||
return GNUK_DO_PRVKEY_AUT;
|
||||
}
|
||||
return GNUK_DO_PRVKEY_SIG;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
get_do_ptr_nr_for_kk (enum kind_of_key kk)
|
||||
{
|
||||
@@ -476,7 +512,10 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
|
||||
decrypt (keystring, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
decrypt (dek, (uint8_t *)&kd, sizeof (struct key_data));
|
||||
if (memcmp (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN) != 0)
|
||||
return -1;
|
||||
{
|
||||
DEBUG_INFO ("gpg_do_load_prvkey failed.\r\n");
|
||||
return -1;
|
||||
}
|
||||
/* XXX: more sanity check */
|
||||
return 1;
|
||||
}
|
||||
@@ -498,7 +537,6 @@ int
|
||||
gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
const uint8_t *keystring)
|
||||
{
|
||||
uint16_t tag = get_tag_for_kk (kk);
|
||||
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
||||
const uint8_t *p;
|
||||
int r;
|
||||
@@ -506,13 +544,14 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
struct prvkey_data *pd;
|
||||
uint8_t *key_addr;
|
||||
uint8_t *dek;
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW1);
|
||||
const uint8_t *ks_rc = gpg_do_read_simple (GNUK_DO_KEYSTRING_RC);
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
||||
|
||||
#if 0
|
||||
assert (key_len == KEY_CONTENT_LEN);
|
||||
#endif
|
||||
|
||||
DEBUG_INFO ("Key import\r\n");
|
||||
DEBUG_SHORT (key_len);
|
||||
|
||||
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
|
||||
@@ -526,7 +565,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
return -1;
|
||||
}
|
||||
|
||||
key_addr = flash_key_alloc (kk);
|
||||
DEBUG_INFO ("Getting keystore address...\r\n");
|
||||
key_addr = flash_key_alloc ();
|
||||
if (key_addr == NULL)
|
||||
{
|
||||
free (pd);
|
||||
@@ -534,6 +574,9 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_INFO ("key_addr: ");
|
||||
DEBUG_WORD ((uint32_t)key_addr);
|
||||
|
||||
memcpy (kd.data, key_data, KEY_CONTENT_LEN);
|
||||
kd.check = calc_check32 (key_data, KEY_CONTENT_LEN);
|
||||
kd.random = get_random ();
|
||||
@@ -565,7 +608,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
encrypt (ks_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
|
||||
/* Only its length */
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, ks_pw1, 1);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, ks_pw1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -576,7 +619,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
|
||||
/* Only but its length */
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, ks123_pw1, 1);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, ks123_pw1, 1);
|
||||
}
|
||||
|
||||
if (ks_rc)
|
||||
@@ -584,7 +627,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
encrypt (ks_rc+1, pd->dek_encrypted_2, DATA_ENCRYPTION_KEY_SIZE);
|
||||
/* Only its length */
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_RC, ks_rc, 1);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_RC, ks_rc, 1);
|
||||
}
|
||||
else
|
||||
memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE);
|
||||
@@ -592,7 +635,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
encrypt (keystring, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
p = flash_do_write (tag, (const uint8_t *)pd, sizeof (struct prvkey_data));
|
||||
p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
|
||||
do_ptr[nr] = p;
|
||||
|
||||
dek_free (dek);
|
||||
@@ -608,7 +651,6 @@ 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)
|
||||
{
|
||||
uint16_t tag = get_tag_for_kk (kk);
|
||||
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];
|
||||
@@ -631,7 +673,7 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
|
||||
dek_p += DATA_ENCRYPTION_KEY_SIZE * (who_new - who_old);
|
||||
memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
p = flash_do_write (tag, (const uint8_t *)pd, sizeof (struct prvkey_data));
|
||||
p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
|
||||
do_ptr[nr] = p;
|
||||
|
||||
free (pd);
|
||||
@@ -770,12 +812,48 @@ gpg_do_table[] = {
|
||||
#define NUM_DO_ENTRIES (int)(sizeof (gpg_do_table) / sizeof (struct do_table_entry))
|
||||
|
||||
/*
|
||||
* Initialize GPG_DO_TABLE reading from Flash ROM
|
||||
* Initialize DO_PTR reading from Flash ROM
|
||||
*/
|
||||
int
|
||||
gpg_do_table_init (void)
|
||||
{
|
||||
const uint8_t *p, *p_start;
|
||||
int len;
|
||||
|
||||
do_ptr[NR_DO_PW_STATUS] = do_pw_status_bytes_template;
|
||||
p_start = flash_do_pool ();
|
||||
|
||||
/* Traverse DO pool */
|
||||
p = p_start;
|
||||
while (*p != 0xff)
|
||||
{
|
||||
uint8_t nr = *p++;
|
||||
uint8_t check = *p++;
|
||||
|
||||
if (check == 0xff)
|
||||
do_ptr[nr] = p;
|
||||
|
||||
if (*p < 128)
|
||||
len = *p++;
|
||||
else if (*p == 0x81)
|
||||
{
|
||||
p++;
|
||||
len = *p++;
|
||||
}
|
||||
else /* 0x82 */
|
||||
{
|
||||
p++;
|
||||
len = (*p << 8) + *(p+1);
|
||||
p += 2;
|
||||
}
|
||||
|
||||
p += len;
|
||||
if (((uint32_t)p & 1))
|
||||
p++;
|
||||
}
|
||||
|
||||
flash_set_do_pool_last (p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -972,7 +1050,9 @@ gpg_do_put_data (uint16_t tag, const uint8_t *data, int len)
|
||||
*do_data_p = NULL;
|
||||
else
|
||||
{
|
||||
*do_data_p = flash_do_write (tag, data, len);
|
||||
uint8_t nr = do_tag_to_nr (tag);
|
||||
|
||||
*do_data_p = flash_do_write (nr, data, len);
|
||||
if (*do_data_p)
|
||||
GPG_SUCCESS ();
|
||||
else
|
||||
@@ -1008,6 +1088,8 @@ gpg_do_public_key (uint8_t kk_byte)
|
||||
const uint8_t *do_data;
|
||||
uint8_t *key_addr;
|
||||
|
||||
DEBUG_INFO ("Public key\r\n");
|
||||
|
||||
if (kk_byte == 0xb6)
|
||||
do_data = do_ptr[NR_DO_PRVKEY_SIG];
|
||||
else if (kk_byte == 0xb8)
|
||||
@@ -1017,6 +1099,7 @@ gpg_do_public_key (uint8_t kk_byte)
|
||||
|
||||
if (do_data == NULL)
|
||||
{
|
||||
DEBUG_INFO ("none.\r\n");
|
||||
GPG_NO_RECORD();
|
||||
return;
|
||||
}
|
||||
@@ -1048,17 +1131,16 @@ gpg_do_public_key (uint8_t kk_byte)
|
||||
res_APDU_size = res_p - res_APDU;
|
||||
}
|
||||
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
gpg_do_read_simple (uint16_t tag)
|
||||
gpg_do_read_simple (uint8_t nr)
|
||||
{
|
||||
const struct do_table_entry *do_p;
|
||||
const uint8_t *do_data;
|
||||
|
||||
do_p = get_do_entry (tag);
|
||||
do_data = *((const uint8_t **)do_p->obj);
|
||||
do_data = do_ptr[nr];
|
||||
if (do_data == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -1071,17 +1153,15 @@ gpg_do_read_simple (uint16_t tag)
|
||||
}
|
||||
|
||||
void
|
||||
gpg_do_write_simple (uint16_t tag, const uint8_t *data, int size)
|
||||
gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
|
||||
{
|
||||
const struct do_table_entry *do_p;
|
||||
const uint8_t **do_data_p;
|
||||
|
||||
do_p = get_do_entry (tag);
|
||||
do_data_p = (const uint8_t **)do_p->obj;
|
||||
do_data_p = (const uint8_t **)&do_ptr[nr];
|
||||
if (*do_data_p)
|
||||
flash_do_release (*do_data_p);
|
||||
|
||||
*do_data_p = flash_do_write (tag, data, size);
|
||||
*do_data_p = flash_do_write (nr, data, size);
|
||||
if (*do_data_p)
|
||||
GPG_SUCCESS ();
|
||||
else
|
||||
@@ -1106,7 +1186,7 @@ gpg_do_increment_digital_signature_counter (void)
|
||||
count_data[1] = (count >> 8) & 0xff;
|
||||
count_data[2] = count & 0xff;
|
||||
|
||||
do_ptr[NR_DO_DS_COUNT] = flash_do_write (GPG_DO_DS_COUNT, count_data,
|
||||
do_ptr[NR_DO_DS_COUNT] = flash_do_write (NR_DO_DS_COUNT, count_data,
|
||||
SIZE_DIGITAL_SIGNATURE_COUNTER);
|
||||
}
|
||||
|
||||
@@ -1129,5 +1209,5 @@ gpg_do_reset_pw_counter (uint8_t which)
|
||||
pwsb[which] = 3;
|
||||
}
|
||||
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
|
||||
125
src/openpgp.c
125
src/openpgp.c
@@ -61,7 +61,7 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = {
|
||||
};
|
||||
|
||||
static const uint8_t const
|
||||
get_data_rb_result[] __attribute__ ((aligned (1))) = {
|
||||
read_binary_result[] __attribute__ ((aligned (1))) = {
|
||||
0x5a, 0x4, 0x01, 0x02, 0x03, 0x04
|
||||
};
|
||||
|
||||
@@ -91,6 +91,7 @@ cmd_verify (void)
|
||||
int r;
|
||||
|
||||
DEBUG_INFO (" - VERIFY\r\n");
|
||||
DEBUG_BYTE (p2);
|
||||
|
||||
len = cmd_APDU[4];
|
||||
if (p2 == 0x81)
|
||||
@@ -101,11 +102,20 @@ cmd_verify (void)
|
||||
r = verify_admin (&cmd_APDU[5], len);
|
||||
|
||||
if (r < 0)
|
||||
GPG_SECURITY_FAILURE ();
|
||||
{
|
||||
DEBUG_INFO ("failed\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
}
|
||||
else if (r == 0)
|
||||
GPG_SECURITY_AUTH_BLOCKED ();
|
||||
{
|
||||
DEBUG_INFO ("blocked\r\n");
|
||||
GPG_SECURITY_AUTH_BLOCKED ();
|
||||
}
|
||||
else
|
||||
GPG_SUCCESS ();
|
||||
{
|
||||
DEBUG_INFO ("good\r\n");
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
@@ -139,14 +149,18 @@ cmd_change_password (void)
|
||||
int who = p2 - 0x80;
|
||||
int r;
|
||||
|
||||
DEBUG_INFO ("Change PW\r\n");
|
||||
DEBUG_BYTE (who);
|
||||
|
||||
if (who == 1) /* PW1 */
|
||||
{
|
||||
const uint8_t *pk = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW1);
|
||||
const uint8_t *pk = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
|
||||
if (pk == NULL)
|
||||
{
|
||||
if (len < 6)
|
||||
{
|
||||
DEBUG_INFO ("permission denied.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
@@ -170,11 +184,13 @@ cmd_change_password (void)
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -192,24 +208,33 @@ cmd_change_password (void)
|
||||
|
||||
r = gpg_change_keystring (who, old_ks, who, new_ks);
|
||||
if (r < -2)
|
||||
GPG_MEMORY_FAILURE ();
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
GPG_MEMORY_FAILURE ();
|
||||
}
|
||||
else if (r < 0)
|
||||
GPG_SECURITY_FAILURE ();
|
||||
{
|
||||
DEBUG_INFO ("security error.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
}
|
||||
else if (r == 0 && who == 1) /* no prvkey */
|
||||
{
|
||||
no_prvkey:
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
ac_reset_pso_cds ();
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
||||
DEBUG_INFO ("Changed DO_KEYSTRING_PW1\r\n");
|
||||
}
|
||||
else if (r > 0 && who == 1)
|
||||
{
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, new_ks0, 1);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
|
||||
ac_reset_pso_cds ();
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
||||
DEBUG_INFO ("Removed content of DO_KEYSTRING_PW1\r\n");
|
||||
}
|
||||
else /* r >= 0 && who == 3 */
|
||||
{
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW3);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
@@ -225,10 +250,13 @@ cmd_reset_user_password (void)
|
||||
int pw_len, newpw_len;
|
||||
int r;
|
||||
|
||||
DEBUG_INFO ("Reset PW1\r\n");
|
||||
DEBUG_BYTE (p1);
|
||||
|
||||
if (p1 == 0x00) /* by User with Reseting Code */
|
||||
{
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
const uint8_t *ks_rc = gpg_do_read_simple (GNUK_DO_KEYSTRING_RC);
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
||||
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
||||
uint8_t *new_ks = &new_ks0[1];
|
||||
@@ -236,12 +264,14 @@ cmd_reset_user_password (void)
|
||||
if (pw_status_bytes == NULL
|
||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
||||
{
|
||||
DEBUG_INFO ("blocked.\r\n");
|
||||
GPG_SECURITY_AUTH_BLOCKED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ks_rc == NULL)
|
||||
{
|
||||
DEBUG_INFO ("security error.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
@@ -254,27 +284,33 @@ cmd_reset_user_password (void)
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (2, old_ks, 1, new_ks);
|
||||
if (r < -2)
|
||||
GPG_MEMORY_FAILURE ();
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
GPG_MEMORY_FAILURE ();
|
||||
}
|
||||
else if (r < 0)
|
||||
{
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
sec_fail:
|
||||
DEBUG_INFO ("failed.\r\n");
|
||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
||||
pwsb[PW_STATUS_RC]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
GPG_SECURITY_FAILURE ();
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
if (memcmp (ks_rc+1, old_ks, KEYSTRING_MD_SIZE) != 0)
|
||||
goto sec_fail;
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
ac_reset_pso_cds ();
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
||||
DEBUG_INFO ("done (no prvkey).\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
ac_reset_pso_cds ();
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
||||
GPG_SUCCESS ();
|
||||
@@ -283,7 +319,10 @@ cmd_reset_user_password (void)
|
||||
else /* by Admin (p1 == 0x02) */
|
||||
{
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
GPG_SECURITY_FAILURE ();
|
||||
{
|
||||
DEBUG_INFO ("permission denied.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t *old_ks = keystring_md_pw3;
|
||||
@@ -296,17 +335,25 @@ cmd_reset_user_password (void)
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (3, old_ks, 1, new_ks);
|
||||
if (r < -2)
|
||||
GPG_MEMORY_FAILURE ();
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
GPG_MEMORY_FAILURE ();
|
||||
}
|
||||
else if (r < 0)
|
||||
GPG_SECURITY_FAILURE ();
|
||||
{
|
||||
DEBUG_INFO ("security error.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
DEBUG_INFO ("done (no privkey).\r\n");
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
ac_reset_pso_cds ();
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
ac_reset_pso_cds ();
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
||||
GPG_SUCCESS ();
|
||||
@@ -344,6 +391,7 @@ static void
|
||||
cmd_pgp_gakp (void)
|
||||
{
|
||||
DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
|
||||
DEBUG_BYTE (cmd_APDU[2]);
|
||||
|
||||
if (cmd_APDU[2] == 0x81)
|
||||
/* Get public key */
|
||||
@@ -354,7 +402,7 @@ cmd_pgp_gakp (void)
|
||||
GPG_SECURITY_FAILURE ();
|
||||
|
||||
/* XXX: Not yet supported */
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
|
||||
GPG_ERROR ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,8 +417,8 @@ cmd_read_binary (void)
|
||||
GPG_BAD_P0_P1 ();
|
||||
else
|
||||
/* Tag 5a, serial number */
|
||||
write_res_apdu ((const uint8_t *)get_data_rb_result,
|
||||
sizeof (get_data_rb_result), 0x90, 0x00);
|
||||
write_res_apdu (read_binary_result,
|
||||
sizeof (read_binary_result), 0x90, 0x00);
|
||||
}
|
||||
else
|
||||
GPG_NO_RECORD();
|
||||
@@ -388,8 +436,6 @@ cmd_select_file (void)
|
||||
*/
|
||||
|
||||
file_selection = FILE_DF_OPENPGP;
|
||||
|
||||
/* XXX: Should return contents??? */
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
else if (cmd_APDU[4] == 2
|
||||
@@ -445,12 +491,16 @@ cmd_get_data (void)
|
||||
static void
|
||||
cmd_pso (void)
|
||||
{
|
||||
int len;
|
||||
int r;
|
||||
|
||||
DEBUG_INFO (" - PSO\r\n");
|
||||
|
||||
if (cmd_APDU[2] == 0x9E && cmd_APDU[3] == 0x9A)
|
||||
if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a)
|
||||
{
|
||||
if (!ac_check_status (AC_PSO_CDS_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
@@ -463,18 +513,16 @@ cmd_pso (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
int len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
int r;
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
|
||||
DEBUG_BYTE (len); /* Should be cmd_APDU_size - 6 */
|
||||
|
||||
r = rsa_sign (&cmd_APDU[7], res_APDU, len);
|
||||
if (r < 0)
|
||||
/* XXX: fail code??? */
|
||||
write_res_apdu (NULL, 0, 0x69, 0x85);
|
||||
GPG_ERROR ();
|
||||
else
|
||||
{ /* Success */
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
||||
|
||||
res_APDU[RSA_SIGNATURE_LENGTH] = 0x90;
|
||||
res_APDU[RSA_SIGNATURE_LENGTH+1] = 0x00;
|
||||
@@ -486,8 +534,23 @@ cmd_pso (void)
|
||||
gpg_do_increment_digital_signature_counter ();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
|
||||
{
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
if (!ac_check_status (AC_PSO_OTHER_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_BYTE (len);
|
||||
|
||||
r = rsa_decrypt (&cmd_APDU[7], res_APDU, len);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
{ /* XXX: not yet supported */
|
||||
@@ -497,6 +560,8 @@ cmd_pso (void)
|
||||
DEBUG_BYTE (cmd_APDU[3]);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
|
||||
DEBUG_INFO ("PSO done.\r\n");
|
||||
}
|
||||
|
||||
struct command
|
||||
|
||||
@@ -5,4 +5,5 @@
|
||||
#define GPG_NO_RECORD() write_res_apdu (NULL, 0, 0x6a, 0x88)
|
||||
#define GPG_BAD_P0_P1() write_res_apdu (NULL, 0, 0x6b, 0x00)
|
||||
#define GPG_NO_INS() write_res_apdu (NULL, 0, 0x6d, 0x00)
|
||||
#define GPG_ERROR() write_res_apdu (NULL, 0, 0x6f, 0x00)
|
||||
#define GPG_SUCCESS() write_res_apdu (NULL, 0, 0x90, 0x00)
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#include "config.h"
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/rsa.h"
|
||||
|
||||
static rsa_context rsa_ctx;
|
||||
|
||||
int
|
||||
rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len)
|
||||
{
|
||||
mpi P1, Q1, H;
|
||||
int r;
|
||||
|
||||
DEBUG_BINARY (kd.data, 256);
|
||||
|
||||
mpi_init (&P1, &Q1, &H, NULL);
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
|
||||
rsa_ctx.len = 2048 / 8;
|
||||
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
||||
mpi_read_binary (&rsa_ctx.P, &kd.data[0], rsa_ctx.len / 2);
|
||||
mpi_read_binary (&rsa_ctx.Q, &kd.data[128], rsa_ctx.len / 2);
|
||||
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
||||
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
||||
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
||||
mpi_mul_mpi (&H, &P1, &Q1);
|
||||
mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H);
|
||||
mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1);
|
||||
mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1);
|
||||
mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P);
|
||||
mpi_free (&P1, &Q1, &H, NULL);
|
||||
|
||||
DEBUG_INFO ("RSA...");
|
||||
|
||||
if ((r = rsa_check_privkey (&rsa_ctx)) == 0)
|
||||
DEBUG_INFO ("ok...");
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("failed.\r\n");
|
||||
DEBUG_SHORT (r);
|
||||
rsa_free (&rsa_ctx);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rsa_pkcs1_sign (&rsa_ctx, RSA_PRIVATE, SIG_RSA_RAW,
|
||||
msg_len, raw_message, output);
|
||||
rsa_free (&rsa_ctx);
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
if (r < 0)
|
||||
{
|
||||
DEBUG_SHORT (r);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
modulus_calc (const uint8_t *p, int len)
|
||||
{
|
||||
mpi P, Q, N;
|
||||
uint8_t *modulus;
|
||||
|
||||
(void)len; /* 2048-bit assumed */
|
||||
modulus = malloc (2048 / 8);
|
||||
if (modulus == NULL)
|
||||
return NULL;
|
||||
|
||||
mpi_init (&P, &Q, &N, NULL);
|
||||
mpi_read_binary (&P, p, 2048 / 8 / 2);
|
||||
mpi_read_binary (&Q, p + 128, 2048 / 8 / 2);
|
||||
mpi_mul_mpi (&N, &P, &Q);
|
||||
|
||||
mpi_write_binary (&N, modulus, 2048 / 8);
|
||||
mpi_free (&P, &Q, &N, NULL);
|
||||
return modulus;
|
||||
}
|
||||
|
||||
void
|
||||
modulus_free (const uint8_t *p)
|
||||
{
|
||||
free ((void *)p);
|
||||
}
|
||||
@@ -435,7 +435,9 @@ icc_handle_timeout (void)
|
||||
switch (icc_state)
|
||||
{
|
||||
case ICC_STATE_EXECUTE:
|
||||
#if 0
|
||||
icc_send_data_block (ICC_CMD_STATUS_TIMEEXT, 0, 0, NULL, 0);
|
||||
#endif
|
||||
break;
|
||||
case ICC_STATE_RECEIVE:
|
||||
case ICC_STATE_SEND:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
*
|
||||
* usb_desc.c - USB Descriptor
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -20,8 +20,8 @@ static const uint8_t gnukDeviceDescriptor[] = {
|
||||
0x00, /* bDeviceSubClass */
|
||||
0x00, /* bDeviceProtocol */
|
||||
0x40, /* bMaxPacketSize0 */
|
||||
0xff, 0xff, /* idVendor = 0xffff */
|
||||
0x01, 0x00, /* idProduct = 0x0001 */
|
||||
0x4b, 0x23, /* idVendor = 0x234b (FSIJ) */
|
||||
0x00, 0x00, /* idProduct = 0x0000 (FSIJ USB Token) */
|
||||
0x00, 0x02, /* bcdDevice = 2.00 */
|
||||
1, /* Index of string descriptor describing manufacturer */
|
||||
2, /* Index of string descriptor describing product */
|
||||
|
||||
Reference in New Issue
Block a user