mirror of
https://salsa.debian.org/gnuk-team/gnuk/gnuk.git
synced 2024-09-20 10:50:09 +00:00
Now, v2 works.
This commit is contained in:
parent
55e9678ab8
commit
40455cd4a5
110
README
110
README
@ -1,34 +1,110 @@
|
||||
Gnuk - A USB Token software implementation
|
||||
|
||||
Version 0.0 2010-09-01
|
||||
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.
|
||||
|
||||
|
||||
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).
|
||||
|
||||
Since this is the initial release, some garbages still remain.
|
||||
|
||||
|
||||
Target
|
||||
======
|
||||
|
||||
We use Olimex STM32-H103 board.
|
||||
|
||||
I think that it runs on Olimex STM32-P103 too. We are porting to
|
||||
STM32 Primer 2.
|
||||
|
||||
|
||||
Souce code
|
||||
==========
|
||||
|
||||
Initially, it is copy of ChibiOS_2.0.2/demos/ARMCM3-STM32F103-GCC/*.
|
||||
Gnuk source code is under src/ directory.
|
||||
|
||||
External source
|
||||
===============
|
||||
|
||||
* ChibiOS_2.0.2
|
||||
License
|
||||
=======
|
||||
|
||||
It is distributed under GNU General Public Licence version 3 or later
|
||||
(GPLv3+).
|
||||
|
||||
|
||||
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.
|
||||
|
||||
* PolarSSS 0.14.0
|
||||
* polarssl-0.14.0/ -- PolarSSL 0.14.0
|
||||
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)
|
||||
I took Libraries/STM32_USB-FS-Device_Driver and a part of
|
||||
Project/Virtual_COM_Port in STM32_USB-FS-Device_Lib distribution.
|
||||
Project/ in STM32_USB-FS-Device_Lib distribution.
|
||||
See http://www.st.com for detail.
|
||||
|
||||
|
||||
HOWTO RUN
|
||||
=================
|
||||
How to compile
|
||||
==============
|
||||
|
||||
$ openocd -f interface/olimex-jtag-tiny.cfg -f board/olimex_stm32_h103.cfg
|
||||
You need GNU Toolchain and newlib for 'arm-none-eabi' target.
|
||||
|
||||
$ arm-none-eabi-gdb --annotate=3 gnuk.elf
|
||||
See http://github.com/esden/summon-arm-toolchain/ for preparation of
|
||||
GNU Toolchain for 'arm-none-eabi' target.
|
||||
|
||||
$ telnet localhost 4444
|
||||
> reset halt
|
||||
> flash write_image erase gnuk.elf
|
||||
> reset
|
||||
> exit
|
||||
$
|
||||
$ cd gnuk-VERSION/src
|
||||
$ make
|
||||
|
||||
Then, we will have "gnuk.elf".
|
||||
|
||||
|
||||
How to run
|
||||
==========
|
||||
|
||||
If you are using Olimex JTAG-Tiny, type following to invoke OpenOCD:
|
||||
|
||||
$ openocd -f interface/olimex-jtag-tiny.cfg -f board/olimex_stm32_h103.cfg
|
||||
|
||||
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
|
||||
|
||||
$ telnet localhost 4444
|
||||
> reset halt
|
||||
> flash write_image erase gnuk.elf
|
||||
> reset
|
||||
> exit
|
||||
$
|
||||
|
||||
|
||||
How to debug
|
||||
============
|
||||
|
||||
We can use GDB.
|
||||
|
||||
$ arm-none-eabi-gdb gnuk.elf
|
||||
|
||||
--
|
||||
|
@ -92,9 +92,8 @@
|
||||
|
||||
/*
|
||||
* Uncomment this macro to store the AES tables in ROM.
|
||||
*
|
||||
#define POLARSSL_AES_ROM_TABLES
|
||||
*/
|
||||
#define POLARSSL_AES_ROM_TABLES
|
||||
|
||||
/*
|
||||
* Module: library/aes.c
|
||||
|
@ -66,7 +66,7 @@ include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/port.mk
|
||||
include $(CHIBIOS)/os/kernel/kernel.mk
|
||||
include stmusb.mk
|
||||
include vcomport.mk
|
||||
include rsa.mk
|
||||
include crypt.mk
|
||||
include ../boards/OLIMEX_STM32_H103/board.mk
|
||||
|
||||
# C sources that can be compiled in ARM or THUMB mode depending on the global
|
||||
@ -80,15 +80,16 @@ CSRC = $(PORTSRC) \
|
||||
$(CHIBIOS)/os/various/syscalls.c \
|
||||
$(STMUSBSRC) \
|
||||
$(VCOMSRC) \
|
||||
$(RSASRC) \
|
||||
main.c hw_config.c usb_lld.c usb_desc.c usb_prop.c \
|
||||
$(CRYPTSRC) \
|
||||
main.c debug.c usb_lld.c \
|
||||
hw_config.c usb_desc.c usb_prop.c \
|
||||
usb-icc.c gpg.c ac.c openpgp-do.c flash.c
|
||||
|
||||
# List ASM source files here
|
||||
ASMSRC = $(PORTASM) \
|
||||
$(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s gpg-data.s
|
||||
|
||||
INCDIR = $(RSAINCDIR) $(STMUSBINCDIR) $(VCOMDIR) \
|
||||
INCDIR = $(CRYPTINCDIR) $(STMUSBINCDIR) $(VCOMDIR) \
|
||||
$(PORTINC) $(KERNINC) $(TESTINC) \
|
||||
$(HALINC) $(PLATFORMINC) $(BOARDINC) \
|
||||
$(CHIBIOS)/os/various
|
||||
|
29
src/ac.c
29
src/ac.c
@ -5,6 +5,9 @@
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/sha1.h"
|
||||
|
||||
static uint8_t auth_status = AC_NONE_AUTHORIZED;
|
||||
|
||||
int
|
||||
@ -26,16 +29,21 @@ ac_check_status (uint8_t ac_flag)
|
||||
* check magic in params
|
||||
*/
|
||||
|
||||
uint8_t keystring_pw1[KEYSTRING_LEN] = {
|
||||
0x62, 0x10, 0x27, 0x44, 0x34, 0x05, 0x2f, 0x20,
|
||||
0xfc, 0xb8, 0x3e, 0x1d, 0x0f, 0x49, 0x22, 0x04,
|
||||
0xfc, 0xb1, 0x18, 0x84
|
||||
};
|
||||
|
||||
int
|
||||
verify_pso_cds (uint8_t *pw, int pw_len)
|
||||
{
|
||||
#if 0
|
||||
compute_hash;
|
||||
if (cmp_hash (pw1_hash, hash) == 0)
|
||||
good;
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
int r;
|
||||
|
||||
sha1 (pw, pw_len, keystring_pw1);
|
||||
if ((r = gpg_load_key (GPG_KEY_FOR_SIGNATURE)) < 0)
|
||||
return r;
|
||||
|
||||
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
||||
return 0;
|
||||
}
|
||||
@ -43,13 +51,6 @@ verify_pso_cds (uint8_t *pw, int pw_len)
|
||||
int
|
||||
verify_pso_other (uint8_t *pw, int pw_len)
|
||||
{
|
||||
#if 0
|
||||
compute_hash;
|
||||
if (cmp_hash (pw1_hash, hash) == 0)
|
||||
good;
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
auth_status |= AC_PSO_OTHER_AUTHORIZED;
|
||||
return 0;
|
||||
}
|
||||
|
6
src/crypt.mk
Normal file
6
src/crypt.mk
Normal file
@ -0,0 +1,6 @@
|
||||
CRYPTDIR = ../polarssl-0.14.0
|
||||
CRYPTSRCDIR = $(CRYPTDIR)/library
|
||||
CRYPTINCDIR = $(CRYPTDIR)/include
|
||||
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/sha1.c \
|
||||
$(CRYPTSRCDIR)/aes.c \
|
||||
rsa-sign.c
|
73
src/debug.c
Normal file
73
src/debug.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* debug.c -- Debuging with virtual COM port
|
||||
*
|
||||
* 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"
|
||||
|
||||
static void
|
||||
put_hex (uint8_t nibble)
|
||||
{
|
||||
uint8_t c;
|
||||
|
||||
if (nibble < 0x0a)
|
||||
c = '0' + nibble;
|
||||
else
|
||||
c = 'a' + nibble - 0x0a;
|
||||
|
||||
_write (&c, 1);
|
||||
}
|
||||
|
||||
void
|
||||
put_byte (uint8_t b)
|
||||
{
|
||||
put_hex (b >> 4);
|
||||
put_hex (b &0x0f);
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
|
||||
void
|
||||
put_byte_with_no_nl (uint8_t b)
|
||||
{
|
||||
_write (" ", 1);
|
||||
put_hex (b >> 4);
|
||||
put_hex (b &0x0f);
|
||||
}
|
||||
|
||||
void
|
||||
put_short (uint16_t x)
|
||||
{
|
||||
put_hex (x >> 12);
|
||||
put_hex ((x >> 8)&0x0f);
|
||||
put_hex ((x >> 4)&0x0f);
|
||||
put_hex (x & 0x0f);
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
|
||||
void
|
||||
put_string (const char *s)
|
||||
{
|
||||
_write (s, strlen (s));
|
||||
}
|
||||
|
||||
|
44
src/flash.c
44
src/flash.c
@ -21,14 +21,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Writing to Flash ROM is NOT YET IMPLEMENTED, just API only
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
static uint8_t do_pool[256];
|
||||
static uint8_t *last_p = do_pool;
|
||||
|
||||
/*
|
||||
* TLV (Tag, Length, and Value)
|
||||
*/
|
||||
uint8_t *
|
||||
flash_do_write (uint16_t tag, uint8_t *data, int len)
|
||||
{
|
||||
static uint8_t do_pool[1024];
|
||||
static uint8_t *last_p = do_pool;
|
||||
uint8_t *p = last_p;
|
||||
|
||||
if (last_p - do_pool + len + 2 + 3 > 1024)
|
||||
@ -54,3 +62,35 @@ flash_do_write (uint16_t tag, uint8_t *data, int len)
|
||||
|
||||
return p + 2;
|
||||
}
|
||||
|
||||
static uint8_t k1[KEY_CONTENT_LEN];
|
||||
#if 0
|
||||
static uint8_t k2[KEY_CONTENT_LEN];
|
||||
static uint8_t k3[KEY_CONTENT_LEN];
|
||||
#endif
|
||||
|
||||
uint8_t *
|
||||
flash_key_alloc (enum kind_of_key kk)
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
flash_key_write (uint8_t *key_addr, uint8_t *key_data)
|
||||
{
|
||||
memcpy (key_addr, key_data, KEY_CONTENT_LEN);
|
||||
return 0;
|
||||
}
|
||||
|
15
src/gen-gpg-data
Normal file
15
src/gen-gpg-data
Normal file
@ -0,0 +1,15 @@
|
||||
#! /bin/sh
|
||||
|
||||
arm-none-eabi-gcc -S -mcpu=cortex-m3 -O0 -ggdb -fomit-frame-pointer \
|
||||
-falign-functions=16 -ffunction-sections \
|
||||
-Wall -Wextra -Wstrict-prototypes -Wa,-alms=gpg-data.lst \
|
||||
-DCORTEX_USE_BASEPRI=TRUE -DTHUMB_PRESENT -mno-thumb-interwork \
|
||||
-DTHUMB_NO_INTERWORKING -mthumb -DTHUMB \
|
||||
-I . -I../STM32_USB-FS-Device_Driver/inc -I../USBCDC \
|
||||
-I../ChibiOS_2.0.2/os/ports/GCC/ARMCMx \
|
||||
-I../ChibiOS_2.0.2/os/ports/GCC/ARMCMx/STM32F10x \
|
||||
-I../ChibiOS_2.0.2/os/ports/GCC/ARMCMx/cmsis \
|
||||
-I../ChibiOS_2.0.2/os/kernel/include -I../ChibiOS_2.0.2/test \
|
||||
-I../ChibiOS_2.0.2/os/hal/include \
|
||||
-I../ChibiOS_2.0.2/os/hal/platforms/STM32 -I../boards/OLIMEX_STM32_H103 \
|
||||
-I../ChibiOS_2.0.2/os/various gpg-data.c
|
32
src/gnuk.h
32
src/gnuk.h
@ -1,6 +1,7 @@
|
||||
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_string (const char *s);
|
||||
|
||||
@ -50,3 +51,34 @@ extern void gpg_do_get_data (uint16_t tag);
|
||||
extern void gpg_do_put_data (uint16_t tag, uint8_t *data, int len);
|
||||
|
||||
extern uint8_t * flash_do_write (uint16_t tag, uint8_t *data, int len);
|
||||
|
||||
enum kind_of_key {
|
||||
GPG_KEY_FOR_SIGNATURE,
|
||||
GPG_KEY_FOR_DECRYPT,
|
||||
GPG_KEY_FOR_AUTHENTICATION,
|
||||
};
|
||||
|
||||
extern uint8_t *flash_key_alloc (enum kind_of_key);
|
||||
|
||||
#define KEY_MAGIC_LEN 8
|
||||
#define KEY_CONTENT_LEN 256
|
||||
#define GNUK_MAGIC "Gnuk KEY"
|
||||
#define KEYSTORE_LEN (KEY_MAGIC_LEN+4+4+KEY_CONTENT_LEN)
|
||||
|
||||
struct key_data {
|
||||
uint8_t *key_addr;
|
||||
/* encrypted data content */
|
||||
char magic[KEY_MAGIC_LEN];
|
||||
uint32_t random;
|
||||
uint32_t check;
|
||||
uint8_t data[KEY_CONTENT_LEN];
|
||||
};
|
||||
|
||||
extern int flash_key_write (uint8_t *key_addr, uint8_t *key_data);
|
||||
|
||||
#define KEYSTRING_LEN 20 /* Use 16-byte for AES encryption */
|
||||
extern uint8_t keystring_pw1[KEYSTRING_LEN];
|
||||
|
||||
extern int gpg_load_key (enum kind_of_key kk);
|
||||
|
||||
extern struct key_data kd;
|
||||
|
41
src/gpg.c
41
src/gpg.c
@ -25,45 +25,7 @@
|
||||
#include "hal.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
static void
|
||||
put_hex (uint8_t nibble)
|
||||
{
|
||||
uint8_t c;
|
||||
|
||||
if (nibble < 0x0a)
|
||||
c = '0' + nibble;
|
||||
else
|
||||
c = 'a' + nibble - 0x0a;
|
||||
|
||||
_write (&c, 1);
|
||||
}
|
||||
|
||||
void
|
||||
put_byte (uint8_t b)
|
||||
{
|
||||
put_hex (b >> 4);
|
||||
put_hex (b &0x0f);
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
|
||||
void
|
||||
put_short (uint16_t x)
|
||||
{
|
||||
put_hex (x >> 12);
|
||||
put_hex ((x >> 8)&0x0f);
|
||||
put_hex ((x >> 4)&0x0f);
|
||||
put_hex (x & 0x0f);
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
|
||||
void
|
||||
put_string (const char *s)
|
||||
{
|
||||
_write (s, strlen (s));
|
||||
}
|
||||
|
||||
|
||||
#define RSA_SIGNATURE_LENGTH 128 /* 256 *//* 256 byte == 2048-bit */
|
||||
#define RSA_SIGNATURE_LENGTH 256 /* 256 byte == 2048-bit */
|
||||
extern unsigned char *rsa_sign (unsigned char *);
|
||||
|
||||
#define INS_PUT_DATA 0xDA
|
||||
@ -277,6 +239,7 @@ process_command_apdu (void)
|
||||
if (cmd_APDU[2] == 0x9E && cmd_APDU[3] == 0x9A)
|
||||
{
|
||||
if (cmd_APDU_size != 8 + 35 && cmd_APDU_size != 8 + 35 + 1)
|
||||
/* Extended Lc: 3-byte */
|
||||
{
|
||||
put_string (" wrong length: ");
|
||||
put_short (cmd_APDU_size);
|
||||
|
306
src/openpgp-do.c
306
src/openpgp-do.c
@ -26,6 +26,9 @@
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/aes.h"
|
||||
|
||||
/*
|
||||
* Compile time vars:
|
||||
* AID, Historical Bytes (template), Extended Capabilities,
|
||||
@ -120,6 +123,7 @@ enum do_type {
|
||||
DO_CN_READ,
|
||||
DO_PROC_READ,
|
||||
DO_PROC_WRITE,
|
||||
DO_PROC_READWRITE,
|
||||
DO_HASH,
|
||||
DO_KEYPTR
|
||||
};
|
||||
@ -142,6 +146,8 @@ static struct do_table_entry *get_do_entry (uint16_t tag);
|
||||
#define GNUK_DO_KEYPTR_DEC 0xff02
|
||||
#define GNUK_DO_KEYPTR_AUT 0xff03
|
||||
#define GNUK_DO_HASH_PW3 0xff04
|
||||
#define GNUK_DO_HASH_RC 0xff05
|
||||
#define GNUK_DO_PW_STATUS 0xff06
|
||||
|
||||
#define GPG_DO_AID 0x004f
|
||||
#define GPG_DO_NAME 0x005b
|
||||
@ -311,24 +317,225 @@ do_kgtime_all (uint16_t tag)
|
||||
}
|
||||
|
||||
static void
|
||||
put_hex (uint8_t nibble)
|
||||
rw_pw_status (uint16_t tag, uint8_t *data, int len, int is_write)
|
||||
{
|
||||
uint8_t c;
|
||||
struct do_table_entry *do_p;
|
||||
|
||||
if (nibble < 0x0a)
|
||||
c = '0' + nibble;
|
||||
if (is_write)
|
||||
{
|
||||
const uint8_t *do_data;
|
||||
|
||||
do_p = get_do_entry (GNUK_DO_PW_STATUS);
|
||||
if (do_p)
|
||||
{
|
||||
do_data = (const uint8_t *)do_p->obj;
|
||||
if (do_data)
|
||||
memcpy (data, &do_data[2], SIZE_PW_STATUS_BYTES - 1);
|
||||
|
||||
do_p->obj = flash_do_write (tag, data, len);
|
||||
if (do_p->obj)
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
|
||||
else
|
||||
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
|
||||
}
|
||||
else
|
||||
/* No record */
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88);
|
||||
}
|
||||
else
|
||||
c = 'a' + nibble - 0x0a;
|
||||
{
|
||||
const uint8_t *do_data;
|
||||
|
||||
_write (&c, 1);
|
||||
if (with_tag)
|
||||
{
|
||||
copy_tag (tag);
|
||||
*res_p++ = SIZE_PW_STATUS_BYTES;
|
||||
}
|
||||
|
||||
do_p = get_do_entry (GNUK_DO_PW_STATUS);
|
||||
do_data = (const uint8_t *)do_p->obj;
|
||||
if (do_data)
|
||||
{
|
||||
memcpy (res_p, &do_data[1], SIZE_PW_STATUS_BYTES);
|
||||
res_p += SIZE_PW_STATUS_BYTES;
|
||||
}
|
||||
else
|
||||
/* No record */
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
o_put_byte (uint8_t b)
|
||||
proc_resetting_code (uint16_t tag, uint8_t *data, int len)
|
||||
{
|
||||
_write (" ", 1);
|
||||
put_hex (b >> 4);
|
||||
put_hex (b &0x0f);
|
||||
/* Not implementad yet */
|
||||
/*
|
||||
* calculate hash, write it to GNUK_DO_HASH_RC.
|
||||
*/
|
||||
/* Then, we need to reset RC counter in GNUK_DO_PW_STATUS */
|
||||
}
|
||||
|
||||
static uint8_t iv[16];
|
||||
|
||||
static aes_context aes;
|
||||
static int iv_offset;
|
||||
|
||||
static void
|
||||
encrypt (uint8_t *key_str, uint8_t *data)
|
||||
{
|
||||
aes_setkey_enc (&aes, key_str, 128);
|
||||
memset (iv, 0, 16);
|
||||
iv_offset = 0;
|
||||
aes_crypt_cfb128 (&aes, AES_ENCRYPT, KEYSTORE_LEN, &iv_offset, iv, data, data);
|
||||
|
||||
{
|
||||
int i, len = KEYSTORE_LEN;
|
||||
|
||||
put_string ("ENC\r\n");
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
put_byte_with_no_nl (data[i]);
|
||||
if ((i & 0x0f) == 0x0f)
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
struct key_data kd;
|
||||
|
||||
static void
|
||||
decrypt (uint8_t *key_str, uint8_t *data)
|
||||
{
|
||||
aes_setkey_enc (&aes, key_str, 128);
|
||||
memset (iv, 0, 16);
|
||||
iv_offset = 0;
|
||||
aes_crypt_cfb128 (&aes, AES_DECRYPT, KEYSTORE_LEN, &iv_offset, iv, data, data);
|
||||
{
|
||||
int i, len = KEYSTORE_LEN;
|
||||
|
||||
put_string ("DEC\r\n");
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
put_byte_with_no_nl (data[i]);
|
||||
if ((i & 0x0f) == 0x0f)
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
gpg_load_key (enum kind_of_key kk)
|
||||
{
|
||||
struct do_table_entry *do_p;
|
||||
|
||||
switch (kk)
|
||||
{
|
||||
case GPG_KEY_FOR_SIGNATURE:
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_SIG);
|
||||
break;
|
||||
case GPG_KEY_FOR_DECRYPT:
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_DEC);
|
||||
break;
|
||||
case GPG_KEY_FOR_AUTHENTICATION:
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_AUT);
|
||||
break;
|
||||
}
|
||||
if (do_p == NULL)
|
||||
return -1;
|
||||
|
||||
kd.key_addr = *(uint8_t **)&((uint8_t *)do_p->obj)[1];
|
||||
memcpy (((uint8_t *)&kd)+4, ((uint8_t *)do_p->obj)+5, KEY_MAGIC_LEN+4+4);
|
||||
memcpy (kd.data, kd.key_addr, KEY_CONTENT_LEN);
|
||||
|
||||
decrypt (keystring_pw1, ((uint8_t *)&kd) + 4);
|
||||
if (memcmp (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN) != 0)
|
||||
return -1;
|
||||
/* XXX: more sanity check */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
get_random (void)
|
||||
{
|
||||
return 0x80808080; /* XXX: for now */
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
calc_check (uint8_t *data, int len)
|
||||
{
|
||||
uint32_t check = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
check += data[i];
|
||||
|
||||
return check;
|
||||
}
|
||||
|
||||
static int
|
||||
gpg_write_do_keyptr (enum kind_of_key kk, uint8_t *key_data, int key_len)
|
||||
{
|
||||
uint8_t *p;
|
||||
int len;
|
||||
int r;
|
||||
uint32_t key_addr;
|
||||
struct do_table_entry *do_p;
|
||||
|
||||
#if 0
|
||||
assert (key_len == KEY_CONTENT_LEN+4);
|
||||
/* key_data should starts with 00 01 00 01 (E) */
|
||||
#endif
|
||||
|
||||
put_short (key_len);
|
||||
|
||||
key_data += 4;
|
||||
|
||||
kd.key_addr = flash_key_alloc (kk);
|
||||
if (kd.key_addr == NULL)
|
||||
return -1;
|
||||
|
||||
memcpy (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN);
|
||||
kd.check = calc_check (key_data, KEY_CONTENT_LEN);
|
||||
kd.random = get_random ();
|
||||
memcpy (kd.data, key_data, KEY_CONTENT_LEN);
|
||||
|
||||
put_string ("enc...");
|
||||
|
||||
encrypt (keystring_pw1, ((uint8_t *)&kd) + 4);
|
||||
|
||||
put_string ("done\r\n");
|
||||
|
||||
if ((r = flash_key_write (kd.key_addr, kd.data)) < 0)
|
||||
return r;
|
||||
|
||||
switch (kk)
|
||||
{
|
||||
case GPG_KEY_FOR_SIGNATURE:
|
||||
p = flash_do_write (GNUK_DO_KEYPTR_SIG, &kd,
|
||||
sizeof (kd) - KEY_CONTENT_LEN);
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_SIG);
|
||||
do_p->obj = p;
|
||||
break;
|
||||
case GPG_KEY_FOR_DECRYPT:
|
||||
p = flash_do_write (GNUK_DO_KEYPTR_DEC, &kd,
|
||||
sizeof (kd) - KEY_CONTENT_LEN);
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_DEC);
|
||||
do_p->obj = p;
|
||||
break;
|
||||
case GPG_KEY_FOR_AUTHENTICATION:
|
||||
p = flash_do_write (GNUK_DO_KEYPTR_AUT, &kd,
|
||||
sizeof (kd) - KEY_CONTENT_LEN);
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_AUT);
|
||||
do_p->obj = p;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -338,22 +545,34 @@ o_put_byte (uint8_t b)
|
||||
* 91 xx
|
||||
* 92 xx
|
||||
* 93 xx
|
||||
* 5f48, xx: cardholder privatge key
|
||||
* 5f48, xx: cardholder private key
|
||||
*/
|
||||
static void
|
||||
proc_key_import (uint16_t tag, uint8_t *data, int len)
|
||||
{
|
||||
int i;
|
||||
int i, r;
|
||||
enum kind_of_key kk;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
o_put_byte (data[i]);
|
||||
put_byte_with_no_nl (data[i]);
|
||||
if ((i & 0x0f) == 0x0f)
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
_write ("\r\n", 2);
|
||||
|
||||
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
|
||||
if (data[4] == 0xa4)
|
||||
kk = GPG_KEY_FOR_AUTHENTICATION;
|
||||
else if (data[4] == 0xb8)
|
||||
kk = GPG_KEY_FOR_DECRYPT;
|
||||
else /* 0xb6 */
|
||||
kk = GPG_KEY_FOR_SIGNATURE;
|
||||
|
||||
r = gpg_write_do_keyptr (kk, &data[22], len - 22);
|
||||
if (r < 0)
|
||||
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
|
||||
else
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
|
||||
}
|
||||
|
||||
static const uint16_t const cn_ch_data[] = {
|
||||
@ -383,11 +602,16 @@ gpg_do_table[] = {
|
||||
{ GNUK_DO_KEYPTR_DEC, DO_KEYPTR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_KEYPTR_AUT, DO_KEYPTR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_HASH_PW3, DO_HASH, AC_NEVER, AC_NEVER, NULL },
|
||||
/* Pseudo DO: calculated */
|
||||
{ GNUK_DO_HASH_RC, DO_HASH, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_PW_STATUS, DO_VAR, AC_NEVER, AC_NEVER, NULL },
|
||||
/* Pseudo DO READ: calculated */
|
||||
{ GPG_DO_HIST_BYTES, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_hist_bytes },
|
||||
{ GPG_DO_FP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_fp_all },
|
||||
{ GPG_DO_CAFP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_cafp_all },
|
||||
{ GPG_DO_KGTIME_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_kgtime_all },
|
||||
/* Pseudo DO READ/WRITE: calculated */
|
||||
{ GPG_DO_PW_STATUS, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
|
||||
rw_pw_status },
|
||||
/* Fixed data */
|
||||
{ GPG_DO_AID, DO_FIXED, AC_ALWAYS, AC_NEVER, aid },
|
||||
{ GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities },
|
||||
@ -397,7 +621,6 @@ gpg_do_table[] = {
|
||||
/* Variable(s): Fixed size, not changeable by user */
|
||||
{ GPG_DO_DS_COUNT, DO_VAR, AC_ALWAYS, AC_NEVER, NULL },
|
||||
/* Variables: Fixed size */
|
||||
{ GPG_DO_PW_STATUS, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
|
||||
{ GPG_DO_SEX, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
|
||||
{ GPG_DO_FP_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
|
||||
{ GPG_DO_FP_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
|
||||
@ -414,12 +637,13 @@ gpg_do_table[] = {
|
||||
{ GPG_DO_NAME, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
|
||||
{ GPG_DO_LANGUAGE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
|
||||
{ GPG_DO_CH_CERTIFICATE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
|
||||
/* Variable(s): Variable size, write only by user */
|
||||
{ GPG_DO_RESETTING_CODE, DO_VAR, AC_NEVER, AC_ADMIN_AUTHORIZED, NULL },
|
||||
/* Compound data: Read access only */
|
||||
{ GPG_DO_CH_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_ch_data },
|
||||
{ GPG_DO_APP_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_app_data },
|
||||
{ GPG_DO_SS_TEMP, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_ss_temp },
|
||||
/* Simple data: write access only */
|
||||
{ GPG_DO_RESETTING_CODE, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
|
||||
proc_resetting_code },
|
||||
/* Compound data: Write access only*/
|
||||
{ GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
|
||||
proc_key_import },
|
||||
@ -448,7 +672,7 @@ gpg_do_table_init (void)
|
||||
|
||||
do_p = get_do_entry (GPG_DO_LOGIN_DATA);
|
||||
do_p->obj = do_5e;
|
||||
do_p = get_do_entry (GPG_DO_PW_STATUS);
|
||||
do_p = get_do_entry (GNUK_DO_PW_STATUS);
|
||||
do_p->obj = do_c4;
|
||||
#if 0
|
||||
do_p = get_do_entry (GPG_DO_FP_SIG);
|
||||
@ -578,6 +802,14 @@ copy_do (struct do_table_entry *do_p)
|
||||
do_func (do_p->tag);
|
||||
break;
|
||||
}
|
||||
case DO_PROC_READWRITE:
|
||||
{
|
||||
void (*rw_func)(uint16_t, uint8_t *, int, int)
|
||||
= (void (*)(uint16_t, uint8_t *, int, int))do_p->obj;
|
||||
|
||||
rw_func (do_p->tag, NULL, 0, 0);
|
||||
break;
|
||||
}
|
||||
case DO_PROC_WRITE:
|
||||
case DO_HASH:
|
||||
case DO_KEYPTR:
|
||||
@ -655,33 +887,25 @@ gpg_do_put_data (uint16_t tag, uint8_t *data, int len)
|
||||
|
||||
flash_do_release (do_data);
|
||||
#endif
|
||||
if (tag == GPG_DO_PW_STATUS)
|
||||
{
|
||||
/* XXX: only the first byte can be changed */
|
||||
}
|
||||
if (len == 0)
|
||||
/* make DO empty */
|
||||
do_p->obj = NULL;
|
||||
else
|
||||
{
|
||||
if (len == 0)
|
||||
/* make DO empty */
|
||||
do_p->obj = NULL;
|
||||
do_p->obj = flash_do_write (tag, data, len);
|
||||
if (do_p->obj)
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
|
||||
else
|
||||
{
|
||||
do_p->obj = flash_do_write (tag, data, len);
|
||||
if (do_p->obj)
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
|
||||
else
|
||||
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
|
||||
}
|
||||
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DO_PROC_READWRITE:
|
||||
{
|
||||
void (*rw_func)(uint16_t, uint8_t *, int, int)
|
||||
= (void (*)(uint16_t, uint8_t *, int, int))do_p->obj;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
if (tag == GPG_DO_RESETTING_CODE)
|
||||
{
|
||||
/* XXX: Changing Resetting code,
|
||||
* we need to reset RC counter in GPG_DO_PW_STATUS */
|
||||
}
|
||||
rw_func (tag, data, len, 1);
|
||||
break;
|
||||
}
|
||||
case DO_PROC_WRITE:
|
||||
|
111
src/rsa-sign.c
111
src/rsa-sign.c
@ -1,118 +1,57 @@
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
#include <polarssl/config.h>
|
||||
#include <polarssl/rsa.h>
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/rsa.h"
|
||||
|
||||
static unsigned char output[256];
|
||||
|
||||
/* big endian */
|
||||
static const unsigned char p[64] = {
|
||||
0xe3,0xec,0x42,0x6c,0x23,0x37,0x1f,0x96,
|
||||
0x55,0x2f,0x1d,0x2a,0x37,0xd2,0x66,0x43,
|
||||
0x3c,0xb1,0xa5,0x24,0x47,0x8e,0x29,0x86,
|
||||
0xee,0xec,0xa9,0x86,0x1e,0x05,0xfb,0xfa,
|
||||
0x00,0x0e,0x69,0xbc,0x60,0x47,0x1c,0x00,
|
||||
0x96,0xdc,0x30,0x00,0x05,0xfb,0xe0,0x00,
|
||||
0xae,0x05,0x38,0x38,0xf9,0x7e,0xa6,0xae,
|
||||
0xf6,0x90,0x68,0x48,0xf5,0x23,0x7f,0x3d,
|
||||
};
|
||||
|
||||
static const unsigned char q[64] = {
|
||||
0xf2,0x8c,0xa0,0x24,0x38,0x7c,0x6e,0x66,
|
||||
0x9c,0x39,0xe9,0x4d,0x2b,0xe3,0x94,0xd1,
|
||||
0x93,0x3f,0x17,0xcb,0x3f,0x4e,0x8d,0xa4,
|
||||
0xdd,0x1f,0xee,0x00,0x7d,0x8c,0x5e,0xbb,
|
||||
0xc7,0x80,0x1a,0xf5,0x79,0x80,0x63,0x5a,
|
||||
0xc7,0xa2,0xb7,0x92,0x75,0x26,0xda,0xd4,
|
||||
0xc9,0x9f,0x83,0x58,0x81,0x0a,0x53,0xa3,
|
||||
0xe4,0x0b,0xd1,0xde,0xe2,0x33,0xf2,0x9b,
|
||||
};
|
||||
|
||||
/* dq = 1/e mod (p - 1) */
|
||||
static const unsigned char dp[64] = {
|
||||
0x44,0x60,0x63,0x88,0xe7,0x83,0xa9,0x01,
|
||||
0x43,0xaa,0xef,0xb7,0xf3,0xa9,0x36,0x2e,
|
||||
0xa3,0xad,0xb3,0x9a,0x4f,0xb1,0x31,0x7a,
|
||||
0x1e,0x81,0x77,0x56,0x19,0xf9,0xb7,0x9f,
|
||||
0x47,0x97,0x0b,0x57,0x8d,0x16,0xa8,0x2a,
|
||||
0xf1,0x17,0x3b,0x7b,0x36,0x50,0x5a,0xe2,
|
||||
0x39,0x52,0xad,0x8c,0x42,0x25,0x21,0xc2,
|
||||
0x49,0x8c,0x07,0x0d,0x24,0x25,0xb3,0x0d,
|
||||
};
|
||||
|
||||
/* dq = 1/e mod (q - 1) */
|
||||
static const unsigned char dq[64] = {
|
||||
0x6c,0xbe,0xbd,0xe1,0xdf,0x6d,0x72,0x76,
|
||||
0x10,0xdf,0x2a,0x09,0x8e,0x7e,0xe7,0xaf,
|
||||
0x1a,0xcc,0x73,0xd7,0x8d,0x57,0xa3,0xcb,
|
||||
0xe1,0xd4,0x39,0xfa,0x00,0x50,0x19,0xfd,
|
||||
0x28,0xd1,0xf7,0xc4,0x4d,0x28,0x51,0xe3,
|
||||
0x56,0x94,0x4e,0xa7,0x9c,0x5c,0xc2,0x4a,
|
||||
0x1a,0xe7,0xa8,0x94,0xda,0xae,0x0d,0x97,
|
||||
0xf2,0x5b,0x96,0x49,0xce,0xb3,0x29,0xb7,
|
||||
};
|
||||
|
||||
/* q_inv = 1/q mod p */
|
||||
static const unsigned char q_inv[64] = {
|
||||
0x19,0x77,0x6a,0xc8,0xd7,0x2b,0x9f,0x82,
|
||||
0x2d,0xbd,0x05,0x89,0xd8,0x0f,0x1e,0xb6,
|
||||
0x19,0x82,0x58,0x2f,0x7f,0xfd,0xee,0x50,
|
||||
0x00,0x75,0x85,0x69,0x64,0x37,0x32,0xa0,
|
||||
0x62,0x55,0x5b,0x13,0x71,0x9e,0x4e,0x1f,
|
||||
0x93,0x4c,0xa2,0x77,0x6c,0x70,0x07,0xa6,
|
||||
0xfb,0xd5,0x4e,0x94,0xab,0xbd,0xa0,0x0e,
|
||||
0x0d,0x42,0x07,0x9d,0xbb,0x5d,0xbc,0x75,
|
||||
};
|
||||
static rsa_context ctx;
|
||||
|
||||
unsigned char *
|
||||
rsa_sign (unsigned char *raw_message)
|
||||
{
|
||||
rsa_context ctx;
|
||||
mpi P1, Q1, H;
|
||||
int len;
|
||||
int r;
|
||||
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6]; /* cmd_APDU_size - 6 */
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
put_byte (len);
|
||||
/* cmd_APDU_size - 6 */
|
||||
|
||||
mpi_init( &P1, &Q1, &H, NULL );
|
||||
rsa_init( &ctx, RSA_PKCS_V15, 0 );
|
||||
|
||||
#if 0
|
||||
ctx.len = 2048 / 8;
|
||||
#else
|
||||
ctx.len = 1024 / 8;
|
||||
mpi_read_string( &ctx.E, 16, "10001" );
|
||||
mpi_read_binary (&ctx.P, p, ctx.len / 2);
|
||||
mpi_read_binary (&ctx.Q, q, ctx.len / 2);
|
||||
mpi_mul_mpi( &ctx.N, &ctx.P, &ctx.Q );
|
||||
mpi_sub_int( &P1, &ctx.P, 1 );
|
||||
mpi_sub_int( &Q1, &ctx.Q, 1 );
|
||||
mpi_mul_mpi( &H, &P1, &Q1 );
|
||||
mpi_inv_mod( &ctx.D , &ctx.E, &H );
|
||||
mpi_read_binary (&ctx.DP, dp, ctx.len / 2);
|
||||
mpi_read_binary (&ctx.DQ, dq, ctx.len / 2);
|
||||
mpi_read_binary (&ctx.QP, q_inv, ctx.len / 2);
|
||||
#endif
|
||||
mpi_read_string ( &ctx.E, 16, "10001" );
|
||||
mpi_read_binary ( &ctx.P, &kd.data[0], ctx.len / 2 );
|
||||
mpi_read_binary ( &ctx.Q, &kd.data[128], ctx.len / 2 );
|
||||
mpi_mul_mpi ( &ctx.N, &ctx.P, &ctx.Q );
|
||||
mpi_sub_int ( &P1, &ctx.P, 1 );
|
||||
mpi_sub_int ( &Q1, &ctx.Q, 1 );
|
||||
mpi_mul_mpi ( &H, &P1, &Q1 );
|
||||
mpi_inv_mod ( &ctx.D , &ctx.E, &H );
|
||||
mpi_mod_mpi ( &ctx.DP, &ctx.D, &P1);
|
||||
mpi_mod_mpi ( &ctx.DQ, &ctx.D, &Q1);
|
||||
mpi_inv_mod ( &ctx.QP, &ctx.Q, &ctx.P);
|
||||
mpi_free (&P1, &Q1, &H, NULL);
|
||||
|
||||
put_string ("RSA...");
|
||||
{
|
||||
int r;
|
||||
if ((r = rsa_check_privkey( &ctx )) == 0)
|
||||
if ((r = rsa_check_privkey ( &ctx )) == 0)
|
||||
put_string ("ok...");
|
||||
else
|
||||
{
|
||||
put_string ("failed.\r\n");
|
||||
put_byte (r);
|
||||
rsa_free (&ctx);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, len, raw_message, output);
|
||||
r = rsa_pkcs1_sign ( &ctx, RSA_PRIVATE, SIG_RSA_RAW,
|
||||
len, raw_message, output );
|
||||
put_short (r);
|
||||
put_string ("done.\r\n");
|
||||
rsa_free (&ctx);
|
||||
return output;
|
||||
#else
|
||||
rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, len, raw_message, output );
|
||||
put_string ("done.\r\n");
|
||||
return output;
|
||||
#endif
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
RSADIR = ../polarssl-0.14.0
|
||||
RSASRCDIR = $(RSADIR)/library
|
||||
RSAINCDIR = $(RSADIR)/include
|
||||
RSASRC = $(RSASRCDIR)/bignum.c $(RSASRCDIR)/rsa.c rsa-sign.c
|
Loading…
Reference in New Issue
Block a user