Compare commits
No commits in common. "master" and "1.1.0" have entirely different histories.
33 changed files with 1132 additions and 3447 deletions
58
Makefile
58
Makefile
|
@ -1,6 +1,4 @@
|
||||||
#*******************************************************************************
|
# Copyright 2017 Cedric Mesnil <cslashm@gmail.com>, Ledger SAS
|
||||||
# Ledger App
|
|
||||||
# (c) 2016-2018 Ledger
|
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -13,61 +11,43 @@
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#*******************************************************************************
|
#
|
||||||
|
|
||||||
ifeq ($(BOLOS_SDK),)
|
ifeq ($(BOLOS_SDK),)
|
||||||
$(error Environment variable BOLOS_SDK is not set)
|
$(error Environment variable BOLOS_SDK is not set)
|
||||||
endif
|
endif
|
||||||
include $(BOLOS_SDK)/Makefile.defines
|
include $(BOLOS_SDK)/Makefile.defines
|
||||||
|
|
||||||
APP_LOAD_PARAMS=--appFlags 0x40 --path "2152157255'" --curve secp256k1 $(COMMON_LOAD_PARAMS)
|
APPNAME = "OpenPGP"
|
||||||
|
APP_LOAD_PARAMS=--appFlags 0x40 --path "2152157255" --curve secp256k1 $(COMMON_LOAD_PARAMS)
|
||||||
APPNAME = OpenPGP
|
|
||||||
|
|
||||||
SPECVERSION="3.3.1"
|
|
||||||
|
|
||||||
APPVERSION_M=1
|
APPVERSION_M=1
|
||||||
APPVERSION_N=2
|
APPVERSION_N=1
|
||||||
APPVERSION_P=1
|
APPVERSION_P=0
|
||||||
|
|
||||||
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
|
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
|
||||||
|
SPECVERSION="3.3.1"
|
||||||
ifeq ($(TARGET_NAME),TARGET_BLUE)
|
|
||||||
ICONNAME=images/icon_pgp_blue.gif
|
|
||||||
else
|
|
||||||
ICONNAME=images/icon_pgp.gif
|
ICONNAME=images/icon_pgp.gif
|
||||||
endif
|
|
||||||
|
|
||||||
DEFINES += $(GPG_CONFIG) GPG_VERSION=$(APPVERSION) GPG_NAME=$(APPNAME) SPEC_VERSION=$(SPECVERSION)
|
|
||||||
|
|
||||||
################
|
################
|
||||||
# Default rule #
|
# Default rule #
|
||||||
################
|
################
|
||||||
|
|
||||||
all: default
|
all: default
|
||||||
|
|
||||||
############
|
############
|
||||||
# Platform #
|
# Platform #
|
||||||
############
|
############
|
||||||
#SCRIPT_LD := script.ld
|
|
||||||
|
|
||||||
ifneq ($(NO_CONSENT),)
|
|
||||||
DEFINES += NO_CONSENT
|
|
||||||
endif
|
|
||||||
|
|
||||||
DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=300
|
|
||||||
DEFINES += HAVE_BAGL HAVE_SPRINTF
|
|
||||||
#DEFINES += HAVE_PRINTF PRINTF=screen_printf
|
|
||||||
DEFINES += PRINTF\(...\)=
|
|
||||||
DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=6 IO_HID_EP_LENGTH=64 HAVE_USB_APDU
|
|
||||||
#DEFINES += HAVE_BLE
|
|
||||||
DEFINES += UNUSED\(x\)=\(void\)x
|
|
||||||
DEFINES += APPVERSION=\"$(APPVERSION)\"
|
|
||||||
DEFINES += CUSTOM_IO_APDU_BUFFER_SIZE=\(255+5+64\)
|
|
||||||
|
|
||||||
|
DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=128
|
||||||
|
DEFINES += HAVE_BAGL HAVE_PRINTF HAVE_SPRINTF
|
||||||
|
DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=7 IO_HID_EP_LENGTH=64 HAVE_USB_APDU
|
||||||
DEFINES += HAVE_USB_CLASS_CCID
|
DEFINES += HAVE_USB_CLASS_CCID
|
||||||
|
|
||||||
|
DEFINES += $(GPG_CONFIG) GPG_VERSION=$(APPVERSION) GPG_NAME=$(APPNAME) SPEC_VERSION=$(SPECVERSION)
|
||||||
|
|
||||||
##############
|
##############
|
||||||
# Compiler #
|
# Compiler #
|
||||||
##############
|
##############
|
||||||
#GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/
|
#GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/
|
||||||
#CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin/
|
#CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin/
|
||||||
|
@ -75,8 +55,6 @@ CC := $(CLANGPATH)clang
|
||||||
|
|
||||||
#CFLAGS += -O0 -gdwarf-2 -gstrict-dwarf
|
#CFLAGS += -O0 -gdwarf-2 -gstrict-dwarf
|
||||||
CFLAGS += -O3 -Os
|
CFLAGS += -O3 -Os
|
||||||
#CFLAGS += -fno-jump-tables -fno-lookup-tables -fsave-optimization-record
|
|
||||||
#$(info $(CFLAGS))
|
|
||||||
|
|
||||||
AS := $(GCCPATH)arm-none-eabi-gcc
|
AS := $(GCCPATH)arm-none-eabi-gcc
|
||||||
|
|
||||||
|
@ -88,9 +66,9 @@ LDLIBS += -lm -lgcc -lc
|
||||||
# import rules to compile glyphs(/pone)
|
# import rules to compile glyphs(/pone)
|
||||||
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
|
### computed variables
|
||||||
APP_SOURCE_PATH += src
|
APP_SOURCE_PATH += src
|
||||||
SDK_SOURCE_PATH += lib_stusb
|
SDK_SOURCE_PATH += lib_stusb lib_stusb_impl
|
||||||
|
|
||||||
|
|
||||||
load: all
|
load: all
|
||||||
|
@ -100,8 +78,8 @@ 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 Makefile.rules
|
include $(BOLOS_SDK)/Makefile.rules
|
||||||
|
|
||||||
#add dependency on custom makefile filename
|
#add dependency on custom makefile filename
|
||||||
dep/%.d: %.c Makefile
|
dep/%.d: %.c Makefile.genericwallet
|
||||||
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#*******************************************************************************
|
|
||||||
# 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
|
|
|
@ -1,196 +0,0 @@
|
||||||
Step1: ...
|
|
||||||
-----
|
|
||||||
Jump into any temp dir
|
|
||||||
|
|
||||||
|
|
||||||
Step2: install nanos
|
|
||||||
-----
|
|
||||||
Do a fresh install of gpg application 1.1.0 from google app manager
|
|
||||||
|
|
||||||
|
|
||||||
Step3: setup conf
|
|
||||||
-----
|
|
||||||
Create a 'manual-test' directory
|
|
||||||
$ mkdir manual-test
|
|
||||||
|
|
||||||
Create a 'manual-test/gnupg'
|
|
||||||
$ mkdir manual-test/gnupg
|
|
||||||
|
|
||||||
Create a 'manual-test/gnupg/scdaemon.conf' file with content:
|
|
||||||
reader-port "Ledger Token [Nano S] (0001) 01 00"
|
|
||||||
allow-admin
|
|
||||||
card-timeout 1
|
|
||||||
debug-level expert
|
|
||||||
debug 11
|
|
||||||
log-file /tmp/scdaemon.log
|
|
||||||
|
|
||||||
Jump into manual-test dir
|
|
||||||
|
|
||||||
Step4: change to host pin style
|
|
||||||
-----
|
|
||||||
Launch gpg NanoS application and:
|
|
||||||
$ killall scdaemon gpg-agent
|
|
||||||
$ gpg2 --homedir `pwd`/gnupg --card-edit
|
|
||||||
gpg: WARNING: unsafe permissions on homedir '/home/cme/Projects/Git/ledgerblue/blue-app-openpgp-card/manual-test/gnupg'
|
|
||||||
gpg: keybox '/home/cme/Projects/Git/ledgerblue/blue-app-openpgp-card/manual-test/gnupg/pubring.kbx' created
|
|
||||||
|
|
||||||
Reader ...........: Ledger Token [Nano S] (0001) 01 00
|
|
||||||
Application ID ...: D2760001240103002C97DDD38BA90000
|
|
||||||
Version ..........: 3.0
|
|
||||||
Manufacturer .....: unknown
|
|
||||||
Serial number ....: DDD38BA9
|
|
||||||
Name of cardholder: [not set]
|
|
||||||
Language prefs ...: [not set]
|
|
||||||
Sex ..............: unspecified
|
|
||||||
URL of public key : [not set]
|
|
||||||
Login data .......: [not set]
|
|
||||||
Signature PIN ....: not forced
|
|
||||||
Key attributes ...: rsa2048 rsa2048 rsa2048
|
|
||||||
Max. PIN lengths .: 12 12 12
|
|
||||||
PIN retry counter : 3 0 3
|
|
||||||
Signature counter : 0
|
|
||||||
Signature key ....: [none]
|
|
||||||
Encryption key....: [none]
|
|
||||||
Authentication key: [none]
|
|
||||||
General key info..: [none]
|
|
||||||
|
|
||||||
gpg/card> verify
|
|
||||||
|
|
||||||
Reader ...........: Ledger Token [Nano S] (0001) 01 00
|
|
||||||
Application ID ...: D2760001240103002C97DDD38BA90000
|
|
||||||
Version ..........: 3.0
|
|
||||||
Manufacturer .....: unknown
|
|
||||||
Serial number ....: DDD38BA9
|
|
||||||
Name of cardholder: [not set]
|
|
||||||
Language prefs ...: [not set]
|
|
||||||
Sex ..............: unspecified
|
|
||||||
URL of public key : [not set]
|
|
||||||
Login data .......: [not set]
|
|
||||||
Signature PIN ....: not forced
|
|
||||||
Key attributes ...: rsa2048 rsa2048 rsa2048
|
|
||||||
Max. PIN lengths .: 12 12 12
|
|
||||||
PIN retry counter : 3 0 3
|
|
||||||
Signature counter : 0
|
|
||||||
Signature key ....: [none]
|
|
||||||
Encryption key....: [none]
|
|
||||||
Authentication key: [none]
|
|
||||||
General key info..: [none]
|
|
||||||
|
|
||||||
gpg/card>
|
|
||||||
|
|
||||||
Then on nanos, goto settings->PIN mode, and select 'Host'
|
|
||||||
Then on nanos, goto settings->PIN mode, and select 'Set as default'
|
|
||||||
|
|
||||||
unplug and replug the nanos
|
|
||||||
|
|
||||||
relaunch the openpgp application
|
|
||||||
|
|
||||||
Goto settings->PIN mode, and check you have "Host # +" (DASH and PLUS)
|
|
||||||
|
|
||||||
|
|
||||||
Step5: create 2048bits RSA keys
|
|
||||||
-----
|
|
||||||
|
|
||||||
|
|
||||||
In 'manual-test' directory, ask key generation. Nota that during this phase PIN has to be validate on Nanos
|
|
||||||
|
|
||||||
$ killall scdaemon gpg-agent
|
|
||||||
$ gpg2 --homedir `pwd`/gnupg --card-edit
|
|
||||||
gpg: WARNING: unsafe permissions on homedir '/home/cme/Projects/Git/ledgerblue/blue-app-openpgp-card/manual-test/gnupg'
|
|
||||||
|
|
||||||
Reader ...........: Ledger Token [Nano S] (0001) 01 00
|
|
||||||
Application ID ...: D2760001240103002C97DDD38BA90000
|
|
||||||
Version ..........: 3.0
|
|
||||||
Manufacturer .....: unknown
|
|
||||||
Serial number ....: DDD38BA9
|
|
||||||
Name of cardholder: [not set]
|
|
||||||
Language prefs ...: [not set]
|
|
||||||
Sex ..............: unspecified
|
|
||||||
URL of public key : [not set]
|
|
||||||
Login data .......: [not set]
|
|
||||||
Signature PIN ....: not forced
|
|
||||||
Key attributes ...: rsa2048 rsa2048 rsa2048
|
|
||||||
Max. PIN lengths .: 12 12 12
|
|
||||||
PIN retry counter : 3 0 3
|
|
||||||
Signature counter : 0
|
|
||||||
Signature key ....: [none]
|
|
||||||
Encryption key....: [none]
|
|
||||||
Authentication key: [none]
|
|
||||||
General key info..: [none]
|
|
||||||
|
|
||||||
gpg/card> admin
|
|
||||||
Admin commands are allowed
|
|
||||||
|
|
||||||
gpg/card> generate
|
|
||||||
Make off-card backup of encryption key? (Y/n) n
|
|
||||||
|
|
||||||
Please note that the factory settings of the PINs are
|
|
||||||
PIN = '123456' Admin PIN = '12345678'
|
|
||||||
You should change them using the command --change-pin
|
|
||||||
|
|
||||||
What keysize do you want for the Signature key? (2048) 2048
|
|
||||||
What keysize do you want for the Encryption key? (2048) 2048
|
|
||||||
What keysize do you want for the Authentication key? (2048) 2048
|
|
||||||
Please specify how long the key should be valid.
|
|
||||||
0 = key does not expire
|
|
||||||
<n> = key expires in n days
|
|
||||||
<n>w = key expires in n weeks
|
|
||||||
<n>m = key expires in n months
|
|
||||||
<n>y = key expires in n years
|
|
||||||
Key is valid for? (0) 0
|
|
||||||
Key does not expire at all
|
|
||||||
Is this correct? (y/N) y
|
|
||||||
|
|
||||||
GnuPG needs to construct a user ID to identify your key.
|
|
||||||
|
|
||||||
Real name: testkey
|
|
||||||
Email address:
|
|
||||||
Comment:
|
|
||||||
You selected this USER-ID:
|
|
||||||
"testkey"
|
|
||||||
|
|
||||||
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
|
|
||||||
gpg: /home/cme/Projects/Git/ledgerblue/blue-app-openpgp-card/manual-test/gnupg/trustdb.gpg: trustdb created
|
|
||||||
gpg: key 5ED17DF289C757A2 marked as ultimately trusted
|
|
||||||
gpg: directory '/home/cme/Projects/Git/ledgerblue/blue-app-openpgp-card/manual-test/gnupg/openpgp-revocs.d' created
|
|
||||||
gpg: revocation certificate stored as '/home/cme/Projects/Git/ledgerblue/blue-app-openpgp-card/manual-test/gnupg/openpgp-revocs.d/7FDC3D2FCD3558CB06631EAB5ED17DF289C757A2.rev'
|
|
||||||
public and secret key created and signed.
|
|
||||||
|
|
||||||
|
|
||||||
gpg/card> quit
|
|
||||||
pub rsa2048 2017-10-03 [SC]
|
|
||||||
7FDC3D2FCD3558CB06631EAB5ED17DF289C757A2
|
|
||||||
uid testkey
|
|
||||||
sub rsa2048 2017-10-03 [A]
|
|
||||||
sub rsa2047 2017-10-03 [E]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Step6: encrypt/decrypt
|
|
||||||
-----
|
|
||||||
encrypt
|
|
||||||
|
|
||||||
$ killall scdaemon gpg-agent
|
|
||||||
$ echo CLEAR > foo.txt
|
|
||||||
$ gpg2 --homedir `pwd`/gnupg -e -r testkey foo.txt
|
|
||||||
gpg: WARNING: unsafe permissions on homedir '/home/cme/Projects/Git/ledgerblue/blue-app-openpgp-card/manual-test/gnupg'
|
|
||||||
gpg: checking the trustdb
|
|
||||||
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
|
|
||||||
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
|
|
||||||
|
|
||||||
Force pin to asked
|
|
||||||
|
|
||||||
$ killall gpg-agent scdaemon
|
|
||||||
|
|
||||||
decrypt
|
|
||||||
|
|
||||||
$ gpg2 --homedir `pwd`/gnupg foo.txt.gpg
|
|
||||||
gpg: WARNING: unsafe permissions on homedir '/home/cme/Projects/Git/ledgerblue/blue-app-openpgp-card/manual-test/gnupg'
|
|
||||||
gpg: encrypted with 2047-bit RSA key, ID 602FE5EB7BFA4B00, created 2017-10-03
|
|
||||||
"testkey"
|
|
||||||
File 'foo.txt' exists. Overwrite? (y/N) y
|
|
||||||
|
|
||||||
Step7: pin on screen
|
|
||||||
------
|
|
||||||
|
|
||||||
Restart from Step1, but skip step4
|
|
Binary file not shown.
|
@ -1,5 +1,5 @@
|
||||||
..
|
..
|
||||||
Copyright 2018 Cedric Mesnil <cslashm@gmail.com>, Ledger SAS
|
Copyright 2017 Cedric Mesnil <cslashm@gmail.com>, Ledger SAS
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
@ -96,7 +96,15 @@ The application is ready to use!
|
||||||
From source
|
From source
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
Building from sources requires the the Nano S SDK 1.4.2.1 on firmware 1.4.2. See https://github.com/LedgerHQ/nanos-secure-sdk
|
Building from sources requires the the Nano S SDK 1.3.1.4 on firmware 1.3.1. See https://github.com/LedgerHQ/nanos-secure-sdk
|
||||||
|
|
||||||
|
The SDK must be slightly modified:
|
||||||
|
|
||||||
|
- replace lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_if.c
|
||||||
|
and lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/usbd_ccid_if.h by the
|
||||||
|
one provided in sdk/ directory
|
||||||
|
- edit script.ld and modify the stack size : STACK_SIZE = 832;
|
||||||
|
|
||||||
|
|
||||||
Refer to the SDK documentation for the compiling/loading...
|
Refer to the SDK documentation for the compiling/loading...
|
||||||
|
|
||||||
|
@ -113,9 +121,9 @@ Linux
|
||||||
|
|
||||||
You have to have to add the NanoS to /etc/libccid_Info.plist
|
You have to have to add the NanoS to /etc/libccid_Info.plist
|
||||||
|
|
||||||
- In <key>ifdVendorID</key> add the entry <string>0x2C97</string>
|
In <key>ifdVendorID</key> add the entry <string>0x2C97</string>
|
||||||
- In <key>ifdProductID</key> add the entry <string>0x0001</string>
|
In <key>ifdProductID</key> add the entry <string>0x0001</string>
|
||||||
- In <key>ifdFriendlyName</key> add the entry <string>Ledger Token</string>
|
In <key>ifdFriendlyName</key> add the entry <string>Ledger Token</string>
|
||||||
|
|
||||||
These 3 entries must be added at the end of each list.
|
These 3 entries must be added at the end of each list.
|
||||||
|
|
||||||
|
@ -127,9 +135,9 @@ MAC
|
||||||
2. You have to add the Nano S to /usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
|
2. You have to add the Nano S to /usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
|
||||||
|
|
||||||
|
|
||||||
- In <key>ifdVendorID</key> add the entry <string>0x2C97</string>
|
In <key>ifdVendorID</key> add the entry <string>0x2C97</string>
|
||||||
- In <key>ifdProductID</key> add the entry <string>0x0001</string>
|
In <key>ifdProductID</key> add the entry <string>0x0001</string>
|
||||||
- In <key>ifdFriendlyName</key> add the entry <string>Ledger Token</string>
|
In <key>ifdFriendlyName</key> add the entry <string>Ledger Token</string>
|
||||||
|
|
||||||
This 3 entries must be added at the end of each list.
|
This 3 entries must be added at the end of each list.
|
||||||
|
|
||||||
|
@ -177,7 +185,6 @@ 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
|
||||||
|
@ -239,39 +246,8 @@ 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 --card-edit`` command line
|
The problem is there is no way with the ``gpg`` command line to easily set
|
||||||
to easily set up the desired template, except for Ed25519.
|
up the desired template. The menu fixes that.
|
||||||
|
|
||||||
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.
|
||||||
|
@ -279,11 +255,10 @@ 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
|
||||||
|
@ -291,7 +266,6 @@ 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
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
@ -366,17 +340,6 @@ 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
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
|
@ -407,7 +370,6 @@ the reader and the delegated PIN support.
|
||||||
Edit the file ~/.gnupg/scdaemon.conf and add the following lines:
|
Edit the file ~/.gnupg/scdaemon.conf and add the following lines:
|
||||||
|
|
||||||
| ``reader-port "Ledger Token [Nano S] (0001) 01 00"``
|
| ``reader-port "Ledger Token [Nano S] (0001) 01 00"``
|
||||||
| ``allow-admin``
|
|
||||||
| ``enable-pinpad-varlen``
|
| ``enable-pinpad-varlen``
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
import binascii
|
|
||||||
|
|
||||||
from gpgcard import GPGCard
|
|
||||||
|
|
||||||
print("Connecting to device ...")
|
|
||||||
gpgcard = GPGCard()
|
|
||||||
gpgcard.connect("pcsc:Ledger")
|
|
||||||
gpgcard.get_all()
|
|
||||||
|
|
||||||
gpgcard.verify_pin(0x81, "123456")
|
|
||||||
gpgcard.verify_pin(0x83, "12345678")
|
|
||||||
|
|
||||||
print("Generating key 1/3 ...")
|
|
||||||
gpgcard.generate_asym_key_pair(0x80, 0xb600)
|
|
||||||
print("Generating key 2/3 ...")
|
|
||||||
gpgcard.generate_asym_key_pair(0x80, 0xb800)
|
|
||||||
print("Generating key 3/3 ...")
|
|
||||||
gpgcard.generate_asym_key_pair(0x80, 0xa400)
|
|
||||||
|
|
||||||
# Use 'gpg -k --with-subkey-fingerprint' to find fingerprints
|
|
||||||
|
|
||||||
print("Setting fingerprints ...")
|
|
||||||
sig_fingerprint = b'A3F35A5124D47C3195FF07B7F85D93686A3A9063'
|
|
||||||
aut_fingerprint = b'9C686F97A39B4A34E0C9D37CDBF45893AB524BBC'
|
|
||||||
dec_fingerprint = b'E4FE54969060DBF2756FC0EFD8203245E390CAEA'
|
|
||||||
|
|
||||||
sig_fingerprint_bin = binascii.unhexlify(sig_fingerprint)
|
|
||||||
aut_fingerprint_bin = binascii.unhexlify(aut_fingerprint)
|
|
||||||
dec_fingerprint_bin = binascii.unhexlify(dec_fingerprint)
|
|
||||||
|
|
||||||
gpgcard.sig_fingerprints = sig_fingerprint_bin
|
|
||||||
gpgcard.aut_fingerprints = aut_fingerprint_bin
|
|
||||||
gpgcard.dec_fingerprints = dec_fingerprint_bin
|
|
||||||
|
|
||||||
gpgcard.set_all()
|
|
167
script.ld
167
script.ld
|
@ -1,167 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* Ledger Blue - Secure firmware
|
|
||||||
* (c) 2016, 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.
|
|
||||||
********************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Global chip memory layout and constants
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
MEMORY
|
|
||||||
{
|
|
||||||
DISCARD (rwx) : ORIGIN = 0xd0000000, LENGTH = 1M
|
|
||||||
|
|
||||||
FLASH (rx) : ORIGIN = 0xc0d00000, LENGTH = 400K
|
|
||||||
SRAM (rwx) : ORIGIN = 0x20001800, LENGTH = 4K
|
|
||||||
}
|
|
||||||
|
|
||||||
PAGE_SIZE = 64;
|
|
||||||
STACK_SIZE = 768;
|
|
||||||
END_STACK = ORIGIN(SRAM) + LENGTH(SRAM);
|
|
||||||
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
ENTRY(main)
|
|
||||||
|
|
||||||
/****************************************************************/
|
|
||||||
/* This section locates the code in FLASH */
|
|
||||||
/****************************************************************/
|
|
||||||
|
|
||||||
/** put text in Flash memory, VMA will be equal to LMA */
|
|
||||||
.text :
|
|
||||||
{
|
|
||||||
/* provide start code symbol, shall be zero */
|
|
||||||
_text = .;
|
|
||||||
_nvram = .;
|
|
||||||
|
|
||||||
PROVIDE(_setjmp = setjmp); /*thanks clang*/
|
|
||||||
|
|
||||||
/* ensure main is always @ 0xC0D00000 */
|
|
||||||
*(.boot*)
|
|
||||||
|
|
||||||
/* place the other code and rodata defined BUT nvram variables that are displaced in a r/w area */
|
|
||||||
*(.text*)
|
|
||||||
*(.rodata.[^UN]*) /*.data.rel.ro* not here to detect invalid PIC usage */
|
|
||||||
*(.rodata.N[^_]*)
|
|
||||||
|
|
||||||
. = ALIGN(4);
|
|
||||||
|
|
||||||
/* all code placed */
|
|
||||||
_etext = .;
|
|
||||||
|
|
||||||
. = ALIGN(PAGE_SIZE);
|
|
||||||
|
|
||||||
_nvram_data = .;
|
|
||||||
|
|
||||||
/* NVM data (ex-filesystem) */
|
|
||||||
*(.rodata.USBD_CfgDesc)
|
|
||||||
*(.bss.N_* .rodata.N_* .rodata.USBD_CfgDesc)
|
|
||||||
. = ALIGN(PAGE_SIZE);
|
|
||||||
_install_parameters = .;
|
|
||||||
PROVIDE(N_install_parameters = .);
|
|
||||||
_envram = .;
|
|
||||||
_nvram_data_size = _envram - _nvram_data;
|
|
||||||
|
|
||||||
} > FLASH = 0x00
|
|
||||||
|
|
||||||
.data (NOLOAD):
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Place RAM initialized variables
|
|
||||||
*/
|
|
||||||
_data = .;
|
|
||||||
|
|
||||||
*(vtable)
|
|
||||||
*(.data*)
|
|
||||||
|
|
||||||
_edata = .;
|
|
||||||
|
|
||||||
} > DISCARD /*> SRAM AT>FLASH = 0x00 */
|
|
||||||
|
|
||||||
.bss :
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Place RAM uninitialized variables
|
|
||||||
*/
|
|
||||||
_bss = .;
|
|
||||||
*(.bss*)
|
|
||||||
_ebss = .;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reserve stack size
|
|
||||||
*/
|
|
||||||
. = ALIGN(4);
|
|
||||||
app_stack_canary = .;
|
|
||||||
PROVIDE(app_stack_canary = .);
|
|
||||||
. += 4;
|
|
||||||
_stack = .;
|
|
||||||
. = _stack + STACK_SIZE;
|
|
||||||
PROVIDE( _stack_size = STACK_SIZE );
|
|
||||||
PROVIDE( _estack = ABSOLUTE(END_STACK) );
|
|
||||||
|
|
||||||
} > SRAM = 0x00
|
|
||||||
|
|
||||||
/****************************************************************/
|
|
||||||
/* DEBUG */
|
|
||||||
/****************************************************************/
|
|
||||||
|
|
||||||
/* remove the debugging information from the standard libraries */
|
|
||||||
DEBUG (NOLOAD) :
|
|
||||||
{
|
|
||||||
libc.a ( * )
|
|
||||||
libm.a ( * )
|
|
||||||
libgcc.a ( * )
|
|
||||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stabs debugging sections. */
|
|
||||||
.stab 0 : { *(.stab) }
|
|
||||||
.stabstr 0 : { *(.stabstr) }
|
|
||||||
.stab.excl 0 : { *(.stab.excl) }
|
|
||||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
|
||||||
.stab.index 0 : { *(.stab.index) }
|
|
||||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
|
||||||
.comment 0 : { *(.comment) }
|
|
||||||
/* DWARF debug sections.
|
|
||||||
Symbols in the DWARF debugging sections are relative to the beginning
|
|
||||||
of the section so we begin them at 0. */
|
|
||||||
/* DWARF 1 */
|
|
||||||
.debug 0 : { *(.debug) }
|
|
||||||
.line 0 : { *(.line) }
|
|
||||||
/* GNU DWARF 1 extensions */
|
|
||||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
|
||||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
|
||||||
/* DWARF 1.1 and DWARF 2 */
|
|
||||||
.debug_aranges 0 : { *(.debug_aranges) }
|
|
||||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
|
||||||
/* DWARF 2 */
|
|
||||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
|
||||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
|
||||||
.debug_line 0 : { *(.debug_line) }
|
|
||||||
.debug_frame 0 : { *(.debug_frame) }
|
|
||||||
.debug_str 0 : { *(.debug_str) }
|
|
||||||
.debug_loc 0 : { *(.debug_loc) }
|
|
||||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
|
||||||
/* SGI/MIPS DWARF 2 extensions */
|
|
||||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
|
||||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
|
||||||
.debug_typenames 0 : { *(.debug_typenames) }
|
|
||||||
.debug_varnames 0 : { *(.debug_varnames) }
|
|
||||||
|
|
||||||
}
|
|
404
src/sdk/usbd_ccid_if.c → sdk/usbd_ccid_if.c
Executable file → Normal file
404
src/sdk/usbd_ccid_if.c → sdk/usbd_ccid_if.c
Executable file → Normal file
|
@ -25,23 +25,27 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma message "Override SDK source file :" __FILE__
|
|
||||||
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
/* Includes ------------------------------------------------------------------*/
|
||||||
#include "os.h"
|
|
||||||
#include "usbd_ccid_if.h"
|
#include "usbd_ccid_if.h"
|
||||||
|
|
||||||
#ifdef HAVE_USB_CLASS_CCID
|
#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 typedef -----------------------------------------------------------*/
|
||||||
/* Private define ------------------------------------------------------------*/
|
/* Private define ------------------------------------------------------------*/
|
||||||
/* Private macro -------------------------------------------------------------*/
|
/* Private macro -------------------------------------------------------------*/
|
||||||
/* Private variables ---------------------------------------------------------*/
|
/* Private variables ---------------------------------------------------------*/
|
||||||
usb_class_ccid_t G_io_ccid;
|
uint8_t Ccid_BulkState;
|
||||||
|
uint8_t ccid_card_inserted;
|
||||||
|
uint8_t UsbIntMessageBuffer[INTR_MAX_PACKET_SIZE]; /* data buffer*/
|
||||||
|
__IO uint8_t PrevXferComplete_IntrIn;
|
||||||
|
usb_ccid_param_t usb_ccid_param;
|
||||||
|
|
||||||
|
uint8_t* pUsbMessageBuffer;
|
||||||
|
static uint32_t UsbMessageLength;
|
||||||
|
Ccid_SlotStatus_t Ccid_SlotStatus;
|
||||||
|
Protocol0_DataStructure_t Protocol0_DataStructure;
|
||||||
|
|
||||||
|
Ccid_bulk_data_t Ccid_bulk_data;
|
||||||
|
|
||||||
/* Private function prototypes -----------------------------------------------*/
|
/* Private function prototypes -----------------------------------------------*/
|
||||||
static void CCID_Response_SendData (USBD_HandleTypeDef *pdev,
|
static void CCID_Response_SendData (USBD_HandleTypeDef *pdev,
|
||||||
|
@ -56,17 +60,23 @@ static void CCID_Response_SendData (USBD_HandleTypeDef *pdev,
|
||||||
*/
|
*/
|
||||||
void CCID_Init (USBD_HandleTypeDef *pdev)
|
void CCID_Init (USBD_HandleTypeDef *pdev)
|
||||||
{
|
{
|
||||||
memset(&G_io_ccid, 0, sizeof(G_io_ccid));
|
memset(&Ccid_BulkState, 0, sizeof(Ccid_BulkState));
|
||||||
|
memset(&UsbIntMessageBuffer, 0, sizeof(UsbIntMessageBuffer));
|
||||||
|
memset(&PrevXferComplete_IntrIn, 0, sizeof(PrevXferComplete_IntrIn));
|
||||||
|
memset(&usb_ccid_param, 0, sizeof(usb_ccid_param));
|
||||||
|
memset(&pUsbMessageBuffer, 0, sizeof(pUsbMessageBuffer));
|
||||||
|
memset(&UsbMessageLength, 0, sizeof(UsbMessageLength));
|
||||||
|
memset(&Ccid_SlotStatus, 0, sizeof(Ccid_SlotStatus));
|
||||||
|
memset(&Protocol0_DataStructure, 0, sizeof(Protocol0_DataStructure));
|
||||||
|
memset(&Ccid_bulk_data, 0, sizeof(Ccid_bulk_data));
|
||||||
|
ccid_card_inserted = 0;
|
||||||
/* CCID Related Initialization */
|
/* CCID Related Initialization */
|
||||||
#ifdef HAVE_CCID_INTERRUPT
|
|
||||||
CCID_SetIntrTransferStatus(1); /* Transfer Complete Status */
|
CCID_SetIntrTransferStatus(1); /* Transfer Complete Status */
|
||||||
#endif // HAVE_CCID_INTERRUPT
|
|
||||||
CCID_UpdSlotChange(1);
|
CCID_UpdSlotChange(1);
|
||||||
SC_InitParams();
|
SC_InitParams();
|
||||||
|
|
||||||
/* Prepare Out endpoint to receive 1st packet */
|
/* Prepare Out endpoint to receive 1st packet */
|
||||||
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
||||||
|
|
||||||
// send the smartcard as inserted state at boot time
|
// send the smartcard as inserted state at boot time
|
||||||
|
@ -82,7 +92,7 @@ void CCID_Init (USBD_HandleTypeDef *pdev)
|
||||||
void CCID_DeInit (USBD_HandleTypeDef *pdev)
|
void CCID_DeInit (USBD_HandleTypeDef *pdev)
|
||||||
{
|
{
|
||||||
UNUSED(pdev);
|
UNUSED(pdev);
|
||||||
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,50 +110,43 @@ void CCID_BulkMessage_In (USBD_HandleTypeDef *pdev,
|
||||||
|
|
||||||
/*************** Handle Bulk Transfer IN data completion *****************/
|
/*************** Handle Bulk Transfer IN data completion *****************/
|
||||||
|
|
||||||
switch (G_io_ccid.Ccid_BulkState)
|
switch (Ccid_BulkState)
|
||||||
{
|
{
|
||||||
case CCID_STATE_SEND_RESP: {
|
case CCID_STATE_SEND_RESP: {
|
||||||
unsigned int remLen = G_io_ccid.UsbMessageLength;
|
unsigned int remLen = UsbMessageLength;
|
||||||
|
|
||||||
// advance with acknowledged sent chunk
|
// advance with acknowledged sent chunk
|
||||||
if (G_io_ccid.pUsbMessageBuffer == &G_io_ccid.bulk_header) {
|
pUsbMessageBuffer += MIN(CCID_BULK_EPIN_SIZE, UsbMessageLength);
|
||||||
// first part of the bulk in sent.
|
UsbMessageLength -= MIN(CCID_BULK_EPIN_SIZE, UsbMessageLength);
|
||||||
// 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 remaining length is > EPIN_SIZE: send a filled bulk packet
|
||||||
if (G_io_ccid.UsbMessageLength >= CCID_BULK_EPIN_SIZE) {
|
if (UsbMessageLength >= CCID_BULK_EPIN_SIZE) {
|
||||||
CCID_Response_SendData(pdev, G_io_ccid.pUsbMessageBuffer,
|
CCID_Response_SendData(pdev, pUsbMessageBuffer,
|
||||||
// use the header declared size packet must be well formed
|
// use the header declared size packet must be well formed
|
||||||
CCID_BULK_EPIN_SIZE);
|
CCID_BULK_EPIN_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if remaining length is 0; send an empty packet and prepare to receive a new command
|
// 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) {
|
else if (UsbMessageLength == 0 && remLen == CCID_BULK_EPIN_SIZE) {
|
||||||
CCID_Response_SendData(pdev, G_io_ccid.pUsbMessageBuffer,
|
CCID_Response_SendData(pdev, pUsbMessageBuffer,
|
||||||
// use the header declared size packet must be well formed
|
// use the header declared size packet must be well formed
|
||||||
0);
|
0);
|
||||||
goto last_xfer; // won't wait ack to avoid missing a command
|
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 no more data, then last packet sent, go back to idle (done on transfer ack)
|
||||||
else if (G_io_ccid.UsbMessageLength == 0) { // robustness only
|
else if (UsbMessageLength == 0) { // robustness only
|
||||||
last_xfer:
|
last_xfer:
|
||||||
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
|
|
||||||
/* Prepare EP to Receive First Cmd */
|
/* Prepare EP to Receive First Cmd */
|
||||||
// not timeout compliant // USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
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
|
// 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) {
|
else if (UsbMessageLength < CCID_BULK_EPIN_SIZE) {
|
||||||
CCID_Response_SendData(pdev, G_io_ccid.pUsbMessageBuffer,
|
CCID_Response_SendData(pdev, pUsbMessageBuffer,
|
||||||
// use the header declared size packet must be well formed
|
// use the header declared size packet must be well formed
|
||||||
G_io_ccid.UsbMessageLength);
|
UsbMessageLength);
|
||||||
goto last_xfer; // won't wait ack to avoid missing a command
|
goto last_xfer; // won't wait ack to avoid missing a command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,35 +157,11 @@ void CCID_BulkMessage_In (USBD_HandleTypeDef *pdev,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef HAVE_CCID_INTERRUPT
|
|
||||||
else if (epnum == (CCID_INTR_IN_EP & 0x7F))
|
else if (epnum == (CCID_INTR_IN_EP & 0x7F))
|
||||||
{
|
{
|
||||||
/* Filter the epnum by masking with 0x7f (mask of IN Direction) */
|
/* Filter the epnum by masking with 0x7f (mask of IN Direction) */
|
||||||
CCID_SetIntrTransferStatus(1); /* Transfer Complete Status */
|
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -195,113 +174,123 @@ void CCID_Send_Reply(USBD_HandleTypeDef *pdev) {
|
||||||
void CCID_BulkMessage_Out (USBD_HandleTypeDef *pdev,
|
void CCID_BulkMessage_Out (USBD_HandleTypeDef *pdev,
|
||||||
uint8_t epnum, uint8_t* buffer, uint16_t dataLen)
|
uint8_t epnum, uint8_t* buffer, uint16_t dataLen)
|
||||||
{
|
{
|
||||||
if (epnum == (CCID_BULK_OUT_EP & 0x7F)) {
|
|
||||||
switch (G_io_ccid.Ccid_BulkState)
|
switch (Ccid_BulkState)
|
||||||
|
{
|
||||||
|
case CCID_STATE_IDLE:
|
||||||
|
if (dataLen == 0x00)
|
||||||
|
{ /* Zero Length Packet Received */
|
||||||
|
Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
|
}
|
||||||
|
else if (dataLen >= CCID_MESSAGE_HEADER_SIZE)
|
||||||
{
|
{
|
||||||
|
UsbMessageLength = dataLen; /* Store for future use */
|
||||||
|
|
||||||
// after a timeout, could be in almost any state :) therefore, clean it and process the newly received command
|
/* Expected Data Length Packet Received */
|
||||||
default:
|
pUsbMessageBuffer = (uint8_t*) &Ccid_bulk_data;
|
||||||
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
|
||||||
// no break is intentional
|
|
||||||
|
|
||||||
case CCID_STATE_IDLE:
|
/* Fill CCID_BulkOut Data Buffer from USB Buffer */
|
||||||
// prepare to receive another packet later on (to avoid troubles with timeout due to other hid command timeouting the ccid endpoint reply)
|
memmove(pUsbMessageBuffer, buffer, dataLen);
|
||||||
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
|
||||||
|
|
||||||
if (dataLen == 0x00)
|
/*
|
||||||
{ /* Zero Length Packet Received, end of transfer */
|
Refer : 6 CCID Messages
|
||||||
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
The response messages always contain the exact same slot number,
|
||||||
}
|
and sequence number fields from the header that was contained in
|
||||||
else if (dataLen >= CCID_HEADER_SIZE)
|
the Bulk-OUT command message.
|
||||||
{
|
*/
|
||||||
G_io_ccid.UsbMessageLength = dataLen; /* Store for future use */
|
Ccid_bulk_data.header.bulkin.bSlot = Ccid_bulk_data.header.bulkout.bSlot;
|
||||||
|
Ccid_bulk_data.header.bulkin.bSeq = Ccid_bulk_data.header.bulkout.bSeq;
|
||||||
/* 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)
|
if (dataLen < CCID_BULK_EPOUT_SIZE)
|
||||||
{/* Short message, less than the EP Out Size, execute the command,
|
{/* Short message, less than the EP Out Size, execute the command,
|
||||||
if parameter like dwLength is too big, the appropriate command will
|
if parameter like dwLength is too big, the appropriate command will
|
||||||
give an error */
|
give an error */
|
||||||
|
|
||||||
/* Full command is received, process the Command */
|
|
||||||
os_memmove(G_io_ccid.pUsbMessageBuffer, buffer, dataLen);
|
|
||||||
CCID_CmdDecode(pdev);
|
CCID_CmdDecode(pdev);
|
||||||
}
|
}
|
||||||
else //if (dataLen == CCID_BULK_EPOUT_SIZE)
|
else
|
||||||
{
|
{ /* Long message, receive additional data with command */
|
||||||
if (G_io_ccid.UsbMessageLength < (G_io_ccid.bulk_header.bulkout.dwLength + CCID_HEADER_SIZE))
|
/* (u8dataLen == CCID_BULK_EPOUT_SIZE) */
|
||||||
{
|
|
||||||
os_memmove(G_io_ccid.pUsbMessageBuffer, buffer, dataLen);
|
if (Ccid_bulk_data.header.bulkout.dwLength > ABDATA_SIZE)
|
||||||
G_io_ccid.pUsbMessageBuffer += dataLen;
|
{ /* Check if length of data to be sent by host is > buffer size */
|
||||||
/* Increment the pointer to receive more data */
|
|
||||||
|
/* Too long data received.... Error ! */
|
||||||
|
Ccid_BulkState = CCID_STATE_UNCORRECT_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{ /* Expect more data on OUT EP */
|
||||||
|
Ccid_BulkState = CCID_STATE_RECEIVE_DATA;
|
||||||
|
pUsbMessageBuffer += dataLen; /* Point to new offset */
|
||||||
|
|
||||||
/* Prepare EP to Receive next Cmd */
|
/* Prepare EP to Receive next Cmd */
|
||||||
// not timeout compliant // USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
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;
|
} /* if (dataLen == CCID_BULK_EPOUT_SIZE) ends */
|
||||||
|
} /* if (dataLen >= CCID_BULK_EPOUT_SIZE) ends */
|
||||||
|
} /* if (dataLen >= CCID_MESSAGE_HEADER_SIZE) ends */
|
||||||
|
break;
|
||||||
|
|
||||||
/*
|
case CCID_STATE_RECEIVE_DATA:
|
||||||
case CCID_STATE_UNCORRECT_LENGTH:
|
|
||||||
G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
UsbMessageLength += dataLen;
|
||||||
|
|
||||||
break;
|
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 */
|
||||||
|
memmove(pUsbMessageBuffer, buffer, dataLen);
|
||||||
|
CCID_CmdDecode(pdev);
|
||||||
}
|
}
|
||||||
|
else if (dataLen == CCID_BULK_EPOUT_SIZE)
|
||||||
|
{
|
||||||
|
if (UsbMessageLength < (Ccid_bulk_data.header.bulkout.dwLength + CCID_CMD_HEADER_SIZE))
|
||||||
|
{
|
||||||
|
memmove(pUsbMessageBuffer, buffer, dataLen);
|
||||||
|
pUsbMessageBuffer += dataLen;
|
||||||
|
/* Increment the pointer to receive more data */
|
||||||
|
|
||||||
|
/* Prepare EP to Receive next Cmd */
|
||||||
|
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
||||||
|
}
|
||||||
|
else if (UsbMessageLength == (Ccid_bulk_data.header.bulkout.dwLength + CCID_CMD_HEADER_SIZE))
|
||||||
|
{
|
||||||
|
/* Full command is received, process the Command */
|
||||||
|
memmove(pUsbMessageBuffer, buffer, dataLen);
|
||||||
|
CCID_CmdDecode(pdev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Too long data received.... Error ! */
|
||||||
|
Ccid_BulkState = CCID_STATE_UNCORRECT_LENGTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CCID_STATE_UNCORRECT_LENGTH:
|
||||||
|
Ccid_BulkState = CCID_STATE_IDLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCID_Send_Reply(USBD_HandleTypeDef *pdev) {
|
||||||
|
/********** Decide for all commands ***************/
|
||||||
|
if (Ccid_BulkState == CCID_STATE_SEND_RESP)
|
||||||
|
{
|
||||||
|
UsbMessageLength = Ccid_bulk_data.header.bulkin.dwLength+CCID_MESSAGE_HEADER_SIZE; /* Store for future use */
|
||||||
|
|
||||||
|
/* Expected Data Length Packet Received */
|
||||||
|
pUsbMessageBuffer = (uint8_t*) &Ccid_bulk_data;
|
||||||
|
|
||||||
|
CCID_Response_SendData(pdev, pUsbMessageBuffer,
|
||||||
|
// use the header declared size packet must be well formed
|
||||||
|
MIN(CCID_BULK_EPIN_SIZE, UsbMessageLength));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +304,7 @@ void CCID_CmdDecode(USBD_HandleTypeDef *pdev)
|
||||||
{
|
{
|
||||||
uint8_t errorCode;
|
uint8_t errorCode;
|
||||||
|
|
||||||
switch (G_io_ccid.bulk_header.bulkout.bMessageType)
|
switch (Ccid_bulk_data.header.bulkout.bMessageType)
|
||||||
{
|
{
|
||||||
case PC_TO_RDR_ICCPOWERON:
|
case PC_TO_RDR_ICCPOWERON:
|
||||||
errorCode = PC_to_RDR_IccPowerOn();
|
errorCode = PC_to_RDR_IccPowerOn();
|
||||||
|
@ -391,7 +380,7 @@ void CCID_CmdDecode(USBD_HandleTypeDef *pdev)
|
||||||
void Transfer_Data_Request(void)
|
void Transfer_Data_Request(void)
|
||||||
{
|
{
|
||||||
/********** Update Global Variables ***************/
|
/********** Update Global Variables ***************/
|
||||||
G_io_ccid.Ccid_BulkState = CCID_STATE_SEND_RESP;
|
Ccid_BulkState = CCID_STATE_SEND_RESP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -407,7 +396,6 @@ static void CCID_Response_SendData(USBD_HandleTypeDef *pdev,
|
||||||
uint8_t* buf,
|
uint8_t* buf,
|
||||||
uint16_t len)
|
uint16_t len)
|
||||||
{
|
{
|
||||||
UNUSED(pdev);
|
|
||||||
// don't ask the MCU to perform bulk split, we could quickly get into a buffer overflow
|
// don't ask the MCU to perform bulk split, we could quickly get into a buffer overflow
|
||||||
if (len > CCID_BULK_EPIN_SIZE) {
|
if (len > CCID_BULK_EPIN_SIZE) {
|
||||||
THROW(EXCEPTION_IO_OVERFLOW);
|
THROW(EXCEPTION_IO_OVERFLOW);
|
||||||
|
@ -423,7 +411,6 @@ static void CCID_Response_SendData(USBD_HandleTypeDef *pdev,
|
||||||
io_seproxyhal_spi_send(buf, len);
|
io_seproxyhal_spi_send(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_CCID_INTERRUPT
|
|
||||||
/**
|
/**
|
||||||
* @brief CCID_IntMessage
|
* @brief CCID_IntMessage
|
||||||
* Send the Interrupt-IN data to the host
|
* Send the Interrupt-IN data to the host
|
||||||
|
@ -432,14 +419,11 @@ static void CCID_Response_SendData(USBD_HandleTypeDef *pdev,
|
||||||
*/
|
*/
|
||||||
void CCID_IntMessage(USBD_HandleTypeDef *pdev)
|
void CCID_IntMessage(USBD_HandleTypeDef *pdev)
|
||||||
{
|
{
|
||||||
UNUSED(pdev);
|
|
||||||
/* Check if there us change in Smartcard Slot status */
|
/* Check if there us change in Smartcard Slot status */
|
||||||
if ( CCID_IsSlotStatusChange() && CCID_IsIntrTransferComplete() )
|
if ( CCID_IsSlotStatusChange() && CCID_IsIntrTransferComplete() )
|
||||||
{
|
{
|
||||||
#ifdef HAVE_CCID_INTERRUPT
|
|
||||||
/* Check Slot Status is changed. Card is Removed/ Fitted */
|
/* Check Slot Status is changed. Card is Removed/ Fitted */
|
||||||
RDR_to_PC_NotifySlotChange();
|
RDR_to_PC_NotifySlotChange();
|
||||||
#endif // HAVE_CCID_INTERRUPT
|
|
||||||
|
|
||||||
CCID_SetIntrTransferStatus(0); /* Reset the Status */
|
CCID_SetIntrTransferStatus(0); /* Reset the Status */
|
||||||
CCID_UpdSlotChange(0); /* Reset the Status of Slot Change */
|
CCID_UpdSlotChange(0); /* Reset the Status of Slot Change */
|
||||||
|
@ -451,7 +435,7 @@ void CCID_IntMessage(USBD_HandleTypeDef *pdev)
|
||||||
G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN;
|
G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN;
|
||||||
G_io_seproxyhal_spi_buffer[5] = 2;
|
G_io_seproxyhal_spi_buffer[5] = 2;
|
||||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6);
|
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6);
|
||||||
io_seproxyhal_spi_send(G_io_ccid.UsbIntMessageBuffer, 2);
|
io_seproxyhal_spi_send(UsbIntMessageBuffer, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +447,7 @@ void CCID_IntMessage(USBD_HandleTypeDef *pdev)
|
||||||
*/
|
*/
|
||||||
uint8_t CCID_IsIntrTransferComplete (void)
|
uint8_t CCID_IsIntrTransferComplete (void)
|
||||||
{
|
{
|
||||||
return G_io_ccid.PrevXferComplete_IntrIn;
|
return PrevXferComplete_IntrIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -474,9 +458,8 @@ uint8_t CCID_IsIntrTransferComplete (void)
|
||||||
*/
|
*/
|
||||||
void CCID_SetIntrTransferStatus (uint8_t xfer_Status)
|
void CCID_SetIntrTransferStatus (uint8_t xfer_Status)
|
||||||
{
|
{
|
||||||
G_io_ccid.PrevXferComplete_IntrIn = xfer_Status;
|
PrevXferComplete_IntrIn = xfer_Status;
|
||||||
}
|
}
|
||||||
#endif // HAVE_CCID_INTERRUPT
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -484,7 +467,12 @@ void CCID_SetIntrTransferStatus (uint8_t xfer_Status)
|
||||||
|
|
||||||
|
|
||||||
uint8_t SC_Detect(void) {
|
uint8_t SC_Detect(void) {
|
||||||
return G_io_ccid.ccid_card_inserted;
|
return ccid_card_inserted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SC_Poweroff(void) {
|
||||||
|
// nothing to do
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SC_InitParams (void) {
|
void SC_InitParams (void) {
|
||||||
|
@ -492,72 +480,64 @@ void SC_InitParams (void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t SC_SetParams (Protocol0_DataStructure_t* pt0) {
|
uint8_t SC_SetParams (Protocol0_DataStructure_t* pt0) {
|
||||||
UNUSED(pt0);
|
|
||||||
return SLOT_NO_ERROR;
|
return SLOT_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t SC_ExecuteEscape (uint8_t* escapePtr, uint32_t escapeLen,
|
||||||
|
uint8_t* responseBuff,
|
||||||
|
uint16_t* responseLen) {
|
||||||
|
io_seproxyhal_se_reset();
|
||||||
|
}
|
||||||
uint8_t SC_SetClock (uint8_t bClockCommand) {
|
uint8_t SC_SetClock (uint8_t bClockCommand) {
|
||||||
UNUSED(bClockCommand);
|
|
||||||
return SLOT_NO_ERROR;
|
return SLOT_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t SC_Request_GetClockFrequencies(uint8_t* pbuf, uint16_t* len);
|
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_Request_GetDataRates(uint8_t* pbuf, uint16_t* len);
|
||||||
uint8_t SC_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse,
|
uint8_t SC_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse,
|
||||||
uint8_t bClassEnvelope) {
|
uint8_t bClassEnvelope) {
|
||||||
UNUSED(bmChanges);
|
|
||||||
UNUSED(bClassGetResponse);
|
|
||||||
UNUSED(bClassEnvelope);
|
|
||||||
return SLOTERROR_CMD_NOT_SUPPORTED;
|
return SLOTERROR_CMD_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
uint8_t SC_Mechanical(uint8_t bFunction) {
|
uint8_t SC_Mechanical(uint8_t bFunction) {
|
||||||
UNUSED(bFunction);
|
|
||||||
return SLOTERROR_CMD_NOT_SUPPORTED;
|
return SLOTERROR_CMD_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
uint8_t SC_SetDataRateAndClockFrequency(uint32_t dwClockFrequency,
|
uint8_t SC_SetDataRateAndClockFrequency(uint32_t dwClockFrequency,
|
||||||
uint32_t dwDataRate) {
|
uint32_t dwDataRate) {
|
||||||
UNUSED(dwClockFrequency);
|
|
||||||
UNUSED(dwDataRate);
|
|
||||||
return SLOT_NO_ERROR;
|
return SLOT_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter,
|
uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter,
|
||||||
uint8_t* pbuf, uint32_t* returnLen ) {
|
uint8_t* pbuf, uint32_t* returnLen ) {
|
||||||
UNUSED(bBWI);
|
|
||||||
UNUSED(wLevelParameter);
|
|
||||||
UNUSED(returnLen);
|
|
||||||
// return SLOTERROR_CMD_NOT_SUPPORTED;
|
// return SLOTERROR_CMD_NOT_SUPPORTED;
|
||||||
uint16_t ret_len,off;
|
uint16_t ret_len,off;
|
||||||
switch(pbuf[0])
|
switch(pbuf[0]) {
|
||||||
{
|
case 0: // verify pin
|
||||||
case 0: // verify pin
|
//ret_len = dwLength - 15;
|
||||||
off = 15;
|
ret_len = 5;
|
||||||
//ret_len = dwLength - 15;
|
off = 15;
|
||||||
ret_len = 5;
|
|
||||||
break;
|
|
||||||
case 1: // modify pin
|
|
||||||
switch(pbuf[11])
|
|
||||||
{
|
|
||||||
case 3:
|
|
||||||
off = 20;
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
|
||||||
case 1:
|
case 1: // modify pin
|
||||||
off = 19;
|
switch(pbuf[11]) {
|
||||||
|
case 3:
|
||||||
|
off = 20;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 1:
|
||||||
|
off = 19;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
off = 18;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//ret_len = dwLength - off;
|
||||||
|
ret_len = 5;
|
||||||
break;
|
break;
|
||||||
// 0 and 4-0xFF
|
|
||||||
default:
|
default: // unsupported
|
||||||
off = 18;
|
Ccid_bulk_data.header.bulkin.dwLength = 0;
|
||||||
break;
|
RDR_to_PC_DataBlock(SLOTERROR_CMD_NOT_SUPPORTED);
|
||||||
}
|
CCID_Send_Reply(&USBD_Device);
|
||||||
//ret_len = dwLength - off;
|
return SLOTERROR_CMD_NOT_SUPPORTED;
|
||||||
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 += off;
|
||||||
pbuf[0] = 0xEF;
|
pbuf[0] = 0xEF;
|
||||||
|
@ -566,15 +546,13 @@ uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter,
|
||||||
|
|
||||||
// prepare the apdu to be processed by the application
|
// prepare the apdu to be processed by the application
|
||||||
uint8_t SC_XferBlock (uint8_t* ptrBlock, uint32_t blockLen, uint16_t* expectedLen) {
|
uint8_t SC_XferBlock (uint8_t* ptrBlock, uint32_t blockLen, uint16_t* expectedLen) {
|
||||||
UNUSED(expectedLen);
|
|
||||||
|
|
||||||
// check for overflow
|
// check for overflow
|
||||||
if (blockLen > IO_APDU_BUFFER_SIZE) {
|
if (blockLen > IO_APDU_BUFFER_SIZE) {
|
||||||
return SLOTERROR_BAD_LENTGH;
|
return SLOTERROR_BAD_LENTGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy received apdu // if G_io_ccid_data_buffer is the buffer apdu, then the memmove will do nothing
|
// copy received apdu
|
||||||
os_memmove(G_io_apdu_buffer, ptrBlock, blockLen);
|
memmove(G_io_apdu_buffer, ptrBlock, blockLen);
|
||||||
G_io_apdu_length = blockLen;
|
G_io_apdu_length = blockLen;
|
||||||
G_io_apdu_media = IO_APDU_MEDIA_USB_CCID; // for application code
|
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
|
G_io_apdu_state = APDU_USB_CCID; // for next call to io_exchange
|
||||||
|
@ -584,26 +562,23 @@ uint8_t SC_XferBlock (uint8_t* ptrBlock, uint32_t blockLen, uint16_t* expectedLe
|
||||||
|
|
||||||
void io_usb_ccid_reply(unsigned char* buffer, unsigned short length) {
|
void io_usb_ccid_reply(unsigned char* buffer, unsigned short length) {
|
||||||
// avoid memory overflow
|
// avoid memory overflow
|
||||||
if (length > IO_CCID_DATA_BUFFER_SIZE) {
|
if (length > sizeof(Ccid_bulk_data.abData)) {
|
||||||
THROW(EXCEPTION_IO_OVERFLOW);
|
THROW(EXCEPTION_IO_OVERFLOW);
|
||||||
}
|
}
|
||||||
// copy the responde apdu
|
// copy the responde apdu
|
||||||
os_memmove(G_io_ccid_data_buffer, buffer, length);
|
memmove(Ccid_bulk_data.abData, buffer, length);
|
||||||
G_io_ccid.bulk_header.bulkin.dwLength = length;
|
Ccid_bulk_data.header.bulkin.dwLength = length;
|
||||||
// forge reply
|
// forge reply
|
||||||
RDR_to_PC_DataBlock(SLOT_NO_ERROR);
|
RDR_to_PC_DataBlock(SLOT_NO_ERROR);
|
||||||
|
|
||||||
// start sending rpely
|
// start sending rpely
|
||||||
CCID_Send_Reply(&USBD_Device);
|
CCID_Send_Reply(&USBD_Device);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ask for power on
|
// ask for power on
|
||||||
void io_usb_ccid_set_card_inserted(unsigned int inserted) {
|
void io_usb_ccid_set_card_inserted(unsigned int inserted) {
|
||||||
G_io_ccid.ccid_card_inserted = inserted;
|
ccid_card_inserted = inserted;
|
||||||
CCID_UpdSlotChange(1);
|
CCID_UpdSlotChange(1);
|
||||||
#ifdef HAVE_CCID_INTERRUPT
|
|
||||||
CCID_IntMessage(&USBD_Device);
|
CCID_IntMessage(&USBD_Device);
|
||||||
#endif // HAVE_CCID_INTERRUPT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -611,7 +586,6 @@ void io_usb_ccid_set_card_inserted(unsigned int inserted) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // HAVE_USB_CLASS_CCID
|
#endif // HAVE_USB_CLASS_CCID
|
||||||
|
|
||||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
209
sdk/usbd_ccid_if.h
Executable file
209
sdk/usbd_ccid_if.h
Executable file
|
@ -0,0 +1,209 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file usbd_ccid_if.h
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @version V1.0.1
|
||||||
|
* @date 31-January-2014
|
||||||
|
* @brief This file provides all the functions prototypes for USB 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.
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||||
|
#ifndef __USBD_CCID_IF_H
|
||||||
|
#define __USBD_CCID_IF_H
|
||||||
|
|
||||||
|
#include "usbd_core.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_USB_CLASS_CCID
|
||||||
|
|
||||||
|
|
||||||
|
/* Exported defines ----------------------------------------------------------*/
|
||||||
|
/* Bulk-only Command Block Wrapper */
|
||||||
|
#define ABDATA_SIZE 261
|
||||||
|
#define CCID_CMD_HEADER_SIZE 10
|
||||||
|
#define CCID_RESPONSE_HEADER_SIZE 10
|
||||||
|
|
||||||
|
|
||||||
|
#define CCID_INT_BUFF_SIZ 2
|
||||||
|
|
||||||
|
#define CARD_SLOT_FITTED 1
|
||||||
|
#define CARD_SLOT_REMOVED 0
|
||||||
|
|
||||||
|
#define BULK_MAX_PACKET_SIZE 0x40
|
||||||
|
#define CCID_IN_EP_SIZE 0x40
|
||||||
|
#define INTR_MAX_PACKET_SIZE 8
|
||||||
|
#define CCID_MESSAGE_HEADER_SIZE 10
|
||||||
|
#define CCID_NUMBER_OF_SLOTS 1
|
||||||
|
/* Number of SLOTS. For single card, this value is 1 */
|
||||||
|
|
||||||
|
/* Following Parameters used in PC_to_RDR_IccPowerOn */
|
||||||
|
#define VOLTAGE_SELECTION_AUTOMATIC 0xFF
|
||||||
|
#define VOLTAGE_SELECTION_3V 0x02
|
||||||
|
#define VOLTAGE_SELECTION_5V 0x01
|
||||||
|
#define VOLTAGE_SELECTION_1V8 0x03
|
||||||
|
|
||||||
|
#define PC_TO_RDR_ICCPOWERON 0x62
|
||||||
|
#define PC_TO_RDR_ICCPOWEROFF 0x63
|
||||||
|
#define PC_TO_RDR_GETSLOTSTATUS 0x65
|
||||||
|
#define PC_TO_RDR_XFRBLOCK 0x6F
|
||||||
|
#define PC_TO_RDR_GETPARAMETERS 0x6C
|
||||||
|
#define PC_TO_RDR_RESETPARAMETERS 0x6D
|
||||||
|
#define PC_TO_RDR_SETPARAMETERS 0x61
|
||||||
|
#define PC_TO_RDR_ESCAPE 0x6B
|
||||||
|
#define PC_TO_RDR_ICCCLOCK 0x6E
|
||||||
|
#define PC_TO_RDR_T0APDU 0x6A
|
||||||
|
#define PC_TO_RDR_SECURE 0x69
|
||||||
|
#define PC_TO_RDR_MECHANICAL 0x71
|
||||||
|
#define PC_TO_RDR_ABORT 0x72
|
||||||
|
#define PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY 0x73
|
||||||
|
|
||||||
|
#define RDR_TO_PC_DATABLOCK 0x80
|
||||||
|
#define RDR_TO_PC_SLOTSTATUS 0x81
|
||||||
|
#define RDR_TO_PC_PARAMETERS 0x82
|
||||||
|
#define RDR_TO_PC_ESCAPE 0x83
|
||||||
|
#define RDR_TO_PC_DATARATEANDCLOCKFREQUENCY 0x84
|
||||||
|
|
||||||
|
#define RDR_TO_PC_NOTIFYSLOTCHANGE 0x50
|
||||||
|
#define RDR_TO_PC_HARDWAREERROR 0x51
|
||||||
|
|
||||||
|
#define OFFSET_INT_BMESSAGETYPE 0
|
||||||
|
#define OFFSET_INT_BMSLOTICCSTATE 1
|
||||||
|
#define SLOT_ICC_PRESENT 0x01
|
||||||
|
/* LSb : (0b = no ICC present, 1b = ICC present) */
|
||||||
|
|
||||||
|
#define SLOT_ICC_CHANGE 0x02 /* MSb : (0b = no change, 1b = change) */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*********************** CCID Bulk Transfer State machine ********************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
#define CCID_STATE_IDLE 0 /* Idle state */
|
||||||
|
#define CCID_STATE_DATA_OUT 1 /* Data Out state */
|
||||||
|
#define CCID_STATE_RECEIVE_DATA 2
|
||||||
|
#define CCID_STATE_SEND_RESP 3
|
||||||
|
#define CCID_STATE_DATAIN 4
|
||||||
|
#define CCID_STATE_UNCORRECT_LENGTH 5
|
||||||
|
|
||||||
|
#define DIR_IN 0
|
||||||
|
#define DIR_OUT 1
|
||||||
|
#define BOTH_DIR 2
|
||||||
|
|
||||||
|
/* Exported types ------------------------------------------------------------*/
|
||||||
|
#pragma pack(1)
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
#pragma pack(1)
|
||||||
|
union {
|
||||||
|
#pragma pack(1)
|
||||||
|
struct {
|
||||||
|
uint8_t bMessageType; /* Offset = 0*/
|
||||||
|
uint32_t dwLength; /* Offset = 1, The length field (dwLength) is the length
|
||||||
|
of the message not including the 10-byte header.*/
|
||||||
|
uint8_t bSlot; /* Offset = 5*/
|
||||||
|
uint8_t bSeq; /* Offset = 6*/
|
||||||
|
uint8_t bSpecific_0; /* Offset = 7*/
|
||||||
|
uint8_t bSpecific_1; /* Offset = 8*/
|
||||||
|
uint8_t bSpecific_2; /* Offset = 9*/
|
||||||
|
} bulkout;
|
||||||
|
#pragma pack(1)
|
||||||
|
struct {
|
||||||
|
uint8_t bMessageType; /* Offset = 0*/
|
||||||
|
uint32_t dwLength; /* Offset = 1*/
|
||||||
|
uint8_t bSlot; /* Offset = 5, Same as Bulk-OUT message */
|
||||||
|
uint8_t bSeq; /* Offset = 6, Same as Bulk-OUT message */
|
||||||
|
uint8_t bStatus; /* Offset = 7, Slot status as defined in § 6.2.6*/
|
||||||
|
uint8_t bError; /* Offset = 8, Slot error as defined in § 6.2.6*/
|
||||||
|
uint8_t bSpecific; /* Offset = 9*/
|
||||||
|
} bulkin;
|
||||||
|
} header;
|
||||||
|
uint8_t abData [ABDATA_SIZE]; /* Offset = 10, For reference, the absolute
|
||||||
|
maximum block size for a TPDU T=0 block is 260 bytes
|
||||||
|
(5 bytes command; 255 bytes data),
|
||||||
|
or for a TPDU T=1 block is 259 bytes,
|
||||||
|
or for a short APDU T=1 block is 261 bytes,
|
||||||
|
or for an extended APDU T=1 block is 65544 bytes.*/
|
||||||
|
} Ccid_bulk_data_t;
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
__IO uint8_t SlotStatus;
|
||||||
|
__IO uint8_t SlotStatusChange;
|
||||||
|
} Ccid_SlotStatus_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
__IO uint8_t bAbortRequestFlag;
|
||||||
|
__IO uint8_t bSeq;
|
||||||
|
__IO uint8_t bSlot;
|
||||||
|
} usb_ccid_param_t;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
typedef struct _Protocol0_DataStructure_t
|
||||||
|
{
|
||||||
|
uint8_t bmFindexDindex;
|
||||||
|
uint8_t bmTCCKST0;
|
||||||
|
uint8_t bGuardTimeT0;
|
||||||
|
uint8_t bWaitingIntegerT0;
|
||||||
|
uint8_t bClockStop;
|
||||||
|
} Protocol0_DataStructure_t;
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "usbd_ccid_core.h"
|
||||||
|
|
||||||
|
extern usb_ccid_param_t usb_ccid_param;
|
||||||
|
extern Ccid_bulk_data_t Ccid_bulk_data; /* Buffer for the Out Data */
|
||||||
|
extern Ccid_SlotStatus_t Ccid_SlotStatus;
|
||||||
|
extern uint8_t UsbIntMessageBuffer[];
|
||||||
|
|
||||||
|
extern Protocol0_DataStructure_t Protocol0_DataStructure;
|
||||||
|
|
||||||
|
/* Exported macros -----------------------------------------------------------*/
|
||||||
|
/* Exported variables --------------------------------------------------------*/
|
||||||
|
/* Exported functions ------------------------------------------------------- */
|
||||||
|
void CCID_BulkMessage_In (USBD_HandleTypeDef *pdev,
|
||||||
|
uint8_t epnum);
|
||||||
|
|
||||||
|
void CCID_BulkMessage_Out (USBD_HandleTypeDef *pdev,
|
||||||
|
uint8_t epnum, uint8_t* buffer, uint16_t buflen);
|
||||||
|
|
||||||
|
void CCID_ReceiveCmdHeader(uint8_t* pDst, uint8_t u8length);
|
||||||
|
void CCID_CmdDecode(USBD_HandleTypeDef *pdev);
|
||||||
|
|
||||||
|
void CCID_IntMessage(USBD_HandleTypeDef *pdev);
|
||||||
|
void CCID_Init(USBD_HandleTypeDef *pdev);
|
||||||
|
void CCID_DeInit(USBD_HandleTypeDef *pdev);
|
||||||
|
|
||||||
|
uint8_t CCID_IsIntrTransferComplete(void);
|
||||||
|
void CCID_SetIntrTransferStatus (uint8_t );
|
||||||
|
void Transfer_Data_Request(void);
|
||||||
|
void Set_CSW (uint8_t CSW_Status, uint8_t Send_Permission);
|
||||||
|
|
||||||
|
void io_usb_ccid_set_card_inserted(unsigned int inserted);
|
||||||
|
|
||||||
|
#endif // HAVE_USB_CLASS_CCID
|
||||||
|
|
||||||
|
#endif /* __USBD_CCID_IF_H */
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -16,11 +16,7 @@
|
||||||
#ifndef GPG_API_H
|
#ifndef GPG_API_H
|
||||||
#define GPG_API_H
|
#define GPG_API_H
|
||||||
|
|
||||||
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);
|
||||||
|
@ -32,7 +28,7 @@ int gpg_apdu_get_data(unsigned int ref) ;
|
||||||
int gpg_apdu_get_next_data(unsigned int ref) ;
|
int gpg_apdu_get_next_data(unsigned int ref) ;
|
||||||
int gpg_apdu_put_data(unsigned int ref) ;
|
int gpg_apdu_put_data(unsigned int ref) ;
|
||||||
|
|
||||||
int gpg_apdu_pso(void);
|
int gpg_apdu_pso(unsigned int ref);
|
||||||
int gpg_apdu_internal_authenticate(void);
|
int gpg_apdu_internal_authenticate(void);
|
||||||
int gpg_apdu_gen(void );
|
int gpg_apdu_gen(void );
|
||||||
int gpg_apdu_get_challenge(void) ;
|
int gpg_apdu_get_challenge(void) ;
|
||||||
|
|
|
@ -44,16 +44,16 @@ int gpg_apdu_get_challenge() {
|
||||||
chain[0] = 'r'; chain[1]='n'; chain[2] = 'd';
|
chain[0] = 'r'; chain[1]='n'; chain[2] = 'd';
|
||||||
|
|
||||||
cx_sha256_init(&G_gpg_vstate.work.md.sha256);
|
cx_sha256_init(&G_gpg_vstate.work.md.sha256);
|
||||||
cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256, 0, Sr, 32, NULL, 0);
|
cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256, 0, Sr, 32, NULL);
|
||||||
cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256, 0, chain, 3, NULL, 0);
|
cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256, 0, chain, 3, NULL);
|
||||||
hlen=cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256,
|
hlen=cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256,
|
||||||
CX_LAST, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
|
CX_LAST, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
|
||||||
G_gpg_vstate.work.io_buffer, 32);
|
G_gpg_vstate.work.io_buffer);
|
||||||
|
|
||||||
cx_sha3_xof_init(&G_gpg_vstate.work.md.sha3, 256, olen);
|
cx_sha3_xof_init(&G_gpg_vstate.work.md.sha3, 256, olen);
|
||||||
cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha3,
|
cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha3,
|
||||||
CX_LAST, G_gpg_vstate.work.io_buffer, hlen,
|
CX_LAST, G_gpg_vstate.work.io_buffer, hlen,
|
||||||
G_gpg_vstate.work.io_buffer,olen);
|
G_gpg_vstate.work.io_buffer);
|
||||||
} else {
|
} else {
|
||||||
cx_rng(G_gpg_vstate.work.io_buffer, olen);
|
cx_rng(G_gpg_vstate.work.io_buffer, olen);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ int gpg_apdu_get_data(unsigned int ref) {
|
||||||
break;
|
break;
|
||||||
/* ----------------- Config RSA exponent ----------------- */
|
/* ----------------- Config RSA exponent ----------------- */
|
||||||
case 0x01F8:
|
case 0x01F8:
|
||||||
gpg_io_insert(N_gpg_pstate->default_RSA_exponent,4);
|
gpg_io_insert_u32(N_gpg_pstate->default_RSA_exponent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* ----------------- Application ----------------- */
|
/* ----------------- Application ----------------- */
|
||||||
|
@ -282,7 +282,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
||||||
if (G_gpg_vstate.io_length != 4) {
|
if (G_gpg_vstate.io_length != 4) {
|
||||||
THROW(SW_WRONG_LENGTH);
|
THROW(SW_WRONG_LENGTH);
|
||||||
}
|
}
|
||||||
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+3] &= ~0x07;
|
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset] &= ~0x07;
|
||||||
nvm_write(&N_gpg_pstate->AID[10], &G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset], 4);
|
nvm_write(&N_gpg_pstate->AID[10], &G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset], 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -367,25 +367,34 @@ 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.rsa.public1024.n;
|
pq = G_gpg_vstate.work.rsa1024.public.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.rsa.public2048.n;
|
pq = G_gpg_vstate.work.rsa2048.public.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.rsa.public3072.n;
|
pq = G_gpg_vstate.work.rsa3072.public.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.rsa.public4096.n;
|
pq = G_gpg_vstate.work.rsa4096.public.n;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ksz = ksz>>1;
|
ksz = ksz>>1;
|
||||||
|
@ -424,12 +433,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
||||||
os_memset(pq+ksz, 0, ksz-len_q);
|
os_memset(pq+ksz, 0, ksz-len_q);
|
||||||
|
|
||||||
//regenerate RSA private key
|
//regenerate RSA private key
|
||||||
unsigned char _e[4];
|
cx_rsa_generate_pair(ksz<<1, rsa_pub, rsa_priv, e, pq);
|
||||||
_e[0] = e>>24;
|
|
||||||
_e[1] = e>>16;
|
|
||||||
_e[2] = e>>8;
|
|
||||||
_e[3] = e>>0;
|
|
||||||
cx_rsa_generate_pair(ksz<<1, rsa_pub, rsa_priv, _e, 4, pq);
|
|
||||||
|
|
||||||
//write keys
|
//write keys
|
||||||
nvm_write(&keygpg->pub_key.rsa, rsa_pub->e, 4);
|
nvm_write(&keygpg->pub_key.rsa, rsa_pub->e, 4);
|
||||||
|
@ -451,14 +455,14 @@ int gpg_apdu_put_data(unsigned int ref) {
|
||||||
THROW(SW_WRONG_DATA);
|
THROW(SW_WRONG_DATA);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ksz = gpg_curve2domainlen(curve);
|
ksz = 32;
|
||||||
if (ksz == len_p) {
|
if (ksz == 32) {
|
||||||
G_gpg_vstate.work.ecfp.private.curve = curve;
|
G_gpg_vstate.work.ecfp256.private.curve = curve;
|
||||||
G_gpg_vstate.work.ecfp.private.d_len = ksz;
|
G_gpg_vstate.work.ecfp256.private.d_len = ksz;
|
||||||
os_memmove(G_gpg_vstate.work.ecfp.private.d, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,ksz);
|
os_memmove(G_gpg_vstate.work.ecfp256.private.d, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,ksz);
|
||||||
cx_ecfp_generate_pair(curve, &G_gpg_vstate.work.ecfp.public, &G_gpg_vstate.work.ecfp.private, 1);
|
cx_ecfp_generate_pair(curve, &G_gpg_vstate.work.ecfp256.public, &G_gpg_vstate.work.ecfp256.private, 1);
|
||||||
nvm_write(&keygpg->pub_key.ecfp, &G_gpg_vstate.work.ecfp.public, sizeof(cx_ecfp_public_key_t));
|
nvm_write(&keygpg->pub_key.ecfp256, &G_gpg_vstate.work.ecfp256.public, sizeof(cx_ecfp_public_key_t));
|
||||||
nvm_write(&keygpg->priv_key.ecfp, &G_gpg_vstate.work.ecfp.private, sizeof(cx_ecfp_private_key_t));
|
nvm_write(&keygpg->key.ecfp256, &G_gpg_vstate.work.ecfp256.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));
|
||||||
|
|
|
@ -236,9 +236,7 @@ int gpg_dispatch() {
|
||||||
unsigned int tag,t,l;
|
unsigned int tag,t,l;
|
||||||
int sw;
|
int sw;
|
||||||
|
|
||||||
if ((G_gpg_vstate.io_cla != 0x00) &&
|
if ((G_gpg_vstate.io_cla != 0x00) && (G_gpg_vstate.io_cla != 0x10) && (G_gpg_vstate.io_cla != 0xEF)) {
|
||||||
(G_gpg_vstate.io_cla != 0x10) &&
|
|
||||||
(G_gpg_vstate.io_cla != 0xEF)) {
|
|
||||||
THROW(SW_CLA_NOT_SUPPORTED);
|
THROW(SW_CLA_NOT_SUPPORTED);
|
||||||
return SW_CLA_NOT_SUPPORTED;
|
return SW_CLA_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -380,9 +378,8 @@ int gpg_dispatch() {
|
||||||
|
|
||||||
/* --- PSO --- */
|
/* --- PSO --- */
|
||||||
case INS_PSO:
|
case INS_PSO:
|
||||||
sw = gpg_apdu_pso();
|
sw = gpg_apdu_pso(tag);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INS_INTERNAL_AUTHENTICATE:
|
case INS_INTERNAL_AUTHENTICATE:
|
||||||
sw = gpg_apdu_internal_authenticate();
|
sw = gpg_apdu_internal_authenticate();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -46,12 +46,12 @@ static void gpg_pso_derive_key_seed(unsigned char *Sn, unsigned char* key_name,
|
||||||
h[1] = idx;
|
h[1] = idx;
|
||||||
|
|
||||||
cx_sha256_init(&G_gpg_vstate.work.md.sha256);
|
cx_sha256_init(&G_gpg_vstate.work.md.sha256);
|
||||||
cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha256, 0, Sn, 32, NULL, 0);
|
cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha256, 0, Sn, 32, NULL);
|
||||||
cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha256, 0, (unsigned char *)key_name, 4, NULL, 0);
|
cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha256, 0, (unsigned char *)key_name, 4, NULL);
|
||||||
cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha256, CX_LAST, h , 2, h,32);
|
cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha256, CX_LAST, h , 2, h);
|
||||||
|
|
||||||
cx_sha3_xof_init(&G_gpg_vstate.work.md.sha3, 256, Ski_len);
|
cx_sha3_xof_init(&G_gpg_vstate.work.md.sha3, 256, Ski_len);
|
||||||
cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha3, CX_LAST, h, 32, Ski, Ski_len);
|
cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha3, CX_LAST, h, 32, Ski);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,20 +113,29 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -144,7 +153,8 @@ int gpg_apdu_gen() {
|
||||||
cx_math_next_prime(pq+size,size);
|
cx_math_next_prime(pq+size,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
cx_rsa_generate_pair(ksz, rsa_pub, rsa_priv, N_gpg_pstate->default_RSA_exponent, 4, pq);
|
|
||||||
|
cx_rsa_generate_pair(ksz, rsa_pub, rsa_priv, N_gpg_pstate->default_RSA_exponent, pq);
|
||||||
|
|
||||||
nvm_write(pkey, rsa_priv, pkey_size);
|
nvm_write(pkey, rsa_priv, pkey_size);
|
||||||
nvm_write(&keygpg->pub_key.rsa[0], rsa_pub->e, 4);
|
nvm_write(&keygpg->pub_key.rsa[0], rsa_pub->e, 4);
|
||||||
|
@ -164,24 +174,19 @@ 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, ksz);
|
gpg_pso_derive_key_seed(seed, name, 1, seed, 32);
|
||||||
cx_ecfp_init_private_key(curve,seed, ksz, &G_gpg_vstate.work.ecfp.private);
|
cx_ecfp_init_private_key(curve,seed, 32, &G_gpg_vstate.work.ecfp256.private);
|
||||||
keepprivate = 1;
|
keepprivate = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx_ecfp_generate_pair(curve,
|
cx_ecfp_generate_pair(curve,
|
||||||
&G_gpg_vstate.work.ecfp.public,
|
&G_gpg_vstate.work.ecfp256.public,
|
||||||
&G_gpg_vstate.work.ecfp.private,
|
&G_gpg_vstate.work.ecfp256.private,
|
||||||
keepprivate);
|
keepprivate);
|
||||||
nvm_write(&keygpg->priv_key.ecfp, &G_gpg_vstate.work.ecfp.private, sizeof(cx_ecfp_private_key_t));
|
nvm_write(&keygpg->key.ecfp256, &G_gpg_vstate.work.ecfp256.private, sizeof(cx_ecfp_private_key_t));
|
||||||
nvm_write(&keygpg->pub_key.ecfp, &G_gpg_vstate.work.ecfp.public, sizeof(cx_ecfp_public_key_t));
|
nvm_write(&keygpg->pub_key.ecfp256, &G_gpg_vstate.work.ecfp256.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));
|
||||||
|
@ -203,32 +208,32 @@ int gpg_apdu_gen() {
|
||||||
gpg_io_mark();
|
gpg_io_mark();
|
||||||
switch(ksz) {
|
switch(ksz) {
|
||||||
case 1024/8:
|
case 1024/8:
|
||||||
if (keygpg->priv_key.rsa1024.size == 0) {
|
if (keygpg->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->priv_key.rsa1024.n);
|
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa1024.n);
|
||||||
break;
|
break;
|
||||||
case 2048/8:
|
case 2048/8:
|
||||||
if (keygpg->priv_key.rsa2048.size == 0) {
|
if (keygpg->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->priv_key.rsa2048.n);
|
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa2048.n);
|
||||||
break;
|
break;
|
||||||
case 3072/8:
|
case 3072/8:
|
||||||
if (keygpg->priv_key.rsa3072.size == 0) {
|
if (keygpg->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->priv_key.rsa3072.n);
|
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa3072.n);
|
||||||
break;
|
break;
|
||||||
case 4096/8:
|
case 4096/8:
|
||||||
if (keygpg->priv_key.rsa4096.size == 0) {
|
if (keygpg->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->priv_key.rsa4096.n);
|
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->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);
|
||||||
|
@ -257,7 +262,7 @@ int gpg_apdu_gen() {
|
||||||
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_Ed25519) {
|
if (curve == CX_CURVE_Ed25519) {
|
||||||
os_memmove(G_gpg_vstate.work.io_buffer+128, keygpg->pub_key.ecfp256.W,keygpg->pub_key.ecfp256.W_len);
|
os_memmove(G_gpg_vstate.work.io_buffer+128, keygpg->pub_key.ecfp256.W,keygpg->pub_key.ecfp256.W_len);
|
||||||
cx_edward_compress_point(CX_CURVE_Ed25519, G_gpg_vstate.work.io_buffer+128, 65);
|
cx_edward_compress_point(CX_CURVE_Ed25519, G_gpg_vstate.work.io_buffer+128);
|
||||||
gpg_io_insert_tlv(0x86, 32, G_gpg_vstate.work.io_buffer+129); //129: discard 02
|
gpg_io_insert_tlv(0x86, 32, G_gpg_vstate.work.io_buffer+129); //129: discard 02
|
||||||
} else if (curve == CX_CURVE_Curve25519) {
|
} else if (curve == CX_CURVE_Curve25519) {
|
||||||
unsigned int i,len;
|
unsigned int i,len;
|
||||||
|
|
188
src/gpg_init.c
188
src/gpg_init.c
|
@ -18,8 +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 "usbd_impl.h"
|
#include "usbd_ccid_impl.h"
|
||||||
|
|
||||||
#define SHORT(x) ((x)>>8)&0xFF, (x)&0xFF
|
#define SHORT(x) ((x)>>8)&0xFF, (x)&0xFF
|
||||||
/* ----------------------*/
|
/* ----------------------*/
|
||||||
/* -- A Kind of Magic -- */
|
/* -- A Kind of Magic -- */
|
||||||
|
@ -32,47 +31,24 @@ const unsigned char C_MAGIC[8] = {
|
||||||
/* --ECC OID -- */
|
/* --ECC OID -- */
|
||||||
/* ----------------------*/
|
/* ----------------------*/
|
||||||
|
|
||||||
/*
|
|
||||||
//brainpool 256t1: 1.3.36.3.3.2.8.1.1.8
|
|
||||||
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
|
|
||||||
const unsigned char C_OID_SECP256R1[8] = {
|
|
||||||
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
|
//secp256k1: 1.3.132.0.10
|
||||||
const unsigned char C_OID_SECP256K1[5] = {
|
const unsigned char C_OID_SECP256K1[5] = {
|
||||||
0x2B, 0x81, 0x04, 0x00, 0x0A
|
0x2B, 0x81, 0x04, 0x00, 0x0A
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//secp256r1 / NIST P256 /ansi-x9.62 : 1.2.840.10045.3.1.7
|
||||||
|
const unsigned char C_OID_SECP256R1[8] = {
|
||||||
|
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07
|
||||||
|
};
|
||||||
|
|
||||||
//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 284r1: 1.3.36.3.3.2.8.1.1.11
|
//brainpool 256t1: 1.3.36.3.3.2.8.1.1.8
|
||||||
const unsigned char C_OID_BRAINPOOL384R1[9] = {
|
const unsigned char C_OID_BRAINPOOL256T1[9] = {
|
||||||
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B
|
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07
|
||||||
};
|
};
|
||||||
//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,
|
||||||
|
@ -83,29 +59,10 @@ 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,
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int gpg_oid2curve(unsigned char* oid, unsigned int len) {
|
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_SECP256R1;
|
return CX_CURVE_256R1;
|
||||||
}
|
|
||||||
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) ) {
|
||||||
|
@ -116,86 +73,20 @@ unsigned 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 -- */
|
||||||
/* -------------------------------*/
|
/* -------------------------------*/
|
||||||
|
@ -231,7 +122,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, 0x03,
|
0x03, 0x00,
|
||||||
//manufacturer
|
//manufacturer
|
||||||
0x2C, 0x97,
|
0x2C, 0x97,
|
||||||
//serial
|
//serial
|
||||||
|
@ -263,7 +154,7 @@ const unsigned char C_default_AlgoAttrRSA[] = {
|
||||||
0x01
|
0x01
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
const unsigned char C_default_AlgoAttrECC_sig[] = {
|
const unsigned char C_default_AlgoAttrECC_sig[] = {
|
||||||
// ecdsa
|
// ecdsa
|
||||||
0x13,
|
0x13,
|
||||||
|
@ -276,20 +167,8 @@ 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
|
|
||||||
const unsigned char C_default_AlgoAttrECC_sig[] = {
|
#else
|
||||||
// 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,
|
||||||
|
@ -403,11 +282,8 @@ 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
|
||||||
G_gpg_vstate.work.io_buffer[0] = (GPG_RSA_DEFAULT_PUB>>24)&0xFF;
|
l = GPG_RSA_DEFAULT_PUB;
|
||||||
G_gpg_vstate.work.io_buffer[1] = (GPG_RSA_DEFAULT_PUB>>16)&0xFF;
|
nvm_write(&N_gpg_pstate->default_RSA_exponent, &l, sizeof(unsigned int));
|
||||||
G_gpg_vstate.work.io_buffer[2] = (GPG_RSA_DEFAULT_PUB>>8)&0xFF;
|
|
||||||
G_gpg_vstate.work.io_buffer[3] = (GPG_RSA_DEFAULT_PUB>>0)&0xFF;
|
|
||||||
nvm_write(&N_gpg_pstate->default_RSA_exponent, G_gpg_vstate.work.io_buffer, 4);
|
|
||||||
|
|
||||||
//config pin
|
//config pin
|
||||||
#if 1
|
#if 1
|
||||||
|
@ -423,9 +299,6 @@ 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++) {
|
||||||
unsigned char uif[2];
|
|
||||||
uif[0] = 0x00;
|
|
||||||
uif[1] = 0x20;
|
|
||||||
#if 1
|
#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);
|
||||||
|
@ -444,25 +317,8 @@ 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);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define USBD_OFFSET_CfgDesc_bPINSupport (sizeof(USBD_CfgDesc)-16)
|
|
||||||
void USBD_CCID_activate_pinpad(int enabled) {
|
|
||||||
unsigned short length;
|
|
||||||
uint8_t *cfgDesc;
|
|
||||||
unsigned char e;
|
|
||||||
e = enabled?3:0;
|
|
||||||
length = 0;
|
|
||||||
cfgDesc = USBD_GetCfgDesc_impl(&length);
|
|
||||||
nvm_write(cfgDesc+(length-16), &e,1);
|
|
||||||
}
|
|
||||||
|
|
|
@ -149,7 +149,10 @@ void gpg_io_insert_tlv(unsigned int T, unsigned int L, unsigned char const *V) {
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
/* FECTH data from received buffer */
|
/* FECTH data from received buffer */
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
void gpg_io_fetch_buffer(unsigned char* buffer, unsigned int len) {
|
||||||
|
os_memmove(buffer, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, len);
|
||||||
|
G_gpg_vstate.io_offset += len;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int gpg_io_fetch_u32() {
|
unsigned int gpg_io_fetch_u32() {
|
||||||
unsigned int v32;
|
unsigned int v32;
|
||||||
|
|
|
@ -165,7 +165,7 @@ __attribute__((section(".boot"))) int main(void) {
|
||||||
//start communication with MCU
|
//start communication with MCU
|
||||||
io_seproxyhal_init();
|
io_seproxyhal_init();
|
||||||
|
|
||||||
USB_power(1);
|
USB_CCID_power(1);
|
||||||
io_usb_ccid_set_card_inserted(1);
|
io_usb_ccid_set_card_inserted(1);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ static int gpg_pin_check_internal(gpg_pin_t *pin, unsigned char *pin_val, int p
|
||||||
counter = pin->counter-1;
|
counter = pin->counter-1;
|
||||||
gpg_nvm_write(&(pin->counter), &counter, sizeof(int));
|
gpg_nvm_write(&(pin->counter), &counter, sizeof(int));
|
||||||
cx_sha256_init(&sha256);
|
cx_sha256_init(&sha256);
|
||||||
cx_hash((cx_hash_t*)&sha256, CX_LAST, pin_val, pin_len, NULL, 0);
|
cx_hash((cx_hash_t*)&sha256, CX_LAST, pin_val, pin_len, NULL);
|
||||||
if (os_memcmp(sha256.acc, pin->value, 32)) {
|
if (os_memcmp(sha256.acc, pin->value, 32)) {
|
||||||
return SW_SECURITY_STATUS_NOT_SATISFIED;
|
return SW_SECURITY_STATUS_NOT_SATISFIED;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ void gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len) {
|
||||||
gpg_pin_t newpin;
|
gpg_pin_t newpin;
|
||||||
|
|
||||||
cx_sha256_init(&sha256);
|
cx_sha256_init(&sha256);
|
||||||
cx_hash((cx_hash_t*)&sha256, CX_LAST, pin_val, pin_len, newpin.value, 32);
|
cx_hash((cx_hash_t*)&sha256, CX_LAST, pin_val, pin_len, newpin.value);
|
||||||
newpin.length = pin_len;
|
newpin.length = pin_len;
|
||||||
newpin.counter = 3;
|
newpin.counter = 3;
|
||||||
|
|
||||||
|
|
112
src/gpg_pso.c
112
src/gpg_pso.c
|
@ -18,7 +18,6 @@
|
||||||
#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
|
||||||
|
@ -42,16 +41,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->priv_key.rsa1024;
|
key = (cx_rsa_private_key_t *)&sigkey->key.rsa1024;
|
||||||
break;
|
break;
|
||||||
case 2048/8:
|
case 2048/8:
|
||||||
key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa2048;
|
key = (cx_rsa_private_key_t *)&sigkey->key.rsa2048;
|
||||||
break;
|
break;
|
||||||
case 3072/8:
|
case 3072/8:
|
||||||
key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa3072;
|
key = (cx_rsa_private_key_t *)&sigkey->key.rsa3072;
|
||||||
break;
|
break;
|
||||||
case 4096/8:
|
case 4096/8:
|
||||||
key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa4096;
|
key = (cx_rsa_private_key_t *)&sigkey->key.rsa4096;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (key->size != ksz) {
|
if (key->size != ksz) {
|
||||||
|
@ -87,27 +86,23 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
||||||
unsigned int sz,i,rs_len;
|
unsigned int sz,i,rs_len;
|
||||||
unsigned char *rs;
|
unsigned char *rs;
|
||||||
|
|
||||||
key = &sigkey->priv_key.ecfp;
|
key = &sigkey->key.ecfp256;
|
||||||
|
if (key->d_len != 32) {
|
||||||
|
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||||
|
return SW_CONDITIONS_NOT_SATISFIED;
|
||||||
|
}
|
||||||
//sign
|
//sign
|
||||||
#define RS (G_gpg_vstate.work.io_buffer+(GPG_IO_BUFFER_LENGTH-256))
|
|
||||||
if (sigkey->attributes.value[0] == 19) {
|
if (sigkey->attributes.value[0] == 19) {
|
||||||
sz = gpg_curve2domainlen(key->curve);
|
|
||||||
if ((sz == 0) || (key->d_len != sz)) {
|
|
||||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
|
||||||
return SW_CONDITIONS_NOT_SATISFIED;
|
|
||||||
}
|
|
||||||
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, sz,
|
G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
|
||||||
RS, 256,
|
G_gpg_vstate.work.io_buffer);
|
||||||
NULL);
|
|
||||||
//reencode r,s in MPI format
|
//reencode r,s in MPI format
|
||||||
gpg_io_discard(0);
|
gpg_io_discard(0);
|
||||||
|
|
||||||
rs_len = RS[3];
|
rs_len = G_gpg_vstate.work.io_buffer[3];
|
||||||
rs = &RS[4];
|
rs = &G_gpg_vstate.work.io_buffer[4];
|
||||||
|
|
||||||
for (i = 0; i<2; i++) {
|
for (i = 0; i<2; i++) {
|
||||||
if (*rs == 0) {
|
if (*rs == 0) {
|
||||||
|
@ -121,17 +116,14 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
||||||
rs += 2;
|
rs += 2;
|
||||||
}
|
}
|
||||||
} else{
|
} else{
|
||||||
sz = cx_eddsa_sign(key,
|
sz = cx_eddsa_sign(key, NULL,
|
||||||
CX_NONE,
|
CX_NONE,
|
||||||
CX_SHA512,
|
CX_SHA512,
|
||||||
G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
|
G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
|
||||||
NULL, 0,
|
G_gpg_vstate.work.io_buffer+128);
|
||||||
RS, 256,
|
|
||||||
NULL);
|
|
||||||
gpg_io_discard(0);
|
gpg_io_discard(0);
|
||||||
gpg_io_insert(RS, sz);
|
gpg_io_insert(G_gpg_vstate.work.io_buffer+128, sz);
|
||||||
}
|
}
|
||||||
#undef RS
|
|
||||||
|
|
||||||
//send
|
//send
|
||||||
gpg_pso_reset_PW1();
|
gpg_pso_reset_PW1();
|
||||||
|
@ -142,38 +134,8 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
||||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gpg_apdu_pso() {
|
int gpg_apdu_pso(unsigned int pso) {
|
||||||
unsigned int t,l,ksz;
|
unsigned int t,l,ksz;
|
||||||
|
|
||||||
unsigned int pso;
|
|
||||||
|
|
||||||
pso = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ;
|
|
||||||
|
|
||||||
//UIF HANDLE
|
|
||||||
switch(pso) {
|
|
||||||
// --- PSO:CDS ---
|
|
||||||
case 0x9e9a:
|
|
||||||
if (G_gpg_vstate.kslot->sig.UIF[0]) {
|
|
||||||
if ((G_gpg_vstate.UIF_flags)==0) {
|
|
||||||
ui_menu_uifconfirm_display(0);
|
|
||||||
return 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);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
G_gpg_vstate.UIF_flags = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- PSO:ENC ---
|
|
||||||
switch(pso) {
|
switch(pso) {
|
||||||
// --- PSO:CDS ---
|
// --- PSO:CDS ---
|
||||||
case 0x9e9a: {
|
case 0x9e9a: {
|
||||||
|
@ -198,7 +160,7 @@ int gpg_apdu_pso() {
|
||||||
sz = cx_aes(key,
|
sz = cx_aes(key,
|
||||||
CX_ENCRYPT|CX_CHAIN_CBC|CX_LAST,
|
CX_ENCRYPT|CX_CHAIN_CBC|CX_LAST,
|
||||||
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, msg_len,
|
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, msg_len,
|
||||||
G_gpg_vstate.work.io_buffer+1, GPG_IO_BUFFER_LENGTH-1);
|
G_gpg_vstate.work.io_buffer+1);
|
||||||
//send
|
//send
|
||||||
gpg_io_discard(0);
|
gpg_io_discard(0);
|
||||||
G_gpg_vstate.work.io_buffer[0] = 0x02;
|
G_gpg_vstate.work.io_buffer[0] = 0x02;
|
||||||
|
@ -226,16 +188,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->priv_key.rsa1024;
|
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa1024;
|
||||||
break;
|
break;
|
||||||
case 2048/8:
|
case 2048/8:
|
||||||
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa2048;
|
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa2048;
|
||||||
break;
|
break;
|
||||||
case 3072/8:
|
case 3072/8:
|
||||||
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa3072;
|
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa3072;
|
||||||
break;
|
break;
|
||||||
case 4096/8:
|
case 4096/8:
|
||||||
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa4096;
|
key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa4096;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +230,7 @@ int gpg_apdu_pso() {
|
||||||
sz = cx_aes(key,
|
sz = cx_aes(key,
|
||||||
CX_DECRYPT|CX_CHAIN_CBC|CX_LAST,
|
CX_DECRYPT|CX_CHAIN_CBC|CX_LAST,
|
||||||
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, msg_len,
|
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, msg_len,
|
||||||
G_gpg_vstate.work.io_buffer, GPG_IO_BUFFER_LENGTH);
|
G_gpg_vstate.work.io_buffer);
|
||||||
//send
|
//send
|
||||||
gpg_io_discard(0);
|
gpg_io_discard(0);
|
||||||
gpg_io_inserted(sz);
|
gpg_io_inserted(sz);
|
||||||
|
@ -284,7 +246,11 @@ 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->priv_key.ecfp;
|
key = &G_gpg_vstate.mse_dec->key.ecfp256;
|
||||||
|
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) {
|
||||||
|
@ -298,10 +264,6 @@ 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;
|
||||||
|
|
||||||
|
@ -311,8 +273,8 @@ int gpg_apdu_pso() {
|
||||||
G_gpg_vstate.work.io_buffer[511] = 0x02;
|
G_gpg_vstate.work.io_buffer[511] = 0x02;
|
||||||
sz = cx_ecdh(key,
|
sz = cx_ecdh(key,
|
||||||
CX_ECDH_X,
|
CX_ECDH_X,
|
||||||
G_gpg_vstate.work.io_buffer+511, 65,
|
G_gpg_vstate.work.io_buffer+511,
|
||||||
G_gpg_vstate.work.io_buffer+256, 160);
|
G_gpg_vstate.work.io_buffer+256);
|
||||||
for (i = 0; i <=31; i++) {
|
for (i = 0; i <=31; i++) {
|
||||||
G_gpg_vstate.work.io_buffer[128+i] = G_gpg_vstate.work.io_buffer[287-i];
|
G_gpg_vstate.work.io_buffer[128+i] = G_gpg_vstate.work.io_buffer[287-i];
|
||||||
}
|
}
|
||||||
|
@ -320,8 +282,8 @@ int gpg_apdu_pso() {
|
||||||
} else {
|
} else {
|
||||||
sz = cx_ecdh(key,
|
sz = cx_ecdh(key,
|
||||||
CX_ECDH_X,
|
CX_ECDH_X,
|
||||||
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, 65,
|
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
|
||||||
G_gpg_vstate.work.io_buffer+128, 160);
|
G_gpg_vstate.work.io_buffer+128);
|
||||||
}
|
}
|
||||||
//send
|
//send
|
||||||
gpg_io_discard(0);
|
gpg_io_discard(0);
|
||||||
|
@ -334,6 +296,7 @@ int gpg_apdu_pso() {
|
||||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--- PSO:yy NOT SUPPPORTED ---
|
//--- PSO:yy NOT SUPPPORTED ---
|
||||||
|
@ -347,15 +310,6 @@ int gpg_apdu_pso() {
|
||||||
|
|
||||||
|
|
||||||
int gpg_apdu_internal_authenticate() {
|
int gpg_apdu_internal_authenticate() {
|
||||||
// --- PSO:AUTH ---
|
|
||||||
if (G_gpg_vstate.kslot->aut.UIF[0]) {
|
|
||||||
if ((G_gpg_vstate.UIF_flags)==0) {
|
|
||||||
ui_menu_uifconfirm_display(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) {
|
||||||
THROW(SW_WRONG_LENGTH);
|
THROW(SW_WRONG_LENGTH);
|
||||||
|
|
|
@ -19,19 +19,10 @@
|
||||||
#include "gpg_types.h"
|
#include "gpg_types.h"
|
||||||
#include "gpg_api.h"
|
#include "gpg_api.h"
|
||||||
#include "gpg_vars.h"
|
#include "gpg_vars.h"
|
||||||
const unsigned char C_MF[] = {0x3F, 0x00};
|
|
||||||
|
|
||||||
int gpg_apdu_select() {
|
int gpg_apdu_select() {
|
||||||
int sw;
|
int sw;
|
||||||
|
if ( (G_gpg_vstate.io_length == 6) &&
|
||||||
//MF
|
|
||||||
if ( (G_gpg_vstate.io_length == 2) &&
|
|
||||||
(os_memcmp(G_gpg_vstate.work.io_buffer, C_MF, G_gpg_vstate.io_length) == 0) ) {
|
|
||||||
gpg_io_discard(0);
|
|
||||||
sw = SW_OK;
|
|
||||||
}
|
|
||||||
//AID APP
|
|
||||||
else if ( (G_gpg_vstate.io_length == 6) &&
|
|
||||||
(os_memcmp(G_gpg_vstate.work.io_buffer, N_gpg_pstate->AID, G_gpg_vstate.io_length) == 0) ) {
|
(os_memcmp(G_gpg_vstate.work.io_buffer, N_gpg_pstate->AID, G_gpg_vstate.io_length) == 0) ) {
|
||||||
G_gpg_vstate.DO_current = 0;
|
G_gpg_vstate.DO_current = 0;
|
||||||
G_gpg_vstate.DO_reccord = 0;
|
G_gpg_vstate.DO_reccord = 0;
|
||||||
|
@ -49,9 +40,7 @@ int gpg_apdu_select() {
|
||||||
THROW(SW_STATE_TERMINATED);
|
THROW(SW_STATE_TERMINATED);
|
||||||
}
|
}
|
||||||
sw = SW_OK;
|
sw = SW_OK;
|
||||||
}
|
} else {
|
||||||
//NOT FOUND
|
|
||||||
else {
|
|
||||||
THROW(SW_FILE_NOT_FOUND);
|
THROW(SW_FILE_NOT_FOUND);
|
||||||
return SW_FILE_NOT_FOUND;
|
return SW_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
#define GPG_KEY_ATTRIBUTES_LENGTH 12
|
#define GPG_KEY_ATTRIBUTES_LENGTH 12
|
||||||
|
|
||||||
#define GPG_RSA_DEFAULT_PUB 0x00010001U
|
#define GPG_RSA_DEFAULT_PUB 0x010001U
|
||||||
|
|
||||||
struct gpg_pin_s {
|
struct gpg_pin_s {
|
||||||
unsigned int ref;
|
unsigned int ref;
|
||||||
|
@ -66,25 +66,15 @@ 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;
|
||||||
cx_ecfp_private_key_t ecfp;
|
} key;
|
||||||
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 ecfp;
|
cx_ecfp_public_key_t ecfp256;
|
||||||
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];
|
||||||
|
@ -126,7 +116,7 @@ struct gpg_nv_state_s {
|
||||||
/* 01F1 (01F2 is volatile)*/
|
/* 01F1 (01F2 is volatile)*/
|
||||||
unsigned char config_slot[3];
|
unsigned char config_slot[3];
|
||||||
/* RSA exponent */
|
/* RSA exponent */
|
||||||
unsigned char default_RSA_exponent[4];
|
unsigned int default_RSA_exponent;
|
||||||
|
|
||||||
/* 0101 0102 0103 0104 */
|
/* 0101 0102 0103 0104 */
|
||||||
LV(private_DO1, GPG_EXT_PRIVATE_DO_LENGTH);
|
LV(private_DO1, GPG_EXT_PRIVATE_DO_LENGTH);
|
||||||
|
@ -188,8 +178,6 @@ struct gpg_v_state_s {
|
||||||
gpg_key_t *mse_dec;
|
gpg_key_t *mse_dec;
|
||||||
unsigned char seed_mode;
|
unsigned char seed_mode;
|
||||||
|
|
||||||
unsigned char UIF_flags;
|
|
||||||
|
|
||||||
/* io state*/
|
/* io state*/
|
||||||
|
|
||||||
unsigned char io_cla;
|
unsigned char io_cla;
|
||||||
|
@ -203,41 +191,26 @@ 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 {
|
||||||
union {
|
cx_rsa_1024_public_key_t public;
|
||||||
cx_rsa_public_key_t public;
|
cx_rsa_1024_private_key_t private;
|
||||||
cx_rsa_1024_public_key_t public1024;
|
}rsa1024;
|
||||||
cx_rsa_2048_public_key_t public2048;
|
|
||||||
cx_rsa_3072_public_key_t public3072;
|
|
||||||
cx_rsa_4096_public_key_t public4096;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
cx_rsa_private_key_t private;
|
|
||||||
cx_rsa_1024_private_key_t private1024;
|
|
||||||
cx_rsa_2048_private_key_t private2048;
|
|
||||||
cx_rsa_3072_private_key_t private3072;
|
|
||||||
cx_rsa_4096_private_key_t private4096;
|
|
||||||
};
|
|
||||||
} rsa;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
union{
|
cx_rsa_2048_public_key_t public;
|
||||||
cx_ecfp_public_key_t public;
|
cx_rsa_2048_private_key_t private;
|
||||||
cx_ecfp_256_public_key_t public256;
|
}rsa2048;
|
||||||
cx_ecfp_384_public_key_t public384;
|
struct {
|
||||||
cx_ecfp_512_public_key_t public512;
|
cx_rsa_3072_public_key_t public;
|
||||||
cx_ecfp_640_public_key_t public640;
|
cx_rsa_3072_private_key_t private;
|
||||||
};
|
}rsa3072;
|
||||||
union {
|
struct {
|
||||||
cx_ecfp_private_key_t private;
|
cx_rsa_4096_public_key_t public;
|
||||||
cx_ecfp_256_private_key_t private256;
|
cx_rsa_4096_private_key_t private;
|
||||||
cx_ecfp_384_private_key_t private384;
|
}rsa4096;
|
||||||
cx_ecfp_512_private_key_t private512;
|
struct {
|
||||||
cx_ecfp_640_private_key_t private640;
|
cx_ecfp_public_key_t public;
|
||||||
};
|
cx_ecfp_private_key_t private;
|
||||||
}ecfp;
|
}ecfp256;
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -257,7 +230,7 @@ struct gpg_v_state_s {
|
||||||
unsigned char pinmode;
|
unsigned char pinmode;
|
||||||
|
|
||||||
/* ux menus */
|
/* ux menus */
|
||||||
char menu[112];
|
char menu[64];
|
||||||
unsigned char ux_pinentry[12];
|
unsigned char ux_pinentry[12];
|
||||||
unsigned int ux_key;
|
unsigned int ux_key;
|
||||||
unsigned int ux_type;
|
unsigned int ux_type;
|
||||||
|
|
|
@ -34,5 +34,3 @@ 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,9 +36,6 @@ 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)
|
||||||
|
@ -57,7 +54,5 @@ extern const char * const C_UIF_INVALID;
|
||||||
#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
|
||||||
|
|
|
@ -91,122 +91,6 @@ void ui_info(const char* msg1, const char* msg2, const void *menu_display, unsig
|
||||||
UX_MENU_DISPLAY(0, G_gpg_vstate.ui_dogsays, NULL);
|
UX_MENU_DISPLAY(0, G_gpg_vstate.ui_dogsays, NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------ UIF CONFIRM UX ----------------------------- */
|
|
||||||
unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int button_mask_counter);
|
|
||||||
unsigned int ui_uifconfirm_prepro(const bagl_element_t* element);
|
|
||||||
|
|
||||||
const bagl_element_t ui_uifconfirm_nanos[] = {
|
|
||||||
// type userid x y w h str rad fill fg bg font_id icon_id
|
|
||||||
{ {BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0},
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
0, 0,
|
|
||||||
NULL, NULL, NULL},
|
|
||||||
|
|
||||||
{ {BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS },
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
0, 0,
|
|
||||||
NULL, NULL, NULL },
|
|
||||||
|
|
||||||
{ {BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK },
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
0, 0,
|
|
||||||
NULL, NULL, NULL },
|
|
||||||
|
|
||||||
{ {BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 },
|
|
||||||
G_gpg_vstate.menu,
|
|
||||||
0,
|
|
||||||
0, 0,
|
|
||||||
NULL, NULL, NULL },
|
|
||||||
{ {BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 },
|
|
||||||
G_gpg_vstate.menu,
|
|
||||||
0,
|
|
||||||
0, 0,
|
|
||||||
NULL, NULL, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
void ui_menu_uifconfirm_display(unsigned int value) {
|
|
||||||
UX_DISPLAY(ui_uifconfirm_nanos, (void*)ui_uifconfirm_prepro);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int ui_uifconfirm_prepro(const bagl_element_t* element) {
|
|
||||||
if (element->component.userid == 1) {
|
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Confirm:");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (element->component.userid == 2) {
|
|
||||||
unsigned int uif_case = (G_gpg_vstate.io_ins<<16)|(G_gpg_vstate.io_p1<<8)|(G_gpg_vstate.io_p2);
|
|
||||||
switch (uif_case) {
|
|
||||||
case 0x002A9E9A:
|
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Signature");
|
|
||||||
return 1;
|
|
||||||
case 0x002A8680:
|
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Encryption");
|
|
||||||
return 1;
|
|
||||||
case 0x002A8086:
|
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Decryption");
|
|
||||||
return 1;
|
|
||||||
case 0x0088000:
|
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Authentication");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Please Cancel");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int button_mask_counter) {
|
|
||||||
unsigned int sw;
|
|
||||||
|
|
||||||
sw = 0x6985;
|
|
||||||
switch(button_mask) {
|
|
||||||
case BUTTON_EVT_RELEASED|BUTTON_LEFT: // CANCEL
|
|
||||||
gpg_io_discard(1);
|
|
||||||
gpg_io_insert_u16(sw);
|
|
||||||
gpg_io_do(IO_RETURN_AFTER_TX);
|
|
||||||
ui_menu_main_display(0);
|
|
||||||
sw = 0x6985;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BUTTON_EVT_RELEASED|BUTTON_RIGHT: // OK
|
|
||||||
BEGIN_TRY {
|
|
||||||
TRY {
|
|
||||||
G_gpg_vstate.UIF_flags = 1;
|
|
||||||
if (G_gpg_vstate.io_ins == INS_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) {
|
|
||||||
gpg_io_discard(1);
|
|
||||||
if ( (e & 0xFFFF0000) ||
|
|
||||||
( ((e&0xF000)!=0x6000) && ((e&0xF000)!=0x9000) ) ) {
|
|
||||||
gpg_io_insert_u32(e);
|
|
||||||
sw = 0x6f42;
|
|
||||||
} else {
|
|
||||||
sw = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FINALLY {
|
|
||||||
G_gpg_vstate.UIF_flags = 0;
|
|
||||||
gpg_io_insert_u16(sw);
|
|
||||||
gpg_io_do(IO_RETURN_AFTER_TX);
|
|
||||||
ui_menu_main_display(0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
} END_TRY;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------ PIN CONFIRM UX ----------------------------- */
|
/* ------------------------------ PIN CONFIRM UX ----------------------------- */
|
||||||
|
|
||||||
const bagl_element_t ui_pinconfirm_nanos[] = {
|
const bagl_element_t ui_pinconfirm_nanos[] = {
|
||||||
|
@ -506,17 +390,12 @@ static unsigned int validate_pin() {
|
||||||
#define LABEL_AUT "Authentication"
|
#define LABEL_AUT "Authentication"
|
||||||
#define LABEL_DEC "Decryption"
|
#define LABEL_DEC "Decryption"
|
||||||
|
|
||||||
#define LABEL_RSA2048 "RSA 2048"
|
#define LABEL_RSA2048 "RSA 2048"
|
||||||
#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_NISTP384 "NIST P384"
|
#define LABEL_BPOOLR1 "Brainpool R1"
|
||||||
//#define LABEL_NISTP521 "NIST P521"
|
#define LABEL_Ed25519 "Ed25519"
|
||||||
#define LABEL_SECP256K1 "SEPC 256K1"
|
|
||||||
#define LABEL_BPOOL256R1 "Brainpool 256R1"
|
|
||||||
//#define LABEL_BPOOL384R1 "Brainpool 384R1"
|
|
||||||
//#define LABEL_BPOOL512R1 "Brainpool 512R1"
|
|
||||||
#define LABEL_Ed25519 "Ed25519"
|
|
||||||
|
|
||||||
const ux_menu_entry_t ui_menu_template[] = {
|
const ux_menu_entry_t ui_menu_template[] = {
|
||||||
{ui_menu_tmpl_key, NULL, -1, NULL, "Choose key...", NULL, 0, 0},
|
{ui_menu_tmpl_key, NULL, -1, NULL, "Choose key...", NULL, 0, 0},
|
||||||
|
@ -560,34 +439,12 @@ 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_SECP384R1:
|
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_NISTP384);
|
|
||||||
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:
|
case CX_CURVE_BrainPoolP256R1:
|
||||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOL256R1);
|
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOLR1);
|
||||||
break;
|
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;
|
||||||
|
@ -608,8 +465,7 @@ 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));
|
||||||
|
@ -626,21 +482,24 @@ 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:
|
||||||
//case CX_CURVE_SECP384R1:
|
if (G_gpg_vstate.ux_key == 2) {
|
||||||
//case CX_CURVE_SECP521R1:
|
attributes.value[0] = 18; //ecdh
|
||||||
|
} 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:
|
if (G_gpg_vstate.ux_key == 2) {
|
||||||
//case CX_CURVE_BrainPoolP512R1:
|
|
||||||
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
|
||||||
}
|
}
|
||||||
oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len);
|
os_memmove(attributes.value+1, C_OID_BRAINPOOL256R1, sizeof(C_OID_BRAINPOOL256R1));
|
||||||
os_memmove(attributes.value+1, oid, sizeof(oid_len));
|
attributes.length = 1+sizeof(C_OID_BRAINPOOL256R1);
|
||||||
attributes.length = 1+oid_len;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CX_CURVE_Ed25519:
|
case CX_CURVE_Ed25519:
|
||||||
|
@ -655,7 +514,7 @@ void ui_menu_tmpl_set_action(unsigned int value) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = TEMPLATE_TYPE;
|
err = TEMPLATE_TYPE;
|
||||||
goto ERROR;
|
goto ERROR;
|
||||||
}
|
}
|
||||||
|
@ -702,18 +561,13 @@ void ui_menu_tmpl_key_action(unsigned int value) {
|
||||||
|
|
||||||
|
|
||||||
const ux_menu_entry_t ui_menu_tmpl_type[] = {
|
const ux_menu_entry_t ui_menu_tmpl_type[] = {
|
||||||
{NULL, ui_menu_tmpl_type_action, 2048, NULL, LABEL_RSA2048, NULL, 0, 0},
|
{NULL, ui_menu_tmpl_type_action, 2048, NULL, LABEL_RSA2048, NULL, 0, 0},
|
||||||
{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_SECP384R1, NULL, LABEL_NISTP384, 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_SECP521R1, NULL, LABEL_NISTP521, 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_SECP256K1, NULL, LABEL_SECP256K1, NULL, 0, 0},
|
{ui_menu_template, NULL, 1, &C_badge_back, "Back", NULL, 61, 40},
|
||||||
{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},
|
|
||||||
{ui_menu_template, NULL, 1, &C_badge_back, "Back", NULL, 61, 40},
|
|
||||||
UX_MENU_END
|
UX_MENU_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -809,7 +663,6 @@ void ui_menu_pinmode_action(unsigned int value) {
|
||||||
} else {
|
} else {
|
||||||
s = 3;
|
s = 3;
|
||||||
}
|
}
|
||||||
//#warning USBD_CCID_activate_pinpad commented
|
|
||||||
USBD_CCID_activate_pinpad(s);
|
USBD_CCID_activate_pinpad(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -840,84 +693,6 @@ 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[] = {
|
||||||
|
@ -944,7 +719,6 @@ 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,5 +22,4 @@ 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
|
File diff suppressed because it is too large
Load diff
|
@ -1,32 +0,0 @@
|
||||||
#ifndef USBD_CCID_IMPL_H
|
|
||||||
#define USBD_CCID_IMPL_H
|
|
||||||
|
|
||||||
#ifdef HAVE_USB_CLASS_CCID
|
|
||||||
|
|
||||||
// ================================================
|
|
||||||
// CCID
|
|
||||||
|
|
||||||
#define TPDU_EXCHANGE 0x01
|
|
||||||
#define SHORT_APDU_EXCHANGE 0x02
|
|
||||||
#define EXTENDED_APDU_EXCHANGE 0x04
|
|
||||||
#define CHARACTER_EXCHANGE 0x00
|
|
||||||
|
|
||||||
#define EXCHANGE_LEVEL_FEATURE SHORT_APDU_EXCHANGE
|
|
||||||
|
|
||||||
#define CCID_INTF 2
|
|
||||||
#define CCID_BULK_IN_EP 0x83
|
|
||||||
#define CCID_BULK_EPIN_SIZE 64
|
|
||||||
#define CCID_BULK_OUT_EP 0x03
|
|
||||||
#define CCID_BULK_EPOUT_SIZE 64
|
|
||||||
|
|
||||||
#ifdef HAVE_CCID_INTERRUPT
|
|
||||||
#define CCID_INTR_IN_EP 0x84
|
|
||||||
#define CCID_INTR_EPIN_SIZE 16
|
|
||||||
#endif // HAVE_CCID_INTERRUPT
|
|
||||||
|
|
||||||
#define IO_CCID_DATA_BUFFER_SIZE IO_APDU_BUFFER_SIZE
|
|
||||||
#define G_io_ccid_data_buffer G_io_apdu_buffer
|
|
||||||
|
|
||||||
#endif // HAVE_USB_CLASS_CCID
|
|
||||||
|
|
||||||
#endif // USBD_CCID_IMPL_H
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef USBD_HID_IMPL_H
|
|
||||||
#define USBD_HID_IMPL_H
|
|
||||||
|
|
||||||
// ================================================
|
|
||||||
// HIDGEN
|
|
||||||
|
|
||||||
#define HID_INTF 0
|
|
||||||
|
|
||||||
#define HID_EPIN_ADDR 0x82
|
|
||||||
#define HID_EPIN_SIZE 0x40
|
|
||||||
|
|
||||||
#define HID_EPOUT_ADDR 0x02
|
|
||||||
#define HID_EPOUT_SIZE 0x40
|
|
||||||
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
// ================================================
|
|
||||||
// HID U2F
|
|
||||||
|
|
||||||
#define U2F_INTF 1
|
|
||||||
|
|
||||||
#define U2F_EPIN_ADDR 0x81
|
|
||||||
#define U2F_EPIN_SIZE 0x40
|
|
||||||
|
|
||||||
#define U2F_EPOUT_ADDR 0x01
|
|
||||||
#define U2F_EPOUT_SIZE 0x40
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
|
|
||||||
#endif // USBD_HID_IMPL_H
|
|
||||||
|
|
|
@ -1,916 +0,0 @@
|
||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* @file usbd_hid.c
|
|
||||||
* @author MCD Application Team
|
|
||||||
* @version V2.2.0
|
|
||||||
* @date 13-June-2014
|
|
||||||
* @brief This file provides the HID core functions.
|
|
||||||
*
|
|
||||||
* @verbatim
|
|
||||||
*
|
|
||||||
* ===================================================================
|
|
||||||
* HID Class Description
|
|
||||||
* ===================================================================
|
|
||||||
* This module manages the HID class V1.11 following the "Device Class Definition
|
|
||||||
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
|
|
||||||
* This driver implements the following aspects of the specification:
|
|
||||||
* - The Boot Interface Subclass
|
|
||||||
* - Usage Page : Generic Desktop
|
|
||||||
* - Usage : Vendor
|
|
||||||
* - Collection : Application
|
|
||||||
*
|
|
||||||
* @note In HS mode and when the DMA is used, all variables and data structures
|
|
||||||
* dealing with the DMA during the transaction process should be 32-bit aligned.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @endverbatim
|
|
||||||
*
|
|
||||||
******************************************************************************
|
|
||||||
* @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__
|
|
||||||
|
|
||||||
#include "os.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "usbd_hid.h"
|
|
||||||
#include "usbd_hid_impl.h"
|
|
||||||
|
|
||||||
#include "usbd_ctlreq.h"
|
|
||||||
|
|
||||||
#include "usbd_core.h"
|
|
||||||
#include "usbd_conf.h"
|
|
||||||
|
|
||||||
#include "usbd_def.h"
|
|
||||||
#include "os_io_seproxyhal.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
#include "u2f_transport.h"
|
|
||||||
#include "u2f_impl.h"
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
|
|
||||||
#ifdef HAVE_USB_CLASS_CCID
|
|
||||||
#include "usbd_ccid_core.h"
|
|
||||||
#endif // HAVE_USB_CLASS_CCID
|
|
||||||
|
|
||||||
|
|
||||||
/** @addtogroup STM32_USB_DEVICE_LIBRARY
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** @defgroup USBD_HID
|
|
||||||
* @brief usbd core module
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @defgroup USBD_HID_Private_TypesDefinitions
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** @defgroup USBD_HID_Private_Defines
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** @defgroup USBD_HID_Private_Macros
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
/** @defgroup USBD_HID_Private_FunctionPrototypes
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @defgroup USBD_HID_Private_Variables
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define HID_EPIN_ADDR 0x82
|
|
||||||
#define HID_EPIN_SIZE 0x40
|
|
||||||
|
|
||||||
#define HID_EPOUT_ADDR 0x02
|
|
||||||
#define HID_EPOUT_SIZE 0x40
|
|
||||||
|
|
||||||
#define USBD_LANGID_STRING 0x409
|
|
||||||
|
|
||||||
#ifdef HAVE_VID_PID_PROBER
|
|
||||||
#define USBD_VID 0x2581
|
|
||||||
#define USBD_PID 0xf1d1
|
|
||||||
#else
|
|
||||||
#define USBD_VID 0x2C97
|
|
||||||
#if defined(TARGET_BLUE) // blue
|
|
||||||
#define USBD_PID 0x0000
|
|
||||||
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
|
|
||||||
4*2+2,
|
|
||||||
USB_DESC_TYPE_STRING,
|
|
||||||
'B', 0,
|
|
||||||
'l', 0,
|
|
||||||
'u', 0,
|
|
||||||
'e', 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
#elif defined(TARGET_NANOS) // nano s
|
|
||||||
#define USBD_PID 0x0001
|
|
||||||
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
|
|
||||||
6*2+2,
|
|
||||||
USB_DESC_TYPE_STRING,
|
|
||||||
'N', 0,
|
|
||||||
'a', 0,
|
|
||||||
'n', 0,
|
|
||||||
'o', 0,
|
|
||||||
' ', 0,
|
|
||||||
'S', 0,
|
|
||||||
};
|
|
||||||
#elif defined(TARGET_ARAMIS) // aramis
|
|
||||||
#define USBD_PID 0x0002
|
|
||||||
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
|
|
||||||
6*2+2,
|
|
||||||
USB_DESC_TYPE_STRING,
|
|
||||||
'A', 0,
|
|
||||||
'r', 0,
|
|
||||||
'a', 0,
|
|
||||||
'm', 0,
|
|
||||||
'i', 0,
|
|
||||||
's', 0,
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
#error unknown TARGET_ID
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB Standard Device Descriptor */
|
|
||||||
static const uint8_t const USBD_LangIDDesc[]=
|
|
||||||
{
|
|
||||||
USB_LEN_LANGID_STR_DESC,
|
|
||||||
USB_DESC_TYPE_STRING,
|
|
||||||
LOBYTE(USBD_LANGID_STRING),
|
|
||||||
HIBYTE(USBD_LANGID_STRING),
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t const USB_SERIAL_STRING[] =
|
|
||||||
{
|
|
||||||
4*2+2,
|
|
||||||
USB_DESC_TYPE_STRING,
|
|
||||||
'0', 0,
|
|
||||||
'0', 0,
|
|
||||||
'0', 0,
|
|
||||||
'1', 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t const USBD_MANUFACTURER_STRING[] = {
|
|
||||||
6*2+2,
|
|
||||||
USB_DESC_TYPE_STRING,
|
|
||||||
'L', 0,
|
|
||||||
'e', 0,
|
|
||||||
'd', 0,
|
|
||||||
'g', 0,
|
|
||||||
'e', 0,
|
|
||||||
'r', 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define USBD_INTERFACE_FS_STRING USBD_PRODUCT_FS_STRING
|
|
||||||
#define USBD_CONFIGURATION_FS_STRING USBD_PRODUCT_FS_STRING
|
|
||||||
|
|
||||||
static const uint8_t const HID_ReportDesc[] = {
|
|
||||||
0x06, 0xA0, 0xFF, // Usage page (vendor defined)
|
|
||||||
0x09, 0x01, // Usage ID (vendor defined)
|
|
||||||
0xA1, 0x01, // Collection (application)
|
|
||||||
|
|
||||||
// The Input report
|
|
||||||
0x09, 0x03, // Usage ID - vendor defined
|
|
||||||
0x15, 0x00, // Logical Minimum (0)
|
|
||||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
0x75, 0x08, // Report Size (8 bits)
|
|
||||||
0x95, HID_EPIN_SIZE, // Report Count (64 fields)
|
|
||||||
0x81, 0x08, // Input (Data, Variable, Absolute)
|
|
||||||
|
|
||||||
// The Output report
|
|
||||||
0x09, 0x04, // Usage ID - vendor defined
|
|
||||||
0x15, 0x00, // Logical Minimum (0)
|
|
||||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
0x75, 0x08, // Report Size (8 bits)
|
|
||||||
0x95, HID_EPOUT_SIZE, // Report Count (64 fields)
|
|
||||||
0x91, 0x08, // Output (Data, Variable, Absolute)
|
|
||||||
0xC0
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
static const uint8_t const HID_ReportDesc_fido[] = {
|
|
||||||
0x06, 0xD0, 0xF1, // Usage page (vendor defined)
|
|
||||||
0x09, 0x01, // Usage ID (vendor defined)
|
|
||||||
0xA1, 0x01, // Collection (application)
|
|
||||||
|
|
||||||
// The Input report
|
|
||||||
0x09, 0x03, // Usage ID - vendor defined
|
|
||||||
0x15, 0x00, // Logical Minimum (0)
|
|
||||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
0x75, 0x08, // Report Size (8 bits)
|
|
||||||
0x95, U2F_EPIN_SIZE, // Report Count (64 fields)
|
|
||||||
0x81, 0x08, // Input (Data, Variable, Absolute)
|
|
||||||
|
|
||||||
// The Output report
|
|
||||||
0x09, 0x04, // Usage ID - vendor defined
|
|
||||||
0x15, 0x00, // Logical Minimum (0)
|
|
||||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
0x75, 0x08, // Report Size (8 bits)
|
|
||||||
0x95, U2F_EPOUT_SIZE, // Report Count (64 fields)
|
|
||||||
0x91, 0x08, // Output (Data, Variable, Absolute)
|
|
||||||
0xC0
|
|
||||||
};
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
|
|
||||||
#define ARRAY_U2LE(l) (l)&0xFF, (l)>>8
|
|
||||||
|
|
||||||
/* USB HID device Configuration Descriptor */
|
|
||||||
static __ALIGN_BEGIN const uint8_t const N_USBD_CfgDesc[] __ALIGN_END =
|
|
||||||
{
|
|
||||||
0x09, /* bLength: Configuration Descriptor size */
|
|
||||||
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
|
||||||
ARRAY_U2LE(0x9 /* wTotalLength: Bytes returned */
|
|
||||||
+0x9+0x9+0x7+0x7
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
+0x9+0x9+0x7+0x7
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
#ifdef HAVE_USB_CLASS_CCID
|
|
||||||
+0x9+0x36+0x7+0x7
|
|
||||||
#endif // HAVE_USB_CLASS_CCID
|
|
||||||
),
|
|
||||||
1
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
+1
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
#ifdef HAVE_USB_CLASS_CCID
|
|
||||||
+1
|
|
||||||
#endif // HAVE_USB_CLASS_CCID
|
|
||||||
, /*bNumInterfaces */
|
|
||||||
0x01, /*bConfigurationValue: Configuration value*/
|
|
||||||
USBD_IDX_PRODUCT_STR, /*iConfiguration: Index of string descriptor describing the configuration*/
|
|
||||||
0xC0, /*bmAttributes: bus powered */
|
|
||||||
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
|
|
||||||
|
|
||||||
/* HIDGEN ################################################################################################ */
|
|
||||||
|
|
||||||
/************** Descriptor of KBD HID interface ****************/
|
|
||||||
0x09, /*bLength: Interface Descriptor size*/
|
|
||||||
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
|
|
||||||
HID_INTF, /*bInterfaceNumber: Number of Interface*/
|
|
||||||
0x00, /*bAlternateSetting: Alternate setting*/
|
|
||||||
0x02, /*bNumEndpoints*/
|
|
||||||
0x03, /*bInterfaceClass: HID*/
|
|
||||||
0x00, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
|
|
||||||
0x00, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
|
|
||||||
USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
|
|
||||||
|
|
||||||
/******************** Descriptor of HID *************************/
|
|
||||||
0x09, /*bLength: HID Descriptor size*/
|
|
||||||
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
|
|
||||||
0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
|
|
||||||
0x01,
|
|
||||||
0x00, /*bCountryCode: Hardware target country*/
|
|
||||||
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
|
|
||||||
0x22, /*bDescriptorType*/
|
|
||||||
sizeof(HID_ReportDesc),/*wItemLength: Total length of Report descriptor*/
|
|
||||||
0x00,
|
|
||||||
|
|
||||||
/******************** Descriptor of Custom HID endpoints ********************/
|
|
||||||
0x07, /*bLength: Endpoint Descriptor size*/
|
|
||||||
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
|
|
||||||
HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
|
|
||||||
0x03, /*bmAttributes: Interrupt endpoint*/
|
|
||||||
HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */
|
|
||||||
0x00,
|
|
||||||
0x01, /*bInterval: Polling Interval (20 ms)*/
|
|
||||||
|
|
||||||
0x07, /* bLength: Endpoint Descriptor size */
|
|
||||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
|
|
||||||
HID_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
|
|
||||||
0x03, /* bmAttributes: Interrupt endpoint */
|
|
||||||
HID_EPOUT_SIZE, /* wMaxPacketSize: 2 Bytes max */
|
|
||||||
0x00,
|
|
||||||
0x01, /* bInterval: Polling Interval (20 ms) */
|
|
||||||
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
/* HID FIDO ################################################################################################ */
|
|
||||||
|
|
||||||
/************** Descriptor of HID FIDO interface ****************/
|
|
||||||
0x09, /*bLength: Interface Descriptor size*/
|
|
||||||
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
|
|
||||||
U2F_INTF, /*bInterfaceNumber: Number of Interface*/
|
|
||||||
0x00, /*bAlternateSetting: Alternate setting*/
|
|
||||||
0x02, /*bNumEndpoints*/
|
|
||||||
0x03, /*bInterfaceClass: HID*/
|
|
||||||
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
|
|
||||||
0x01, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
|
|
||||||
USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
|
|
||||||
|
|
||||||
/******************** Descriptor of HID *************************/
|
|
||||||
0x09, /*bLength: HID Descriptor size*/
|
|
||||||
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
|
|
||||||
0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
|
|
||||||
0x01,
|
|
||||||
0x21, /*bCountryCode: Hardware target country*/ // 0x21: US, 0x08: FR, 0x0D: ISO Intl
|
|
||||||
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
|
|
||||||
0x22, /*bDescriptorType*/
|
|
||||||
sizeof(HID_ReportDesc_fido),/*wItemLength: Total length of Report descriptor*/
|
|
||||||
0x00,
|
|
||||||
/******************** Descriptor of Custom HID endpoints ********************/
|
|
||||||
0x07, /*bLength: Endpoint Descriptor size*/
|
|
||||||
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
|
|
||||||
U2F_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
|
|
||||||
0x03, /*bmAttributes: Interrupt endpoint*/
|
|
||||||
U2F_EPIN_SIZE, /*wMaxPacketSize: */
|
|
||||||
0x00,
|
|
||||||
0x01, /*bInterval: Polling Interval */
|
|
||||||
|
|
||||||
0x07, /* bLength: Endpoint Descriptor size */
|
|
||||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
|
|
||||||
U2F_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
|
|
||||||
0x03, /* bmAttributes: Interrupt endpoint */
|
|
||||||
U2F_EPOUT_SIZE, /* wMaxPacketSize: */
|
|
||||||
0x00,
|
|
||||||
0x01,/* bInterval: Polling Interval */
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
|
|
||||||
#ifdef HAVE_USB_CLASS_CCID
|
|
||||||
/* CCID ################################################################################################ */
|
|
||||||
|
|
||||||
/******************** CCID **** interface ********************/
|
|
||||||
0x09, /* bLength: Interface Descriptor size */
|
|
||||||
0x04, /* bDescriptorType: */
|
|
||||||
CCID_INTF, /* bInterfaceNumber: Number of Interface */
|
|
||||||
0x00, /* bAlternateSetting: Alternate setting */
|
|
||||||
0x02, /* bNumEndpoints: endpoints used */
|
|
||||||
0x0B, /* bInterfaceClass: user's interface for CCID */
|
|
||||||
0x00, /* bInterfaceSubClass : */
|
|
||||||
0x00, /* nInterfaceProtocol : None */
|
|
||||||
0x05, /* iInterface: */
|
|
||||||
|
|
||||||
/******************* CCID class descriptor ********************/
|
|
||||||
0x36, /* bLength: CCID Descriptor size */
|
|
||||||
0x21, /* bDescriptorType: Functional Descriptor type. */
|
|
||||||
0x10, /* bcdCCID(LSB): CCID Class Spec release number (1.00) */
|
|
||||||
0x01, /* bcdCCID(MSB) */
|
|
||||||
|
|
||||||
0x00, /* bMaxSlotIndex :highest available slot on this device */
|
|
||||||
0x03, /* bVoltageSupport: bit Wise OR for 01h-5.0V 02h-3.0V
|
|
||||||
04h 1.8V*/
|
|
||||||
|
|
||||||
0x01,0x00,0x00,0x00, /* dwProtocols: 0001h = Protocol T=0 */
|
|
||||||
0x10,0x0E,0x00,0x00, /* dwDefaultClock: 3.6Mhz = 3600kHz = 0x0E10,
|
|
||||||
for 4 Mhz the value is (0x00000FA0) :
|
|
||||||
This is used in ETU and waiting time calculations*/
|
|
||||||
0x10,0x0E,0x00,0x00, /* dwMaximumClock: Maximum supported ICC clock frequency
|
|
||||||
in KHz. So, 3.6Mhz = 3600kHz = 0x0E10,
|
|
||||||
4 Mhz (0x00000FA0) : */
|
|
||||||
0x00, /* bNumClockSupported : no setting from PC
|
|
||||||
If the value is 00h, the
|
|
||||||
supported clock frequencies are assumed to be the
|
|
||||||
default clock frequency defined by dwDefaultClock
|
|
||||||
and the maximum clock frequency defined by
|
|
||||||
dwMaximumClock */
|
|
||||||
|
|
||||||
0xCD,0x25,0x00,0x00, /* dwDataRate: Default ICC I/O data rate in bps
|
|
||||||
9677 bps = 0x25CD
|
|
||||||
for example 10752 bps (0x00002A00) */
|
|
||||||
|
|
||||||
0xCD,0x25,0x00,0x00, /* dwMaxDataRate: Maximum supported ICC I/O data
|
|
||||||
rate in bps */
|
|
||||||
0x00, /* bNumDataRatesSupported :
|
|
||||||
The number of data rates that are supported by the CCID
|
|
||||||
If the value is 00h, all data rates between the default
|
|
||||||
data rate dwDataRate and the maximum data rate
|
|
||||||
dwMaxDataRate are supported.
|
|
||||||
Dont support GET_CLOCK_FREQUENCIES
|
|
||||||
*/
|
|
||||||
//46
|
|
||||||
0x00,0x00,0x00,0x00, /* dwMaxIFSD: 0 (T=0 only) */
|
|
||||||
0x00,0x00,0x00,0x00, /* dwSynchProtocols */
|
|
||||||
0x00,0x00,0x00,0x00, /* dwMechanical: no special characteristics */
|
|
||||||
|
|
||||||
0xBA, 0x06, 0x02, 0x00,
|
|
||||||
//0x38,0x00,EXCHANGE_LEVEL_FEATURE,0x00,
|
|
||||||
/* dwFeatures: clk, baud rate, voltage : automatic */
|
|
||||||
/* 00000008h Automatic ICC voltage selection
|
|
||||||
00000010h Automatic ICC clock frequency change
|
|
||||||
00000020h Automatic baud rate change according to
|
|
||||||
active parameters provided by the Host or self
|
|
||||||
determined 00000100h CCID can set
|
|
||||||
ICC in clock stop mode
|
|
||||||
|
|
||||||
Only one of the following values may be present to
|
|
||||||
select a level of exchange:
|
|
||||||
00010000h TPDU level exchanges with CCID
|
|
||||||
00020000h Short APDU level exchange with CCID
|
|
||||||
00040000h Short and Extended APDU level exchange
|
|
||||||
If none of those values : character level of exchange*/
|
|
||||||
0x0F,0x01,0x00,0x00, /* dwMaxCCIDMessageLength: Maximum block size + header*/
|
|
||||||
/* 261 + 10 */
|
|
||||||
|
|
||||||
0x00, /* bClassGetResponse*/
|
|
||||||
0x00, /* bClassEnvelope */
|
|
||||||
0x00,0x00, /* wLcdLayout : 0000h no LCD. */
|
|
||||||
0x00, /* bPINSupport : no PIN verif and modif */
|
|
||||||
0x01, /* bMaxCCIDBusySlots */
|
|
||||||
|
|
||||||
/******************** CCID Endpoints ********************/
|
|
||||||
0x07, /*Endpoint descriptor length = 7*/
|
|
||||||
0x05, /*Endpoint descriptor type */
|
|
||||||
CCID_BULK_IN_EP, /*Endpoint address (IN, address 1) */
|
|
||||||
0x02, /*Bulk endpoint type */
|
|
||||||
LOBYTE(CCID_BULK_EPIN_SIZE),
|
|
||||||
HIBYTE(CCID_BULK_EPIN_SIZE),
|
|
||||||
0x00, /*Polling interval in milliseconds */
|
|
||||||
|
|
||||||
0x07, /*Endpoint descriptor length = 7 */
|
|
||||||
0x05, /*Endpoint descriptor type */
|
|
||||||
CCID_BULK_OUT_EP, /*Endpoint address (OUT, address 1) */
|
|
||||||
0x02, /*Bulk endpoint type */
|
|
||||||
LOBYTE(CCID_BULK_EPOUT_SIZE),
|
|
||||||
HIBYTE(CCID_BULK_EPOUT_SIZE),
|
|
||||||
0x00, /*Polling interval in milliseconds*/
|
|
||||||
#endif // HAVE_USB_CLASS_CCID
|
|
||||||
} ;
|
|
||||||
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
/* USB HID device Configuration Descriptor */
|
|
||||||
__ALIGN_BEGIN const uint8_t const USBD_HID_Desc_fido[] __ALIGN_END =
|
|
||||||
{
|
|
||||||
/******************** Descriptor of HID *************************/
|
|
||||||
0x09, /*bLength: HID Descriptor size*/
|
|
||||||
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
|
|
||||||
0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
|
|
||||||
0x01,
|
|
||||||
0x21, /*bCountryCode: Hardware target country*/ // 0x21: US, 0x08: FR, 0x0D: ISO Intl
|
|
||||||
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
|
|
||||||
0x22, /*bDescriptorType*/
|
|
||||||
sizeof(HID_ReportDesc_fido),/*wItemLength: Total length of Report descriptor*/
|
|
||||||
0x00,
|
|
||||||
};
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
|
|
||||||
/* USB HID device Configuration Descriptor */
|
|
||||||
__ALIGN_BEGIN const uint8_t const USBD_HID_Desc[] __ALIGN_END =
|
|
||||||
{
|
|
||||||
/* 18 */
|
|
||||||
0x09, /*bLength: HID Descriptor size*/
|
|
||||||
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
|
|
||||||
0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
|
|
||||||
0x01,
|
|
||||||
0x00, /*bCountryCode: Hardware target country*/
|
|
||||||
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
|
|
||||||
0x22, /*bDescriptorType*/
|
|
||||||
sizeof(HID_ReportDesc),/*wItemLength: Total length of Report descriptor*/
|
|
||||||
0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* USB Standard Device Descriptor */
|
|
||||||
static __ALIGN_BEGIN const uint8_t const USBD_DeviceQualifierDesc[] __ALIGN_END =
|
|
||||||
{
|
|
||||||
USB_LEN_DEV_QUALIFIER_DESC,
|
|
||||||
USB_DESC_TYPE_DEVICE_QUALIFIER,
|
|
||||||
0x00,
|
|
||||||
0x02,
|
|
||||||
0x00,
|
|
||||||
0x00,
|
|
||||||
0x00,
|
|
||||||
0x40,
|
|
||||||
0x01,
|
|
||||||
0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* USB Standard Device Descriptor */
|
|
||||||
static const uint8_t const USBD_DeviceDesc[]= {
|
|
||||||
0x12, /* bLength */
|
|
||||||
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
|
|
||||||
0x00, /* bcdUSB */
|
|
||||||
0x02,
|
|
||||||
0x00, /* bDeviceClass */
|
|
||||||
0x00, /* bDeviceSubClass */
|
|
||||||
0x00, /* bDeviceProtocol */
|
|
||||||
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
|
|
||||||
LOBYTE(USBD_VID), /* idVendor */
|
|
||||||
HIBYTE(USBD_VID), /* idVendor */
|
|
||||||
LOBYTE(USBD_PID), /* idVendor */
|
|
||||||
HIBYTE(USBD_PID), /* idVendor */
|
|
||||||
0x00, /* bcdDevice rel. 2.00 */
|
|
||||||
0x02,
|
|
||||||
USBD_IDX_MFC_STR, /* Index of manufacturer string */
|
|
||||||
USBD_IDX_PRODUCT_STR, /* Index of product string */
|
|
||||||
USBD_IDX_SERIAL_STR, /* Index of serial number string */
|
|
||||||
1 /* bNumConfigurations */
|
|
||||||
}; /* USB_DeviceDescriptor */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the device descriptor.
|
|
||||||
* @param speed: Current device speed
|
|
||||||
* @param length: Pointer to data length variable
|
|
||||||
* @retval Pointer to descriptor buffer
|
|
||||||
*/
|
|
||||||
uint8_t *USBD_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
||||||
{
|
|
||||||
UNUSED(speed);
|
|
||||||
*length = sizeof(USBD_DeviceDesc);
|
|
||||||
return (uint8_t*)USBD_DeviceDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the LangID string descriptor.
|
|
||||||
* @param speed: Current device speed
|
|
||||||
* @param length: Pointer to data length variable
|
|
||||||
* @retval Pointer to descriptor buffer
|
|
||||||
*/
|
|
||||||
uint8_t *USBD_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
||||||
{
|
|
||||||
UNUSED(speed);
|
|
||||||
*length = sizeof(USBD_LangIDDesc);
|
|
||||||
return (uint8_t*)USBD_LangIDDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the product string descriptor.
|
|
||||||
* @param speed: Current device speed
|
|
||||||
* @param length: Pointer to data length variable
|
|
||||||
* @retval Pointer to descriptor buffer
|
|
||||||
*/
|
|
||||||
uint8_t *USBD_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
||||||
{
|
|
||||||
UNUSED(speed);
|
|
||||||
*length = sizeof(USBD_PRODUCT_FS_STRING);
|
|
||||||
return (uint8_t*)USBD_PRODUCT_FS_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the manufacturer string descriptor.
|
|
||||||
* @param speed: Current device speed
|
|
||||||
* @param length: Pointer to data length variable
|
|
||||||
* @retval Pointer to descriptor buffer
|
|
||||||
*/
|
|
||||||
uint8_t *USBD_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
||||||
{
|
|
||||||
UNUSED(speed);
|
|
||||||
*length = sizeof(USBD_MANUFACTURER_STRING);
|
|
||||||
return (uint8_t*)USBD_MANUFACTURER_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the serial number string descriptor.
|
|
||||||
* @param speed: Current device speed
|
|
||||||
* @param length: Pointer to data length variable
|
|
||||||
* @retval Pointer to descriptor buffer
|
|
||||||
*/
|
|
||||||
uint8_t *USBD_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
||||||
{
|
|
||||||
UNUSED(speed);
|
|
||||||
*length = sizeof(USB_SERIAL_STRING);
|
|
||||||
return (uint8_t*)USB_SERIAL_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the configuration string descriptor.
|
|
||||||
* @param speed: Current device speed
|
|
||||||
* @param length: Pointer to data length variable
|
|
||||||
* @retval Pointer to descriptor buffer
|
|
||||||
*/
|
|
||||||
uint8_t *USBD_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
||||||
{
|
|
||||||
UNUSED(speed);
|
|
||||||
*length = sizeof(USBD_CONFIGURATION_FS_STRING);
|
|
||||||
return (uint8_t*)USBD_CONFIGURATION_FS_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the interface string descriptor.
|
|
||||||
* @param speed: Current device speed
|
|
||||||
* @param length: Pointer to data length variable
|
|
||||||
* @retval Pointer to descriptor buffer
|
|
||||||
*/
|
|
||||||
uint8_t *USBD_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
||||||
{
|
|
||||||
UNUSED(speed);
|
|
||||||
*length = sizeof(USBD_INTERFACE_FS_STRING);
|
|
||||||
return (uint8_t*)USBD_INTERFACE_FS_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief DeviceQualifierDescriptor
|
|
||||||
* return Device Qualifier descriptor
|
|
||||||
* @param length : pointer data length
|
|
||||||
* @retval pointer to descriptor buffer
|
|
||||||
*/
|
|
||||||
uint8_t *USBD_GetDeviceQualifierDesc_impl (uint16_t *length)
|
|
||||||
{
|
|
||||||
*length = sizeof (USBD_DeviceQualifierDesc);
|
|
||||||
return (uint8_t*)USBD_DeviceQualifierDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USBD_CUSTOM_HID_GetCfgDesc
|
|
||||||
* return configuration descriptor
|
|
||||||
* @param speed : current device speed
|
|
||||||
* @param length : pointer data length
|
|
||||||
* @retval pointer to descriptor buffer
|
|
||||||
*/
|
|
||||||
uint8_t *USBD_GetCfgDesc_impl (uint16_t *length)
|
|
||||||
{
|
|
||||||
*length = sizeof (N_USBD_CfgDesc);
|
|
||||||
return (uint8_t*)N_USBD_CfgDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* USBD_HID_GetHidDescriptor_impl(uint16_t* len) {
|
|
||||||
switch (USBD_Device.request.wIndex&0xFF) {
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
case U2F_INTF:
|
|
||||||
*len = sizeof(USBD_HID_Desc_fido);
|
|
||||||
return (uint8_t*)USBD_HID_Desc_fido;
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
case HID_INTF:
|
|
||||||
*len = sizeof(USBD_HID_Desc);
|
|
||||||
return (uint8_t*)USBD_HID_Desc;
|
|
||||||
}
|
|
||||||
*len = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* USBD_HID_GetReportDescriptor_impl(uint16_t* len) {
|
|
||||||
switch (USBD_Device.request.wIndex&0xFF) {
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
case U2F_INTF:
|
|
||||||
|
|
||||||
// very dirty work due to lack of callback when USB_HID_Init is called
|
|
||||||
USBD_LL_OpenEP(&USBD_Device,
|
|
||||||
U2F_EPIN_ADDR,
|
|
||||||
USBD_EP_TYPE_INTR,
|
|
||||||
U2F_EPIN_SIZE);
|
|
||||||
|
|
||||||
USBD_LL_OpenEP(&USBD_Device,
|
|
||||||
U2F_EPOUT_ADDR,
|
|
||||||
USBD_EP_TYPE_INTR,
|
|
||||||
U2F_EPOUT_SIZE);
|
|
||||||
|
|
||||||
/* Prepare Out endpoint to receive 1st packet */
|
|
||||||
USBD_LL_PrepareReceive(&USBD_Device, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE);
|
|
||||||
|
|
||||||
|
|
||||||
*len = sizeof(HID_ReportDesc_fido);
|
|
||||||
return (uint8_t*)HID_ReportDesc_fido;
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
case HID_INTF:
|
|
||||||
*len = sizeof(HID_ReportDesc);
|
|
||||||
return (uint8_t*)HID_ReportDesc;
|
|
||||||
}
|
|
||||||
*len = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USBD_HID_DataOut
|
|
||||||
* handle data OUT Stage
|
|
||||||
* @param pdev: device instance
|
|
||||||
* @param epnum: endpoint index
|
|
||||||
* @retval status
|
|
||||||
*
|
|
||||||
* This function is the default behavior for our implementation when data are sent over the out hid endpoint
|
|
||||||
*/
|
|
||||||
extern volatile unsigned short G_io_apdu_length;
|
|
||||||
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
uint8_t USBD_U2F_DataIn_impl (USBD_HandleTypeDef *pdev,
|
|
||||||
uint8_t epnum)
|
|
||||||
{
|
|
||||||
UNUSED(pdev);
|
|
||||||
// only the data hid endpoint will receive data
|
|
||||||
switch (epnum) {
|
|
||||||
// FIDO endpoint
|
|
||||||
case (U2F_EPIN_ADDR&0x7F):
|
|
||||||
// advance the u2f sending machine state
|
|
||||||
u2f_transport_sent(&G_io_u2f, U2F_MEDIA_USB);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return USBD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t USBD_U2F_DataOut_impl (USBD_HandleTypeDef *pdev,
|
|
||||||
uint8_t epnum, uint8_t* buffer)
|
|
||||||
{
|
|
||||||
switch (epnum) {
|
|
||||||
// FIDO endpoint
|
|
||||||
case (U2F_EPOUT_ADDR&0x7F):
|
|
||||||
USBD_LL_PrepareReceive(pdev, U2F_EPOUT_ADDR , U2F_EPOUT_SIZE);
|
|
||||||
u2f_transport_received(&G_io_u2f, buffer, io_seproxyhal_get_ep_rx_size(U2F_EPOUT_ADDR), U2F_MEDIA_USB);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return USBD_OK;
|
|
||||||
}
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
|
|
||||||
uint8_t USBD_HID_DataOut_impl (USBD_HandleTypeDef *pdev,
|
|
||||||
uint8_t epnum, uint8_t* buffer)
|
|
||||||
{
|
|
||||||
// only the data hid endpoint will receive data
|
|
||||||
switch (epnum) {
|
|
||||||
|
|
||||||
// HID gen endpoint
|
|
||||||
case (HID_EPOUT_ADDR&0x7F):
|
|
||||||
// prepare receiving the next chunk (masked time)
|
|
||||||
USBD_LL_PrepareReceive(pdev, HID_EPOUT_ADDR , HID_EPOUT_SIZE);
|
|
||||||
|
|
||||||
// avoid troubles when an apdu has not been replied yet
|
|
||||||
if (G_io_apdu_media == IO_APDU_MEDIA_NONE) {
|
|
||||||
// add to the hid transport
|
|
||||||
switch(io_usb_hid_receive(io_usb_send_apdu_data, buffer, io_seproxyhal_get_ep_rx_size(HID_EPOUT_ADDR))) {
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IO_USB_APDU_RECEIVED:
|
|
||||||
G_io_apdu_media = IO_APDU_MEDIA_USB_HID; // for application code
|
|
||||||
G_io_apdu_state = APDU_USB_HID; // for next call to io_exchange
|
|
||||||
G_io_apdu_length = G_io_usb_hid_total_length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return USBD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @defgroup USBD_HID_Private_Functions
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
// note: how core lib usb calls the hid class
|
|
||||||
const USBD_DescriptorsTypeDef const HID_Desc = {
|
|
||||||
USBD_DeviceDescriptor,
|
|
||||||
USBD_LangIDStrDescriptor,
|
|
||||||
USBD_ManufacturerStrDescriptor,
|
|
||||||
USBD_ProductStrDescriptor,
|
|
||||||
USBD_SerialStrDescriptor,
|
|
||||||
USBD_ConfigStrDescriptor,
|
|
||||||
USBD_InterfaceStrDescriptor,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
static const USBD_ClassTypeDef const USBD_U2F =
|
|
||||||
{
|
|
||||||
USBD_HID_Init,
|
|
||||||
USBD_HID_DeInit,
|
|
||||||
USBD_HID_Setup,
|
|
||||||
NULL, /*EP0_TxSent*/
|
|
||||||
NULL, /*EP0_RxReady*/ /* STATUS STAGE IN */
|
|
||||||
USBD_U2F_DataIn_impl, /*DataIn*/
|
|
||||||
USBD_U2F_DataOut_impl, /*DataOut*/
|
|
||||||
NULL, /*SOF */
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
USBD_GetCfgDesc_impl,
|
|
||||||
USBD_GetCfgDesc_impl,
|
|
||||||
USBD_GetCfgDesc_impl,
|
|
||||||
USBD_GetDeviceQualifierDesc_impl,
|
|
||||||
};
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
|
|
||||||
static const USBD_ClassTypeDef const USBD_HID =
|
|
||||||
{
|
|
||||||
USBD_HID_Init,
|
|
||||||
USBD_HID_DeInit,
|
|
||||||
USBD_HID_Setup,
|
|
||||||
NULL, /*EP0_TxSent*/
|
|
||||||
NULL, /*EP0_RxReady*/ /* STATUS STAGE IN */
|
|
||||||
NULL, /*DataIn*/
|
|
||||||
USBD_HID_DataOut_impl, /*DataOut*/
|
|
||||||
NULL, /*SOF */
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
USBD_GetCfgDesc_impl,
|
|
||||||
USBD_GetCfgDesc_impl,
|
|
||||||
USBD_GetCfgDesc_impl,
|
|
||||||
USBD_GetDeviceQualifierDesc_impl,
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef HAVE_USB_CLASS_CCID
|
|
||||||
static const USBD_ClassTypeDef USBD_CCID =
|
|
||||||
{
|
|
||||||
USBD_CCID_Init,
|
|
||||||
USBD_CCID_DeInit,
|
|
||||||
USBD_CCID_Setup,
|
|
||||||
NULL, /*EP0_TxSent*/
|
|
||||||
NULL, /*EP0_RxReady*/
|
|
||||||
USBD_CCID_DataIn,
|
|
||||||
USBD_CCID_DataOut,
|
|
||||||
NULL, /*SOF */
|
|
||||||
NULL, /*ISOIn*/
|
|
||||||
NULL, /*ISOOut*/
|
|
||||||
USBD_GetCfgDesc_impl,
|
|
||||||
USBD_GetCfgDesc_impl,
|
|
||||||
USBD_GetCfgDesc_impl,
|
|
||||||
USBD_GetDeviceQualifierDesc_impl,
|
|
||||||
};
|
|
||||||
|
|
||||||
uint8_t SC_AnswerToReset (uint8_t voltage, uint8_t* atr_buffer) {
|
|
||||||
UNUSED(voltage);
|
|
||||||
// return the atr length
|
|
||||||
atr_buffer[0] = 0x3B;
|
|
||||||
atr_buffer[1] = 0;
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SC_Poweroff(void) {
|
|
||||||
// nothing to do ?
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t SC_ExecuteEscape (uint8_t* escapePtr, uint32_t escapeLen,
|
|
||||||
uint8_t* responseBuff,
|
|
||||||
uint16_t* responseLen) {
|
|
||||||
UNUSED(escapePtr);
|
|
||||||
UNUSED(escapeLen);
|
|
||||||
UNUSED(responseBuff);
|
|
||||||
UNUSED(responseLen);
|
|
||||||
// nothing to do ?
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif // HAVE_USB_CLASS_CCID
|
|
||||||
|
|
||||||
void USB_power(unsigned char enabled) {
|
|
||||||
os_memset(&USBD_Device, 0, sizeof(USBD_Device));
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
os_memset(&USBD_Device, 0, sizeof(USBD_Device));
|
|
||||||
/* Init Device Library */
|
|
||||||
USBD_Init(&USBD_Device, (USBD_DescriptorsTypeDef*)&HID_Desc, 0);
|
|
||||||
|
|
||||||
/* Register the HID class */
|
|
||||||
USBD_RegisterClassForInterface(HID_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_HID);
|
|
||||||
#ifdef HAVE_IO_U2F
|
|
||||||
USBD_RegisterClassForInterface(U2F_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_U2F);
|
|
||||||
// initialize the U2F tunnel transport
|
|
||||||
u2f_transport_init(&G_io_u2f, G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
|
|
||||||
#endif // HAVE_IO_U2F
|
|
||||||
#ifdef HAVE_USB_CLASS_CCID
|
|
||||||
USBD_RegisterClassForInterface(CCID_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_CCID);
|
|
||||||
#endif // HAVE_USB_CLASS_CCID
|
|
||||||
|
|
||||||
|
|
||||||
/* Start Device Process */
|
|
||||||
USBD_Start(&USBD_Device);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
USBD_DeInit(&USBD_Device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
|
@ -1,7 +0,0 @@
|
||||||
#ifndef USBD_IMPL_H
|
|
||||||
#define USBD_IMPL_H
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t *USBD_GetCfgDesc_impl (uint16_t *length);
|
|
||||||
|
|
||||||
#endif //USBD_IMPL_H
|
|
463
src/usbd_ccid_impl.c
Normal file
463
src/usbd_ccid_impl.c
Normal file
|
@ -0,0 +1,463 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file usbd_ccid_core.c
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @version V1.0.1
|
||||||
|
* @date 31-January-2014
|
||||||
|
* @brief This file provides all the CCID core functions.
|
||||||
|
*
|
||||||
|
* @verbatim
|
||||||
|
*
|
||||||
|
* ===================================================================
|
||||||
|
* CCID Class Description
|
||||||
|
* ===================================================================
|
||||||
|
* This module manages the Specification for Integrated Circuit(s)
|
||||||
|
* Cards Interface Revision 1.1
|
||||||
|
* This driver implements the following aspects of the specification:
|
||||||
|
* - Bulk Transfers
|
||||||
|
*
|
||||||
|
* @endverbatim
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "usbd_ccid_core.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_USB_CLASS_CCID
|
||||||
|
|
||||||
|
#define USBD_LANGID_STRING 0x409
|
||||||
|
|
||||||
|
#define USBD_VID 0x2C97
|
||||||
|
#if TARGET_ID == 0x31000002 // blue
|
||||||
|
#define USBD_PID 0x0000
|
||||||
|
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
|
||||||
|
4*2+2,
|
||||||
|
USB_DESC_TYPE_STRING,
|
||||||
|
'B', 0,
|
||||||
|
'l', 0,
|
||||||
|
'u', 0,
|
||||||
|
'e', 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif TARGET_ID == 0x31100002 // nano s
|
||||||
|
#define USBD_PID 0x0001
|
||||||
|
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
|
||||||
|
6*2+2,
|
||||||
|
USB_DESC_TYPE_STRING,
|
||||||
|
'N', 0,
|
||||||
|
'a', 0,
|
||||||
|
'n', 0,
|
||||||
|
'o', 0,
|
||||||
|
' ', 0,
|
||||||
|
'S', 0,
|
||||||
|
};
|
||||||
|
#elif TARGET_ID == 0x31200002 // aramis
|
||||||
|
#define USBD_PID 0x0002
|
||||||
|
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
|
||||||
|
6*2+2,
|
||||||
|
USB_DESC_TYPE_STRING,
|
||||||
|
'A', 0,
|
||||||
|
'r', 0,
|
||||||
|
'a', 0,
|
||||||
|
'm', 0,
|
||||||
|
'i', 0,
|
||||||
|
's', 0,
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
#error unknown TARGET_ID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* USB Standard Device Descriptor */
|
||||||
|
static __ALIGN_BEGIN const uint8_t const USBD_DeviceQualifierDesc[] __ALIGN_END =
|
||||||
|
{
|
||||||
|
USB_LEN_DEV_QUALIFIER_DESC,
|
||||||
|
USB_DESC_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* USB Standard Device Descriptor */
|
||||||
|
static const uint8_t const USBD_LangIDDesc[]=
|
||||||
|
{
|
||||||
|
USB_LEN_LANGID_STR_DESC,
|
||||||
|
USB_DESC_TYPE_STRING,
|
||||||
|
LOBYTE(USBD_LANGID_STRING),
|
||||||
|
HIBYTE(USBD_LANGID_STRING),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t const USB_SERIAL_STRING[] =
|
||||||
|
{
|
||||||
|
4*2+2,
|
||||||
|
USB_DESC_TYPE_STRING,
|
||||||
|
'0', 0,
|
||||||
|
'0', 0,
|
||||||
|
'0', 0,
|
||||||
|
'1', 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t const USBD_MANUFACTURER_STRING[] = {
|
||||||
|
6*2+2,
|
||||||
|
USB_DESC_TYPE_STRING,
|
||||||
|
'L', 0,
|
||||||
|
'e', 0,
|
||||||
|
'd', 0,
|
||||||
|
'g', 0,
|
||||||
|
'e', 0,
|
||||||
|
'r', 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define USBD_INTERFACE_FS_STRING USBD_PRODUCT_FS_STRING
|
||||||
|
#define USBD_CONFIGURATION_FS_STRING USBD_PRODUCT_FS_STRING
|
||||||
|
|
||||||
|
|
||||||
|
/* USB Standard Device Descriptor */
|
||||||
|
static const uint8_t const USBD_DeviceDesc[]= {
|
||||||
|
0x12, /* bLength */
|
||||||
|
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
|
||||||
|
0x00, /* bcdUSB */
|
||||||
|
0x02,
|
||||||
|
0x00, /* bDeviceClass */
|
||||||
|
0x00, /* bDeviceSubClass */
|
||||||
|
0x00, /* bDeviceProtocol */
|
||||||
|
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
|
||||||
|
LOBYTE(USBD_VID), /* idVendor */
|
||||||
|
HIBYTE(USBD_VID), /* idVendor */
|
||||||
|
LOBYTE(USBD_PID), /* idVendor */
|
||||||
|
HIBYTE(USBD_PID), /* idVendor */
|
||||||
|
0x00, /* bcdDevice rel. 2.00 */
|
||||||
|
0x02,
|
||||||
|
USBD_IDX_MFC_STR, /* Index of manufacturer string */
|
||||||
|
USBD_IDX_PRODUCT_STR, /* Index of product string */
|
||||||
|
USBD_IDX_SERIAL_STR, /* Index of serial number string */
|
||||||
|
USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
|
||||||
|
}; /* USB_DeviceDescriptor */
|
||||||
|
|
||||||
|
|
||||||
|
/* USB Mass storage device Configuration Descriptor */
|
||||||
|
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
|
||||||
|
#define USBD_OFFSET_CfgDesc_bPINSupport 70
|
||||||
|
const uint8_t N_USBD_CfgDesc[] =
|
||||||
|
{
|
||||||
|
|
||||||
|
0x09, /* bLength: Configuration Descriptor size */
|
||||||
|
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
||||||
|
0x9+0x9+0x36+0x7+0x7+0x7,
|
||||||
|
|
||||||
|
0x00,
|
||||||
|
0x01, /* bNumInterfaces: 1 interface */
|
||||||
|
0x01, /* bConfigurationValue: */
|
||||||
|
0x04, /* iConfiguration: */
|
||||||
|
0x80, /*bmAttributes: bus powered */
|
||||||
|
0x32, /* MaxPower 100 mA */
|
||||||
|
|
||||||
|
/******************** CCID **** interface ********************/
|
||||||
|
0x09, /* bLength: Interface Descriptor size */
|
||||||
|
0x04, /* bDescriptorType: */
|
||||||
|
0x00, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: Alternate setting */
|
||||||
|
0x03, /* bNumEndpoints: 3 endpoints used */
|
||||||
|
0x0B, /* bInterfaceClass: user's interface for CCID */
|
||||||
|
0x00, /* bInterfaceSubClass : */
|
||||||
|
0x00, /* nInterfaceProtocol : None */
|
||||||
|
0x05, /* iInterface: */
|
||||||
|
|
||||||
|
/******************* CCID class descriptor ********************/
|
||||||
|
0x36, /* bLength: CCID Descriptor size */
|
||||||
|
0x21, /* bDescriptorType: Functional Descriptor type. */
|
||||||
|
0x10, /* bcdCCID(LSB): CCID Class Spec release number (1.00) */
|
||||||
|
0x01, /* bcdCCID(MSB) */
|
||||||
|
|
||||||
|
0x00, /* bMaxSlotIndex :highest available slot on this device */
|
||||||
|
0x03, /* bVoltageSupport: bit Wise OR for 01h-5.0V 02h-3.0V
|
||||||
|
04h 1.8V*/
|
||||||
|
|
||||||
|
0x01,0x00,0x00,0x00, /* dwProtocols: 0001h = Protocol T=0 */
|
||||||
|
0x10,0x0E,0x00,0x00, /* dwDefaultClock: 3.6Mhz = 3600kHz = 0x0E10,
|
||||||
|
for 4 Mhz the value is (0x00000FA0) :
|
||||||
|
This is used in ETU and waiting time calculations*/
|
||||||
|
0x10,0x0E,0x00,0x00, /* dwMaximumClock: Maximum supported ICC clock frequency
|
||||||
|
in KHz. So, 3.6Mhz = 3600kHz = 0x0E10,
|
||||||
|
4 Mhz (0x00000FA0) : */
|
||||||
|
0x00, /* bNumClockSupported : no setting from PC
|
||||||
|
If the value is 00h, the
|
||||||
|
supported clock frequencies are assumed to be the
|
||||||
|
default clock frequency defined by dwDefaultClock
|
||||||
|
and the maximum clock frequency defined by
|
||||||
|
dwMaximumClock */
|
||||||
|
|
||||||
|
0xCD,0x25,0x00,0x00, /* dwDataRate: Default ICC I/O data rate in bps
|
||||||
|
9677 bps = 0x25CD
|
||||||
|
for example 10752 bps (0x00002A00) */
|
||||||
|
|
||||||
|
0xCD,0x25,0x00,0x00, /* dwMaxDataRate: Maximum supported ICC I/O data
|
||||||
|
rate in bps */
|
||||||
|
0x00, /* bNumDataRatesSupported :
|
||||||
|
The number of data rates that are supported by the CCID
|
||||||
|
If the value is 00h, all data rates between the default
|
||||||
|
data rate dwDataRate and the maximum data rate
|
||||||
|
dwMaxDataRate are supported.
|
||||||
|
Dont support GET_CLOCK_FREQUENCIES
|
||||||
|
*/
|
||||||
|
//46
|
||||||
|
0x00,0x00,0x00,0x00, /* dwMaxIFSD: 0 (T=0 only) */
|
||||||
|
0x00,0x00,0x00,0x00, /* dwSynchProtocols */
|
||||||
|
0x00,0x00,0x00,0x00, /* dwMechanical: no special characteristics */
|
||||||
|
|
||||||
|
0x38,0x00,EXCHANGE_LEVEL_FEATURE,0x00,
|
||||||
|
/* dwFeatures: clk, baud rate, voltage : automatic */
|
||||||
|
/* 00000008h Automatic ICC voltage selection
|
||||||
|
00000010h Automatic ICC clock frequency change
|
||||||
|
00000020h Automatic baud rate change according to
|
||||||
|
active parameters provided by the Host or self
|
||||||
|
determined 00000100h CCID can set
|
||||||
|
ICC in clock stop mode
|
||||||
|
|
||||||
|
Only one of the following values may be present to
|
||||||
|
select a level of exchange:
|
||||||
|
00010000h TPDU level exchanges with CCID
|
||||||
|
00020000h Short APDU level exchange with CCID
|
||||||
|
00040000h Short and Extended APDU level exchange
|
||||||
|
If none of those values : character level of exchange*/
|
||||||
|
#if 1
|
||||||
|
0x0F,0x01,0x00,0x00, /* dwMaxCCIDMessageLength: Maximum block size + header*/
|
||||||
|
/* 261 + 10 */
|
||||||
|
#else
|
||||||
|
0xF8,0x00,0x00,0x00, /* dwMaxCCIDMessageLength: Maximum block size + header*/
|
||||||
|
/* EEh + 10 */
|
||||||
|
#endif
|
||||||
|
0x00, /* bClassGetResponse*/
|
||||||
|
0x00, /* bClassEnvelope */
|
||||||
|
0x00,0x00, /* wLcdLayout : 0000h no LCD. */
|
||||||
|
0x03, /* bPINSupport : no PIN verif and modif */ //<= offset: 70
|
||||||
|
0x01, /* bMaxCCIDBusySlots */
|
||||||
|
|
||||||
|
//72
|
||||||
|
/******************** CCID Endpoints ********************/
|
||||||
|
0x07, /*Endpoint descriptor length = 7*/
|
||||||
|
0x05, /*Endpoint descriptor type */
|
||||||
|
CCID_BULK_IN_EP, /*Endpoint address (IN, address 1) */
|
||||||
|
0x02, /*Bulk endpoint type */
|
||||||
|
LOBYTE(CCID_BULK_EPIN_SIZE),
|
||||||
|
HIBYTE(CCID_BULK_EPIN_SIZE),
|
||||||
|
0x00, /*Polling interval in milliseconds */
|
||||||
|
|
||||||
|
0x07, /*Endpoint descriptor length = 7 */
|
||||||
|
0x05, /*Endpoint descriptor type */
|
||||||
|
CCID_BULK_OUT_EP, /*Endpoint address (OUT, address 1) */
|
||||||
|
0x02, /*Bulk endpoint type */
|
||||||
|
LOBYTE(CCID_BULK_EPOUT_SIZE),
|
||||||
|
HIBYTE(CCID_BULK_EPOUT_SIZE),
|
||||||
|
0x00, /*Polling interval in milliseconds*/
|
||||||
|
|
||||||
|
|
||||||
|
0x07, /*bLength: Endpoint Descriptor size*/
|
||||||
|
0x05, /*bDescriptorType:*/
|
||||||
|
CCID_INTR_IN_EP, /*bEndpointAddress: Endpoint Address (IN)*/
|
||||||
|
0x03, /* bmAttributes: Interrupt endpoint */
|
||||||
|
LOBYTE(CCID_INTR_EPIN_SIZE),
|
||||||
|
HIBYTE(CCID_INTR_EPIN_SIZE),
|
||||||
|
0x18 /*Polling interval in milliseconds */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t *USBD_GetCfgDesc_impl (uint16_t *length)
|
||||||
|
{
|
||||||
|
*length = sizeof (N_USBD_CfgDesc);
|
||||||
|
return (uint8_t*)(N_USBD_CfgDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the device descriptor.
|
||||||
|
* @param speed: Current device speed
|
||||||
|
* @param length: Pointer to data length variable
|
||||||
|
* @retval Pointer to descriptor buffer
|
||||||
|
*/
|
||||||
|
static uint8_t *USBD_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||||
|
{
|
||||||
|
UNUSED(speed);
|
||||||
|
*length = sizeof(USBD_DeviceDesc);
|
||||||
|
return (uint8_t*)USBD_DeviceDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the LangID string descriptor.
|
||||||
|
* @param speed: Current device speed
|
||||||
|
* @param length: Pointer to data length variable
|
||||||
|
* @retval Pointer to descriptor buffer
|
||||||
|
*/
|
||||||
|
static uint8_t *USBD_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||||
|
{
|
||||||
|
UNUSED(speed);
|
||||||
|
*length = sizeof(USBD_LangIDDesc);
|
||||||
|
return (uint8_t*)USBD_LangIDDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the product string descriptor.
|
||||||
|
* @param speed: Current device speed
|
||||||
|
* @param length: Pointer to data length variable
|
||||||
|
* @retval Pointer to descriptor buffer
|
||||||
|
*/
|
||||||
|
static uint8_t *USBD_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||||
|
{
|
||||||
|
UNUSED(speed);
|
||||||
|
*length = sizeof(USBD_PRODUCT_FS_STRING);
|
||||||
|
return (uint8_t*)USBD_PRODUCT_FS_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the manufacturer string descriptor.
|
||||||
|
* @param speed: Current device speed
|
||||||
|
* @param length: Pointer to data length variable
|
||||||
|
* @retval Pointer to descriptor buffer
|
||||||
|
*/
|
||||||
|
static uint8_t *USBD_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||||
|
{
|
||||||
|
UNUSED(speed);
|
||||||
|
*length = sizeof(USBD_MANUFACTURER_STRING);
|
||||||
|
return (uint8_t*)USBD_MANUFACTURER_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the serial number string descriptor.
|
||||||
|
* @param speed: Current device speed
|
||||||
|
* @param length: Pointer to data length variable
|
||||||
|
* @retval Pointer to descriptor buffer
|
||||||
|
*/
|
||||||
|
static uint8_t *USBD_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||||
|
{
|
||||||
|
UNUSED(speed);
|
||||||
|
*length = sizeof(USB_SERIAL_STRING);
|
||||||
|
return (uint8_t*)USB_SERIAL_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the configuration string descriptor.
|
||||||
|
* @param speed: Current device speed
|
||||||
|
* @param length: Pointer to data length variable
|
||||||
|
* @retval Pointer to descriptor buffer
|
||||||
|
*/
|
||||||
|
static uint8_t *USBD_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||||
|
{
|
||||||
|
UNUSED(speed);
|
||||||
|
*length = sizeof(USBD_CONFIGURATION_FS_STRING);
|
||||||
|
return (uint8_t*)USBD_CONFIGURATION_FS_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the interface string descriptor.
|
||||||
|
* @param speed: Current device speed
|
||||||
|
* @param length: Pointer to data length variable
|
||||||
|
* @retval Pointer to descriptor buffer
|
||||||
|
*/
|
||||||
|
static uint8_t *USBD_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||||
|
{
|
||||||
|
UNUSED(speed);
|
||||||
|
*length = sizeof(USBD_INTERFACE_FS_STRING);
|
||||||
|
return (uint8_t*)USBD_INTERFACE_FS_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief DeviceQualifierDescriptor
|
||||||
|
* return Device Qualifier descriptor
|
||||||
|
* @param length : pointer data length
|
||||||
|
* @retval pointer to descriptor buffer
|
||||||
|
*/
|
||||||
|
static uint8_t *USBD_GetDeviceQualifierDesc_impl (uint16_t *length)
|
||||||
|
{
|
||||||
|
*length = sizeof (USBD_DeviceQualifierDesc);
|
||||||
|
return (uint8_t*)USBD_DeviceQualifierDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t SC_AnswerToReset (uint8_t voltage, uint8_t* atr_buffer) {
|
||||||
|
// return the atr length
|
||||||
|
atr_buffer[0] = 0x3B;
|
||||||
|
atr_buffer[1] = 0;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// note: how core lib usb calls the hid class
|
||||||
|
static const USBD_DescriptorsTypeDef const CCID_Desc = {
|
||||||
|
USBD_DeviceDescriptor,
|
||||||
|
USBD_LangIDStrDescriptor,
|
||||||
|
USBD_ManufacturerStrDescriptor,
|
||||||
|
USBD_ProductStrDescriptor,
|
||||||
|
USBD_SerialStrDescriptor,
|
||||||
|
USBD_ConfigStrDescriptor,
|
||||||
|
USBD_InterfaceStrDescriptor,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const USBD_ClassTypeDef USBD_CCID =
|
||||||
|
{
|
||||||
|
USBD_CCID_Init,
|
||||||
|
USBD_CCID_DeInit,
|
||||||
|
USBD_CCID_Setup,
|
||||||
|
NULL, /*EP0_TxSent*/
|
||||||
|
NULL, /*EP0_RxReady*/
|
||||||
|
USBD_CCID_DataIn,
|
||||||
|
USBD_CCID_DataOut,
|
||||||
|
NULL, /*SOF */
|
||||||
|
NULL, /*ISOIn*/
|
||||||
|
NULL, /*ISOOut*/
|
||||||
|
USBD_GetCfgDesc_impl,
|
||||||
|
USBD_GetCfgDesc_impl,
|
||||||
|
USBD_GetCfgDesc_impl,
|
||||||
|
USBD_GetDeviceQualifierDesc_impl,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void USBD_CCID_activate_pinpad(int enabled) {
|
||||||
|
unsigned char e;
|
||||||
|
e = enabled?3:0;
|
||||||
|
nvm_write(((char*)PIC(N_USBD_CfgDesc))+USBD_OFFSET_CfgDesc_bPINSupport, &e,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB_CCID_power(unsigned char enabled) {
|
||||||
|
os_memset(&USBD_Device, 0, sizeof(USBD_Device));
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
os_memset(&USBD_Device, 0, sizeof(USBD_Device));
|
||||||
|
/* Init Device Library */
|
||||||
|
USBD_Init(&USBD_Device, (USBD_DescriptorsTypeDef*)&CCID_Desc, 0);
|
||||||
|
|
||||||
|
/* Register the HID class */
|
||||||
|
USBD_RegisterClass(&USBD_Device, (USBD_ClassTypeDef*)&USBD_CCID);
|
||||||
|
|
||||||
|
/* Start Device Process */
|
||||||
|
USBD_Start(&USBD_Device);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
USBD_DeInit(&USBD_Device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HAVE_USB_CLASS_CCID
|
24
src/usbd_ccid_impl.h
Normal file
24
src/usbd_ccid_impl.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef USBD_CCID_IMPL_H
|
||||||
|
#define USBD_CCID_IMPL_H
|
||||||
|
|
||||||
|
#define TPDU_EXCHANGE 0x01
|
||||||
|
#define SHORT_APDU_EXCHANGE 0x02
|
||||||
|
#define EXTENDED_APDU_EXCHANGE 0x04
|
||||||
|
#define CHARACTER_EXCHANGE 0x00
|
||||||
|
|
||||||
|
#define EXCHANGE_LEVEL_FEATURE SHORT_APDU_EXCHANGE
|
||||||
|
|
||||||
|
|
||||||
|
#define CCID_BULK_IN_EP 0x82
|
||||||
|
#define CCID_BULK_EPIN_SIZE 64
|
||||||
|
#define CCID_BULK_OUT_EP 0x02
|
||||||
|
#define CCID_BULK_EPOUT_SIZE 64
|
||||||
|
#define CCID_INTR_IN_EP 0x81
|
||||||
|
#define CCID_INTR_EPIN_SIZE 16
|
||||||
|
|
||||||
|
#define CCID_EP0_BUFF_SIZ 64
|
||||||
|
|
||||||
|
void USB_CCID_power(unsigned char enabled);
|
||||||
|
void USBD_CCID_activate_pinpad(int enabled);
|
||||||
|
|
||||||
|
#endif // USBD_CCID_IMPL_H
|
Loading…
Add table
Reference in a new issue