1.2.0 code
SDK 1.4.2.x port Add uif support Refactor memory layout Try to add more curve gpg 2.2.x handle curves other than ed25519 in a such strange way that it is very difficult to do such support. So secp256k1, secp256r1 and brainpoolp256 seems works, but according to gpg code it works by side effects :-/ Update user documentation for UIF There is still an issue with ssh authentication with Ed25519. It works with NIST-P256, Brainpool256 curves
This commit is contained in:
parent
a0d537dcec
commit
281ea42cbb
15
Makefile
15
Makefile
@ -15,13 +15,6 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#*******************************************************************************
|
#*******************************************************************************
|
||||||
|
|
||||||
BOLOS_SDK=/home/cme/Projects/Git/ledger/nanos-secure-sdk-cslashm
|
|
||||||
|
|
||||||
|
|
||||||
CLANGPATH=/home/cme/Projects/Git/ledger/compilers/clang+llvm-4.0.0-x86_64-linux-gnu-ubuntu-16.10/bin/
|
|
||||||
GCCPATH=/home/cme/Projects/Git/ledger/compilers/gcc-arm-none-eabi-5_3-2016q1/bin/
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(BOLOS_SDK),)
|
ifeq ($(BOLOS_SDK),)
|
||||||
$(error Environment variable BOLOS_SDK is not set)
|
$(error Environment variable BOLOS_SDK is not set)
|
||||||
endif
|
endif
|
||||||
@ -34,8 +27,8 @@ APPNAME = OpenPGP
|
|||||||
SPECVERSION="3.3.1"
|
SPECVERSION="3.3.1"
|
||||||
|
|
||||||
APPVERSION_M=1
|
APPVERSION_M=1
|
||||||
APPVERSION_N=1
|
APPVERSION_N=2
|
||||||
APPVERSION_P=1
|
APPVERSION_P=0
|
||||||
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
|
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
|
||||||
|
|
||||||
ifeq ($(TARGET_NAME),TARGET_BLUE)
|
ifeq ($(TARGET_NAME),TARGET_BLUE)
|
||||||
@ -96,7 +89,7 @@ LDLIBS += -lm -lgcc -lc
|
|||||||
include $(BOLOS_SDK)/Makefile.glyphs
|
include $(BOLOS_SDK)/Makefile.glyphs
|
||||||
|
|
||||||
### variables processed by the common makefile.rules of the SDK to grab source files and include dirs
|
### variables processed by the common makefile.rules of the SDK to grab source files and include dirs
|
||||||
APP_SOURCE_PATH += src src/lib_stusb_impl
|
APP_SOURCE_PATH += src
|
||||||
SDK_SOURCE_PATH += lib_stusb
|
SDK_SOURCE_PATH += lib_stusb
|
||||||
|
|
||||||
|
|
||||||
@ -107,7 +100,7 @@ delete:
|
|||||||
python -m ledgerblue.deleteApp $(COMMON_DELETE_PARAMS)
|
python -m ledgerblue.deleteApp $(COMMON_DELETE_PARAMS)
|
||||||
|
|
||||||
# import generic rules from the sdk
|
# import generic rules from the sdk
|
||||||
include $(BOLOS_SDK)/Makefile.rules
|
include Makefile.rules
|
||||||
|
|
||||||
#add dependency on custom makefile filename
|
#add dependency on custom makefile filename
|
||||||
dep/%.d: %.c Makefile
|
dep/%.d: %.c Makefile
|
||||||
|
29
Makefile.rules
Normal file
29
Makefile.rules
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#*******************************************************************************
|
||||||
|
# Ledger SDK
|
||||||
|
# (c) 2017 Ledger
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#*******************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
#Make the SDK modified SDK sources prioritar to the original ones
|
||||||
|
|
||||||
|
SOURCE_PATH += $(dir $(foreach libdir, $(APP_SOURCE_PATH), $(dir $(shell find $(libdir) | grep "\.c$$")))) $(BOLOS_SDK)/src $(foreach libdir, $(SDK_SOURCE_PATH), $(dir $(shell find $(BOLOS_SDK)/$(libdir) | grep "\.c$$")))
|
||||||
|
SOURCE_FILES := $(foreach path, $(SOURCE_PATH),$(shell find $(path) | grep "\.c$$") ) $(GLYPH_DESTC)
|
||||||
|
INCLUDES_PATH := $(dir $(foreach libdir, $(APP_SOURCE_PATH), $(dir $(shell find $(libdir) | grep "\.h$$")))) $(dir $(foreach libdir, $(SDK_SOURCE_PATH), $(dir $(shell find $(BOLOS_SDK)/$(libdir) | grep "\.h$$")))) include $(BOLOS_SDK)/include $(BOLOS_SDK)/include/arm
|
||||||
|
|
||||||
|
VPATH := $(dir $(SOURCE_FILES))
|
||||||
|
OBJECT_FILES := $(sort $(addprefix obj/, $(addsuffix .o, $(basename $(notdir $(SOURCE_FILES))))))
|
||||||
|
DEPEND_FILES := $(sort $(addprefix dep/, $(addsuffix .d, $(basename $(notdir $(SOURCE_FILES))))))
|
||||||
|
|
||||||
|
include $(BOLOS_SDK)/Makefile.rules_generic
|
Binary file not shown.
@ -185,6 +185,7 @@ The full menu layout is :
|
|||||||
| Set on
|
| Set on
|
||||||
| Set off
|
| Set off
|
||||||
| PIN mode
|
| PIN mode
|
||||||
|
| UIF mode
|
||||||
| \ *Choose:*
|
| \ *Choose:*
|
||||||
| Host
|
| Host
|
||||||
| On Screen
|
| On Screen
|
||||||
@ -246,8 +247,39 @@ A key template is defined by the OpenGPG card application specification. It
|
|||||||
describes the key to be generated with the ``generate`` command in
|
describes the key to be generated with the ``generate`` command in
|
||||||
``gpg --card-edit``
|
``gpg --card-edit``
|
||||||
|
|
||||||
The problem is there is no way with the ``gpg`` command line to easily set
|
The problem is there is no way with the ``gpg --card-edit`` command line
|
||||||
up the desired template. The menu fixes that.
|
to easily set up the desired template, except for Ed25519.
|
||||||
|
|
||||||
|
To set up a new ECC template you have tow choice: the NanoS menu or the
|
||||||
|
gpg-connect-agent tools.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**gpg-connect-agent** (recommended)
|
||||||
|
|
||||||
|
This method suppose you have correctly configured your GnuPG tool.
|
||||||
|
See the dedicated section for that.
|
||||||
|
|
||||||
|
In a terminal launch :
|
||||||
|
|
||||||
|
gpg-connect-agent "SCD SETATTR KEY-ATTR --force 1 <tag> <curvename>" /bye
|
||||||
|
gpg-connect-agent "SCD SETATTR KEY-ATTR --force 2 18 <curvename>" /bye
|
||||||
|
gpg-connect-agent "SCD SETATTR KEY-ATTR --force 3 <tag> <curvename>" /bye
|
||||||
|
|
||||||
|
This 3 commands fix, in that order, the template for Signature, Decryption, Authentication keys.
|
||||||
|
|
||||||
|
Supported curve name are:
|
||||||
|
|
||||||
|
- secp256k1 with tag 19
|
||||||
|
- nistp256 with tag 19
|
||||||
|
- brainpoolP256r1 with tag 19
|
||||||
|
- cv25519 (only for key 2)
|
||||||
|
- ed25519 with tag 22 (only for key 1 and 3)
|
||||||
|
|
||||||
|
|
||||||
|
To show the current template use the ``gpg --card-status`` command.
|
||||||
|
|
||||||
|
**NanoS menu**
|
||||||
|
|
||||||
First under *Choose Key* menu, select the one of three keys for which you want to modify
|
First under *Choose Key* menu, select the one of three keys for which you want to modify
|
||||||
the template. Then under "Choose Type", select the desired key template.
|
the template. Then under "Choose Type", select the desired key template.
|
||||||
@ -255,10 +287,11 @@ Finally select "Set Template" entry to set it.
|
|||||||
|
|
||||||
To show the current template use the ``gpg --card-status`` command.
|
To show the current template use the ``gpg --card-status`` command.
|
||||||
|
|
||||||
|
|
||||||
Seed mode
|
Seed mode
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
|
**WARNING** : SEED MODE IS EXPERIMENTAL
|
||||||
|
|
||||||
When generating new keys on NanoS, those keys can be generated randomly
|
When generating new keys on NanoS, those keys can be generated randomly
|
||||||
or in a deterministic way. The deterministic way is specified in [GPGADD].
|
or in a deterministic way. The deterministic way is specified in [GPGADD].
|
||||||
The current mode is displayed in the first sub menu. To activate the seeded
|
The current mode is displayed in the first sub menu. To activate the seeded
|
||||||
@ -266,6 +299,7 @@ The current mode is displayed in the first sub menu. To activate the seeded
|
|||||||
|
|
||||||
When the application starts, the seeded mode is always set to *OFF*
|
When the application starts, the seeded mode is always set to *OFF*
|
||||||
|
|
||||||
|
**WARNING** : SEED MODE IS EXPERIMENTAL
|
||||||
|
|
||||||
PIN mode
|
PIN mode
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
@ -340,6 +374,17 @@ This is the default mode after application installation.
|
|||||||
Act as if the PIN is always validated. This is a dangerous mode which should only be
|
Act as if the PIN is always validated. This is a dangerous mode which should only be
|
||||||
used in a highly secure environment.
|
used in a highly secure environment.
|
||||||
|
|
||||||
|
UIF mode
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
|
By activating UIF mode for either signature, decryption or authentication, a user validation
|
||||||
|
will be ask by the device each time the related operation is performed.
|
||||||
|
|
||||||
|
To activate or deactivate the UIF, select the operation to protect and press both button.
|
||||||
|
When activated, a '+' symbol appears after the operation name.
|
||||||
|
|
||||||
|
|
||||||
Reset
|
Reset
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
|
|
||||||
void USBD_CCID_activate_pinpad(int enabled);
|
void USBD_CCID_activate_pinpad(int enabled);
|
||||||
|
|
||||||
int gpg_oid2curve(unsigned char* oid, unsigned int len);
|
unsigned int gpg_oid2curve(unsigned char* oid, unsigned int len);
|
||||||
|
unsigned char* gpg_curve2oid(unsigned int cv, unsigned int *len);
|
||||||
|
unsigned int gpg_curve2domainlen(unsigned int cv);
|
||||||
|
|
||||||
void gpg_init(void);
|
void gpg_init(void);
|
||||||
void gpg_init_ux(void);
|
void gpg_init_ux(void);
|
||||||
|
@ -367,34 +367,25 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||||||
//check length
|
//check length
|
||||||
ksz = (keygpg->attributes.value[1]<<8)|keygpg->attributes.value[2];
|
ksz = (keygpg->attributes.value[1]<<8)|keygpg->attributes.value[2];
|
||||||
ksz = ksz >> 3;
|
ksz = ksz >> 3;
|
||||||
|
rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa.public;
|
||||||
|
rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa.private;
|
||||||
|
pkey = &keygpg->priv_key.rsa;
|
||||||
switch(ksz) {
|
switch(ksz) {
|
||||||
case 1024/8:
|
case 1024/8:
|
||||||
rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa1024.public;
|
|
||||||
rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa1024.private;
|
|
||||||
pkey = (cx_rsa_private_key_t*)&keygpg->key.rsa1024;
|
|
||||||
pkey_size = sizeof(cx_rsa_1024_private_key_t);
|
pkey_size = sizeof(cx_rsa_1024_private_key_t);
|
||||||
pq = G_gpg_vstate.work.rsa1024.public.n;
|
pq = G_gpg_vstate.work.rsa.public1024.n;
|
||||||
break;
|
break;
|
||||||
case 2048/8:
|
case 2048/8:
|
||||||
rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa2048.public;
|
|
||||||
rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa2048.private;
|
|
||||||
pkey = (cx_rsa_private_key_t*)&keygpg->key.rsa2048;
|
|
||||||
pkey_size = sizeof(cx_rsa_2048_private_key_t);
|
pkey_size = sizeof(cx_rsa_2048_private_key_t);
|
||||||
pq = G_gpg_vstate.work.rsa2048.public.n;
|
pq = G_gpg_vstate.work.rsa.public2048.n;
|
||||||
break;
|
break;
|
||||||
case 3072/8:
|
case 3072/8:
|
||||||
rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa3072.public;
|
|
||||||
rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa3072.private;
|
|
||||||
pkey = (cx_rsa_private_key_t*)&keygpg->key.rsa3072;
|
|
||||||
pkey_size = sizeof(cx_rsa_3072_private_key_t);
|
pkey_size = sizeof(cx_rsa_3072_private_key_t);
|
||||||
pq = G_gpg_vstate.work.rsa3072.public.n;
|
pq = G_gpg_vstate.work.rsa.public3072.n;
|
||||||
break;
|
break;
|
||||||
case 4096/8:
|
case 4096/8:
|
||||||
rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa4096.public;
|
|
||||||
rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa4096.private;
|
|
||||||
pkey = (cx_rsa_private_key_t*)&keygpg->key.rsa4096;
|
|
||||||
pkey_size = sizeof(cx_rsa_4096_private_key_t);
|
pkey_size = sizeof(cx_rsa_4096_private_key_t);
|
||||||
pq = G_gpg_vstate.work.rsa4096.public.n;
|
pq = G_gpg_vstate.work.rsa.public4096.n;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ksz = ksz>>1;
|
ksz = ksz>>1;
|
||||||
@ -460,14 +451,14 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||||||
THROW(SW_WRONG_DATA);
|
THROW(SW_WRONG_DATA);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ksz = 32;
|
ksz = gpg_curve2domainlen(curve);
|
||||||
if (ksz == 32) {
|
if (ksz == len_p) {
|
||||||
G_gpg_vstate.work.ecfp256.private.curve = curve;
|
G_gpg_vstate.work.ecfp.private.curve = curve;
|
||||||
G_gpg_vstate.work.ecfp256.private.d_len = ksz;
|
G_gpg_vstate.work.ecfp.private.d_len = ksz;
|
||||||
os_memmove(G_gpg_vstate.work.ecfp256.private.d, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,ksz);
|
os_memmove(G_gpg_vstate.work.ecfp.private.d, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,ksz);
|
||||||
cx_ecfp_generate_pair(curve, &G_gpg_vstate.work.ecfp256.public, &G_gpg_vstate.work.ecfp256.private, 1);
|
cx_ecfp_generate_pair(curve, &G_gpg_vstate.work.ecfp.public, &G_gpg_vstate.work.ecfp.private, 1);
|
||||||
nvm_write(&keygpg->pub_key.ecfp256, &G_gpg_vstate.work.ecfp256.public, sizeof(cx_ecfp_public_key_t));
|
nvm_write(&keygpg->pub_key.ecfp, &G_gpg_vstate.work.ecfp.public, sizeof(cx_ecfp_public_key_t));
|
||||||
nvm_write(&keygpg->key.ecfp256, &G_gpg_vstate.work.ecfp256.private, sizeof(cx_ecfp_private_key_t));
|
nvm_write(&keygpg->priv_key.ecfp, &G_gpg_vstate.work.ecfp.private, sizeof(cx_ecfp_private_key_t));
|
||||||
if (reset_cnt) {
|
if (reset_cnt) {
|
||||||
reset_cnt = 0;
|
reset_cnt = 0;
|
||||||
nvm_write(&G_gpg_vstate.kslot->sig_count,&reset_cnt,sizeof(unsigned int));
|
nvm_write(&G_gpg_vstate.kslot->sig_count,&reset_cnt,sizeof(unsigned int));
|
||||||
|
@ -113,29 +113,20 @@ int gpg_apdu_gen() {
|
|||||||
|
|
||||||
ksz = (keygpg->attributes.value[1]<<8)|keygpg->attributes.value[2];
|
ksz = (keygpg->attributes.value[1]<<8)|keygpg->attributes.value[2];
|
||||||
ksz = ksz >> 3;
|
ksz = ksz >> 3;
|
||||||
|
rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa.public;
|
||||||
|
rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa.private;
|
||||||
|
pkey = &keygpg->priv_key.rsa;
|
||||||
switch(ksz) {
|
switch(ksz) {
|
||||||
case 1024/8:
|
case 1024/8:
|
||||||
rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa1024.public;
|
|
||||||
rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa1024.private;
|
|
||||||
pkey = (cx_rsa_private_key_t*)&keygpg->key.rsa1024;
|
|
||||||
pkey_size = sizeof(cx_rsa_1024_private_key_t);
|
pkey_size = sizeof(cx_rsa_1024_private_key_t);
|
||||||
break;
|
break;
|
||||||
case 2048/8:
|
case 2048/8:
|
||||||
rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa2048.public;
|
|
||||||
rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa2048.private;
|
|
||||||
pkey = (cx_rsa_private_key_t*)&keygpg->key.rsa2048;
|
|
||||||
pkey_size = sizeof(cx_rsa_2048_private_key_t);
|
pkey_size = sizeof(cx_rsa_2048_private_key_t);
|
||||||
break;
|
break;
|
||||||
case 3072/8:
|
case 3072/8:
|
||||||
rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa3072.public;
|
|
||||||
rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa3072.private;
|
|
||||||
pkey = (cx_rsa_private_key_t*)&keygpg->key.rsa3072;
|
|
||||||
pkey_size = sizeof(cx_rsa_3072_private_key_t);
|
pkey_size = sizeof(cx_rsa_3072_private_key_t);
|
||||||
break;
|
break;
|
||||||
case 4096/8:
|
case 4096/8:
|
||||||
rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa4096.public;
|
|
||||||
rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa4096.private;
|
|
||||||
pkey = (cx_rsa_private_key_t*)&keygpg->key.rsa4096;
|
|
||||||
pkey_size = sizeof(cx_rsa_4096_private_key_t);
|
pkey_size = sizeof(cx_rsa_4096_private_key_t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -173,19 +164,24 @@ int gpg_apdu_gen() {
|
|||||||
unsigned int curve,keepprivate;
|
unsigned int curve,keepprivate;
|
||||||
keepprivate = 0;
|
keepprivate = 0;
|
||||||
curve = gpg_oid2curve(keygpg->attributes.value+1, keygpg->attributes.length-1);
|
curve = gpg_oid2curve(keygpg->attributes.value+1, keygpg->attributes.length-1);
|
||||||
|
if (curve == CX_CURVE_NONE) {
|
||||||
|
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||||
|
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||||
|
}
|
||||||
if ((G_gpg_vstate.io_p2 == 0x01) | (G_gpg_vstate.seed_mode)) {
|
if ((G_gpg_vstate.io_p2 == 0x01) | (G_gpg_vstate.seed_mode)) {
|
||||||
|
ksz = gpg_curve2domainlen(curve);
|
||||||
gpg_pso_derive_slot_seed(G_gpg_vstate.slot, seed);
|
gpg_pso_derive_slot_seed(G_gpg_vstate.slot, seed);
|
||||||
gpg_pso_derive_key_seed(seed, name, 1, seed, 32);
|
gpg_pso_derive_key_seed(seed, name, 1, seed, ksz);
|
||||||
cx_ecfp_init_private_key(curve,seed, 32, &G_gpg_vstate.work.ecfp256.private);
|
cx_ecfp_init_private_key(curve,seed, ksz, &G_gpg_vstate.work.ecfp.private);
|
||||||
keepprivate = 1;
|
keepprivate = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx_ecfp_generate_pair(curve,
|
cx_ecfp_generate_pair(curve,
|
||||||
&G_gpg_vstate.work.ecfp256.public,
|
&G_gpg_vstate.work.ecfp.public,
|
||||||
&G_gpg_vstate.work.ecfp256.private,
|
&G_gpg_vstate.work.ecfp.private,
|
||||||
keepprivate);
|
keepprivate);
|
||||||
nvm_write(&keygpg->key.ecfp256, &G_gpg_vstate.work.ecfp256.private, sizeof(cx_ecfp_private_key_t));
|
nvm_write(&keygpg->priv_key.ecfp, &G_gpg_vstate.work.ecfp.private, sizeof(cx_ecfp_private_key_t));
|
||||||
nvm_write(&keygpg->pub_key.ecfp256, &G_gpg_vstate.work.ecfp256.public, sizeof(cx_ecfp_public_key_t));
|
nvm_write(&keygpg->pub_key.ecfp, &G_gpg_vstate.work.ecfp.public, sizeof(cx_ecfp_public_key_t));
|
||||||
if (reset_cnt) {
|
if (reset_cnt) {
|
||||||
reset_cnt = 0;
|
reset_cnt = 0;
|
||||||
nvm_write(&G_gpg_vstate.kslot->sig_count,&reset_cnt,sizeof(unsigned int));
|
nvm_write(&G_gpg_vstate.kslot->sig_count,&reset_cnt,sizeof(unsigned int));
|
||||||
@ -207,32 +203,32 @@ int gpg_apdu_gen() {
|
|||||||
gpg_io_mark();
|
gpg_io_mark();
|
||||||
switch(ksz) {
|
switch(ksz) {
|
||||||
case 1024/8:
|
case 1024/8:
|
||||||
if (keygpg->key.rsa1024.size == 0) {
|
if (keygpg->priv_key.rsa1024.size == 0) {
|
||||||
THROW (SW_REFERENCED_DATA_NOT_FOUND);
|
THROW (SW_REFERENCED_DATA_NOT_FOUND);
|
||||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa1024.n);
|
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->priv_key.rsa1024.n);
|
||||||
break;
|
break;
|
||||||
case 2048/8:
|
case 2048/8:
|
||||||
if (keygpg->key.rsa2048.size == 0) {
|
if (keygpg->priv_key.rsa2048.size == 0) {
|
||||||
THROW (SW_REFERENCED_DATA_NOT_FOUND);
|
THROW (SW_REFERENCED_DATA_NOT_FOUND);
|
||||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa2048.n);
|
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->priv_key.rsa2048.n);
|
||||||
break;
|
break;
|
||||||
case 3072/8:
|
case 3072/8:
|
||||||
if (keygpg->key.rsa3072.size == 0) {
|
if (keygpg->priv_key.rsa3072.size == 0) {
|
||||||
THROW (SW_REFERENCED_DATA_NOT_FOUND);
|
THROW (SW_REFERENCED_DATA_NOT_FOUND);
|
||||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa3072.n);
|
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->priv_key.rsa3072.n);
|
||||||
break;
|
break;
|
||||||
case 4096/8:
|
case 4096/8:
|
||||||
if (keygpg->key.rsa4096.size == 0) {
|
if (keygpg->priv_key.rsa4096.size == 0) {
|
||||||
THROW (SW_REFERENCED_DATA_NOT_FOUND);
|
THROW (SW_REFERENCED_DATA_NOT_FOUND);
|
||||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa4096.n);
|
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->priv_key.rsa4096.n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gpg_io_insert_tlv(0x82, 4, keygpg->pub_key.rsa);
|
gpg_io_insert_tlv(0x82, 4, keygpg->pub_key.rsa);
|
||||||
|
165
src/gpg_init.c
165
src/gpg_init.c
@ -32,24 +32,47 @@ const unsigned char C_MAGIC[8] = {
|
|||||||
/* --ECC OID -- */
|
/* --ECC OID -- */
|
||||||
/* ----------------------*/
|
/* ----------------------*/
|
||||||
|
|
||||||
//secp256k1: 1.3.132.0.10
|
/*
|
||||||
const unsigned char C_OID_SECP256K1[5] = {
|
//brainpool 256t1: 1.3.36.3.3.2.8.1.1.8
|
||||||
0x2B, 0x81, 0x04, 0x00, 0x0A
|
const unsigned char C_OID_BRAINPOOL256T1[9] = {
|
||||||
|
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
//secp256r1 / NIST P256 /ansi-x9.62 : 1.2.840.10045.3.1.7
|
//secp256r1 / NIST P256 /ansi-x9.62 : 1.2.840.10045.3.1.7
|
||||||
const unsigned char C_OID_SECP256R1[8] = {
|
const unsigned char C_OID_SECP256R1[8] = {
|
||||||
0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07
|
0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07
|
||||||
};
|
};
|
||||||
|
//secp384r1 / NIST P384 /ansi-x9.62 :1.3.132.0.34
|
||||||
|
const unsigned char C_OID_SECP384R1[5] = {
|
||||||
|
0x2B, 0x81, 0x04, 0x00 , 0x22
|
||||||
|
};
|
||||||
|
//secp521r1 / NIST P521 /ansi-x9.62 : 1.3.132.0.35
|
||||||
|
const unsigned char C_OID_SECP521R1[5] = {
|
||||||
|
0x2B, 0x81, 0x04, 0x00, 0x23
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//secp256k1: 1.3.132.0.10
|
||||||
|
const unsigned char C_OID_SECP256K1[5] = {
|
||||||
|
0x2B, 0x81, 0x04, 0x00, 0x0A
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//brainpool 256r1: 1.3.36.3.3.2.8.1.1.7
|
//brainpool 256r1: 1.3.36.3.3.2.8.1.1.7
|
||||||
const unsigned char C_OID_BRAINPOOL256R1[9] = {
|
const unsigned char C_OID_BRAINPOOL256R1[9] = {
|
||||||
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x08
|
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x08
|
||||||
};
|
};
|
||||||
//brainpool 256t1: 1.3.36.3.3.2.8.1.1.8
|
//brainpool 284r1: 1.3.36.3.3.2.8.1.1.11
|
||||||
const unsigned char C_OID_BRAINPOOL256T1[9] = {
|
const unsigned char C_OID_BRAINPOOL384R1[9] = {
|
||||||
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07
|
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B
|
||||||
};
|
};
|
||||||
|
//brainpool 512r1: 1.3.36.3.3.2.8.1.1.13
|
||||||
|
const unsigned char C_OID_BRAINPOOL512R1[9] = {
|
||||||
|
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//Ed25519/curve25519: 1.3.6.1.4.1.11591.15.1
|
//Ed25519/curve25519: 1.3.6.1.4.1.11591.15.1
|
||||||
const unsigned char C_OID_Ed25519[9] = {
|
const unsigned char C_OID_Ed25519[9] = {
|
||||||
0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01,
|
0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01,
|
||||||
@ -60,10 +83,29 @@ const unsigned char C_OID_cv25519[10] = {
|
|||||||
0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01,
|
0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01,
|
||||||
};
|
};
|
||||||
|
|
||||||
int gpg_oid2curve(unsigned char* oid, unsigned int len) {
|
unsigned int gpg_oid2curve(unsigned char* oid, unsigned int len) {
|
||||||
|
if ( (len == sizeof(C_OID_SECP256K1)) && (os_memcmp(oid, C_OID_SECP256K1, len)==0) ) {
|
||||||
|
return CX_CURVE_SECP256K1;
|
||||||
|
}
|
||||||
|
|
||||||
if ( (len == sizeof(C_OID_SECP256R1)) && (os_memcmp(oid, C_OID_SECP256R1, len)==0) ) {
|
if ( (len == sizeof(C_OID_SECP256R1)) && (os_memcmp(oid, C_OID_SECP256R1, len)==0) ) {
|
||||||
return CX_CURVE_256R1;
|
return CX_CURVE_SECP256R1;
|
||||||
|
}
|
||||||
|
if ( (len == sizeof(C_OID_SECP384R1)) && (os_memcmp(oid, C_OID_SECP384R1, len)==0) ) {
|
||||||
|
return CX_CURVE_SECP384R1;
|
||||||
|
}
|
||||||
|
if ( (len == sizeof(C_OID_SECP521R1)) && (os_memcmp(oid, C_OID_SECP521R1, len)==0) ) {
|
||||||
|
return CX_CURVE_SECP521R1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (len == sizeof(C_OID_BRAINPOOL256R1)) && (os_memcmp(oid, C_OID_BRAINPOOL256R1, len)==0) ) {
|
||||||
|
return CX_CURVE_BrainPoolP256R1;
|
||||||
|
}
|
||||||
|
if ( (len == sizeof(C_OID_BRAINPOOL384R1)) && (os_memcmp(oid, C_OID_BRAINPOOL384R1, len)==0) ) {
|
||||||
|
return CX_CURVE_BrainPoolP384R1;
|
||||||
|
}
|
||||||
|
if ( (len == sizeof(C_OID_BRAINPOOL512R1)) && (os_memcmp(oid, C_OID_BRAINPOOL512R1, len)==0) ) {
|
||||||
|
return CX_CURVE_BrainPoolP512R1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (len == sizeof(C_OID_Ed25519)) && (os_memcmp(oid, C_OID_Ed25519, len)==0) ) {
|
if ( (len == sizeof(C_OID_Ed25519)) && (os_memcmp(oid, C_OID_Ed25519, len)==0) ) {
|
||||||
@ -74,20 +116,86 @@ int gpg_oid2curve(unsigned char* oid, unsigned int len) {
|
|||||||
return CX_CURVE_Curve25519;
|
return CX_CURVE_Curve25519;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if ( (len == sizeof(C_OID_SECP256K1)) && (os_memcmp(oid, C_OID_SECP256K1, len)==0) ) {
|
if ( (len == sizeof(C_OID_SECP256K1)) && (os_memcmp(oid, C_OID_SECP256K1, len)==0) ) {
|
||||||
return CX_CURVE_256K1;
|
return CX_CURVE_256K1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (len == sizeof(C_OID_BRAINPOOL256R1)) && (os_memcmp(oid, C_OID_BRAINPOOL256R1, len)==0) ) {
|
|
||||||
return CX_CURVE_BrainPoolP256R1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (len == sizeof(C_OID_BRAINPOOL256T1)) && (os_memcmp(oid, C_OID_BRAINPOOL256T1, len)==0) ) {
|
if ( (len == sizeof(C_OID_BRAINPOOL256T1)) && (os_memcmp(oid, C_OID_BRAINPOOL256T1, len)==0) ) {
|
||||||
return CX_CURVE_BrainPoolP256T1;
|
return CX_CURVE_BrainPoolP256T1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return CX_CURVE_NONE;
|
return CX_CURVE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char* gpg_curve2oid(unsigned int cv, unsigned int *len) {
|
||||||
|
switch (cv) {
|
||||||
|
|
||||||
|
case CX_CURVE_SECP256K1:
|
||||||
|
*len = sizeof(C_OID_SECP256K1);
|
||||||
|
return (unsigned char*)PIC(C_OID_SECP256K1);
|
||||||
|
|
||||||
|
case CX_CURVE_SECP256R1:
|
||||||
|
*len = sizeof(C_OID_SECP256R1);
|
||||||
|
return (unsigned char*)PIC(C_OID_SECP256R1);
|
||||||
|
|
||||||
|
case CX_CURVE_SECP384R1:
|
||||||
|
*len = sizeof(C_OID_SECP384R1);
|
||||||
|
return (unsigned char*)PIC(C_OID_SECP384R1);
|
||||||
|
|
||||||
|
case CX_CURVE_SECP521R1:
|
||||||
|
*len = sizeof(C_OID_SECP521R1);
|
||||||
|
return (unsigned char*)PIC(C_OID_SECP521R1);
|
||||||
|
|
||||||
|
case CX_CURVE_BrainPoolP256R1:
|
||||||
|
*len = sizeof(C_OID_SECP256R1);
|
||||||
|
return (unsigned char*)PIC(C_OID_SECP256R1);
|
||||||
|
|
||||||
|
case CX_CURVE_BrainPoolP384R1:
|
||||||
|
*len = sizeof(C_OID_SECP384R1);
|
||||||
|
return (unsigned char*)PIC(C_OID_SECP384R1);
|
||||||
|
|
||||||
|
case CX_CURVE_BrainPoolP512R1:
|
||||||
|
*len = sizeof(C_OID_SECP521R1);
|
||||||
|
return (unsigned char*)PIC(C_OID_SECP521R1);
|
||||||
|
|
||||||
|
case CX_CURVE_Ed25519:
|
||||||
|
*len = sizeof(C_OID_Ed25519);
|
||||||
|
return (unsigned char*)PIC(C_OID_Ed25519);
|
||||||
|
|
||||||
|
case CX_CURVE_Curve25519:
|
||||||
|
*len = sizeof(C_OID_cv25519);
|
||||||
|
return (unsigned char*)PIC(C_OID_cv25519);
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int gpg_curve2domainlen(unsigned int cv) {
|
||||||
|
switch (cv) {
|
||||||
|
|
||||||
|
case CX_CURVE_SECP256K1:
|
||||||
|
case CX_CURVE_SECP256R1:
|
||||||
|
case CX_CURVE_BrainPoolP256R1:
|
||||||
|
case CX_CURVE_Ed25519:
|
||||||
|
case CX_CURVE_Curve25519:
|
||||||
|
return 32;
|
||||||
|
|
||||||
|
case CX_CURVE_SECP384R1:
|
||||||
|
case CX_CURVE_BrainPoolP384R1:
|
||||||
|
return 48;
|
||||||
|
|
||||||
|
case CX_CURVE_BrainPoolP512R1:
|
||||||
|
return 64;
|
||||||
|
|
||||||
|
case CX_CURVE_SECP521R1:
|
||||||
|
return 66;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------*/
|
/* -------------------------------*/
|
||||||
/* -- Non Mutable Capabilities -- */
|
/* -- Non Mutable Capabilities -- */
|
||||||
/* -------------------------------*/
|
/* -------------------------------*/
|
||||||
@ -123,7 +231,7 @@ const unsigned char C_ext_length[8] = {
|
|||||||
const unsigned char C_default_AID[] = {
|
const unsigned char C_default_AID[] = {
|
||||||
0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
|
0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
|
||||||
//version
|
//version
|
||||||
0x03, 0x00,
|
0x03, 0x03,
|
||||||
//manufacturer
|
//manufacturer
|
||||||
0x2C, 0x97,
|
0x2C, 0x97,
|
||||||
//serial
|
//serial
|
||||||
@ -155,7 +263,7 @@ const unsigned char C_default_AlgoAttrRSA[] = {
|
|||||||
0x01
|
0x01
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
const unsigned char C_default_AlgoAttrECC_sig[] = {
|
const unsigned char C_default_AlgoAttrECC_sig[] = {
|
||||||
// ecdsa
|
// ecdsa
|
||||||
0x13,
|
0x13,
|
||||||
@ -168,8 +276,20 @@ const unsigned char C_default_AlgoAttrECC_dec[] = {
|
|||||||
// NIST-P256
|
// NIST-P256
|
||||||
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07
|
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07
|
||||||
};
|
};
|
||||||
|
#elif 0
|
||||||
#else
|
const unsigned char C_default_AlgoAttrECC_sig[] = {
|
||||||
|
// ecdsa
|
||||||
|
0x13,
|
||||||
|
// NIST-P384
|
||||||
|
0x2B, 0x81, 0x04, 0x00 , 0x22
|
||||||
|
};
|
||||||
|
const unsigned char C_default_AlgoAttrECC_dec[] = {
|
||||||
|
// ecdh
|
||||||
|
0x12,
|
||||||
|
// NIST-P384
|
||||||
|
0x2B, 0x81, 0x04, 0x00 , 0x22
|
||||||
|
};
|
||||||
|
#elif 1
|
||||||
const unsigned char C_default_AlgoAttrECC_sig[] = {
|
const unsigned char C_default_AlgoAttrECC_sig[] = {
|
||||||
// eddsa
|
// eddsa
|
||||||
0x16,
|
0x16,
|
||||||
@ -283,7 +403,6 @@ int gpg_install(unsigned char app_state) {
|
|||||||
gpg_nvm_write(&N_gpg_pstate->config_slot, G_gpg_vstate.work.io_buffer, 3);
|
gpg_nvm_write(&N_gpg_pstate->config_slot, G_gpg_vstate.work.io_buffer, 3);
|
||||||
|
|
||||||
//config rsa pub
|
//config rsa pub
|
||||||
#define GPG_RSA_DEFAULT_PUB 0x00010001
|
|
||||||
G_gpg_vstate.work.io_buffer[0] = (GPG_RSA_DEFAULT_PUB>>24)&0xFF;
|
G_gpg_vstate.work.io_buffer[0] = (GPG_RSA_DEFAULT_PUB>>24)&0xFF;
|
||||||
G_gpg_vstate.work.io_buffer[1] = (GPG_RSA_DEFAULT_PUB>>16)&0xFF;
|
G_gpg_vstate.work.io_buffer[1] = (GPG_RSA_DEFAULT_PUB>>16)&0xFF;
|
||||||
G_gpg_vstate.work.io_buffer[2] = (GPG_RSA_DEFAULT_PUB>>8)&0xFF;
|
G_gpg_vstate.work.io_buffer[2] = (GPG_RSA_DEFAULT_PUB>>8)&0xFF;
|
||||||
@ -304,7 +423,10 @@ int gpg_install(unsigned char app_state) {
|
|||||||
//default key template: RSA 2048)
|
//default key template: RSA 2048)
|
||||||
|
|
||||||
for (int s = 0; s< GPG_KEYS_SLOTS; s++) {
|
for (int s = 0; s< GPG_KEYS_SLOTS; s++) {
|
||||||
#if 0
|
unsigned char uif[2];
|
||||||
|
uif[0] = 0x00;
|
||||||
|
uif[1] = 0x20;
|
||||||
|
#if 1
|
||||||
l = sizeof(C_default_AlgoAttrRSA);
|
l = sizeof(C_default_AlgoAttrRSA);
|
||||||
gpg_nvm_write(&N_gpg_pstate->keys[s].sig.attributes.value, (void*)C_default_AlgoAttrRSA, l);
|
gpg_nvm_write(&N_gpg_pstate->keys[s].sig.attributes.value, (void*)C_default_AlgoAttrRSA, l);
|
||||||
gpg_nvm_write(&N_gpg_pstate->keys[s].sig.attributes.length, &l, sizeof(unsigned int));
|
gpg_nvm_write(&N_gpg_pstate->keys[s].sig.attributes.length, &l, sizeof(unsigned int));
|
||||||
@ -322,6 +444,11 @@ int gpg_install(unsigned char app_state) {
|
|||||||
gpg_nvm_write(&N_gpg_pstate->keys[s].dec.attributes.value, (void*)C_default_AlgoAttrECC_dec, l);
|
gpg_nvm_write(&N_gpg_pstate->keys[s].dec.attributes.value, (void*)C_default_AlgoAttrECC_dec, l);
|
||||||
gpg_nvm_write(&N_gpg_pstate->keys[s].dec.attributes.length, &l, sizeof(unsigned int));
|
gpg_nvm_write(&N_gpg_pstate->keys[s].dec.attributes.length, &l, sizeof(unsigned int));
|
||||||
#endif
|
#endif
|
||||||
|
gpg_nvm_write(&N_gpg_pstate->keys[s].sig.UIF, &uif, 2);
|
||||||
|
gpg_nvm_write(&N_gpg_pstate->keys[s].dec.UIF, &uif, 2);
|
||||||
|
gpg_nvm_write(&N_gpg_pstate->keys[s].aut.UIF, &uif, 2);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "gpg_types.h"
|
#include "gpg_types.h"
|
||||||
#include "gpg_api.h"
|
#include "gpg_api.h"
|
||||||
#include "gpg_vars.h"
|
#include "gpg_vars.h"
|
||||||
|
#include "gpg_ux_nanos.h"
|
||||||
|
|
||||||
const unsigned char gpg_oid_sha256[] = {
|
const unsigned char gpg_oid_sha256[] = {
|
||||||
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||||
@ -41,16 +42,16 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
|||||||
ksz = ksz>>3;
|
ksz = ksz>>3;
|
||||||
switch(ksz) {
|
switch(ksz) {
|
||||||
case 1024/8:
|
case 1024/8:
|
||||||
key = (cx_rsa_private_key_t *)&sigkey->key.rsa1024;
|
key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa1024;
|
||||||
break;
|
break;
|
||||||
case 2048/8:
|
case 2048/8:
|
||||||
key = (cx_rsa_private_key_t *)&sigkey->key.rsa2048;
|
key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa2048;
|
||||||
break;
|
break;
|
||||||
case 3072/8:
|
case 3072/8:
|
||||||
key = (cx_rsa_private_key_t *)&sigkey->key.rsa3072;
|
key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa3072;
|
||||||
break;
|
break;
|
||||||
case 4096/8:
|
case 4096/8:
|
||||||
key = (cx_rsa_private_key_t *)&sigkey->key.rsa4096;
|
key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa4096;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (key->size != ksz) {
|
if (key->size != ksz) {
|
||||||
@ -83,21 +84,21 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
|||||||
if ((sigkey->attributes.value[0] == 19) ||
|
if ((sigkey->attributes.value[0] == 19) ||
|
||||||
(sigkey->attributes.value[0] == 22)) {
|
(sigkey->attributes.value[0] == 22)) {
|
||||||
cx_ecfp_private_key_t *key;
|
cx_ecfp_private_key_t *key;
|
||||||
unsigned int sz,i,rs_len,info;
|
unsigned int sz,i,rs_len;
|
||||||
unsigned char *rs;
|
unsigned char *rs;
|
||||||
|
|
||||||
key = &sigkey->key.ecfp256;
|
key = &sigkey->priv_key.ecfp;
|
||||||
if (key->d_len != 32) {
|
//sign
|
||||||
|
if (sigkey->attributes.value[0] == 19) {
|
||||||
|
sz = gpg_curve2domainlen(key->curve);
|
||||||
|
if ((sz == 0) || (key->d_len != sz)) {
|
||||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||||
return SW_CONDITIONS_NOT_SATISFIED;
|
return SW_CONDITIONS_NOT_SATISFIED;
|
||||||
}
|
}
|
||||||
//sign
|
|
||||||
if (sigkey->attributes.value[0] == 19) {
|
|
||||||
|
|
||||||
sz = cx_ecdsa_sign(key,
|
sz = cx_ecdsa_sign(key,
|
||||||
CX_RND_TRNG,
|
CX_RND_TRNG,
|
||||||
CX_NONE,
|
CX_NONE,
|
||||||
G_gpg_vstate.work.io_buffer, 32/*G_gpg_vstate.io_length*/,
|
G_gpg_vstate.work.io_buffer, sz,
|
||||||
G_gpg_vstate.work.io_buffer, GPG_IO_BUFFER_LENGTH,
|
G_gpg_vstate.work.io_buffer, GPG_IO_BUFFER_LENGTH,
|
||||||
NULL);
|
NULL);
|
||||||
//reencode r,s in MPI format
|
//reencode r,s in MPI format
|
||||||
@ -149,19 +150,27 @@ int gpg_apdu_pso() {
|
|||||||
switch(pso) {
|
switch(pso) {
|
||||||
// --- PSO:CDS ---
|
// --- PSO:CDS ---
|
||||||
case 0x9e9a:
|
case 0x9e9a:
|
||||||
if ((G_gpg_vstate.kslot->sig.UIF[0]) && ((G_gpg_vstate.UIF_flags)==0)) {
|
if (G_gpg_vstate.kslot->sig.UIF[0]) {
|
||||||
|
if ((G_gpg_vstate.UIF_flags)==0) {
|
||||||
ui_menu_uifconfirm_display(0);
|
ui_menu_uifconfirm_display(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
G_gpg_vstate.UIF_flags = 0;
|
||||||
case 0x8680:
|
}
|
||||||
if ((G_gpg_vstate.kslot->dec.UIF[0]) && ((G_gpg_vstate.UIF_flags)==0)) {
|
break;
|
||||||
|
// --- PSO:DEC ---
|
||||||
|
case 0x8096:
|
||||||
|
if (G_gpg_vstate.kslot->dec.UIF[0]) {
|
||||||
|
if ((G_gpg_vstate.UIF_flags)==0) {
|
||||||
ui_menu_uifconfirm_display(0);
|
ui_menu_uifconfirm_display(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
G_gpg_vstate.UIF_flags = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- PSO:ENC ---
|
||||||
switch(pso) {
|
switch(pso) {
|
||||||
// --- PSO:CDS ---
|
// --- PSO:CDS ---
|
||||||
case 0x9e9a: {
|
case 0x9e9a: {
|
||||||
@ -214,16 +223,16 @@ int gpg_apdu_pso() {
|
|||||||
key = NULL;
|
key = NULL;
|
||||||
switch(ksz) {
|
switch(ksz) {
|
||||||
case 1024/8:
|
case 1024/8:
|
||||||
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa1024;
|
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa1024;
|
||||||
break;
|
break;
|
||||||
case 2048/8:
|
case 2048/8:
|
||||||
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa2048;
|
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa2048;
|
||||||
break;
|
break;
|
||||||
case 3072/8:
|
case 3072/8:
|
||||||
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa3072;
|
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa3072;
|
||||||
break;
|
break;
|
||||||
case 4096/8:
|
case 4096/8:
|
||||||
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa4096;
|
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa4096;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,11 +281,7 @@ int gpg_apdu_pso() {
|
|||||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||||
return SW_CONDITIONS_NOT_SATISFIED;
|
return SW_CONDITIONS_NOT_SATISFIED;
|
||||||
}
|
}
|
||||||
key = &G_gpg_vstate.mse_dec->key.ecfp256;
|
key = &G_gpg_vstate.mse_dec->priv_key.ecfp;
|
||||||
if (key->d_len != 32) {
|
|
||||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
|
||||||
return SW_CONDITIONS_NOT_SATISFIED;
|
|
||||||
}
|
|
||||||
gpg_io_fetch_l(&l);
|
gpg_io_fetch_l(&l);
|
||||||
gpg_io_fetch_tl(&t, &l);
|
gpg_io_fetch_tl(&t, &l);
|
||||||
if (t != 0x7f49) {
|
if (t != 0x7f49) {
|
||||||
@ -290,6 +295,10 @@ int gpg_apdu_pso() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
curve = gpg_oid2curve(G_gpg_vstate.mse_dec->attributes.value+1, G_gpg_vstate.mse_dec->attributes.length-1);
|
curve = gpg_oid2curve(G_gpg_vstate.mse_dec->attributes.value+1, G_gpg_vstate.mse_dec->attributes.length-1);
|
||||||
|
if (key->curve != curve) {
|
||||||
|
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||||
|
return SW_CONDITIONS_NOT_SATISFIED;
|
||||||
|
}
|
||||||
if (curve == CX_CURVE_Curve25519) {
|
if (curve == CX_CURVE_Curve25519) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -335,10 +344,14 @@ int gpg_apdu_pso() {
|
|||||||
|
|
||||||
|
|
||||||
int gpg_apdu_internal_authenticate() {
|
int gpg_apdu_internal_authenticate() {
|
||||||
if ((G_gpg_vstate.kslot->aut.UIF[0]) && ((G_gpg_vstate.UIF_flags)==0)) {
|
// --- PSO:AUTH ---
|
||||||
|
if (G_gpg_vstate.kslot->aut.UIF[0]) {
|
||||||
|
if ((G_gpg_vstate.UIF_flags)==0) {
|
||||||
ui_menu_uifconfirm_display(0);
|
ui_menu_uifconfirm_display(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
G_gpg_vstate.UIF_flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (G_gpg_vstate.mse_aut->attributes.value[0] == 1) {
|
if (G_gpg_vstate.mse_aut->attributes.value[0] == 1) {
|
||||||
if ( G_gpg_vstate.io_length > ((G_gpg_vstate.mse_aut->attributes.value[1]<<8)|G_gpg_vstate.mse_aut->attributes.value[2])*40/100) {
|
if ( G_gpg_vstate.io_length > ((G_gpg_vstate.mse_aut->attributes.value[1]<<8)|G_gpg_vstate.mse_aut->attributes.value[2])*40/100) {
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
#define GPG_KEY_ATTRIBUTES_LENGTH 12
|
#define GPG_KEY_ATTRIBUTES_LENGTH 12
|
||||||
|
|
||||||
#define GPG_RSA_DEFAULT_PUB 0x010001U
|
#define GPG_RSA_DEFAULT_PUB 0x00010001U
|
||||||
|
|
||||||
struct gpg_pin_s {
|
struct gpg_pin_s {
|
||||||
unsigned int ref;
|
unsigned int ref;
|
||||||
@ -66,15 +66,25 @@ typedef struct gpg_key_s {
|
|||||||
LV(attributes,GPG_KEY_ATTRIBUTES_LENGTH);
|
LV(attributes,GPG_KEY_ATTRIBUTES_LENGTH);
|
||||||
/* key value */
|
/* key value */
|
||||||
union {
|
union {
|
||||||
|
cx_rsa_private_key_t rsa;
|
||||||
cx_rsa_1024_private_key_t rsa1024;
|
cx_rsa_1024_private_key_t rsa1024;
|
||||||
cx_rsa_2048_private_key_t rsa2048;
|
cx_rsa_2048_private_key_t rsa2048;
|
||||||
cx_rsa_3072_private_key_t rsa3072;
|
cx_rsa_3072_private_key_t rsa3072;
|
||||||
cx_rsa_4096_private_key_t rsa4096;
|
cx_rsa_4096_private_key_t rsa4096;
|
||||||
cx_ecfp_private_key_t ecfp256;
|
|
||||||
} key;
|
cx_ecfp_private_key_t ecfp;
|
||||||
|
cx_ecfp_256_private_key_t ecfp256;
|
||||||
|
cx_ecfp_384_private_key_t ecfp384;
|
||||||
|
cx_ecfp_512_private_key_t ecfp512;
|
||||||
|
cx_ecfp_640_private_key_t ecfp640;
|
||||||
|
} priv_key;
|
||||||
union {
|
union {
|
||||||
unsigned char rsa[4];
|
unsigned char rsa[4];
|
||||||
cx_ecfp_public_key_t ecfp256;
|
cx_ecfp_public_key_t ecfp;
|
||||||
|
cx_ecfp_256_public_key_t ecfp256;
|
||||||
|
cx_ecfp_384_public_key_t ecfp384;
|
||||||
|
cx_ecfp_512_public_key_t ecfp512;
|
||||||
|
cx_ecfp_640_public_key_t ecfp640;
|
||||||
} pub_key;
|
} pub_key;
|
||||||
/* C7 C8 C9 , C5 = C7|C8|C9*/
|
/* C7 C8 C9 , C5 = C7|C8|C9*/
|
||||||
unsigned char fingerprints[20];
|
unsigned char fingerprints[20];
|
||||||
@ -193,26 +203,41 @@ struct gpg_v_state_s {
|
|||||||
unsigned short io_mark;
|
unsigned short io_mark;
|
||||||
union {
|
union {
|
||||||
unsigned char io_buffer[GPG_IO_BUFFER_LENGTH];
|
unsigned char io_buffer[GPG_IO_BUFFER_LENGTH];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
cx_rsa_1024_public_key_t public;
|
union {
|
||||||
cx_rsa_1024_private_key_t private;
|
cx_rsa_public_key_t public;
|
||||||
}rsa1024;
|
cx_rsa_1024_public_key_t public1024;
|
||||||
struct {
|
cx_rsa_2048_public_key_t public2048;
|
||||||
cx_rsa_2048_public_key_t public;
|
cx_rsa_3072_public_key_t public3072;
|
||||||
cx_rsa_2048_private_key_t private;
|
cx_rsa_4096_public_key_t public4096;
|
||||||
}rsa2048;
|
};
|
||||||
struct {
|
union {
|
||||||
cx_rsa_3072_public_key_t public;
|
cx_rsa_private_key_t private;
|
||||||
cx_rsa_3072_private_key_t private;
|
cx_rsa_1024_private_key_t private1024;
|
||||||
}rsa3072;
|
cx_rsa_2048_private_key_t private2048;
|
||||||
struct {
|
cx_rsa_3072_private_key_t private3072;
|
||||||
cx_rsa_4096_public_key_t public;
|
cx_rsa_4096_private_key_t private4096;
|
||||||
cx_rsa_4096_private_key_t private;
|
};
|
||||||
}rsa4096;
|
} rsa;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
union{
|
||||||
cx_ecfp_public_key_t public;
|
cx_ecfp_public_key_t public;
|
||||||
|
cx_ecfp_256_public_key_t public256;
|
||||||
|
cx_ecfp_384_public_key_t public384;
|
||||||
|
cx_ecfp_512_public_key_t public512;
|
||||||
|
cx_ecfp_640_public_key_t public640;
|
||||||
|
};
|
||||||
|
union {
|
||||||
cx_ecfp_private_key_t private;
|
cx_ecfp_private_key_t private;
|
||||||
}ecfp256;
|
cx_ecfp_256_private_key_t private256;
|
||||||
|
cx_ecfp_384_private_key_t private384;
|
||||||
|
cx_ecfp_512_private_key_t private512;
|
||||||
|
cx_ecfp_640_private_key_t private640;
|
||||||
|
};
|
||||||
|
}ecfp;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
unsigned char md_buffer[GPG_IO_BUFFER_LENGTH-MAX(sizeof(cx_sha3_t),sizeof(cx_sha256_t))];
|
unsigned char md_buffer[GPG_IO_BUFFER_LENGTH-MAX(sizeof(cx_sha3_t),sizeof(cx_sha256_t))];
|
||||||
union {
|
union {
|
||||||
|
@ -34,3 +34,5 @@ const char * const C_NOT_ALLOWED = "Not Allowed ";
|
|||||||
|
|
||||||
const char * const C_DEFAULT_MODE = "Default mode";
|
const char * const C_DEFAULT_MODE = "Default mode";
|
||||||
|
|
||||||
|
|
||||||
|
const char * const C_UIF_LOCKED = "UIF locked";
|
||||||
|
@ -36,6 +36,9 @@ extern const char * const C_NOT_ALLOWED;
|
|||||||
|
|
||||||
extern const char * const C_DEFAULT_MODE;
|
extern const char * const C_DEFAULT_MODE;
|
||||||
|
|
||||||
|
extern const char * const C_UIF_LOCKED;
|
||||||
|
extern const char * const C_UIF_INVALID;
|
||||||
|
|
||||||
#define PICSTR(x) ((char*)PIC(x))
|
#define PICSTR(x) ((char*)PIC(x))
|
||||||
|
|
||||||
#define TEMPLATE_TYPE PICSTR(C_TEMPLATE_TYPE)
|
#define TEMPLATE_TYPE PICSTR(C_TEMPLATE_TYPE)
|
||||||
@ -54,5 +57,7 @@ extern const char * const C_DEFAULT_MODE;
|
|||||||
#define ALLOWED PICSTR(C_ALLOWED)
|
#define ALLOWED PICSTR(C_ALLOWED)
|
||||||
#define NOT_ALLOWED PICSTR(C_NOT_ALLOWED)
|
#define NOT_ALLOWED PICSTR(C_NOT_ALLOWED)
|
||||||
#define DEFAULT_MODE PICSTR(C_DEFAULT_MODE)
|
#define DEFAULT_MODE PICSTR(C_DEFAULT_MODE)
|
||||||
|
#define UIF_LOCKED PICSTR(C_UIF_LOCKED)
|
||||||
|
#define UIF_INVALID PICSTR(C_UIF_INVALID)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -134,7 +134,7 @@ void ui_menu_uifconfirm_display(unsigned int value) {
|
|||||||
|
|
||||||
unsigned int ui_uifconfirm_prepro(const bagl_element_t* element) {
|
unsigned int ui_uifconfirm_prepro(const bagl_element_t* element) {
|
||||||
if (element->component.userid == 1) {
|
if (element->component.userid == 1) {
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Confirm Operation:");
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Confirm:");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (element->component.userid == 2) {
|
if (element->component.userid == 2) {
|
||||||
@ -175,7 +175,14 @@ unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int b
|
|||||||
BEGIN_TRY {
|
BEGIN_TRY {
|
||||||
TRY {
|
TRY {
|
||||||
G_gpg_vstate.UIF_flags = 1;
|
G_gpg_vstate.UIF_flags = 1;
|
||||||
|
if (G_gpg_vstate.io_ins == INS_PSO) {
|
||||||
sw = gpg_apdu_pso();
|
sw = gpg_apdu_pso();
|
||||||
|
} else if (G_gpg_vstate.io_ins == INS_INTERNAL_AUTHENTICATE) {
|
||||||
|
sw = gpg_apdu_internal_authenticate();
|
||||||
|
} else {
|
||||||
|
gpg_io_discard(1);
|
||||||
|
sw = 0x6985;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CATCH_OTHER(e) {
|
CATCH_OTHER(e) {
|
||||||
gpg_io_discard(1);
|
gpg_io_discard(1);
|
||||||
@ -503,7 +510,12 @@ static unsigned int validate_pin() {
|
|||||||
#define LABEL_RSA3072 "RSA 3072"
|
#define LABEL_RSA3072 "RSA 3072"
|
||||||
#define LABEL_RSA4096 "RSA 4096"
|
#define LABEL_RSA4096 "RSA 4096"
|
||||||
#define LABEL_NISTP256 "NIST P256"
|
#define LABEL_NISTP256 "NIST P256"
|
||||||
#define LABEL_BPOOLR1 "Brainpool R1"
|
//#define LABEL_NISTP384 "NIST P384"
|
||||||
|
//#define LABEL_NISTP521 "NIST P521"
|
||||||
|
#define LABEL_SECP256K1 "SEPC 256K1"
|
||||||
|
#define LABEL_BPOOL256R1 "Brainpool 256R1"
|
||||||
|
//#define LABEL_BPOOL384R1 "Brainpool 384R1"
|
||||||
|
//#define LABEL_BPOOL512R1 "Brainpool 512R1"
|
||||||
#define LABEL_Ed25519 "Ed25519"
|
#define LABEL_Ed25519 "Ed25519"
|
||||||
|
|
||||||
const ux_menu_entry_t ui_menu_template[] = {
|
const ux_menu_entry_t ui_menu_template[] = {
|
||||||
@ -548,12 +560,34 @@ const bagl_element_t* ui_menu_template_preprocessor(const ux_menu_entry_t* entry
|
|||||||
case 4096:
|
case 4096:
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_RSA4096);
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_RSA4096);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CX_CURVE_SECP256R1:
|
case CX_CURVE_SECP256R1:
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_NISTP256);
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_NISTP256);
|
||||||
break;
|
break;
|
||||||
case CX_CURVE_BrainPoolP256R1:
|
/*
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOLR1);
|
case CX_CURVE_SECP384R1:
|
||||||
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_NISTP384);
|
||||||
break;
|
break;
|
||||||
|
case CX_CURVE_SECP521R1:
|
||||||
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_NISTP521);
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
case CX_CURVE_SECP256K1:
|
||||||
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_SECP256K1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX_CURVE_BrainPoolP256R1:
|
||||||
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOL256R1);
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
case CX_CURVE_BrainPoolP384R1:
|
||||||
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOL384R1);
|
||||||
|
break;
|
||||||
|
case CX_CURVE_BrainPoolP512R1:
|
||||||
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOL512R1);
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
|
||||||
case CX_CURVE_Ed25519:
|
case CX_CURVE_Ed25519:
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_Ed25519);
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_Ed25519);
|
||||||
break;
|
break;
|
||||||
@ -574,7 +608,8 @@ void ui_menu_tmpl_set_action(unsigned int value) {
|
|||||||
LV(attributes,GPG_KEY_ATTRIBUTES_LENGTH);
|
LV(attributes,GPG_KEY_ATTRIBUTES_LENGTH);
|
||||||
gpg_key_t* dest;
|
gpg_key_t* dest;
|
||||||
const char* err;
|
const char* err;
|
||||||
|
const unsigned char *oid;
|
||||||
|
unsigned int oid_len;
|
||||||
err = NULL;
|
err = NULL;
|
||||||
|
|
||||||
os_memset(&attributes, 0, sizeof(attributes));
|
os_memset(&attributes, 0, sizeof(attributes));
|
||||||
@ -591,24 +626,21 @@ void ui_menu_tmpl_set_action(unsigned int value) {
|
|||||||
attributes.length = 6;
|
attributes.length = 6;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CX_CURVE_SECP256K1:
|
||||||
case CX_CURVE_SECP256R1:
|
case CX_CURVE_SECP256R1:
|
||||||
if (G_gpg_vstate.ux_key == 2) {
|
//case CX_CURVE_SECP384R1:
|
||||||
attributes.value[0] = 18; //ecdh
|
//case CX_CURVE_SECP521R1:
|
||||||
} else {
|
|
||||||
attributes.value[0] = 19; //ecdsa
|
|
||||||
}
|
|
||||||
os_memmove(attributes.value+1, C_OID_SECP256R1, sizeof(C_OID_SECP256R1));
|
|
||||||
attributes.length = 1+sizeof(C_OID_SECP256R1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CX_CURVE_BrainPoolP256R1:
|
case CX_CURVE_BrainPoolP256R1:
|
||||||
|
//case CX_CURVE_BrainPoolP384R1:
|
||||||
|
//case CX_CURVE_BrainPoolP512R1:
|
||||||
if (G_gpg_vstate.ux_key == 2) {
|
if (G_gpg_vstate.ux_key == 2) {
|
||||||
attributes.value[0] = 18; //ecdh
|
attributes.value[0] = 18; //ecdh
|
||||||
} else {
|
} else {
|
||||||
attributes.value[0] = 19; //ecdsa
|
attributes.value[0] = 19; //ecdsa
|
||||||
}
|
}
|
||||||
os_memmove(attributes.value+1, C_OID_BRAINPOOL256R1, sizeof(C_OID_BRAINPOOL256R1));
|
oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len);
|
||||||
attributes.length = 1+sizeof(C_OID_BRAINPOOL256R1);
|
os_memmove(attributes.value+1, oid, sizeof(oid_len));
|
||||||
|
attributes.length = 1+oid_len;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CX_CURVE_Ed25519:
|
case CX_CURVE_Ed25519:
|
||||||
@ -674,7 +706,12 @@ const ux_menu_entry_t ui_menu_tmpl_type[] = {
|
|||||||
{NULL, ui_menu_tmpl_type_action, 3072, NULL, LABEL_RSA3072, NULL, 0, 0},
|
{NULL, ui_menu_tmpl_type_action, 3072, NULL, LABEL_RSA3072, NULL, 0, 0},
|
||||||
{NULL, ui_menu_tmpl_type_action, 4096, NULL, LABEL_RSA4096, NULL, 0, 0},
|
{NULL, ui_menu_tmpl_type_action, 4096, NULL, LABEL_RSA4096, NULL, 0, 0},
|
||||||
{NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256R1, NULL, LABEL_NISTP256, NULL, 0, 0},
|
{NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256R1, NULL, LABEL_NISTP256, NULL, 0, 0},
|
||||||
{NULL, ui_menu_tmpl_type_action, CX_CURVE_BrainPoolP256R1, NULL, LABEL_BPOOLR1, NULL, 0, 0},
|
// {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP384R1, NULL, LABEL_NISTP384, NULL, 0, 0},
|
||||||
|
// {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP521R1, NULL, LABEL_NISTP521, NULL, 0, 0},
|
||||||
|
{NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256K1, NULL, LABEL_SECP256K1, NULL, 0, 0},
|
||||||
|
{NULL, ui_menu_tmpl_type_action, CX_CURVE_BrainPoolP256R1, NULL, LABEL_BPOOL256R1, NULL, 0, 0},
|
||||||
|
// {NULL, ui_menu_tmpl_type_action, CX_CURVE_BrainPoolP384R1, NULL, LABEL_BPOOL384R1, NULL, 0, 0},
|
||||||
|
// {NULL, ui_menu_tmpl_type_action, CX_CURVE_BrainPoolP512R1, NULL, LABEL_BPOOL512R1, NULL, 0, 0},
|
||||||
{NULL, ui_menu_tmpl_type_action, CX_CURVE_Ed25519, NULL, LABEL_Ed25519, NULL, 0, 0},
|
{NULL, ui_menu_tmpl_type_action, CX_CURVE_Ed25519, NULL, LABEL_Ed25519, NULL, 0, 0},
|
||||||
{ui_menu_template, NULL, 1, &C_badge_back, "Back", NULL, 61, 40},
|
{ui_menu_template, NULL, 1, &C_badge_back, "Back", NULL, 61, 40},
|
||||||
UX_MENU_END
|
UX_MENU_END
|
||||||
@ -803,6 +840,84 @@ void ui_menu_pinmode_action(unsigned int value) {
|
|||||||
// redisplay first entry of the idle menu
|
// redisplay first entry of the idle menu
|
||||||
ui_menu_pinmode_display(0);
|
ui_menu_pinmode_display(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------- UIF MODE UX ------------------------------ */
|
||||||
|
const ux_menu_entry_t ui_menu_uifmode[];
|
||||||
|
void ui_menu_uifmode_display(unsigned int value);
|
||||||
|
const bagl_element_t* ui_menu_uifmode_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element);
|
||||||
|
void ui_menu_uifmode_action(unsigned int value);
|
||||||
|
|
||||||
|
const ux_menu_entry_t ui_menu_uifmode[] = {
|
||||||
|
{NULL, NULL, -1, NULL, "Activate (+) for:", NULL, 0, 0},
|
||||||
|
{NULL, ui_menu_uifmode_action, 1, NULL, "Signature", NULL, 0, 0},
|
||||||
|
{NULL, ui_menu_uifmode_action, 2, NULL, "Decryption", NULL, 0, 0},
|
||||||
|
{NULL, ui_menu_uifmode_action, 3, NULL, "Authentication", NULL, 0, 0},
|
||||||
|
{ui_menu_settings, NULL, 1, &C_badge_back, "Back", NULL, 61, 40},
|
||||||
|
UX_MENU_END
|
||||||
|
};
|
||||||
|
|
||||||
|
void ui_menu_uifmode_display(unsigned int value) {
|
||||||
|
UX_MENU_DISPLAY(value, ui_menu_uifmode, ui_menu_uifmode_preprocessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bagl_element_t* ui_menu_uifmode_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element) {
|
||||||
|
if (element->component.userid==0x20) {
|
||||||
|
if ((entry->userid >= 1) && (entry->userid<=3)) {
|
||||||
|
unsigned char uif[2] ;
|
||||||
|
uif[0] = 0;
|
||||||
|
uif[1] = 0;
|
||||||
|
switch (entry->userid) {
|
||||||
|
case 1:
|
||||||
|
*uif = G_gpg_vstate.kslot->sig.UIF[0]?'+':' ';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
*uif = G_gpg_vstate.kslot->dec.UIF[0]?'+':' ';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
*uif = G_gpg_vstate.kslot->aut.UIF[0]?'+':' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s %s",
|
||||||
|
(char*)PIC(entry->line1), uif);
|
||||||
|
element->text = G_gpg_vstate.menu;
|
||||||
|
element->component.height = 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_menu_uifmode_action(unsigned int value) {
|
||||||
|
unsigned char *uif;
|
||||||
|
unsigned char new_uif;
|
||||||
|
switch (value) {
|
||||||
|
case 1:
|
||||||
|
uif = &G_gpg_vstate.kslot->sig.UIF[0];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
uif = &G_gpg_vstate.kslot->dec.UIF[0];
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
uif = &G_gpg_vstate.kslot->aut.UIF[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ui_info(INVALID_SELECTION, NULL, ui_menu_uifmode_display,0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (uif[0] == 0) {
|
||||||
|
new_uif = 1;
|
||||||
|
gpg_nvm_write(&uif[0], &new_uif, 1);
|
||||||
|
} else if (uif[0] == 1) {
|
||||||
|
new_uif = 0;
|
||||||
|
gpg_nvm_write(&uif[0], &new_uif, 1) ;
|
||||||
|
} else /*if (uif[0] == 2 )*/ {
|
||||||
|
ui_info(UIF_LOCKED, NULL, ui_menu_uifmode_display,0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ui_menu_uifmode_display(value);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------- RESET UX --------------------------------- */
|
/* -------------------------------- RESET UX --------------------------------- */
|
||||||
|
|
||||||
const ux_menu_entry_t ui_menu_reset[] = {
|
const ux_menu_entry_t ui_menu_reset[] = {
|
||||||
@ -829,6 +944,7 @@ const ux_menu_entry_t ui_menu_settings[] = {
|
|||||||
{NULL, ui_menu_template_display, 0, NULL, "Key template", NULL, 0, 0},
|
{NULL, ui_menu_template_display, 0, NULL, "Key template", NULL, 0, 0},
|
||||||
{NULL, ui_menu_seed_display, 0, NULL, "Seed mode", NULL, 0, 0},
|
{NULL, ui_menu_seed_display, 0, NULL, "Seed mode", NULL, 0, 0},
|
||||||
{NULL, ui_menu_pinmode_display, 0, NULL, "PIN mode", NULL, 0, 0},
|
{NULL, ui_menu_pinmode_display, 0, NULL, "PIN mode", NULL, 0, 0},
|
||||||
|
{NULL, ui_menu_uifmode_display, 0, NULL, "UIF mode", NULL, 0, 0},
|
||||||
{ui_menu_reset, NULL, 0, NULL, "Reset", NULL, 0, 0},
|
{ui_menu_reset, NULL, 0, NULL, "Reset", NULL, 0, 0},
|
||||||
{NULL, ui_menu_main_display, 2, &C_badge_back, "Back", NULL, 61, 40},
|
{NULL, ui_menu_main_display, 2, &C_badge_back, "Back", NULL, 61, 40},
|
||||||
UX_MENU_END
|
UX_MENU_END
|
||||||
|
@ -22,4 +22,5 @@ void ui_init(void);
|
|||||||
void ui_main_display(unsigned int value);
|
void ui_main_display(unsigned int value);
|
||||||
void ui_menu_pinconfirm_display(unsigned int value);
|
void ui_menu_pinconfirm_display(unsigned int value);
|
||||||
void ui_menu_pinentry_display(unsigned int value);
|
void ui_menu_pinentry_display(unsigned int value);
|
||||||
|
void ui_menu_uifconfirm_display(unsigned int value);
|
||||||
#endif
|
#endif
|
1057
src/sdk/usbd_ccid_cmd.c
Executable file
1057
src/sdk/usbd_ccid_cmd.c
Executable file
File diff suppressed because it is too large
Load Diff
617
src/sdk/usbd_ccid_if.c
Executable file
617
src/sdk/usbd_ccid_if.c
Executable file
@ -0,0 +1,617 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file usbd_ccid_if.c
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @version V1.0.1
|
||||||
|
* @date 31-January-2014
|
||||||
|
* @brief This file provides all the functions for USB Interface for CCID
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
|
||||||
|
*
|
||||||
|
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.st.com/software_license_agreement_liberty_v2
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma message "Override SDK source file :" __FILE__
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "os.h"
|
||||||
|
#include "usbd_ccid_if.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_USB_CLASS_CCID
|
||||||
|
|
||||||
|
#if CCID_BULK_EPIN_SIZE > USB_SEGMENT_SIZE
|
||||||
|
#error configuration error, the USB MAX SEGMENT SIZE does not support the CCID endpoint (CCID_BULK_EPIN_SIZE vs USB_SEGMENT_SIZE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Private typedef -----------------------------------------------------------*/
|
||||||
|
/* Private define ------------------------------------------------------------*/
|
||||||
|
/* Private macro -------------------------------------------------------------*/
|
||||||
|
/* Private variables ---------------------------------------------------------*/
|
||||||
|
usb_class_ccid_t G_io_ccid;
|
||||||
|
|
||||||
|
/* Private function prototypes -----------------------------------------------*/
|
||||||
|
static void CCID_Response_SendData (USBD_HandleTypeDef *pdev,
|
||||||
|
uint8_t* pbuf,
|
||||||
|
uint16_t len);
|
||||||
|
/* Private function ----------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief CCID_Init
|
||||||
|
* Initialize the CCID USB Layer
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void CCID_Init (USBD_HandleTypeDef *pdev)
|
||||||
|
{
|
||||||
|
memset(&G_io_ccid, 0, sizeof(G_io_ccid));
|
||||||
|
|
||||||
|
/* CCID Related Initialization */
|
||||||
|
#ifdef HAVE_CCID_INTERRUPT
|
||||||
|
CCID_SetIntrTransferStatus(1); /* Transfer Complete Status */
|
||||||
|
#endif // HAVE_CCID_INTERRUPT
|
||||||
|
CCID_UpdSlotChange(1);
|
||||||
|
SC_InitParams();
|
||||||
|
|
||||||
|
/* Prepare Out endpoint to receive 1st packet */
|
||||||
|
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
|
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
||||||
|
|
||||||
|
// send the smartcard as inserted state at boot time
|
||||||
|
io_usb_ccid_set_card_inserted(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCID_DeInit
|
||||||
|
* Uninitialize the CCID Machine
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void CCID_DeInit (USBD_HandleTypeDef *pdev)
|
||||||
|
{
|
||||||
|
UNUSED(pdev);
|
||||||
|
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCID_Message_In
|
||||||
|
* Handle Bulk IN & Intr IN data stage
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @param uint8_t epnum: endpoint index
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void CCID_BulkMessage_In (USBD_HandleTypeDef *pdev,
|
||||||
|
uint8_t epnum)
|
||||||
|
{
|
||||||
|
if (epnum == (CCID_BULK_IN_EP & 0x7F))
|
||||||
|
{/* Filter the epnum by masking with 0x7f (mask of IN Direction) */
|
||||||
|
|
||||||
|
/*************** Handle Bulk Transfer IN data completion *****************/
|
||||||
|
|
||||||
|
switch (G_io_ccid.Ccid_BulkState)
|
||||||
|
{
|
||||||
|
case CCID_STATE_SEND_RESP: {
|
||||||
|
unsigned int remLen = G_io_ccid.UsbMessageLength;
|
||||||
|
|
||||||
|
// advance with acknowledged sent chunk
|
||||||
|
if (G_io_ccid.pUsbMessageBuffer == &G_io_ccid.bulk_header) {
|
||||||
|
// first part of the bulk in sent.
|
||||||
|
// advance in the data buffer to transmit. (mixed source leap)
|
||||||
|
G_io_ccid.pUsbMessageBuffer = G_io_ccid_data_buffer+MIN(CCID_BULK_EPIN_SIZE, G_io_ccid.UsbMessageLength)-CCID_HEADER_SIZE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
G_io_ccid.pUsbMessageBuffer += MIN(CCID_BULK_EPIN_SIZE, G_io_ccid.UsbMessageLength);
|
||||||
|
}
|
||||||
|
G_io_ccid.UsbMessageLength -= MIN(CCID_BULK_EPIN_SIZE, G_io_ccid.UsbMessageLength);
|
||||||
|
|
||||||
|
// if remaining length is > EPIN_SIZE: send a filled bulk packet
|
||||||
|
if (G_io_ccid.UsbMessageLength >= CCID_BULK_EPIN_SIZE) {
|
||||||
|
CCID_Response_SendData(pdev, G_io_ccid.pUsbMessageBuffer,
|
||||||
|
// use the header declared size packet must be well formed
|
||||||
|
CCID_BULK_EPIN_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if remaining length is 0; send an empty packet and prepare to receive a new command
|
||||||
|
else if (G_io_ccid.UsbMessageLength == 0 && remLen == CCID_BULK_EPIN_SIZE) {
|
||||||
|
CCID_Response_SendData(pdev, G_io_ccid.pUsbMessageBuffer,
|
||||||
|
// use the header declared size packet must be well formed
|
||||||
|
0);
|
||||||
|
goto last_xfer; // won't wait ack to avoid missing a command
|
||||||
|
}
|
||||||
|
// else if no more data, then last packet sent, go back to idle (done on transfer ack)
|
||||||
|
else if (G_io_ccid.UsbMessageLength == 0) { // robustness only
|
||||||
|
last_xfer:
|
||||||
|
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
|
|
||||||
|
/* Prepare EP to Receive First Cmd */
|
||||||
|
// not timeout compliant // USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if remaining length is < EPIN_SIZE: send packet and prepare to receive a new command
|
||||||
|
else if (G_io_ccid.UsbMessageLength < CCID_BULK_EPIN_SIZE) {
|
||||||
|
CCID_Response_SendData(pdev, G_io_ccid.pUsbMessageBuffer,
|
||||||
|
// use the header declared size packet must be well formed
|
||||||
|
G_io_ccid.UsbMessageLength);
|
||||||
|
goto last_xfer; // won't wait ack to avoid missing a command
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef HAVE_CCID_INTERRUPT
|
||||||
|
else if (epnum == (CCID_INTR_IN_EP & 0x7F))
|
||||||
|
{
|
||||||
|
/* Filter the epnum by masking with 0x7f (mask of IN Direction) */
|
||||||
|
CCID_SetIntrTransferStatus(1); /* Transfer Complete Status */
|
||||||
|
}
|
||||||
|
#endif // HAVE_CCID_INTERRUPT
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCID_Send_Reply(USBD_HandleTypeDef *pdev) {
|
||||||
|
/********** Decide for all commands ***************/
|
||||||
|
if (G_io_ccid.Ccid_BulkState == CCID_STATE_SEND_RESP)
|
||||||
|
{
|
||||||
|
G_io_ccid.UsbMessageLength = G_io_ccid.bulk_header.bulkin.dwLength+CCID_HEADER_SIZE; /* Store for future use */
|
||||||
|
|
||||||
|
/* Expected Data Length Packet Received */
|
||||||
|
G_io_ccid.pUsbMessageBuffer = (uint8_t*) &G_io_ccid.bulk_header;
|
||||||
|
|
||||||
|
// send bulk header and first pat of the message at once
|
||||||
|
os_memmove(G_io_usb_ep_buffer, &G_io_ccid.bulk_header, CCID_HEADER_SIZE);
|
||||||
|
if (G_io_ccid.UsbMessageLength>CCID_HEADER_SIZE) {
|
||||||
|
// copy start of data if bigger size than a header
|
||||||
|
os_memmove(G_io_usb_ep_buffer+CCID_HEADER_SIZE, G_io_ccid_data_buffer, MIN(CCID_BULK_EPIN_SIZE, G_io_ccid.UsbMessageLength)-CCID_HEADER_SIZE);
|
||||||
|
}
|
||||||
|
// send the first mixed source chunk
|
||||||
|
CCID_Response_SendData(pdev, G_io_usb_ep_buffer,
|
||||||
|
// use the header declared size packet must be well formed
|
||||||
|
MIN(CCID_BULK_EPIN_SIZE, G_io_ccid.UsbMessageLength));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCID_BulkMessage_Out
|
||||||
|
* Proccess CCID OUT data
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @param uint8_t epnum: endpoint index
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void CCID_BulkMessage_Out (USBD_HandleTypeDef *pdev,
|
||||||
|
uint8_t epnum, uint8_t* buffer, uint16_t dataLen)
|
||||||
|
{
|
||||||
|
if (epnum == (CCID_BULK_OUT_EP & 0x7F)) {
|
||||||
|
switch (G_io_ccid.Ccid_BulkState)
|
||||||
|
{
|
||||||
|
|
||||||
|
// after a timeout, could be in almost any state :) therefore, clean it and process the newly received command
|
||||||
|
default:
|
||||||
|
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
|
// no break is intentional
|
||||||
|
|
||||||
|
case CCID_STATE_IDLE:
|
||||||
|
// prepare to receive another packet later on (to avoid troubles with timeout due to other hid command timeouting the ccid endpoint reply)
|
||||||
|
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
||||||
|
|
||||||
|
if (dataLen == 0x00)
|
||||||
|
{ /* Zero Length Packet Received, end of transfer */
|
||||||
|
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
|
}
|
||||||
|
else if (dataLen >= CCID_HEADER_SIZE)
|
||||||
|
{
|
||||||
|
G_io_ccid.UsbMessageLength = dataLen; /* Store for future use */
|
||||||
|
|
||||||
|
/* Expected Data Length Packet Received */
|
||||||
|
// endianness is little :) useful for our ARM convention
|
||||||
|
G_io_ccid.pUsbMessageBuffer = (uint8_t*) &G_io_ccid.bulk_header;
|
||||||
|
|
||||||
|
// copy the ccid bulk header only
|
||||||
|
os_memmove(G_io_ccid.pUsbMessageBuffer, buffer, CCID_HEADER_SIZE);
|
||||||
|
// copy remaining part in the data buffer (split from the ccid to allow for overlaying with another ressource buffer)
|
||||||
|
if (dataLen>CCID_HEADER_SIZE) {
|
||||||
|
os_memmove(G_io_ccid_data_buffer, buffer+CCID_HEADER_SIZE, dataLen-CCID_HEADER_SIZE);
|
||||||
|
// we're now receiving in the data buffer (all subsequent calls)
|
||||||
|
G_io_ccid.pUsbMessageBuffer = G_io_ccid_data_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_io_ccid.bulk_header.bulkout.dwLength > IO_CCID_DATA_BUFFER_SIZE)
|
||||||
|
{ /* Check if length of data to be sent by host is > buffer size */
|
||||||
|
|
||||||
|
/* Too long data received.... Error ! */
|
||||||
|
G_io_ccid.Ccid_BulkState = CCID_STATE_UNCORRECT_LENGTH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// everything received in the first packet
|
||||||
|
if (G_io_ccid.UsbMessageLength == (G_io_ccid.bulk_header.bulkout.dwLength + CCID_HEADER_SIZE)) {
|
||||||
|
/* Short message, less than the EP Out Size, execute the command,
|
||||||
|
if parameter like dwLength is too big, the appropriate command will
|
||||||
|
give an error */
|
||||||
|
CCID_CmdDecode(pdev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* Long message, receive additional data with command */
|
||||||
|
G_io_ccid.Ccid_BulkState = CCID_STATE_RECEIVE_DATA;
|
||||||
|
G_io_ccid.pUsbMessageBuffer += dataLen-CCID_HEADER_SIZE; /* Point to new offset */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CCID_STATE_RECEIVE_DATA:
|
||||||
|
|
||||||
|
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
||||||
|
|
||||||
|
G_io_ccid.UsbMessageLength += dataLen;
|
||||||
|
|
||||||
|
if (dataLen < CCID_BULK_EPOUT_SIZE)
|
||||||
|
{/* Short message, less than the EP Out Size, execute the command,
|
||||||
|
if parameter like dwLength is too big, the appropriate command will
|
||||||
|
give an error */
|
||||||
|
|
||||||
|
/* Full command is received, process the Command */
|
||||||
|
os_memmove(G_io_ccid.pUsbMessageBuffer, buffer, dataLen);
|
||||||
|
CCID_CmdDecode(pdev);
|
||||||
|
}
|
||||||
|
else //if (dataLen == CCID_BULK_EPOUT_SIZE)
|
||||||
|
{
|
||||||
|
if (G_io_ccid.UsbMessageLength < (G_io_ccid.bulk_header.bulkout.dwLength + CCID_HEADER_SIZE))
|
||||||
|
{
|
||||||
|
os_memmove(G_io_ccid.pUsbMessageBuffer, buffer, dataLen);
|
||||||
|
G_io_ccid.pUsbMessageBuffer += dataLen;
|
||||||
|
/* Increment the pointer to receive more data */
|
||||||
|
|
||||||
|
/* Prepare EP to Receive next Cmd */
|
||||||
|
// not timeout compliant // USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
||||||
|
}
|
||||||
|
else if (G_io_ccid.UsbMessageLength == (G_io_ccid.bulk_header.bulkout.dwLength + CCID_HEADER_SIZE))
|
||||||
|
{
|
||||||
|
/* Full command is received, process the Command */
|
||||||
|
os_memmove(G_io_ccid.pUsbMessageBuffer, buffer, dataLen);
|
||||||
|
CCID_CmdDecode(pdev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Too long data received.... Error ! */
|
||||||
|
G_io_ccid.Ccid_BulkState = CCID_STATE_UNCORRECT_LENGTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
case CCID_STATE_UNCORRECT_LENGTH:
|
||||||
|
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCID_CmdDecode
|
||||||
|
* Parse the commands and Proccess command
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void CCID_CmdDecode(USBD_HandleTypeDef *pdev)
|
||||||
|
{
|
||||||
|
uint8_t errorCode;
|
||||||
|
|
||||||
|
switch (G_io_ccid.bulk_header.bulkout.bMessageType)
|
||||||
|
{
|
||||||
|
case PC_TO_RDR_ICCPOWERON:
|
||||||
|
errorCode = PC_to_RDR_IccPowerOn();
|
||||||
|
RDR_to_PC_DataBlock(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_ICCPOWEROFF:
|
||||||
|
errorCode = PC_to_RDR_IccPowerOff();
|
||||||
|
RDR_to_PC_SlotStatus(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_GETSLOTSTATUS:
|
||||||
|
errorCode = PC_to_RDR_GetSlotStatus();
|
||||||
|
RDR_to_PC_SlotStatus(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_XFRBLOCK:
|
||||||
|
errorCode = PC_to_RDR_XfrBlock();
|
||||||
|
// asynchronous // RDR_to_PC_DataBlock(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_GETPARAMETERS:
|
||||||
|
errorCode = PC_to_RDR_GetParameters();
|
||||||
|
RDR_to_PC_Parameters(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_RESETPARAMETERS:
|
||||||
|
errorCode = PC_to_RDR_ResetParameters();
|
||||||
|
RDR_to_PC_Parameters(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_SETPARAMETERS:
|
||||||
|
errorCode = PC_to_RDR_SetParameters();
|
||||||
|
RDR_to_PC_Parameters(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_ESCAPE:
|
||||||
|
errorCode = PC_to_RDR_Escape();
|
||||||
|
RDR_to_PC_Escape(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_ICCCLOCK:
|
||||||
|
errorCode = PC_to_RDR_IccClock();
|
||||||
|
RDR_to_PC_SlotStatus(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_ABORT:
|
||||||
|
errorCode = PC_to_RDR_Abort();
|
||||||
|
RDR_to_PC_SlotStatus(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_T0APDU:
|
||||||
|
errorCode = PC_TO_RDR_T0Apdu();
|
||||||
|
RDR_to_PC_SlotStatus(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_MECHANICAL:
|
||||||
|
errorCode = PC_TO_RDR_Mechanical();
|
||||||
|
RDR_to_PC_SlotStatus(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY:
|
||||||
|
errorCode = PC_TO_RDR_SetDataRateAndClockFrequency();
|
||||||
|
RDR_to_PC_DataRateAndClockFrequency(errorCode);
|
||||||
|
break;
|
||||||
|
case PC_TO_RDR_SECURE:
|
||||||
|
errorCode = PC_TO_RDR_Secure();
|
||||||
|
// asynchronous // RDR_to_PC_DataBlock(errorCode);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RDR_to_PC_SlotStatus(SLOTERROR_CMD_NOT_SUPPORTED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCID_Send_Reply(pdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transfer_Data_Request
|
||||||
|
* Prepare the request response to be sent to the host
|
||||||
|
* @param uint8_t* dataPointer: Pointer to the data buffer to send
|
||||||
|
* @param uint16_t dataLen : number of bytes to send
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void Transfer_Data_Request(void)
|
||||||
|
{
|
||||||
|
/********** Update Global Variables ***************/
|
||||||
|
G_io_ccid.Ccid_BulkState = CCID_STATE_SEND_RESP;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCID_Response_SendData
|
||||||
|
* Send the data on bulk-in EP
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @param uint8_t* buf: pointer to data buffer
|
||||||
|
* @param uint16_t len: Data Length
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
static void CCID_Response_SendData(USBD_HandleTypeDef *pdev,
|
||||||
|
uint8_t* buf,
|
||||||
|
uint16_t len)
|
||||||
|
{
|
||||||
|
UNUSED(pdev);
|
||||||
|
// don't ask the MCU to perform bulk split, we could quickly get into a buffer overflow
|
||||||
|
if (len > CCID_BULK_EPIN_SIZE) {
|
||||||
|
THROW(EXCEPTION_IO_OVERFLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE;
|
||||||
|
G_io_seproxyhal_spi_buffer[1] = (3+len)>>8;
|
||||||
|
G_io_seproxyhal_spi_buffer[2] = (3+len);
|
||||||
|
G_io_seproxyhal_spi_buffer[3] = CCID_BULK_IN_EP;
|
||||||
|
G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN;
|
||||||
|
G_io_seproxyhal_spi_buffer[5] = len;
|
||||||
|
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6);
|
||||||
|
io_seproxyhal_spi_send(buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_CCID_INTERRUPT
|
||||||
|
/**
|
||||||
|
* @brief CCID_IntMessage
|
||||||
|
* Send the Interrupt-IN data to the host
|
||||||
|
* @param pdev: device instance
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void CCID_IntMessage(USBD_HandleTypeDef *pdev)
|
||||||
|
{
|
||||||
|
UNUSED(pdev);
|
||||||
|
/* Check if there us change in Smartcard Slot status */
|
||||||
|
if ( CCID_IsSlotStatusChange() && CCID_IsIntrTransferComplete() )
|
||||||
|
{
|
||||||
|
#ifdef HAVE_CCID_INTERRUPT
|
||||||
|
/* Check Slot Status is changed. Card is Removed/ Fitted */
|
||||||
|
RDR_to_PC_NotifySlotChange();
|
||||||
|
#endif // HAVE_CCID_INTERRUPT
|
||||||
|
|
||||||
|
CCID_SetIntrTransferStatus(0); /* Reset the Status */
|
||||||
|
CCID_UpdSlotChange(0); /* Reset the Status of Slot Change */
|
||||||
|
|
||||||
|
G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE;
|
||||||
|
G_io_seproxyhal_spi_buffer[1] = (3+2)>>8;
|
||||||
|
G_io_seproxyhal_spi_buffer[2] = (3+2);
|
||||||
|
G_io_seproxyhal_spi_buffer[3] = CCID_INTR_IN_EP;
|
||||||
|
G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN;
|
||||||
|
G_io_seproxyhal_spi_buffer[5] = 2;
|
||||||
|
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6);
|
||||||
|
io_seproxyhal_spi_send(G_io_ccid.UsbIntMessageBuffer, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCID_IsIntrTransferComplete
|
||||||
|
* Provides the status of previous Interrupt transfer status
|
||||||
|
* @param None
|
||||||
|
* @retval uint8_t PrevXferComplete_IntrIn: Value of the previous transfer status
|
||||||
|
*/
|
||||||
|
uint8_t CCID_IsIntrTransferComplete (void)
|
||||||
|
{
|
||||||
|
return G_io_ccid.PrevXferComplete_IntrIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCID_IsIntrTransferComplete
|
||||||
|
* Set the value of the Interrupt transfer status
|
||||||
|
* @param uint8_t xfer_Status: Value of the Interrupt transfer status to set
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void CCID_SetIntrTransferStatus (uint8_t xfer_Status)
|
||||||
|
{
|
||||||
|
G_io_ccid.PrevXferComplete_IntrIn = xfer_Status;
|
||||||
|
}
|
||||||
|
#endif // HAVE_CCID_INTERRUPT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t SC_Detect(void) {
|
||||||
|
return G_io_ccid.ccid_card_inserted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SC_InitParams (void) {
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SC_SetParams (Protocol0_DataStructure_t* pt0) {
|
||||||
|
UNUSED(pt0);
|
||||||
|
return SLOT_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t SC_SetClock (uint8_t bClockCommand) {
|
||||||
|
UNUSED(bClockCommand);
|
||||||
|
return SLOT_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SC_Request_GetClockFrequencies(uint8_t* pbuf, uint16_t* len);
|
||||||
|
uint8_t SC_Request_GetDataRates(uint8_t* pbuf, uint16_t* len);
|
||||||
|
uint8_t SC_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse,
|
||||||
|
uint8_t bClassEnvelope) {
|
||||||
|
UNUSED(bmChanges);
|
||||||
|
UNUSED(bClassGetResponse);
|
||||||
|
UNUSED(bClassEnvelope);
|
||||||
|
return SLOTERROR_CMD_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
uint8_t SC_Mechanical(uint8_t bFunction) {
|
||||||
|
UNUSED(bFunction);
|
||||||
|
return SLOTERROR_CMD_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
uint8_t SC_SetDataRateAndClockFrequency(uint32_t dwClockFrequency,
|
||||||
|
uint32_t dwDataRate) {
|
||||||
|
UNUSED(dwClockFrequency);
|
||||||
|
UNUSED(dwDataRate);
|
||||||
|
return SLOT_NO_ERROR;
|
||||||
|
}
|
||||||
|
uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter,
|
||||||
|
uint8_t* pbuf, uint32_t* returnLen ) {
|
||||||
|
UNUSED(bBWI);
|
||||||
|
UNUSED(wLevelParameter);
|
||||||
|
UNUSED(returnLen);
|
||||||
|
// return SLOTERROR_CMD_NOT_SUPPORTED;
|
||||||
|
uint16_t ret_len,off;
|
||||||
|
switch(pbuf[0])
|
||||||
|
{
|
||||||
|
case 0: // verify pin
|
||||||
|
off = 15;
|
||||||
|
//ret_len = dwLength - 15;
|
||||||
|
ret_len = 5;
|
||||||
|
break;
|
||||||
|
case 1: // modify pin
|
||||||
|
switch(pbuf[11])
|
||||||
|
{
|
||||||
|
case 3:
|
||||||
|
off = 20;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 1:
|
||||||
|
off = 19;
|
||||||
|
break;
|
||||||
|
// 0 and 4-0xFF
|
||||||
|
default:
|
||||||
|
off = 18;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//ret_len = dwLength - off;
|
||||||
|
ret_len = 5;
|
||||||
|
break;
|
||||||
|
default: // unsupported
|
||||||
|
G_io_ccid.bulk_header.bulkin.dwLength = 0;
|
||||||
|
RDR_to_PC_DataBlock(SLOTERROR_CMD_NOT_SUPPORTED);
|
||||||
|
CCID_Send_Reply(&USBD_Device);
|
||||||
|
return SLOTERROR_CMD_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
pbuf += off;
|
||||||
|
pbuf[0] = 0xEF;
|
||||||
|
return SC_XferBlock(pbuf, ret_len, &ret_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare the apdu to be processed by the application
|
||||||
|
uint8_t SC_XferBlock (uint8_t* ptrBlock, uint32_t blockLen, uint16_t* expectedLen) {
|
||||||
|
UNUSED(expectedLen);
|
||||||
|
|
||||||
|
// check for overflow
|
||||||
|
if (blockLen > IO_APDU_BUFFER_SIZE) {
|
||||||
|
return SLOTERROR_BAD_LENTGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy received apdu // if G_io_ccid_data_buffer is the buffer apdu, then the memmove will do nothing
|
||||||
|
os_memmove(G_io_apdu_buffer, ptrBlock, blockLen);
|
||||||
|
G_io_apdu_length = blockLen;
|
||||||
|
G_io_apdu_media = IO_APDU_MEDIA_USB_CCID; // for application code
|
||||||
|
G_io_apdu_state = APDU_USB_CCID; // for next call to io_exchange
|
||||||
|
|
||||||
|
return SLOT_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void io_usb_ccid_reply(unsigned char* buffer, unsigned short length) {
|
||||||
|
// avoid memory overflow
|
||||||
|
if (length > IO_CCID_DATA_BUFFER_SIZE) {
|
||||||
|
THROW(EXCEPTION_IO_OVERFLOW);
|
||||||
|
}
|
||||||
|
// copy the responde apdu
|
||||||
|
os_memmove(G_io_ccid_data_buffer, buffer, length);
|
||||||
|
G_io_ccid.bulk_header.bulkin.dwLength = length;
|
||||||
|
// forge reply
|
||||||
|
RDR_to_PC_DataBlock(SLOT_NO_ERROR);
|
||||||
|
|
||||||
|
// start sending rpely
|
||||||
|
CCID_Send_Reply(&USBD_Device);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ask for power on
|
||||||
|
void io_usb_ccid_set_card_inserted(unsigned int inserted) {
|
||||||
|
G_io_ccid.ccid_card_inserted = inserted;
|
||||||
|
CCID_UpdSlotChange(1);
|
||||||
|
#ifdef HAVE_CCID_INTERRUPT
|
||||||
|
CCID_IntMessage(&USBD_Device);
|
||||||
|
#endif // HAVE_CCID_INTERRUPT
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // HAVE_USB_CLASS_CCID
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
@ -44,8 +44,11 @@
|
|||||||
*
|
*
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
#pragma message "Override SDK source file :" __FILE__
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "usbd_hid.h"
|
#include "usbd_hid.h"
|
Loading…
Reference in New Issue
Block a user