Add NanoX support

- embed shake256 as NanoX bug workarround
- replace 'C' by 'C' in PIN Entry
- fix the fact cx_hash does not accept any more NULL as output buff
- add clang formatter
pull/56/head
cslashm 5 years ago
parent f92dd4730c
commit 72df4f7d20

@ -0,0 +1,119 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
#AlignConsecutiveMacros: true
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
#AllowAllArgumentsOnNextLine: false
#AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
#AllowShortLambdasOnASingleLine: None
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: false
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
#IndentPPDirectives: BeforeHash
IndentWidth: 2
IndentWrappedFunctionNames: true
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
RawStringFormats:
- Delimiter: pb
Language: TextProto
BasedOnStyle: google
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
...

@ -21,12 +21,11 @@ $(error Environment variable BOLOS_SDK is not set)
endif
include $(BOLOS_SDK)/Makefile.defines
APP_LOAD_PARAMS=--appFlags 0x40 --path "2152157255'" --curve secp256k1 $(COMMON_LOAD_PARAMS)
APP_LOAD_PARAMS=--appFlags 0x240 --path "2152157255'" --curve secp256k1 $(COMMON_LOAD_PARAMS)
ifeq ($(MULTISLOT),)
MULTISLOT := 0
endif
ifeq ($(MULTISLOT),0)
GPG_MULTISLOT:=0
APPNAME:=OpenPGP
@ -35,22 +34,36 @@ GPG_MULTISLOT:=1
APPNAME:=OpenPGP.XL
endif
APP_LOAD_PARAMS=--appFlags 0x40 --path "2152157255'" --curve secp256k1 $(COMMON_LOAD_PARAMS)
SPECVERSION:="3.3.1"
ifeq ($(TARGET_NAME),TARGET_BLUE)
ICONNAME = images/icon_monero_blue.gif
else ifeq ($(TARGET_NAME),TARGET_NANOX)
ICONNAME = images/icon_pgp_nanox.gif
else
ICONNAME = images/icon_pgp.gif
endif
APPVERSION_M:=1
APPVERSION_N:=3
APPVERSION_P:=1
APPVERSION_P:=2
APPVERSION:=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
SPECVERSION:="3.3.1"
ifeq ($(TARGET_NAME),TARGET_BLUE)
ICONNAME=images/icon_pgp_blue.gif
DEFINES += $(OPENPGP_CONFIG)
DEFINES += OPENPGP_VERSION_MAJOR=$(APPVERSION_M) OPENPGP_VERSION_MINOR=$(APPVERSION_N) OPENPGP_VERSION_MICRO=$(APPVERSION_P)
DEFINES += OPENPGP_VERSION=$(APPVERSION)
DEFINES += OPENPGP_NAME=$(APPNAME)
DEFINES += SPEC_VERSION=$(SPECVERSION)
DEFINES += GPG_MULTISLOT=$(GPG_MULTISLOT)
ifeq ($(TARGET_NAME),TARGET_NANOX)
DEFINES += UI_NANO_X
DEFINES += GPG_SHAKE256
else ifeq ($(TARGET_NAME),TARGET_BLUE)
DEFINES += UI_BLUE
else
ICONNAME=images/icon_pgp.gif
DEFINES += UI_NANO_S
endif
DEFINES += GPG_MULTISLOT=$(GPG_MULTISLOT) $(GPG_CONFIG) GPG_VERSION=$(APPVERSION) GPG_NAME=$(APPNAME) SPEC_VERSION=$(SPECVERSION)
################
# Default rule #
@ -82,18 +95,51 @@ ifneq ($(NO_CONSENT),)
DEFINES += NO_CONSENT
endif
DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=300
DEFINES += OS_IO_SEPROXYHAL
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 += CUSTOM_IO_APDU_BUFFER_SIZE=\(255+5+64\)
DEFINES += USB_SEGMENT_SIZE=64
DEFINES += U2F_PROXY_MAGIC=\"MOON\"
#DEFINES += HAVE_IO_U2F HAVE_U2F
DEFINES += UNUSED\(x\)=\(void\)x
DEFINES += APPVERSION=\"$(APPVERSION)\"
DEFINES += CUSTOM_IO_APDU_BUFFER_SIZE=\(255+5+64\)
DEFINES += HAVE_USB_CLASS_CCID
ifeq ($(TARGET_NAME),TARGET_NANOX)
# DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000
# DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE
DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300
DEFINES += HAVE_GLO096
DEFINES += HAVE_BAGL BAGL_WIDTH=128 BAGL_HEIGHT=64
DEFINES += HAVE_BAGL_ELLIPSIS # long label truncation feature
DEFINES += HAVE_BAGL_FONT_OPEN_SANS_REGULAR_11PX
DEFINES += HAVE_BAGL_FONT_OPEN_SANS_EXTRABOLD_11PX
DEFINES += HAVE_BAGL_FONT_OPEN_SANS_LIGHT_16PX
DEFINES += HAVE_UX_FLOW
else
DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128
endif
# Enabling debug PRINTF
DEBUG = 0
ifneq ($(DEBUG),0)
ifeq ($(TARGET_NAME),TARGET_NANOX)
DEFINES += HAVE_PRINTF PRINTF=mcu_usb_printf
else
DEFINES += HAVE_PRINTF PRINTF=screen_printf
endif
else
DEFINES += PRINTF\(...\)=
endif
##############
# Compiler #
##############
@ -118,9 +164,16 @@ include $(BOLOS_SDK)/Makefile.glyphs
### variables processed by the common makefile.rules of the SDK to grab source files and include dirs
APP_SOURCE_PATH += src
SDK_SOURCE_PATH += lib_stusb
SDK_SOURCE_PATH += lib_stusb lib_stusb_impl
#SDK_SOURCE_PATH += lib_u2f
ifeq ($(TARGET_NAME),TARGET_NANOX)
SDK_SOURCE_PATH += lib_ux
endif
cformat:
clang-format -i src/*.c src/*.h
load: all
cp -a release/$(APPNAME).elf bin/app.elf
cp -a release/$(APPNAME).hex bin/app.hex
@ -137,9 +190,12 @@ exit:
delete:
python -m ledgerblue.deleteApp $(COMMON_DELETE_PARAMS)
# import generic rules from the sdk
include Makefile.rules
#add dependency on custom makefile filename
dep/%.d: %.c Makefile

@ -1,14 +1,14 @@
## GnuPG application: blue-app-gnupg
GnuPG application for Ledger Blue and Nano S
GnuPG application for Nano S and Nano X
This application implements "The OpenPGP card" specification revision 3.0. This specification is available in *doc* directory and at https://g10code.com/p-card.html .
The application supports:
- RSA with key up to 4096 bits
- ECDSA with secp256k1, secp256r1, brainpool 256r1 and brainpool 256t1 curves
- ECDSA with secp256k1
- EDDSA with Ed25519 curve
- ECDH with secp256k1, secp256r1, brainpool 256r1, brainpool 256t1 and curve25519 curves
- ECDH with secp256k1 and curve25519 curves
This release has known missing parts (see also Add-on) :

@ -1131,6 +1131,7 @@ Then you must precise if you want a backup or a restore with ``--backup`` or ``-
By default backup is performed without saving keys, assuming you use the seed mode.
If you also want to backup keys you have to pass the ``--backup-keys`` option.
In a general manner it is better to also save your keys with ``--backup-keys`` option.
Note that backup and restore works on current slot, so you have to perform a backup per slot
even if some data are shared. You can precise the slot/backup to restore with ``--slot``
@ -1140,23 +1141,25 @@ even if some data are shared. You can precise the slot/backup to restore with ``
Backup and Restore example
~~~~~~~~~~~~~~~~~~~~~~~~~~
First you must have the path of the `ledger-app-openpgp-card/pytools` in your PYTHONPATH.
full backup command:
| ``python3 -m gpgcard.gpgcli --backup --pinpad --backup-keys``
| ``python3 -m gpgcard.gpgcli --backup --pinpad --backup-keys --file my_bck_file_name.pickle``
backup command without private keys:
| ``python3 -m gpgcard.gpgcli --backup --pinpad ``
| ``python3 -m gpgcard.gpgcli --backup --pinpad --file my_bck_file_name.pickle``
full restore command:
| ``python3 -m gpgcard.gpgcli --backup --pinpad``
| ``python3 -m gpgcard.gpgcli --backup --pinpad --file my_bck_file_name.pickle``
full restore command with seed key generation:
| ``python3 -m gpgcard.gpgcli --backup --pinpad --seed``
| ``python3 -m gpgcard.gpgcli --backup --pinpad --seed --file my_bck_file_name.pickle``
Restore without backup
~~~~~~~~~~~~~~~~~~~~~~

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 B

@ -62,6 +62,7 @@ class GPGCardExcpetion(Exception):
class GPGCard() :
def __init__(self):
self.reset()
self.log = False
def reset(self):
#token info
@ -158,29 +159,43 @@ class GPGCard() :
cond = False
return resp,sw
def log_apdu(self,l):
self.log = l
def alog(self, m,dt,sw=0):
if self.log:
print("%s %.04x %s"%(m,sw,''.join(["%.02x"%b for b in dt])))
def _exchange_pcsc(self,apdu, data=None, sw_expected=0x9000, sw_mask=0xFFFF):
if data:
data = [x for x in data]
apdu = [x for x in apdu]
#send
if data:
while len(data) > 0xFE:
apdux = apdu[0:5]+[0xfe]+data[0:0xFE]
apdux[0] |= 0x10
self.alog('send', apdux)
resp, sw1, sw2 = self.connection.transmit(apdux)
sw = (sw1<<8)|sw2
self.alog('recv',resp,sw)
if sw != 0x9000:
return resp,sw
data = data[0xFE:]
apdu = apdu+[len(data)]+data
self.alog('send', apdu)
resp, sw1, sw2 = self.connection.transmit(apdu)
sw = (sw1<<8)|sw2
self.alog('recv', resp, sw)
#receive
while sw1==0x61:
apdu = binascii.unhexlify(b"00c00000%.02x"%sw2)
apdu = [x for x in apdu]
self.alog('send', apdu)
resp2, sw1, sw2 = self.connection.transmit(apdu)
sw = (sw1<<8)|sw2
self.alog('recv', resp2, sw)
resp = resp + resp2
resp = bytes(resp)
sw = (sw1<<8)|sw2
@ -315,6 +330,7 @@ class GPGCard() :
self.dec_key,sw = self.get_data(0x00B8)
self.aut_key,sw = self.get_data(0x00A4)
return True
def set_all(self):
@ -353,6 +369,7 @@ class GPGCard() :
self.put_data(0xd8, self.UIF_AUT)
if len(self.sig_key):
print('COUCOU')
self.put_data(0x00B6, self.sig_key)
if len(self.dec_key):
self.put_data(0x00B8, self.dec_key)
@ -362,7 +379,7 @@ class GPGCard() :
def _backup_file_name(self,file_name):
return file_name+"_slot%d"%(self.slot[0]+1)+".pickle"
return file_name #file_name+"_slot%d"%(self.slot[0]+1)+".pickle"
def backup(self, file_name, with_key=False):
self.get_all(with_key)

@ -39,7 +39,8 @@ Template identifiers are ed2559, cv25519, rsa2048, rsa3072, rsa4096.
parser.add_argument('--set-fingerprints', metavar='SIG:DEC:AUT', help='sig:dec:aut fingerprints, 20 bytes each in hexa')
parser.add_argument('--seed-key', help='Regenerate all keys, based on seed mode', action='store_true')
parser.add_argument('--slot', metavar='SLOT', help='slot to backup', type=int, default=1)
parser.add_argument('--user-pin', metavar='PIN', help='User PIN, if pinpad not used')
parser.add_argument('--user-pin', metavar='PIN', help='User PIN, if pinpad not used'),
parser.add_argument('--apdu', help='Log APDU exchange', action='store_true')
return parser
def banner():
@ -74,6 +75,8 @@ try:
print("Connect to card %s..."%args.reader, end='', flush=True)
gpgcard = GPGCard()
if args.apdu:
gpgcard.log_apdu(args.apdu)
gpgcard.connect(args.reader)
print("OK")

@ -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) }
}

@ -1,30 +0,0 @@
#include "glyphs.h"
unsigned int const C_badge_back_colors[]
= {
0x00000000,
0x00ffffff,
};
unsigned char const C_badge_back_bitmap[] = {
0xe0, 0x01, 0xfe, 0xc1, 0xfd, 0x38, 0x7f, 0x06, 0xdf, 0x81, 0xff, 0xc4, 0x7f, 0xf3, 0xff, 0xbc,
0x1f, 0xe7, 0xe7, 0xf1, 0x3f, 0xf8, 0x07, 0x78, 0x00, };
#ifdef OS_IO_SEPROXYHAL
#include "os_io_seproxyhal.h"
const bagl_icon_details_t C_badge_back = { GLYPH_badge_back_WIDTH, GLYPH_badge_back_HEIGHT, 1, C_badge_back_colors, C_badge_back_bitmap };
#endif // OS_IO_SEPROXYHAL
#include "glyphs.h"
unsigned int const C_icon_dashboard_colors[]
= {
0x00000000,
0x00ffffff,
};
unsigned char const C_icon_dashboard_bitmap[] = {
0xe0, 0x01, 0xfe, 0xc1, 0xff, 0x38, 0x70, 0x06, 0xd8, 0x79, 0x7e, 0x9e, 0x9f, 0xe7, 0xe7, 0xb9,
0x01, 0xe6, 0xc0, 0xf1, 0x3f, 0xf8, 0x07, 0x78, 0x00, };
#ifdef OS_IO_SEPROXYHAL
#include "os_io_seproxyhal.h"
const bagl_icon_details_t C_icon_dashboard = { GLYPH_icon_dashboard_WIDTH, GLYPH_icon_dashboard_HEIGHT, 1, C_icon_dashboard_colors, C_icon_dashboard_bitmap };
#endif // OS_IO_SEPROXYHAL

@ -1,30 +0,0 @@
#ifndef GLYPH_badge_back_BPP
#define GLYPH_badge_back_WIDTH 14
#define GLYPH_badge_back_HEIGHT 14
#define GLYPH_badge_back_BPP 1
extern
unsigned int const C_badge_back_colors[]
;
extern
unsigned char const C_badge_back_bitmap[];
#ifdef OS_IO_SEPROXYHAL
#include "os_io_seproxyhal.h"
extern
const bagl_icon_details_t C_badge_back;
#endif // GLYPH_badge_back_BPP
#endif // OS_IO_SEPROXYHAL
#ifndef GLYPH_icon_dashboard_BPP
#define GLYPH_icon_dashboard_WIDTH 14
#define GLYPH_icon_dashboard_HEIGHT 14
#define GLYPH_icon_dashboard_BPP 1
extern
unsigned int const C_icon_dashboard_colors[]
;
extern
unsigned char const C_icon_dashboard_bitmap[];
#ifdef OS_IO_SEPROXYHAL
#include "os_io_seproxyhal.h"
extern
const bagl_icon_details_t C_icon_dashboard;
#endif // GLYPH_icon_dashboard_BPP
#endif // OS_IO_SEPROXYHAL

@ -35,8 +35,11 @@ int gpg_apdu_get_key_data(unsigned int ref);
int gpg_apdu_put_key_data(unsigned int ref);
void gpg_pso_derive_slot_seed(int slot, unsigned char *seed);
void gpg_pso_derive_key_seed(unsigned char *Sn, unsigned char* key_name, unsigned int idx,
unsigned char *Ski, unsigned int Ski_len);
void gpg_pso_derive_key_seed(unsigned char *Sn,
unsigned char *key_name,
unsigned int idx,
unsigned char *Ski,
unsigned int Ski_len);
int gpg_apdu_pso(void);
int gpg_apdu_internal_authenticate(void);
int gpg_apdu_gen(void);
@ -58,6 +61,14 @@ void gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len);
int gpg_mse_reset();
int gpg_apdu_mse();
#ifdef GPG_SHAKE256
void cx_shake256_init(cx_sha3_t *hash, unsigned int out_length);
void cx_shake256_update(cx_sha3_t *ctx, const uint8_t *data, size_t len);
int cx_shake256_final(cx_sha3_t *hash, uint8_t *digest);
#endif
/* ----------------------------------------------------------------------- */
/* --- IO ---- */
/* ----------------------------------------------------------------------- */
@ -99,7 +110,7 @@ void io_usb_ccid_set_card_inserted(unsigned int inserted);
/* --- DEBUG ---- */
/* ----------------------------------------------------------------------- */
#ifdef GPG_DEBUG
#error "UNSUPPORTDED: to be fixed"
#include "gpg_debug.h"
#else

@ -41,18 +41,18 @@ int gpg_apdu_get_challenge() {
path[0] = 0x80475047;
path[1] = 0x0F0F0F0F;
os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 2, Sr, chain);
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_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, chain, 3, NULL, 0);
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,
G_gpg_vstate.work.io_buffer, 32);
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, G_gpg_vstate.work.io_buffer, 32);
cx_sha3_xof_init(&G_gpg_vstate.work.md.sha3, 256, olen);
cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha3,
CX_LAST, G_gpg_vstate.work.io_buffer, hlen,
cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha3, CX_LAST, G_gpg_vstate.work.io_buffer, hlen,
G_gpg_vstate.work.io_buffer, olen);
} else {
cx_rng(G_gpg_vstate.work.io_buffer, olen);

@ -29,8 +29,6 @@ int gpg_apdu_select_data(unsigned int ref, int reccord) {
int gpg_apdu_get_data(unsigned int ref) {
int sw;
if (G_gpg_vstate.DO_current != ref) {
G_gpg_vstate.DO_current = ref;
G_gpg_vstate.DO_reccord = 0;
@ -111,9 +109,7 @@ int gpg_apdu_get_data(unsigned int ref) {
gpg_io_mark();
gpg_io_insert_tlv(0xC0,
sizeof(C_ext_capabilities),
C_ext_capabilities);
gpg_io_insert_tlv(0xC0, sizeof(C_ext_capabilities), C_ext_capabilities);
gpg_io_insert_tlv(0xC1, G_gpg_vstate.kslot->sig.attributes.length, G_gpg_vstate.kslot->sig.attributes.value);
gpg_io_insert_tlv(0xC2, G_gpg_vstate.kslot->dec.attributes.length, G_gpg_vstate.kslot->dec.attributes.value);
gpg_io_insert_tlv(0xC3, G_gpg_vstate.kslot->aut.attributes.length, G_gpg_vstate.kslot->aut.attributes.value);
@ -258,8 +254,7 @@ int gpg_apdu_put_data(unsigned int ref) {
THROW(SW_CONDITIONS_NOT_SATISFIED);
return 0;
}
if ((G_gpg_vstate.io_length != 1) ||
(G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset] >= GPG_KEYS_SLOTS)) {
if ((G_gpg_vstate.io_length != 1) || (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset] >= GPG_KEYS_SLOTS)) {
THROW(SW_WRONG_DATA);
return 0;
}
@ -278,7 +273,6 @@ int gpg_apdu_put_data(unsigned int ref) {
break;
}
/* ----------------- Serial -----------------*/
case 0x4f:
if (G_gpg_vstate.io_length != 4) {
@ -325,7 +319,9 @@ int gpg_apdu_put_data(unsigned int ref) {
THROW(SW_REFERENCED_DATA_NOT_FOUND);
return 0;
}
len_e = 0; len_p = 0; len_q = 0;
len_e = 0;
len_p = 0;
len_q = 0;
endof = G_gpg_vstate.io_offset + l;
while (G_gpg_vstate.io_offset < endof) {
gpg_io_fetch_tl(&t, &l);
@ -391,7 +387,6 @@ int gpg_apdu_put_data(unsigned int ref) {
}
ksz = ksz >> 1;
// fetch e
e = 0;
switch (len_e) {
@ -441,8 +436,7 @@ int gpg_apdu_put_data(unsigned int ref) {
}
}
// --- ECC KEY ---
else if ((keygpg->attributes.value[0] == 19) ||
(keygpg->attributes.value[0] == 18) ||
else if ((keygpg->attributes.value[0] == 19) || (keygpg->attributes.value[0] == 18) ||
(keygpg->attributes.value[0] == 22)) {
unsigned int curve;
@ -475,7 +469,6 @@ int gpg_apdu_put_data(unsigned int ref) {
break;
} // endof of 3fff
/* ----------------- User -----------------*/
/* Name */
case 0x5B:
@ -640,7 +633,6 @@ int gpg_apdu_put_data(unsigned int ref) {
gpg_nvm_write(pkey, &aes_key, sizeof(cx_aes_key_t));
break;
/* AES key: one shot */
case 0xF4:
cx_aes_init_key(G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length, &aes_key);
@ -658,15 +650,11 @@ int gpg_apdu_put_data(unsigned int ref) {
if (G_gpg_vstate.io_length == 0) {
gpg_nvm_write(pin, NULL, sizeof(gpg_pin_t));
}
else if ((G_gpg_vstate.io_length > GPG_MAX_PW_LENGTH) ||
(G_gpg_vstate.io_length < 8)) {
} else if ((G_gpg_vstate.io_length > GPG_MAX_PW_LENGTH) || (G_gpg_vstate.io_length < 8)) {
THROW(SW_WRONG_DATA);
return SW_WRONG_DATA;
} else {
gpg_pin_set(pin,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
G_gpg_vstate.io_length);
gpg_pin_set(pin, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, G_gpg_vstate.io_length);
}
sw = SW_OK;
break;
@ -698,8 +686,6 @@ int gpg_apdu_put_data(unsigned int ref) {
gpg_io_discard(1);
return sw;
}
static void gpg_init_keyenc(cx_aes_key_t *keyenc) {
@ -738,7 +724,6 @@ int gpg_apdu_get_key_data(unsigned int ref) {
gpg_io_insert_u32(TARGET_ID);
gpg_io_insert_u32(CX_APILEVEL);
gpg_io_insert_u32(CX_COMPAT_APILEVEL);
// encrypted part
switch (keygpg->attributes.value[0]) {
case 0x01: // RSA
@ -748,8 +733,7 @@ int gpg_apdu_get_key_data(unsigned int ref) {
// insert privkey
gpg_io_mark();
len = cx_aes(&keyenc,
CX_ENCRYPT|CX_CHAIN_CBC|CX_PAD_ISO9797M2|CX_LAST,
len = cx_aes(&keyenc, CX_ENCRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST,
(unsigned char *)&keygpg->priv_key.rsa4096, sizeof(cx_rsa_4096_private_key_t),
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, GPG_IO_BUFFER_LENGTH - G_gpg_vstate.io_offset);
gpg_io_inserted(len);
@ -767,8 +751,7 @@ int gpg_apdu_get_key_data(unsigned int ref) {
// insert privkey
gpg_io_mark();
len = cx_aes(&keyenc,
CX_ENCRYPT|CX_CHAIN_CBC|CX_PAD_ISO9797M2|CX_LAST,
len = cx_aes(&keyenc, CX_ENCRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST,
(unsigned char *)&keygpg->priv_key.ecfp640, sizeof(cx_ecfp_640_private_key_t),
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, GPG_IO_BUFFER_LENGTH - G_gpg_vstate.io_offset);
gpg_io_inserted(len);
@ -791,7 +774,6 @@ int gpg_apdu_put_key_data(unsigned int ref) {
gpg_key_t * keygpg;
unsigned int len;
unsigned int offset;
gpg_init_keyenc(&keyenc);
switch (ref) {
@ -817,7 +799,8 @@ int gpg_apdu_put_key_data(unsigned int ref) {
gpg_io_fetch_u32();
switch (keygpg->attributes.value[0]) {
case 0x01: //RSA
// RSA
case 0x01:
// insert pubkey;
len = gpg_io_fetch_u32();
if (len != 4) {
@ -833,19 +816,18 @@ int gpg_apdu_put_key_data(unsigned int ref) {
}
offset = G_gpg_vstate.io_offset;
gpg_io_discard(0);
len = cx_aes(&keyenc,
CX_DECRYPT|CX_CHAIN_CBC|CX_PAD_ISO9797M2|CX_LAST,
G_gpg_vstate.work.io_buffer+offset, len,
G_gpg_vstate.work.io_buffer, GPG_IO_BUFFER_LENGTH);
len = cx_aes(&keyenc, CX_DECRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST, G_gpg_vstate.work.io_buffer + offset,
len, G_gpg_vstate.work.io_buffer, GPG_IO_BUFFER_LENGTH);
if (len != sizeof(cx_rsa_4096_private_key_t)) {
THROW(SW_WRONG_DATA);
}
gpg_nvm_write((unsigned char *)&keygpg->priv_key.rsa4096, G_gpg_vstate.work.io_buffer, len);
break;
case 18: //ECC
case 19:
case 22:
// ECC
case 18: /* 12h */
case 19: /* 13h */
case 22: /* 16h */
// insert pubkey;
len = gpg_io_fetch_u32();
if (len != sizeof(cx_ecfp_640_public_key_t)) {
@ -861,10 +843,9 @@ int gpg_apdu_put_key_data(unsigned int ref) {
}
offset = G_gpg_vstate.io_offset;
gpg_io_discard(0);
len = cx_aes(&keyenc,
CX_DECRYPT|CX_CHAIN_CBC|CX_PAD_ISO9797M2|CX_LAST,
G_gpg_vstate.work.io_buffer+offset, len,
G_gpg_vstate.work.io_buffer, GPG_IO_BUFFER_LENGTH);
len = cx_aes(&keyenc, CX_DECRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST, G_gpg_vstate.work.io_buffer + offset,
len, G_gpg_vstate.work.io_buffer, GPG_IO_BUFFER_LENGTH);
if (len != sizeof(cx_ecfp_640_private_key_t)) {
THROW(SW_WRONG_DATA);
return SW_WRONG_DATA;

@ -19,8 +19,6 @@
#include "gpg_api.h"
#include "gpg_vars.h"
void gpg_check_access_ins() {
unsigned int ref;
@ -245,16 +243,12 @@ void gpg_check_access_write_DO() {
THROW(SW_CONDITIONS_NOT_SATISFIED);
}
/* assume command is fully received */
int gpg_dispatch() {
unsigned int tag, t, l;
int sw;
if ((G_gpg_vstate.io_cla != 0x00) &&
(G_gpg_vstate.io_cla != 0x10) &&
(G_gpg_vstate.io_cla != 0xEF)) {
if ((G_gpg_vstate.io_cla != 0x00) && (G_gpg_vstate.io_cla != 0x10) && (G_gpg_vstate.io_cla != 0xEF)) {
THROW(SW_CLA_NOT_SUPPORTED);
return SW_CLA_NOT_SUPPORTED;
}
@ -288,7 +282,6 @@ int gpg_dispatch() {
break;
}
/* Other commands allowed if not terminated */
if (N_gpg_pstate->histo[7] != 0x07) {
THROW(SW_STATE_TERMINATED);
@ -298,8 +291,6 @@ int gpg_dispatch() {
gpg_check_access_ins();
switch (G_gpg_vstate.io_ins) {
#ifdef GPG_DEBUG_APDU
case 0x42:
sw = debug_apdu();
@ -361,7 +352,6 @@ int gpg_dispatch() {
sw = gpg_apdu_get_next_data(tag);
break;
case INS_PUT_DATA_ODD:
case INS_PUT_DATA:
gpg_check_access_write_DO();
@ -379,29 +369,21 @@ int gpg_dispatch() {
/* --- PIN -- */
case INS_VERIFY:
if ((G_gpg_vstate.io_p2 == 0x81) ||
(G_gpg_vstate.io_p2 == 0x82) ||
(G_gpg_vstate.io_p2 == 0x83)
) {
if ((G_gpg_vstate.io_p2 == 0x81) || (G_gpg_vstate.io_p2 == 0x82) || (G_gpg_vstate.io_p2 == 0x83)) {
sw = gpg_apdu_verify();
break;
}
THROW(SW_INCORRECT_P1P2);
case INS_CHANGE_REFERENCE_DATA:
if ((G_gpg_vstate.io_p2 == 0x81) ||
(G_gpg_vstate.io_p2 == 0x83)
) {
if ((G_gpg_vstate.io_p2 == 0x81) || (G_gpg_vstate.io_p2 == 0x83)) {
sw = gpg_apdu_change_ref_data();
break;
}
THROW(SW_INCORRECT_P1P2);
case INS_RESET_RETRY_COUNTER:
if ((G_gpg_vstate.io_p2 == 0x81) &&
( (G_gpg_vstate.io_p1 == 0) ||
(G_gpg_vstate.io_p1 == 2) )
) {
if ((G_gpg_vstate.io_p2 == 0x81) && ((G_gpg_vstate.io_p1 == 0) || (G_gpg_vstate.io_p1 == 2))) {
sw = gpg_apdu_reset_retry_counter();
break;
}

@ -38,9 +38,11 @@ void gpg_pso_derive_slot_seed(int slot, unsigned char *seed) {
* @out Ski generated sub_seed
* @in Ski_len sub-seed length
*/
void gpg_pso_derive_key_seed(unsigned char *Sn, unsigned char* key_name, unsigned int idx,
unsigned char *Ski, unsigned int Ski_len) {
void gpg_pso_derive_key_seed(unsigned char *Sn,
unsigned char *key_name,
unsigned int idx,
unsigned char *Ski,
unsigned int Ski_len) {
unsigned char h[32];
h[0] = idx >> 8;
h[1] = idx;
@ -49,12 +51,16 @@ void gpg_pso_derive_key_seed(unsigned char *Sn, unsigned char* key_name, unsigne
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, (unsigned char *)key_name, 4, NULL, 0);
cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256, CX_LAST, h, 2, h, 32);
#ifdef GPG_SHAKE256
cx_shake256_init(&G_gpg_vstate.work.md.sha3, Ski_len);
cx_shake256_update(&G_gpg_vstate.work.md.sha3, h, 32);
cx_shake256_final(&G_gpg_vstate.work.md.sha3, Ski);
#else
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);
#endif
}
/* assume command is fully received */
int gpg_apdu_gen() {
unsigned int t, l, ksz, reset_cnt;
@ -105,7 +111,6 @@ int gpg_apdu_gen() {
case 0x8001:
// RSA
if (keygpg->attributes.value[0] == 0x01) {
unsigned char * pq;
cx_rsa_public_key_t * rsa_pub;
cx_rsa_private_key_t *rsa_priv, *pkey;
@ -155,11 +160,9 @@ int gpg_apdu_gen() {
gpg_io_clear();
goto send_rsa_pub;
}
// ECC
if ((keygpg->attributes.value[0] == 18) ||
(keygpg->attributes.value[0] == 19) ||
if ((keygpg->attributes.value[0] == 18) || (keygpg->attributes.value[0] == 19) ||
(keygpg->attributes.value[0] == 22)) {
unsigned int curve, keepprivate;
keepprivate = 0;
@ -176,10 +179,7 @@ int gpg_apdu_gen() {
keepprivate = 1;
}
cx_ecfp_generate_pair(curve,
&G_gpg_vstate.work.ecfp.public,
&G_gpg_vstate.work.ecfp.private,
keepprivate);
cx_ecfp_generate_pair(curve, &G_gpg_vstate.work.ecfp.public, &G_gpg_vstate.work.ecfp.private, keepprivate);
nvm_write(&keygpg->priv_key.ecfp, &G_gpg_vstate.work.ecfp.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));
if (reset_cnt) {
@ -241,8 +241,7 @@ int gpg_apdu_gen() {
return SW_OK;
}
if ((keygpg->attributes.value[0] == 18) ||
(keygpg->attributes.value[0] == 19) ||
if ((keygpg->attributes.value[0] == 18) || (keygpg->attributes.value[0] == 19) ||
(keygpg->attributes.value[0] == 22)) {
unsigned int curve;
/// read ECC
@ -276,7 +275,6 @@ int gpg_apdu_gen() {
return SW_OK;
}
break;
}
THROW(SW_WRONG_DATA);

@ -25,18 +25,13 @@
/* -- A Kind of Magic -- */
/* ----------------------*/
const unsigned char C_MAGIC[8] = {
'G','P','G','C','A','R','D','3'
};
const unsigned char C_MAGIC[8] = {'G', 'P', 'G', 'C', 'A', 'R', 'D', '3'};
/* ----------------------*/
/* --ECC OID -- */
/* ----------------------*/
// 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
};
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] = {
@ -53,7 +48,6 @@ const unsigned char C_OID_SECP256K1[5] = {
};
*/
/*
//brainpool 256t1: 1.3.36.3.3.2.8.1.1.8
const unsigned char C_OID_BRAINPOOL256T1[9] = {
@ -84,7 +78,6 @@ const unsigned char C_OID_cv25519[10] = {
};
unsigned int gpg_oid2curve(unsigned char *oid, unsigned int len) {
if ((len == sizeof(C_OID_SECP256R1)) && (os_memcmp(oid, C_OID_SECP256R1, len) == 0)) {
return CX_CURVE_SECP256R1;
}
@ -131,7 +124,6 @@ unsigned int gpg_oid2curve(unsigned char* oid, unsigned int len) {
return CX_CURVE_NONE;
}
unsigned char *gpg_curve2oid(unsigned int cv, unsigned int *len) {
switch (cv) {
case CX_CURVE_SECP256R1:
@ -210,18 +202,13 @@ const unsigned char C_ext_capabilities[10] = {
};
const unsigned char C_ext_length[8] = {
0x02, 0x02, SHORT(GPG_APDU_LENGTH),
0x02, 0x02, SHORT(GPG_APDU_LENGTH)
};
const unsigned char C_ext_length[8] = {0x02, 0x02, SHORT(GPG_APDU_LENGTH), 0x02, 0x02, SHORT(GPG_APDU_LENGTH)};
/* ---------------------*/
/* -- default values -- */
/* ---------------------*/
const unsigned char C_default_AID[] = {
0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
const unsigned char C_default_AID[] = {0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
// version
0x03, 0x03,
// manufacturer
@ -229,21 +216,16 @@ const unsigned char C_default_AID[] = {
// serial
0x00, 0x00, 0x00, 0x00,
// RFU
0x00,0x00
};
0x00, 0x00};
const unsigned char C_default_Histo[] = {
0x00,
0x31,
const unsigned char C_default_Histo[] = {0x00, 0x31,
0xC5, // select method: by DF/partialDF; IO-file:readbinary; RFU???
0x73,
0xC0, // select method: by DF/partialDF ,
0x01, // data coding style: ontime/byte
0x80, // chaining
0x7F, // zero state
0x90, 0x00
};
0x90, 0x00};
// Default template: RSA2048 010800002001 / 010800002001
#if 1
@ -255,8 +237,7 @@ const unsigned char C_default_AlgoAttr_sig[] = {
// PubExp length 32
0x00, 0x20,
// std: e,p,q with modulus (n)
0x01
};
0x01};
const unsigned char C_default_AlgoAttr_dec[] = {
// RSA
0x01,
@ -265,8 +246,7 @@ const unsigned char C_default_AlgoAttr_dec[] = {
// PubExp length 32
0x00, 0x20,
// std: e,p,q with modulus (n)
0x01
};
0x01};
#endif
// Default template: NIST P256 132A8648CE3D030107 / 122A8648CE3D030107
@ -285,7 +265,6 @@ const unsigned char C_default_AlgoAttr_dec[] = {
};
#endif
// Default template: Ed/Cv-25519 162B06010401DA470F01 / 122B060104019755010501
#if 0
const unsigned char C_default_AlgoAttr_sig[] = {
@ -304,30 +283,25 @@ const unsigned char C_default_AlgoAttr_dec[] = {
// sha256 0x3132343536
const unsigned char C_sha256_PW1[] = {
0x8d, 0x96, 0x9e, 0xef, 0x6e, 0xca, 0xd3, 0xc2,
0x9a, 0x3a, 0x62, 0x92, 0x80, 0xe6, 0x86, 0xcf,
0x0c, 0x3f, 0x5d, 0x5a, 0x86, 0xaf, 0xf3, 0xca,
0x12, 0x02, 0x0c, 0x92, 0x3a, 0xdc, 0x6c, 0x92,
0x8d, 0x96, 0x9e, 0xef, 0x6e, 0xca, 0xd3, 0xc2, 0x9a, 0x3a, 0x62, 0x92, 0x80, 0xe6, 0x86, 0xcf,
0x0c, 0x3f, 0x5d, 0x5a, 0x86, 0xaf, 0xf3, 0xca, 0x12, 0x02, 0x0c, 0x92, 0x3a, 0xdc, 0x6c, 0x92,
};
// sha256 0x31323435363738
const unsigned char C_sha256_PW2[] = {
0xef, 0x79, 0x7c, 0x81, 0x18, 0xf0, 0x2d, 0xfb,
0x64, 0x96, 0x07, 0xdd, 0x5d, 0x3f, 0x8c, 0x76,
0x23, 0x04, 0x8c, 0x9c, 0x06, 0x3d, 0x53, 0x2c,
0xc9, 0x5c, 0x5e, 0xd7, 0xa8, 0x98, 0xa6, 0x4f,
0xef, 0x79, 0x7c, 0x81, 0x18, 0xf0, 0x2d, 0xfb, 0x64, 0x96, 0x07, 0xdd, 0x5d, 0x3f, 0x8c, 0x76,
0x23, 0x04, 0x8c, 0x9c, 0x06, 0x3d, 0x53, 0x2c, 0xc9, 0x5c, 0x5e, 0xd7, 0xa8, 0x98, 0xa6, 0x4f,
};
/* ----------------------------------------------------------------------- */
/* --- boot init --- */
/* ----------------------------------------------------------------------- */
void gpg_init() {
os_memset(&G_gpg_vstate, 0, sizeof(gpg_v_state_t));
// first init ?
if (os_memcmp(N_gpg_pstate->magic, (void*)C_MAGIC, sizeof(C_MAGIC)) != 0) {
if (os_memcmp((void *)(N_gpg_pstate->magic), (void *)C_MAGIC, sizeof(C_MAGIC)) != 0) {
gpg_install(STATE_ACTIVATE);
gpg_nvm_write(N_gpg_pstate->magic, (void*)C_MAGIC, sizeof(C_MAGIC));
gpg_nvm_write((void *)(N_gpg_pstate->magic), (void *)C_MAGIC, sizeof(C_MAGIC));
os_memset(&G_gpg_vstate, 0, sizeof(gpg_v_state_t));
}
@ -354,66 +328,65 @@ int gpg_install(unsigned char app_state) {
unsigned int l;
// full reset data
gpg_nvm_write(N_gpg_pstate, NULL, sizeof(gpg_nv_state_t));
gpg_nvm_write((void *)(N_gpg_pstate), NULL, sizeof(gpg_nv_state_t));
// historical bytes
os_memmove(G_gpg_vstate.work.io_buffer, C_default_Histo, sizeof(C_default_Histo));
G_gpg_vstate.work.io_buffer[7] = app_state;
gpg_nvm_write(N_gpg_pstate->histo, G_gpg_vstate.work.io_buffer, sizeof(C_default_Histo));
gpg_nvm_write((void *)(N_gpg_pstate->histo), G_gpg_vstate.work.io_buffer, sizeof(C_default_Histo));
// AID
os_memmove(G_gpg_vstate.work.io_buffer, C_default_AID, sizeof(C_default_AID));
gpg_nvm_write(N_gpg_pstate->AID, &G_gpg_vstate.work.io_buffer, sizeof(C_default_AID));
gpg_nvm_write((void *)(N_gpg_pstate->AID), &G_gpg_vstate.work.io_buffer, sizeof(C_default_AID));
// Serial
cx_rng(G_gpg_vstate.work.io_buffer, 4 * GPG_KEYS_SLOTS);
for (int s = 0; s < GPG_KEYS_SLOTS; s++) {
gpg_nvm_write(N_gpg_pstate->keys[s].serial, G_gpg_vstate.work.io_buffer+4*s, 4);
gpg_nvm_write((void *)(N_gpg_pstate->keys[s].serial), G_gpg_vstate.work.io_buffer + 4 * s, 4);
}
if (app_state == STATE_ACTIVATE) {
// default sex: none
G_gpg_vstate.work.io_buffer[0] = 0x39;
gpg_nvm_write(&N_gpg_pstate->sex, G_gpg_vstate.work.io_buffer, 1);
gpg_nvm_write((void *)(&N_gpg_pstate->sex), G_gpg_vstate.work.io_buffer, 1);
// default PW1/PW2: 1 2 3 4 5 6
os_memmove(pin.value, C_sha256_PW1, sizeof(C_sha256_PW1));
pin.length = 6;
pin.counter = 3;
pin.ref = PIN_ID_PW1;
gpg_nvm_write(&N_gpg_pstate->PW1, &pin, sizeof(gpg_pin_t));
gpg_nvm_write((void *)(&N_gpg_pstate->PW1), &pin, sizeof(gpg_pin_t));
// default PW3: 1 2 3 4 5 6 7 8
os_memmove(pin.value, C_sha256_PW2, sizeof(C_sha256_PW2));
pin.length = 8;
pin.counter = 3;
pin.ref = PIN_ID_PW3;
gpg_nvm_write(&N_gpg_pstate->PW3, &pin, sizeof(gpg_pin_t));
gpg_nvm_write((void *)(&N_gpg_pstate->PW3), &pin, sizeof(gpg_pin_t));
// PWs status
G_gpg_vstate.work.io_buffer[0] = 1;
G_gpg_vstate.work.io_buffer[1] = GPG_MAX_PW_LENGTH;
G_gpg_vstate.work.io_buffer[2] = GPG_MAX_PW_LENGTH;
G_gpg_vstate.work.io_buffer[3] = GPG_MAX_PW_LENGTH;
gpg_nvm_write(&N_gpg_pstate->PW_status, G_gpg_vstate.work.io_buffer, 4);
gpg_nvm_write((void *)(&N_gpg_pstate->PW_status), G_gpg_vstate.work.io_buffer, 4);
// config slot
G_gpg_vstate.work.io_buffer[0] = GPG_KEYS_SLOTS;
G_gpg_vstate.work.io_buffer[1] = 0;
G_gpg_vstate.work.io_buffer[2] = 3; // 3: selection by APDU and screen
gpg_nvm_write(&N_gpg_pstate->config_slot, G_gpg_vstate.work.io_buffer, 3);
gpg_nvm_write((void *)(&N_gpg_pstate->config_slot), G_gpg_vstate.work.io_buffer, 3);
// config rsa pub
G_gpg_vstate.work.io_buffer[0] = (GPG_RSA_DEFAULT_PUB >> 24) & 0xFF;
G_gpg_vstate.work.io_buffer[1] = (GPG_RSA_DEFAULT_PUB >> 16) & 0xFF;
G_gpg_vstate.work.io_buffer[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);
nvm_write((void *)(&N_gpg_pstate->default_RSA_exponent), G_gpg_vstate.work.io_buffer, 4);
// config pin
G_gpg_vstate.work.io_buffer[0] = PIN_MODE_CONFIRM;
gpg_nvm_write(&N_gpg_pstate->config_pin, G_gpg_vstate.work.io_buffer, 1);
gpg_nvm_write((void *)(&N_gpg_pstate->config_pin), G_gpg_vstate.work.io_buffer, 1);
USBD_CCID_activate_pinpad(3);
// default key template: RSA 2048)
@ -423,24 +396,24 @@ int gpg_install(unsigned char app_state) {
uif[0] = 0x00;
uif[1] = 0x20;
l = sizeof(C_default_AlgoAttr_sig);
gpg_nvm_write(&N_gpg_pstate->keys[s].sig.attributes.value, (void*)C_default_AlgoAttr_sig, l);
gpg_nvm_write(&N_gpg_pstate->keys[s].sig.attributes.length, &l, sizeof(unsigned int));
gpg_nvm_write(&N_gpg_pstate->keys[s].aut.attributes.value, (void*)C_default_AlgoAttr_sig, l);
gpg_nvm_write(&N_gpg_pstate->keys[s].aut.attributes.length, &l, sizeof(unsigned int));
gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].sig.attributes.value), (void *)C_default_AlgoAttr_sig, l);
gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].sig.attributes.length), &l, sizeof(unsigned int));
gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].aut.attributes.value), (void *)C_default_AlgoAttr_sig, l);
gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].aut.attributes.length), &l, sizeof(unsigned int));
l = sizeof(C_default_AlgoAttr_dec);
gpg_nvm_write(&N_gpg_pstate->keys[s].dec.attributes.value, (void*)C_default_AlgoAttr_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].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);
gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].dec.attributes.value), (void *)C_default_AlgoAttr_dec, l);
gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].dec.attributes.length), &l, sizeof(unsigned int));
gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].sig.UIF), &uif, 2);
gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].dec.UIF), &uif, 2);
gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].aut.UIF), &uif, 2);
}
}
return 0;
}
#define USBD_OFFSET_CfgDesc_bPINSupport (sizeof(USBD_CfgDesc) - 16)
void USBD_CCID_activate_pinpad(int enabled) {
#ifdef HAVE_USB_CLASS_CCID
unsigned short length;
uint8_t * cfgDesc;
unsigned char e;
@ -448,4 +421,5 @@ void USBD_CCID_activate_pinpad(int enabled) {
length = 0;
cfgDesc = USBD_GetCfgDesc_impl(&length);
nvm_write(cfgDesc + (length - 16), &e, 1);
#endif
}

@ -19,7 +19,6 @@
#include "gpg_api.h"
#include "gpg_vars.h"
/*
* io_buff: contains current message part
* io_off: offset in current message part
@ -33,25 +32,20 @@
void gpg_io_set_offset(unsigned int offset) {
if (offset == IO_OFFSET_END) {
G_gpg_vstate.io_offset = G_gpg_vstate.io_length;
}
else if (offset == IO_OFFSET_MARK) {
} else if (offset == IO_OFFSET_MARK) {
G_gpg_vstate.io_offset = G_gpg_vstate.io_mark;
}
else if (offset < G_gpg_vstate.io_length) {
} else if (offset < G_gpg_vstate.io_length) {
G_gpg_vstate.io_offset = G_gpg_vstate.io_length;
}
else {
} else {
THROW(ERROR_IO_OFFSET);
return;
}
}
void gpg_io_mark() {
G_gpg_vstate.io_mark = G_gpg_vstate.io_offset;
}
void gpg_io_inserted(unsigned int len) {
G_gpg_vstate.io_offset += len;
G_gpg_vstate.io_length += len;
@ -80,8 +74,7 @@ void gpg_io_hole(unsigned int sz) {
return;
}
os_memmove(G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset + sz,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
G_gpg_vstate.io_length-G_gpg_vstate.io_offset);
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, G_gpg_vstate.io_length - G_gpg_vstate.io_offset);
G_gpg_vstate.io_length += sz;
}
@ -98,7 +91,6 @@ void gpg_io_insert_u32(unsigned int v32) {
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 2] = v32 >> 8;
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 3] = v32 >> 0;
G_gpg_vstate.io_offset += 4;
}
void gpg_io_insert_u24(unsigned int v24) {
@ -145,12 +137,10 @@ void gpg_io_insert_tlv(unsigned int T, unsigned int L, unsigned char const *V) {
gpg_io_insert(V, L);
}
/* ----------------------------------------------------------------------- */
/* FECTH data from received buffer */
/* ----------------------------------------------------------------------- */
unsigned int gpg_io_fetch_u32() {
unsigned int v32;
v32 = ((G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] << 24) |
@ -204,7 +194,8 @@ int gpg_io_fetch_l(unsigned int *L) {
*L = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 1];
G_gpg_vstate.io_offset += 2;
} else if (*L == 2) {
*L = (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+1] << 8) | G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+2] ;
*L = (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 1] << 8) |
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 2];
G_gpg_vstate.io_offset += 3;
} else {
*L = -1;
@ -234,7 +225,6 @@ int gpg_io_fetch(unsigned char* buffer, int len) {
return len;
}
/* ----------------------------------------------------------------------- */
/* REAL IO */
/* ----------------------------------------------------------------------- */
@ -272,9 +262,7 @@ int gpg_io_do(unsigned int io_flags) {
G_io_apdu_buffer[tx + 1] = xx;
rx = gpg_io_exchange(CHANNEL_APDU, tx + 2);
// check get response
if ((G_io_apdu_buffer[0] != 0x00) ||
(G_io_apdu_buffer[1] != 0xc0) ||
(G_io_apdu_buffer[2] != 0x00) ||
if ((G_io_apdu_buffer[0] != 0x00) || (G_io_apdu_buffer[1] != 0xc0) || (G_io_apdu_buffer[2] != 0x00) ||
(G_io_apdu_buffer[3] != 0x00)) {
THROW(SW_COMMAND_NOT_ALLOWED);
return 0;
@ -337,15 +325,12 @@ int gpg_io_do(unsigned int io_flags) {
}
while (G_gpg_vstate.io_cla & 0x10) {
G_io_apdu_buffer[0] = 0x90;
G_io_apdu_buffer[1] = 0x00;
rx = gpg_io_exchange(CHANNEL_APDU, 2);
in_chaining:
if ((rx < 4) ||
((G_io_apdu_buffer[0] & 0xEF) != (G_gpg_vstate.io_cla& 0xEF)) ||
(G_io_apdu_buffer[1] != G_gpg_vstate.io_ins) ||
(G_io_apdu_buffer[2] != G_gpg_vstate.io_p1) ||
if ((rx < 4) || ((G_io_apdu_buffer[0] & 0xEF) != (G_gpg_vstate.io_cla & 0xEF)) ||
(G_io_apdu_buffer[1] != G_gpg_vstate.io_ins) || (G_io_apdu_buffer[2] != G_gpg_vstate.io_p1) ||
(G_io_apdu_buffer[3] != G_gpg_vstate.io_p2)) {
THROW(SW_COMMAND_NOT_ALLOWED);
return SW_COMMAND_NOT_ALLOWED;
@ -363,6 +348,5 @@ int gpg_io_do(unsigned int io_flags) {
G_gpg_vstate.io_length += G_gpg_vstate.io_lc;
}
return 0;
}

@ -28,7 +28,6 @@
#include "string.h"
#include "glyphs.h"
/* ----------------------------------------------------------------------- */
/* --- Application Entry --- */
/* ----------------------------------------------------------------------- */
@ -45,8 +44,7 @@ void gpg_main(void) {
}
CATCH_OTHER(e) {
gpg_io_discard(1);
if ( (e & 0xFFFF0000) ||
( ((e&0xF000)!=0x6000) && ((e&0xF000)!=0x9000) ) ) {
if ((e & 0xFFFF0000) || (((e & 0xF000) != 0x6000) && ((e & 0xF000) != 0x9000))) {
gpg_io_insert_u32(e);
sw = 0x6f42;
} else {
@ -64,10 +62,8 @@ void gpg_main(void) {
}
END_TRY;
}
}
unsigned char io_event(unsigned char channel) {
// nothing done with the event, throw an error on the transport layer if
// needed
@ -81,7 +77,6 @@ unsigned char io_event(unsigned char channel) {
UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer);
break;
// other events are propagated to the UX just in case
default:
UX_DEFAULT_EVENT();
@ -91,8 +86,7 @@ unsigned char io_event(unsigned char channel) {
UX_DISPLAYED_EVENT({});
break;
case SEPROXYHAL_TAG_TICKER_EVENT:
UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer,
{
UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {
// only allow display when not locked of overlayed by an OS UX.
if (UX_ALLOWED) {
UX_REDISPLAY();
@ -125,8 +119,7 @@ unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) {
return 0; // nothing received from the master so far (it's a tx
// transaction)
} else {
return io_seproxyhal_spi_recv(G_io_apdu_buffer,
sizeof(G_io_apdu_buffer), 0);
return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0);
}
default:
@ -153,7 +146,6 @@ __attribute__((section(".boot"))) int main(void) {
// exit critical section
__asm volatile("cpsie i");
// ensure exception will work as planned
os_boot();
for (;;) {
@ -161,13 +153,13 @@ __attribute__((section(".boot"))) int main(void) {
BEGIN_TRY {
TRY {
// start communication with MCU
io_seproxyhal_init();
USB_power(1);
#if HAVE_USB_CLASS_CCID
io_usb_ccid_set_card_inserted(1);
#endif
// set up
gpg_init();
@ -175,8 +167,6 @@ __attribute__((section(".boot"))) int main(void) {
// set up initial screen
ui_init();
// start the application
// the first exchange will:
// - display the initial screen

@ -20,7 +20,6 @@
#include "gpg_vars.h"
static int gpg_mse_set(int crt, int ref) {
if (crt == 0xA4) {
if (ref == 0x02) {
G_gpg_vstate.mse_aut = &G_gpg_vstate.kslot->dec;
@ -41,8 +40,6 @@ static int gpg_mse_set(int crt, int ref) {
return 0;
}
int gpg_mse_reset() {
gpg_mse_set(0xA4, 0x03);
gpg_mse_set(0xB8, 0x02);
@ -52,9 +49,7 @@ int gpg_mse_reset() {
int gpg_apdu_mse() {
int crt, ref;
if ((G_gpg_vstate.io_p1 != 0x41) ||
((G_gpg_vstate.io_p2 != 0xA4)&&(G_gpg_vstate.io_p2 != 0xB8))) {
if ((G_gpg_vstate.io_p1 != 0x41) || ((G_gpg_vstate.io_p2 != 0xA4) && (G_gpg_vstate.io_p2 != 0xB8))) {
THROW(SW_INCORRECT_P1P2);
return SW_INCORRECT_P1P2;
}
@ -74,5 +69,4 @@ int gpg_apdu_mse() {
gpg_mse_set(crt, ref);
gpg_io_discard(1);
return SW_OK;
}

@ -19,4 +19,8 @@
#include "gpg_api.h"
#include "gpg_vars.h"
#ifdef TARGET_NANOX
const gpg_nv_state_t N_state_pic;
#else
gpg_nv_state_t N_state_pic;
#endif

@ -34,8 +34,6 @@ gpg_pin_t *gpg_pin_get_pin(int pinref) {
return NULL;
}
static int gpg_pin_get_state_index(unsigned int pinref) {
switch (pinref) {
case PIN_ID_PW1:
@ -46,25 +44,23 @@ static int gpg_pin_get_state_index(unsigned int pinref) {
return 3;
case PIN_ID_RC:
return 4;
}
return -1;
}
static int gpg_pin_check_internal(gpg_pin_t *pin, unsigned char *pin_val, int pin_len) {
cx_sha256_t sha256;
unsigned int counter;
if (pin->counter == 0) {
return SW_PIN_BLOCKED;
}
counter = pin->counter - 1;
gpg_nvm_write(&(pin->counter), &counter, sizeof(int));
cx_sha256_init(&sha256);
cx_hash((cx_hash_t*)&sha256, CX_LAST, pin_val, pin_len, NULL, 0);
if (os_memcmp(sha256.acc, pin->value, 32)) {
cx_sha256_init(&G_gpg_vstate.work.md.sha256);
cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256, CX_LAST, pin_val, pin_len, G_gpg_vstate.work.md.H,
sizeof(G_gpg_vstate.work.md.H));
if (os_memcmp(G_gpg_vstate.work.md.H, pin->value, 32)) {
return SW_SECURITY_STATUS_NOT_SATISFIED;
}
@ -73,8 +69,7 @@ static int gpg_pin_check_internal(gpg_pin_t *pin, unsigned char *pin_val, int p
return SW_OK;
}
static void gpg_pin_check_throw(gpg_pin_t *pin, int pinID,
unsigned char *pin_val, int pin_len) {
static void gpg_pin_check_throw(gpg_pin_t *pin, int pinID, unsigned char *pin_val, int pin_len) {
int sw;
gpg_pin_set_verified(pinID, 0);
sw = gpg_pin_check_internal(pin, pin_val, pin_len);
@ -86,8 +81,7 @@ static void gpg_pin_check_throw(gpg_pin_t *pin, int pinID,
return;
}
int gpg_pin_check(gpg_pin_t *pin, int pinID,
unsigned char *pin_val, unsigned int pin_len) {
int gpg_pin_check(gpg_pin_t *pin, int pinID, unsigned char *pin_val, unsigned int pin_len) {
int sw;
gpg_pin_set_verified(pinID, 0);
sw = gpg_pin_check_internal(pin, pin_val, pin_len);
@ -129,12 +123,10 @@ int gpg_pin_is_verified(int pinID) {
return 0;
}
int gpg_pin_is_blocked(gpg_pin_t *pin) {
return pin->counter == 0;
}
int gpg_apdu_verify() {
gpg_pin_t *pin;
@ -178,8 +170,7 @@ int gpg_apdu_verify() {
THROW(SW_PIN_BLOCKED);
return SW_PIN_BLOCKED;
}
gpg_pin_check_throw(pin, G_gpg_vstate.io_p2,
G_gpg_vstate.work.io_buffer+ G_gpg_vstate.io_offset,
gpg_pin_check_throw(pin, G_gpg_vstate.io_p2, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
G_gpg_vstate.io_length);
gpg_io_discard(1);
return SW_OK;
@ -203,7 +194,6 @@ int gpg_apdu_verify() {
THROW(SW_WRONG_DATA);
return SW_WRONG_DATA;
}
int gpg_apdu_change_ref_data() {
@ -218,9 +208,6 @@ int gpg_apdu_change_ref_data() {
gpg_pin_set_verified(pin->ref, 0);
// --- PW1/PW3 pin ---
if (gpg_pin_is_blocked(pin)) {
THROW(SW_PIN_BLOCKED);
@ -242,20 +229,15 @@ int gpg_apdu_change_ref_data() {
len = pin->length;
}
gpg_pin_check_throw(pin, pin->ref,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
len);
gpg_pin_check_throw(pin, pin->ref, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, len);
newlen = G_gpg_vstate.io_length - len;
if ( (newlen > GPG_MAX_PW_LENGTH) ||
((pin->ref == PIN_ID_PW1) && (newlen < 6)) ||
if ((newlen > GPG_MAX_PW_LENGTH) || ((pin->ref == PIN_ID_PW1) && (newlen < 6)) ||
((pin->ref == PIN_ID_PW3) && (newlen < 8))) {
THROW(SW_WRONG_DATA);
return SW_WRONG_DATA;
}
gpg_pin_set(pin,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset+len,
newlen);
gpg_pin_set(pin, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset + len, newlen);
gpg_io_discard(1);
return SW_OK;
}
@ -278,7 +260,6 @@ int gpg_apdu_reset_retry_counter() {
rc_len = 0;
pw1_len = G_gpg_vstate.io_length;
} else {
// avoid any-overflow whitout giving info
if (pin_rc->length > G_gpg_vstate.io_length) {
rc_len = G_gpg_vstate.io_length;
@ -286,18 +267,14 @@ int gpg_apdu_reset_retry_counter() {
rc_len = pin_rc->length;
}
pw1_len = G_gpg_vstate.io_length - rc_len;
gpg_pin_check_throw(pin_rc,pin_rc->ref,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
rc_len);
gpg_pin_check_throw(pin_rc, pin_rc->ref, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, rc_len);
}
if ((pw1_len > GPG_MAX_PW_LENGTH) || (pw1_len < 6)) {
THROW(SW_WRONG_DATA);
return SW_WRONG_DATA;
}
gpg_pin_set(pin_pw1,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset+rc_len,
pw1_len);
gpg_pin_set(pin_pw1, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset + rc_len, pw1_len);
gpg_io_discard(1);
return SW_OK;
}

@ -20,12 +20,10 @@
#include "gpg_vars.h"
#include "gpg_ux_nanos.h"
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
};
const unsigned char gpg_oid_sha512[] = {
0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
};
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};
const unsigned char gpg_oid_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
static void gpg_pso_reset_PW1() {
if (N_gpg_pstate->PW_status[0] == 0) {
@ -62,18 +60,12 @@ static int gpg_sign(gpg_key_t *sigkey) {
// sign
l = ksz - G_gpg_vstate.io_length;
os_memmove(G_gpg_vstate.work.io_buffer+l,
G_gpg_vstate.work.io_buffer,
G_gpg_vstate.io_length);
os_memmove(G_gpg_vstate.work.io_buffer + l, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
os_memset(G_gpg_vstate.work.io_buffer, 0xFF, l);
G_gpg_vstate.work.io_buffer[0] = 0;
G_gpg_vstate.work.io_buffer[1] = 1;
G_gpg_vstate.work.io_buffer[l - 1] = 0;
ksz = cx_rsa_decrypt(key,
CX_PAD_NONE,
CX_NONE,
G_gpg_vstate.work.io_buffer, ksz,
G_gpg_vstate.work.io_buffer, ksz);
ksz = cx_rsa_decrypt(key, CX_PAD_NONE, CX_NONE, G_gpg_vstate.work.io_buffer, ksz, G_gpg_vstate.work.io_buffer, ksz);
// send
gpg_io_discard(0);
gpg_io_inserted(ksz);
@ -81,8 +73,7 @@ static int gpg_sign(gpg_key_t *sigkey) {
return SW_OK;
}
// --- ECDSA/EdDSA
if ((sigkey->attributes.value[0] == 19) ||
(sigkey->attributes.value[0] == 22)) {
if ((sigkey->attributes.value[0] == 19) || (sigkey->attributes.value[0] == 22)) {
cx_ecfp_private_key_t *key;
unsigned int sz, i, rs_len;
unsigned char * rs;
@ -97,12 +88,7 @@ static int gpg_sign(gpg_key_t *sigkey) {
THROW(SW_CONDITIONS_NOT_SATISFIED);
return SW_CONDITIONS_NOT_SATISFIED;
}
sz = cx_ecdsa_sign(key,
CX_RND_TRNG,
CX_NONE,
G_gpg_vstate.work.io_buffer, sz,
RS, 256,
NULL);
sz = cx_ecdsa_sign(key, CX_RND_TRNG, CX_NONE, G_gpg_vstate.work.io_buffer, sz, RS, 256, NULL);
// reencode r,s in MPI format
gpg_io_discard(0);
@ -121,12 +107,7 @@ static int gpg_sign(gpg_key_t *sigkey) {
rs += 2;
}
} else {
sz = cx_eddsa_sign(key,
CX_NONE,
CX_SHA512,
G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
NULL, 0,
RS, 256,
sz = cx_eddsa_sign(key, CX_NONE, CX_SHA512, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length, NULL, 0, RS, 256,
NULL);
gpg_io_discard(0);
gpg_io_insert(RS, sz);
@ -196,9 +177,7 @@ int gpg_apdu_pso() {
return SW_CONDITIONS_NOT_SATISFIED;
}
msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset;
sz = cx_aes(key,
CX_ENCRYPT|CX_CHAIN_CBC|CX_LAST,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, msg_len,
sz = cx_aes(key, 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 + 1, GPG_IO_BUFFER_LENGTH - 1);
// send
gpg_io_discard(0);
@ -245,10 +224,7 @@ int gpg_apdu_pso() {
return SW_CONDITIONS_NOT_SATISFIED;
}
msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset;
sz = cx_rsa_decrypt(key,
CX_PAD_PKCS1_1o5,
CX_NONE,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, msg_len,
sz = cx_rsa_decrypt(key, CX_PAD_PKCS1_1o5, CX_NONE, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, msg_len,
G_gpg_vstate.work.io_buffer, ksz);
// send
gpg_io_discard(0);
@ -266,10 +242,8 @@ int gpg_apdu_pso() {
return SW_CONDITIONS_NOT_SATISFIED;
}
msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset;
sz = cx_aes(key,
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, GPG_IO_BUFFER_LENGTH);
sz = cx_aes(key, 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, GPG_IO_BUFFER_LENGTH);
// send
gpg_io_discard(0);
gpg_io_inserted(sz);
@ -310,18 +284,13 @@ int gpg_apdu_pso() {
G_gpg_vstate.work.io_buffer[512 + i] = (G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset)[31 - i];
}
G_gpg_vstate.work.io_buffer[511] = 0x02;
sz = cx_ecdh(key,
CX_ECDH_X,
G_gpg_vstate.work.io_buffer+511, 65,
G_gpg_vstate.work.io_buffer+256, 160);
sz = cx_ecdh(key, CX_ECDH_X, G_gpg_vstate.work.io_buffer + 511, 65, G_gpg_vstate.work.io_buffer + 256, 160);
for (i = 0; i <= 31; i++) {
G_gpg_vstate.work.io_buffer[128 + i] = G_gpg_vstate.work.io_buffer[287 - i];
}
sz = 32;
} else {
sz = cx_ecdh(key,
CX_ECDH_X,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, 65,
sz = cx_ecdh(key, CX_ECDH_X, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, 65,
G_gpg_vstate.work.io_buffer + 128, 160);
}
// send
@ -346,7 +315,6 @@ int gpg_apdu_pso() {
return SW_REFERENCED_DATA_NOT_FOUND;
}
int gpg_apdu_internal_authenticate() {
// --- PSO:AUTH ---
if (G_gpg_vstate.kslot->aut.UIF[0]) {
@ -358,7 +326,8 @@ int gpg_apdu_internal_authenticate() {
}
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);
return SW_WRONG_LENGTH;
}

@ -18,19 +18,21 @@
#include "gpg_types.h"
#include "gpg_api.h"
#include "gpg_vars.h"
#include "os_io_seproxyhal.h"
#ifndef GPG_DEBUG_MAIN
unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
#ifdef TARGET_NANOX
#include "ux.h"
ux_state_t G_ux;
bolos_ux_params_t G_ux_params;
#else
ux_state_t ux;
#endif
#ifndef GPG_DEBUG_MAIN
unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
#else
extern unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
int apdu_n;
#endif
gpg_v_state_t G_gpg_vstate;

@ -13,7 +13,6 @@
* limitations under the License.
*/
#include "os.h"
#include "cx.h"
#include "gpg_types.h"
@ -25,8 +24,7 @@ int gpg_apdu_select() {
int sw;
// MF
if ( (G_gpg_vstate.io_length == 2) &&
(os_memcmp(G_gpg_vstate.work.io_buffer, C_MF, G_gpg_vstate.io_length) == 0) ) {
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;
}

@ -17,12 +17,15 @@
#define GPG_TYPES_H
#include "os_io_seproxyhal.h"
#ifdef TARGET_NANOX
#include "ux.h"
#endif
/* cannot send more that F0 bytes in CCID, why? do not know for now
* So set up length to F0 minus 2 bytes for SW
*/
#define GPG_APDU_LENGTH 0xFE
/* big private DO */
#define GPG_EXT_PRIVATE_DO_LENGTH 512
/* will be fixed..1024 is not enougth */
@ -52,8 +55,6 @@ struct gpg_pin_s {
};
typedef struct gpg_pin_s gpg_pin_t;
#define LV(name, maxlen) \
struct { \
unsigned int length; \
@ -105,7 +106,6 @@ typedef struct gpg_key_s {
unsigned char UIF[2];
} gpg_key_t;
typedef struct gpg_key_slot_s {
unsigned char serial[4];
/* */
@ -120,7 +120,6 @@ typedef struct gpg_key_slot_s{
} gpg_key_slot_t;
struct gpg_nv_state_s {
/* magic */
unsigned char magic[8];
@ -244,7 +243,8 @@ struct gpg_v_state_s {
} ecfp;
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 - (32 + MAX(sizeof(cx_sha3_t), sizeof(cx_sha256_t)))];
unsigned char H[32];
union {
cx_sha3_t sha3;
cx_sha256_t sha256;
@ -266,7 +266,18 @@ struct gpg_v_state_s {
unsigned char ux_pinentry[12];
unsigned int ux_key;
unsigned int ux_type;
#ifdef UI_NANO_S
ux_menu_entry_t ui_dogsays[2];
#endif
#ifdef UI_NANO_X
char ux_buff1[32];
char ux_buff2[32];
char ux_buff3[32];
char ux_buff4[32];
char ux_buff5[32];
#endif
#ifdef GPG_DEBUG
unsigned char print;
@ -283,12 +294,10 @@ typedef struct gpg_v_state_s gpg_v_state_t;
/* --- IDentifiers --- */
#define ID_AUTH 1
#define ID_DEC 2
#define ID_SIG 3
#define STATE_ACTIVATE 0x07
#define STATE_TERMINATE 0x03
@ -305,8 +314,6 @@ typedef struct gpg_v_state_s gpg_v_state_t;
#define PIN_MODE_CONFIRM 3
#define PIN_MODE_TRUST 4
/* --- INS --- */
#define INS_EXIT 0x02
@ -334,7 +341,6 @@ typedef struct gpg_v_state_s gpg_v_state_t;
#define INS_GET_CHALLENGE 0x84
#define INS_GET_RESPONSE 0xc0
/* --- IO constants --- */
#define OFFSET_CLA 0
#define OFFSET_INS 1
@ -344,7 +350,6 @@ typedef struct gpg_v_state_s gpg_v_state_t;
#define OFFSET_CDATA 5
#define OFFSET_EXT_CDATA 7
#define SW_OK 0x9000
#define SW_ALGORITHM_UNSUPPORTED 0x9484
@ -385,5 +390,4 @@ typedef struct gpg_v_state_s gpg_v_state_t;
#define SW_UNKNOWN 0x6f00
#endif

@ -14,20 +14,16 @@
* limitations under the License.
*/
#include "os.h"
#include "cx.h"
#include "gpg_types.h"
#include "gpg_api.h"
#include "gpg_vars.h"
#include "os_io_seproxyhal.h"
#include "string.h"
#include "glyphs.h"
/* ----------------------------------------------------------------------- */
/* --- Blue UI layout --- */
/* ----------------------------------------------------------------------- */

@ -34,5 +34,4 @@ const char * const C_NOT_ALLOWED = "Not Allowed ";
const char *const C_DEFAULT_MODE = "Default mode";
const char *const C_UIF_LOCKED = "UIF locked";

@ -13,7 +13,7 @@
* limitations under the License.
*/
#ifdef UI_NANO_S
#include "os.h"
#include "cx.h"
@ -27,12 +27,10 @@
#include "string.h"
#include "glyphs.h"
/* ----------------------------------------------------------------------- */
/* --- NanoS UI layout --- */
/* ----------------------------------------------------------------------- */
const ux_menu_entry_t ui_menu_template[];
void ui_menu_template_display(unsigned int value);
const bagl_element_t *ui_menu_template_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element);
@ -68,7 +66,6 @@ void ui_menu_pinconfirm_action(unsigned int value);
unsigned int ui_pinconfirm_nanos_button(unsigned int button_mask, unsigned int button_mask_counter);
unsigned int ui_pinconfirm_prepro(const bagl_element_t *element);
const bagl_element_t ui_pinentry_nanos[];
void ui_menu_pinentry_display(unsigned int value);
void ui_menu_pinentry_action(unsigned int value);
@ -93,41 +90,50 @@ void ui_info(const char* msg1, const char* msg2, const void *menu_display, unsig
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_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 },
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 },
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 },
{{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 },
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 },
0,
0,
NULL,
NULL,
NULL},
};
void ui_menu_uifconfirm_display(unsigned int value) {
@ -188,8 +194,7 @@ unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int b
}
CATCH_OTHER(e) {
gpg_io_discard(1);
if ( (e & 0xFFFF0000) ||
( ((e&0xF000)!=0x6000) && ((e&0xF000)!=0x9000) ) ) {
if ((e & 0xFFFF0000) || (((e & 0xF000) != 0x6000) && ((e & 0xF000) != 0x9000))) {
gpg_io_insert_u32(e);
sw = 0x6f42;
} else {
@ -203,8 +208,8 @@ unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int b
ui_menu_main_display(0);
}
break;
} END_TRY;
}
END_TRY;
}
return 0;
}
@ -213,34 +218,44 @@ unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int b
const bagl_element_t ui_pinconfirm_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_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 },
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 },
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 },
{{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 },
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 },
0,
0,
NULL,
NULL,
NULL},
};
void ui_menu_pinconfirm_display(unsigned int value) {
@ -256,7 +271,8 @@ unsigned int ui_pinconfirm_prepro(const bagl_element_t* element) {
}
if (element->component.userid == 2) {
if ((G_gpg_vstate.io_p2 == 0x81) || (G_gpg_vstate.io_p2 == 0x82) || (G_gpg_vstate.io_p2 == 0x83)) {
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s %x", G_gpg_vstate.io_p2 == 0x83?"Admin":"User",G_gpg_vstate.io_p2);
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s %x", G_gpg_vstate.io_p2 == 0x83 ? "Admin" : "User",
G_gpg_vstate.io_p2);
return 1;
}
}
@ -290,40 +306,49 @@ unsigned int ui_pinconfirm_nanos_button(unsigned int button_mask, unsigned int b
/* ------------------------------- PIN ENTRY UX ------------------------------ */
const bagl_element_t ui_pinentry_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_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_DOWN},
NULL,
0,
0, 0,
NULL, NULL, NULL },
0,
0,
NULL,
NULL,
NULL},
{{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_UP},
NULL,
0,
0, 0,
NULL, NULL, NULL },
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 },
{{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_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 },
0,
0,
NULL,
NULL,
NULL},
{{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
G_gpg_vstate.menu,
0,
0, 0,
NULL, NULL, NULL },
0,
0,
NULL,
NULL,
NULL},
};
static const char C_pin_digit[] = {'0','1','2','3','4','5','6','7','8','9','C','A','V'};
static const char C_pin_digit[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '<', 'A', 'V'};
void ui_menu_pinentry_display(unsigned int value) {
if (value == 0) {
@ -339,26 +364,29 @@ unsigned int ui_pinentry_prepro(const bagl_element_t* element) {
if (G_gpg_vstate.io_ins == 0x24) {
switch (G_gpg_vstate.io_p1) {
case 0:
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Current %s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User");
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Current %s PIN",
(G_gpg_vstate.io_p2 == 0x83) ? "Admin" : "User");
break;
case 1:
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "New %s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User");
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "New %s PIN",
(G_gpg_vstate.io_p2 == 0x83) ? "Admin" : "User");
break;
case 2:
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Confirm %s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User");
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Confirm %s PIN",
(G_gpg_vstate.io_p2 == 0x83) ? "Admin" : "User");
break;
default:
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "WAT %s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User");
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "WAT %s PIN",
(G_gpg_vstate.io_p2 == 0x83) ? "Admin" : "User");
break;
}
} else {
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s PIN", (G_gpg_vstate.io_p2 == 0x83) ? "Admin" : "User");
}
}
else if (element->component.userid == 2) {
} else if (element->component.userid == 2) {
unsigned int i;
G_gpg_vstate.menu[0] = ' ';
#if 1
#if 0
for (i = 1; i <= G_gpg_vstate.ux_pinentry[0]; i++) {
G_gpg_vstate.menu[i] = C_pin_digit[G_gpg_vstate.ux_pinentry[i]];
}
@ -444,7 +472,6 @@ static unsigned int validate_pin() {
unsigned int offset, len, sw;
gpg_pin_t * pin;
for (offset = 1; offset < G_gpg_vstate.ux_pinentry[0]; offset++) {
G_gpg_vstate.menu[offset] = C_pin_digit[G_gpg_vstate.ux_pinentry[offset]];
}
@ -471,7 +498,8 @@ static unsigned int validate_pin() {
}
if (G_gpg_vstate.io_p1 == 3) {
pin = gpg_pin_get_pin(G_gpg_vstate.io_p2);
if (gpg_pin_check(pin, G_gpg_vstate.io_p2, G_gpg_vstate.work.io_buffer+1, G_gpg_vstate.work.io_buffer[0])!=SW_OK) {
if (gpg_pin_check(pin, G_gpg_vstate.io_p2, G_gpg_vstate.work.io_buffer + 1, G_gpg_vstate.work.io_buffer[0]) !=
SW_OK) {
gpg_io_discard(1);
gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED);
gpg_io_do(IO_RETURN_AFTER_TX);
@ -482,7 +510,8 @@ static unsigned int validate_pin() {
offset = 1 + G_gpg_vstate.work.io_buffer[0];
len = G_gpg_vstate.work.io_buffer[offset];
if ((len != G_gpg_vstate.work.io_buffer[offset + 1 + len]) ||
(os_memcmp(G_gpg_vstate.work.io_buffer+offset + 1, G_gpg_vstate.work.io_buffer+offset+ 1+len+1, len) != 0)) {
(os_memcmp(G_gpg_vstate.work.io_buffer + offset + 1, G_gpg_vstate.work.io_buffer + offset + 1 + len + 1,
len) != 0)) {
gpg_io_discard(1);
gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED);
gpg_io_do(IO_RETURN_AFTER_TX);
@ -520,13 +549,11 @@ static unsigned int validate_pin() {
//#define LABEL_BPOOL512R1 "Brainpool 512R1"
#define LABEL_Ed25519 "Ed25519"
const ux_menu_entry_t ui_menu_template[] = {
{ui_menu_tmpl_key, NULL, -1, NULL, "Choose key...", NULL, 0, 0},
const ux_menu_entry_t ui_menu_template[] = {{ui_menu_tmpl_key, NULL, -1, NULL, "Choose key...", NULL, 0, 0},
{ui_menu_tmpl_type, NULL, -1, NULL, "Choose type...", NULL, 0, 0},
{NULL, ui_menu_tmpl_set_action, -1, NULL, "Set template", NULL, 0, 0},
{ui_menu_settings, NULL, 0, &C_badge_back, "Back", NULL, 61, 40},
UX_MENU_END
};
UX_MENU_END};
void ui_menu_template_display(unsigned int value) {
UX_MENU_DISPLAY(value, ui_menu_template, ui_menu_template_preprocessor);
@ -602,9 +629,6 @@ const bagl_element_t* ui_menu_template_preprocessor(const ux_menu_entry_t* entry
return element;
}
void ui_menu_tmpl_set_action(unsigned int value) {
LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH);
gpg_key_t * dest;
@ -684,24 +708,19 @@ void ui_menu_tmpl_set_action(unsigned int value) {
ERROR:
ui_info(INVALID_SELECTION, err, ui_menu_template_display, 0);
}
const ux_menu_entry_t ui_menu_tmpl_key[] = {
{NULL, ui_menu_tmpl_key_action, 1, NULL, LABEL_SIG, NULL, 0, 0},
const ux_menu_entry_t ui_menu_tmpl_key[] = {{NULL, ui_menu_tmpl_key_action, 1, NULL, LABEL_SIG, NULL, 0, 0},
{NULL, ui_menu_tmpl_key_action, 2, NULL, LABEL_DEC, NULL, 0, 0},
{NULL, ui_menu_tmpl_key_action, 3, NULL, LABEL_AUT, NULL, 0, 0},
{ui_menu_template, NULL, 0, &C_badge_back, "Back", NULL, 61, 40},
UX_MENU_END
};
UX_MENU_END};
void ui_menu_tmpl_key_action(unsigned int value) {
G_gpg_vstate.ux_key = value;
ui_menu_template_display(0);
}
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, 3072, NULL, LABEL_RSA3072, NULL, 0, 0},
@ -715,8 +734,7 @@ const ux_menu_entry_t ui_menu_tmpl_type[] = {
// {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, 0, &C_badge_back, "Back", NULL, 61, 40},
UX_MENU_END
};
UX_MENU_END};
void ui_menu_tmpl_type_action(unsigned int value) {
G_gpg_vstate.ux_type = value;
@ -725,13 +743,11 @@ void ui_menu_tmpl_type_action(unsigned int value) {
/* --------------------------------- SEED UX --------------------------------- */
const ux_menu_entry_t ui_menu_seed[] = {
{NULL, NULL, 0, NULL, "", NULL, 0, 0},
const ux_menu_entry_t ui_menu_seed[] = {{NULL, NULL, 0, NULL, "", NULL, 0, 0},
{NULL, ui_menu_seed_action, 1, NULL, "Set on", NULL, 0, 0},
{NULL, ui_menu_seed_action, 0, NULL, "Set off", NULL, 0, 0},
{ui_menu_settings, NULL, 0, &C_badge_back, "Back", NULL, 61, 40},
UX_MENU_END
};
UX_MENU_END};
void ui_menu_seed_display(unsigned int value) {
UX_MENU_DISPLAY(value, ui_menu_seed, ui_menu_seed_preprocessor);
@ -752,7 +768,6 @@ void ui_menu_seed_action(unsigned int value) {
ui_menu_seed_display(0);
}
/* ------------------------------- PIN MODE UX ------------------------------ */
const ux_menu_entry_t ui_menu_pinmode[];
void ui_menu_pinmode_display(unsigned int value);
@ -767,8 +782,7 @@ const ux_menu_entry_t ui_menu_pinmode[] = {
{NULL, ui_menu_pinmode_action, 0x8000 | PIN_MODE_TRUST, NULL, "Trust", NULL, 0, 0},
{NULL, ui_menu_pinmode_action, 128, NULL, "Set Default", NULL, 0, 0},
{ui_menu_settings, NULL, 0, &C_badge_back, "Back", NULL, 61, 40},
UX_MENU_END
};
UX_MENU_END};
void ui_menu_pinmode_display(unsigned int value) {
UX_MENU_DISPLAY(value, ui_menu_pinmode, ui_menu_pinmode_preprocessor);
@ -778,8 +792,7 @@ const bagl_element_t* ui_menu_pinmode_preprocessor(const ux_menu_entry_t* entry
if (element->component.userid == 0x20) {
if ((entry->userid >= (0x8000 | PIN_MODE_HOST)) && (entry->userid <= (0x8000 | PIN_MODE_TRUST))) {
unsigned char id = entry->userid & 0x7FFFF;
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s %s %s",
(char*)PIC(entry->line1),
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s %s %s", (char *)PIC(entry->line1),
id == N_gpg_pstate->config_pin[0] ? "#" : " ", /* default */
id == G_gpg_vstate.pinmode ? "+" : " " /* selected*/);
element->text = G_gpg_vstate.menu;
@ -810,8 +823,7 @@ void ui_menu_pinmode_action(unsigned int value) {
//#warning USBD_CCID_activate_pinpad commented
USBD_CCID_activate_pinpad(s);
}
}
else {
} else {
switch (value) {
case PIN_MODE_HOST:
case PIN_MODE_SCREEN:
@ -822,7 +834,6 @@ void ui_menu_pinmode_action(unsigned int value) {
}
break;
case PIN_MODE_TRUST:
if (!gpg_pin_is_verified(PIN_ID_PW3)) {
ui_info(PIN_ADMIN, NOT_VERIFIED, ui_menu_pinmode_display, 0);
@ -839,22 +850,18 @@ void ui_menu_pinmode_action(unsigned int value) {
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},
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, 0, &C_badge_back, "Back", NULL, 61, 40},
UX_MENU_END
};
UX_MENU_END};
void ui_menu_uifmode_display(unsigned int value) {
UX_MENU_DISPLAY(value, ui_menu_uifmode, ui_menu_uifmode_preprocessor);
@ -877,8 +884,7 @@ const bagl_element_t* ui_menu_uifmode_preprocessor(const ux_menu_entry_t* entry
*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);
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;
}
@ -918,16 +924,17 @@ void ui_menu_uifmode_action(unsigned int value) {
/* -------------------------------- RESET UX --------------------------------- */
const ux_menu_entry_t ui_menu_reset[] = {
{NULL, NULL, 0, NULL, "Really Reset ?", NULL, 0, 0},
const ux_menu_entry_t ui_menu_reset[] = {{NULL, NULL, 0, NULL, "Really Reset ?", NULL, 0, 0},
{NULL, ui_menu_main_display, 0, &C_badge_back, "No", NULL, 61, 40},
{NULL, ui_menu_reset_action, 0, NULL, "Yes", NULL, 0, 0},
UX_MENU_END
};
UX_MENU_END};
void ui_menu_reset_action(unsigned int value) {
unsigned char magic[4];
magic[0] = 0; magic[1] = 0; magic[2] = 0; magic[3] = 0;
magic[0] = 0;
magic[1] = 0;
magic[2] = 0;
magic[3] = 0;
gpg_nvm_write(N_gpg_pstate->magic, magic, 4);
gpg_init();
ui_CCID_reset();
@ -935,16 +942,13 @@ void ui_menu_reset_action(unsigned int value) {
}
/* ------------------------------- SETTINGS UX ------------------------------- */
const ux_menu_entry_t ui_menu_settings[] = {
{NULL, ui_menu_template_display, 0, NULL, "Key template", NULL, 0, 0},
const ux_menu_entry_t ui_menu_settings[] = {{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_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},
{NULL, ui_menu_main_display, 2, &C_badge_back, "Back", NULL, 61, 40},
UX_MENU_END
};
UX_MENU_END};
/* --------------------------------- SLOT UX --------------------------------- */
@ -953,20 +957,17 @@ const ux_menu_entry_t ui_menu_settings[] = {
#error menu definition not correct for current value of GPG_KEYS_SLOTS
#endif
const ux_menu_entry_t ui_menu_slot[] = {
{NULL, NULL, -1, NULL, "Choose:", NULL, 0, 0},
const ux_menu_entry_t ui_menu_slot[] = {{NULL, NULL, -1, NULL, "Choose:", NULL, 0, 0},
{NULL, ui_menu_slot_action, 1, NULL, "", NULL, 0, 0},
{NULL, ui_menu_slot_action, 2, NULL, "", NULL, 0, 0},
{NULL, ui_menu_slot_action, 3, NULL, "", NULL, 0, 0},
{NULL, ui_menu_slot_action, 128, NULL, "Set Default", NULL, 0, 0},
{NULL, ui_menu_main_display, 1, &C_badge_back, "Back", NULL, 61, 40},
UX_MENU_END
};
UX_MENU_END};
void ui_menu_slot_display(unsigned int value) {
UX_MENU_DISPLAY(value, ui_menu_slot, ui_menu_slot_preprocessor);
}
const bagl_element_t *ui_menu_slot_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element) {
unsigned int slot;
if (element->component.userid == 0x20) {
@ -976,8 +977,7 @@ const bagl_element_t* ui_menu_slot_preprocessor(const ux_menu_entry_t* entry, b
}
}
if (slot != 4) {
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Slot %d %s %s",
slot,
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Slot %d %s %s", slot,
slot == N_gpg_pstate->config_slot[1] + 1 ? "#" : " ", /* default */
slot == G_gpg_vstate.slot + 1 ? "+" : " " /* selected*/);
element->text = G_gpg_vstate.menu;
@ -992,8 +992,7 @@ void ui_menu_slot_action(unsigned int value) {
s = G_gpg_vstate.slot;
gpg_nvm_write(&N_gpg_pstate->config_slot[1], &s, 1);
value = s + 1;
}
else {
} else {
s = (unsigned char)(value - 1);
if (s != G_gpg_vstate.slot) {
G_gpg_vstate.slot = s;
@ -1012,30 +1011,26 @@ void ui_menu_slot_action(unsigned int value) {
#define STR(x) #x
#define XSTR(x) STR(x)
const ux_menu_entry_t ui_menu_info[] = {
{NULL, NULL, -1, NULL, "OpenPGP Card", NULL, 0, 0},
const ux_menu_entry_t ui_menu_info[] = {{NULL, NULL, -1, NULL, "OpenPGP Card", NULL, 0, 0},
{NULL, NULL, -1, NULL, "(c) Ledger SAS", NULL, 0, 0},
{NULL, NULL, -1, NULL, "Spec " XSTR(SPEC_VERSION), NULL, 0, 0},
{NULL, NULL, -1, NULL, "App " XSTR(GPG_VERSION), NULL, 0, 0},
{NULL, NULL, -1, NULL, "App " XSTR(OPENPGP_VERSION), NULL, 0, 0},
{NULL, ui_menu_main_display, 3, &C_badge_back, "Back", NULL, 61, 40},
UX_MENU_END
};
UX_MENU_END};
#undef STR
#undef XSTR
/* --------------------------------- MAIN UX --------------------------------- */
const ux_menu_entry_t ui_menu_main[] = {
{NULL, NULL, 0, NULL, "", "", 0, 0},
const ux_menu_entry_t ui_menu_main[] = {{NULL, NULL, 0, NULL, "", "", 0, 0},
#if GPG_MULTISLOT
{NULL, ui_menu_slot_display, 0, NULL, "Select slot", NULL, 0, 0},
#endif
{ui_menu_settings, NULL, 0, NULL, "Settings", NULL, 0, 0},
{ui_menu_info, NULL, 0, NULL, "About", NULL, 0, 0},
{NULL, os_sched_exit, 0, &C_icon_dashboard, "Quit app", NULL, 50, 29},
UX_MENU_END
};
UX_MENU_END};
extern const uint8_t N_USBD_CfgDesc[];
const bagl_element_t *ui_menu_main_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element) {
if (entry == &ui_menu_main[0]) {
@ -1054,19 +1049,14 @@ const bagl_element_t* ui_menu_main_preprocessor(const ux_menu_entry_t* entry, ba
}
if (element->component.userid == 0x22) {
unsigned int serial;
serial = (G_gpg_vstate.kslot->serial[0] << 24) |
(G_gpg_vstate.kslot->serial[1] << 16) |
(G_gpg_vstate.kslot->serial[2] << 8) |
(G_gpg_vstate.kslot->serial[3]);
serial = (G_gpg_vstate.kslot->serial[0] << 24) | (G_gpg_vstate.kslot->serial[1] << 16) |
(G_gpg_vstate.kslot->serial[2] << 8) | (G_gpg_vstate.kslot->serial[3]);
os_memset(G_gpg_vstate.menu, 0, sizeof(G_gpg_vstate.menu));
#if GPG_MULTISLOT
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "ID: %x / %d",
serial, G_gpg_vstate.slot+1);
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "ID: %x / %d", serial, G_gpg_vstate.slot + 1);
#else
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "ID: %x",
serial);
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "ID: %x", serial);
#endif
}
element->text = G_gpg_vstate.menu;
}
@ -1085,3 +1075,5 @@ void ui_init(void) {
void io_seproxyhal_display(const bagl_element_t *element) {
io_seproxyhal_display_default((bagl_element_t *)element);
}
#endif

@ -14,7 +14,6 @@
* limitations under the License.
*/
#ifndef GPG_UX_NANOS_H
#define GPG_UX_NANOS_H

File diff suppressed because it is too large Load Diff

@ -32,9 +32,14 @@ extern const unsigned char C_OID_Ed25519[9];
extern const unsigned char C_OID_cv25519[10];
extern gpg_v_state_t G_gpg_vstate;
#ifdef TARGET_NANOX
extern const gpg_nv_state_t N_state_pic;
#define N_gpg_pstate ((volatile gpg_nv_state_t *)PIC(&N_state_pic))
#else
extern gpg_nv_state_t N_state_pic;
#define N_gpg_pstate ((WIDE gpg_nv_state_t *)PIC(&N_state_pic))
#endif
#ifdef GPG_DEBUG_MAIN
extern int apdu_n;

@ -27,12 +27,13 @@
#pragma message "Override SDK source file :" __FILE__
#ifdef HAVE_USB_CLASS_CCID
#include "sdk_compat.h"
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid_cmd.h"
#ifdef HAVE_USB_CLASS_CCID
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/

@ -29,10 +29,12 @@
/* Includes ------------------------------------------------------------------*/
#include "os.h"
#include "usbd_ccid_if.h"
#include "sdk_compat.h"
#ifdef HAVE_USB_CLASS_CCID
#include "usbd_ccid_if.h"
#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
@ -531,16 +533,14 @@ uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter,
UNUSED(returnLen);
// return SLOTERROR_CMD_NOT_SUPPORTED;
uint16_t ret_len,off;
switch(pbuf[0])
{
switch(pbuf[0]) {
case 0: // verify pin
off = 15;
//ret_len = dwLength - 15;
ret_len = 5;
break;
case 1: // modify pin
switch(pbuf[11])
{
switch(pbuf[11]) {
case 3:
off = 20;
break;

@ -25,5 +25,23 @@
#define U2F_EPOUT_SIZE 0x40
#endif // HAVE_IO_U2F
#ifdef HAVE_WEBUSB
#define WEBUSB_EPIN_ADDR 0x83
#define WEBUSB_EPIN_SIZE 0x40
#define WEBUSB_EPOUT_ADDR 0x03
#define WEBUSB_EPOUT_SIZE 0x40
#ifdef HAVE_USB_CLASS_CCID
#error Unsupported CCID+WEBUSB, not enough endpoints
#endif // HAVE_USB_CLASS_CCID
#ifdef HAVE_IO_U2F
#define WEBUSB_INTF 2
#else // HAVE_IO_U2F
#define WEBUSB_INTF 1
#endif // HAVE_IO_U2F
#endif // HAVE_WEBUSB
#endif // USBD_HID_IMPL_H

@ -47,6 +47,7 @@
#pragma message "Override SDK source file :" __FILE__
#include "os.h"
#include "sdk_compat.h"
/* Includes ------------------------------------------------------------------*/
@ -118,12 +119,6 @@
* @{
*/
#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
@ -131,9 +126,9 @@
#define USBD_PID 0xf1d1
#else
#define USBD_VID 0x2C97
#if defined(TARGET_BLUE) // blue
#if defined(TARGET_BLUE)
#define USBD_PID 0x0000
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
static uint8_t const USBD_PRODUCT_FS_STRING[] = {
4*2+2,
USB_DESC_TYPE_STRING,
'B', 0,
@ -142,9 +137,9 @@ static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
'e', 0,
};
#elif defined(TARGET_NANOS) // nano s
#elif defined(TARGET_NANOS)
#define USBD_PID 0x0001
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
static uint8_t const USBD_PRODUCT_FS_STRING[] = {
6*2+2,
USB_DESC_TYPE_STRING,
'N', 0,
@ -154,9 +149,9 @@ static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
' ', 0,
'S', 0,
};
#elif defined(TARGET_ARAMIS) // aramis
#elif defined(TARGET_ARAMIS)
#define USBD_PID 0x0002
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
static uint8_t const USBD_PRODUCT_FS_STRING[] = {
6*2+2,
USB_DESC_TYPE_STRING,
'A', 0,
@ -166,13 +161,34 @@ static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
'i', 0,
's', 0,
};
#elif defined(TARGET_HW2)
#define USBD_PID 0x0003
static uint8_t const USBD_PRODUCT_FS_STRING[] = {
3*2+2,
USB_DESC_TYPE_STRING,
'H', 0,
'W', 0,
'2', 0,
};
#elif defined(TARGET_NANOX)
#define USBD_PID 0x0004
static uint8_t const USBD_PRODUCT_FS_STRING[] = {
6*2+2,
USB_DESC_TYPE_STRING,
'N', 0,
'a', 0,
'n', 0,
'o', 0,
' ', 0,
'X', 0,
};
#else
#error unknown TARGET_ID
#endif
#endif
/* USB Standard Device Descriptor */
static const uint8_t const USBD_LangIDDesc[]=
static uint8_t const USBD_LangIDDesc[]=
{
USB_LEN_LANGID_STR_DESC,
USB_DESC_TYPE_STRING,
@ -180,7 +196,7 @@ static const uint8_t const USBD_LangIDDesc[]=
HIBYTE(USBD_LANGID_STRING),
};
static const uint8_t const USB_SERIAL_STRING[] =
static uint8_t const USB_SERIAL_STRING[] =
{
4*2+2,
USB_DESC_TYPE_STRING,
@ -190,7 +206,7 @@ static const uint8_t const USB_SERIAL_STRING[] =
'1', 0,
};
static const uint8_t const USBD_MANUFACTURER_STRING[] = {
static uint8_t const USBD_MANUFACTURER_STRING[] = {
6*2+2,
USB_DESC_TYPE_STRING,
'L', 0,
@ -204,7 +220,7 @@ static const uint8_t const USBD_MANUFACTURER_STRING[] = {
#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[] = {
static uint8_t const HID_ReportDesc[] = {
0x06, 0xA0, 0xFF, // Usage page (vendor defined)
0x09, 0x01, // Usage ID (vendor defined)
0xA1, 0x01, // Collection (application)
@ -228,7 +244,7 @@ static const uint8_t const HID_ReportDesc[] = {
};
#ifdef HAVE_IO_U2F
static const uint8_t const HID_ReportDesc_fido[] = {
static uint8_t const HID_ReportDesc_fido[] = {
0x06, 0xD0, 0xF1, // Usage page (vendor defined)
0x09, 0x01, // Usage ID (vendor defined)
0xA1, 0x01, // Collection (application)
@ -255,7 +271,7 @@ static const uint8_t const HID_ReportDesc_fido[] = {
#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 =
static __ALIGN_BEGIN uint8_t const N_USBD_CfgDesc[] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
@ -267,6 +283,9 @@ static __ALIGN_BEGIN const uint8_t const N_USBD_CfgDesc[] __ALIGN_END =
#ifdef HAVE_USB_CLASS_CCID
+0x9+0x36+0x7+0x7
#endif // HAVE_USB_CLASS_CCID
#ifdef HAVE_WEBUSB
+0x9+0x7+0x7
#endif // HAVE_WEBUSB
),
1
#ifdef HAVE_IO_U2F
@ -275,6 +294,9 @@ static __ALIGN_BEGIN const uint8_t const N_USBD_CfgDesc[] __ALIGN_END =
#ifdef HAVE_USB_CLASS_CCID
+1
#endif // HAVE_USB_CLASS_CCID
#ifdef HAVE_WEBUSB
+1
#endif // HAVE_WEBUSB
, /*bNumInterfaces */
0x01, /*bConfigurationValue: Configuration value*/
USBD_IDX_PRODUCT_STR, /*iConfiguration: Index of string descriptor describing the configuration*/
@ -462,11 +484,43 @@ static __ALIGN_BEGIN const uint8_t const N_USBD_CfgDesc[] __ALIGN_END =
HIBYTE(CCID_BULK_EPOUT_SIZE),
0x00, /*Polling interval in milliseconds*/
#endif // HAVE_USB_CLASS_CCID
#ifdef HAVE_WEBUSB
/* WEBUSB ################################################################################################ */
/************** Descriptor of WEBUSB interface ****************/
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
WEBUSB_INTF, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x02, /*bNumEndpoints*/
0xFF, /*bInterfaceClass: WINUSB*/
0xFF, /*bInterfaceSubClass : WINUSB*/
0xFF, /*nInterfaceProtocol : WINUSB*/
USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
/******************** Descriptor of endpoints ********************/
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
WEBUSB_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
WEBUSB_EPIN_SIZE, /*wMaxPacketSize: */
0x00,
0x01, /*bInterval: Polling Interval */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
WEBUSB_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
0x03, /* bmAttributes: Interrupt endpoint */
WEBUSB_EPOUT_SIZE, /* wMaxPacketSize: */
0x00,
0x01,/* bInterval: Polling Interval */
#endif // HAVE_WEBUSB
} ;
#ifdef HAVE_IO_U2F
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN const uint8_t const USBD_HID_Desc_fido[] __ALIGN_END =
__ALIGN_BEGIN uint8_t const USBD_HID_Desc_fido[] __ALIGN_END =
{
/******************** Descriptor of HID *************************/
0x09, /*bLength: HID Descriptor size*/
@ -482,7 +536,7 @@ __ALIGN_BEGIN const uint8_t const USBD_HID_Desc_fido[] __ALIGN_END =
#endif // HAVE_IO_U2F
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN const uint8_t const USBD_HID_Desc[] __ALIGN_END =
__ALIGN_BEGIN uint8_t const USBD_HID_Desc[] __ALIGN_END =
{
/* 18 */
0x09, /*bLength: HID Descriptor size*/
@ -497,7 +551,7 @@ __ALIGN_BEGIN const uint8_t const USBD_HID_Desc[] __ALIGN_END =
};
/* USB Standard Device Descriptor */
static __ALIGN_BEGIN const uint8_t const USBD_DeviceQualifierDesc[] __ALIGN_END =
static __ALIGN_BEGIN uint8_t const USBD_DeviceQualifierDesc[] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
@ -512,7 +566,7 @@ static __ALIGN_BEGIN const uint8_t const USBD_DeviceQualifierDesc[] __ALIGN_END
};
/* USB Standard Device Descriptor */
static const uint8_t const USBD_DeviceDesc[]= {
static uint8_t const USBD_DeviceDesc[]= {
0x12, /* bLength */
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
0x00, /* bcdUSB */
@ -710,9 +764,39 @@ uint8_t* USBD_HID_GetReportDescriptor_impl(uint16_t* len) {
*
* 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
/**
* @brief USBD_HID_Init
* Initialize the HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
uint8_t USBD_U2F_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
UNUSED(cfgidx);
/* Open EP IN */
USBD_LL_OpenEP(pdev,
U2F_EPIN_ADDR,
USBD_EP_TYPE_INTR,
U2F_EPIN_SIZE);
/* Open EP OUT */
USBD_LL_OpenEP(pdev,
U2F_EPOUT_ADDR,
USBD_EP_TYPE_INTR,
U2F_EPOUT_SIZE);
/* Prepare Out endpoint to receive 1st packet */
USBD_LL_PrepareReceive(pdev, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE);
return USBD_OK;
}
uint8_t USBD_U2F_DataIn_impl (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
@ -743,6 +827,20 @@ uint8_t USBD_U2F_DataOut_impl (USBD_HandleTypeDef *pdev,
}
#endif // HAVE_IO_U2F
uint8_t USBD_HID_DataIn_impl (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
UNUSED(pdev);
switch (epnum) {
// HID gen endpoint
case (HID_EPIN_ADDR&0x7F):
io_usb_hid_sent(io_usb_send_apdu_data);
break;
}
return USBD_OK;
}
uint8_t USBD_HID_DataOut_impl (USBD_HandleTypeDef *pdev,
uint8_t epnum, uint8_t* buffer)
{
@ -774,12 +872,97 @@ uint8_t USBD_HID_DataOut_impl (USBD_HandleTypeDef *pdev,
return USBD_OK;
}
#ifdef HAVE_WEBUSB
uint8_t USBD_WEBUSB_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
UNUSED(cfgidx);
/* Open EP IN */
USBD_LL_OpenEP(pdev,
WEBUSB_EPIN_ADDR,
USBD_EP_TYPE_INTR,
WEBUSB_EPIN_SIZE);
/* Open EP OUT */
USBD_LL_OpenEP(pdev,
WEBUSB_EPOUT_ADDR,
USBD_EP_TYPE_INTR,
WEBUSB_EPOUT_SIZE);
/* Prepare Out endpoint to receive 1st packet */
USBD_LL_PrepareReceive(pdev, WEBUSB_EPOUT_ADDR, WEBUSB_EPOUT_SIZE);
return USBD_OK;
}
uint8_t USBD_WEBUSB_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx) {
UNUSED(pdev);
UNUSED(cfgidx);
return USBD_OK;
}
uint8_t USBD_WEBUSB_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
UNUSED(pdev);
UNUSED(req);
return USBD_OK;
}
uint8_t USBD_WEBUSB_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
UNUSED(pdev);
switch (epnum) {
// HID gen endpoint
case (WEBUSB_EPIN_ADDR&0x7F):
io_usb_hid_sent(io_usb_send_apdu_data_ep0x83);
break;
}
return USBD_OK;
}
uint8_t USBD_WEBUSB_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum, uint8_t* buffer)
{
// only the data hid endpoint will receive data
switch (epnum) {
// HID gen endpoint
case (WEBUSB_EPOUT_ADDR&0x7F):
// prepare receiving the next chunk (masked time)
USBD_LL_PrepareReceive(pdev, WEBUSB_EPOUT_ADDR, WEBUSB_EPOUT_SIZE);
// avoid troubles when an apdu has not been replied yet
if (G_io_app.apdu_media == IO_APDU_MEDIA_NONE) {
// add to the hid transport
switch(io_usb_hid_receive(io_usb_send_apdu_data_ep0x83, buffer, io_seproxyhal_get_ep_rx_size(WEBUSB_EPOUT_ADDR))) {
default:
break;
case IO_USB_APDU_RECEIVED:
G_io_app.apdu_media = IO_APDU_MEDIA_USB_WEBUSB; // for application code
G_io_app.apdu_state = APDU_USB_WEBUSB; // for next call to io_exchange
G_io_app.apdu_length = G_io_usb_hid_total_length;
break;
}
}
break;
}
return USBD_OK;
}
#endif // HAVE_WEBUSB
/** @defgroup USBD_HID_Private_Functions
* @{
*/
// note: how core lib usb calls the hid class
const USBD_DescriptorsTypeDef const HID_Desc = {
USBD_DescriptorsTypeDef const HID_Desc = {
USBD_DeviceDescriptor,
USBD_LangIDStrDescriptor,
USBD_ManufacturerStrDescriptor,
@ -791,9 +974,9 @@ const USBD_DescriptorsTypeDef const HID_Desc = {
};
#ifdef HAVE_IO_U2F
static const USBD_ClassTypeDef const USBD_U2F =
static USBD_ClassTypeDef const USBD_U2F =
{
USBD_HID_Init,
USBD_U2F_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /*EP0_TxSent*/
@ -810,14 +993,14 @@ static const USBD_ClassTypeDef const USBD_U2F =
};
#endif // HAVE_IO_U2F
static const USBD_ClassTypeDef const USBD_HID =
static 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_DataIn_impl, /*DataIn*/
USBD_HID_DataOut_impl, /*DataOut*/
NULL, /*SOF */
NULL,
@ -828,6 +1011,102 @@ static const USBD_ClassTypeDef const USBD_HID =
USBD_GetDeviceQualifierDesc_impl,
};
#ifdef HAVE_WEBUSB
// arbitrary vendor choosen
#define WEBUSB_VENDOR_CODE 0x1E
// from https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
// see also this (for endianness explanation)
// https://github.com/WICG/webusb/issues/115#issuecomment-352206549
#define WEBUSB_UUID 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65
#define WEBUSB_REQ_GET_URL 0x02
#define WEBUSB_DT_DESCRIPTOR_SET_HEADER 0
#define WEBUSB_DT_CONFIGURATION_SUBSET_HEADER 1
#define WEBUSB_DT_FUNCTION_SUBSET_HEADER 2
#define WEBUSB_DT_URL 3
#define WEBUSB_URL_SCHEME_HTTP 0
#define WEBUSB_URL_SCHEME_HTTPS 1
#define WEBUSB_URL_SCHEME_CUSTOM 255
unsigned char const C_webusb_url_descriptor[] = {
// bLength
3 + WEBUSB_URL_SIZE_B,
// bDescriptorType
WEBUSB_DT_URL,
// bScheme
WEBUSB_URL_SCHEME_HTTPS,
// URL
WEBUSB_URL
};
/* USB 3.1 Descriptor Types - Table 9-6 */
#define USB_DT_BOS 15
#define USB_DT_DEVICE_CAPABILITY 16
#define USB_DT_BOS_SIZE 5
/* USB Device Capability Types - USB 3.1 Table 9-14 */
#define USB_DC_PLATFORM 5
unsigned char const C_usb_bos[] = {
USB_DT_BOS_SIZE, // bLength (5)
USB_DT_BOS, // bDescriptorType
(5+8+16), // wTotalLength
(5+8+16)>>8,
1, //bNumberDeviceCapabilities
// capability descriptor
8+16, // bLength
USB_DT_DEVICE_CAPABILITY, // bDescriptorType
USB_DC_PLATFORM, // bDevCapability
0, // bReserved
WEBUSB_UUID, // UUID[16]
0x00, // bcdVersion
0x01,
WEBUSB_VENDOR_CODE, // bVencordCode
1 // iLanding
};
// upon unsupported request, check for webusb request
void USBD_CtlError( USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) {
if ((req->bmRequest & 0x80) && req->bRequest == WEBUSB_VENDOR_CODE && req->wIndex == WEBUSB_REQ_GET_URL
// HTTPS url
&& req->wValue == 1) {
// return the URL descriptor
USBD_CtlSendData (pdev, (unsigned char*)C_webusb_url_descriptor, sizeof(C_webusb_url_descriptor));
}
else if ((req->bmRequest & 0x80) && req->bRequest == USB_REQ_GET_DESCRIPTOR && (req->wValue>>8) == USB_DT_BOS) {
USBD_CtlSendData(pdev, (unsigned char*)C_usb_bos, sizeof(C_usb_bos));
}
else {
USBD_CtlStall(pdev);
}
}
static const USBD_ClassTypeDef USBD_WEBUSB =
{
USBD_WEBUSB_Init,
USBD_WEBUSB_DeInit,
USBD_WEBUSB_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_WEBUSB_DataIn,
USBD_WEBUSB_DataOut,
NULL, /*SOF */
NULL, /*ISOIn*/
NULL, /*ISOOut*/
USBD_GetCfgDesc_impl,
USBD_GetCfgDesc_impl,
USBD_GetCfgDesc_impl,
USBD_GetDeviceQualifierDesc_impl,
};
#endif // HAVE_WEBUSB
#ifdef HAVE_USB_CLASS_CCID
static const USBD_ClassTypeDef USBD_CCID =
{
@ -874,6 +1153,12 @@ uint8_t SC_ExecuteEscape (uint8_t* escapePtr, uint32_t escapeLen,
void USB_power(unsigned char enabled) {
os_memset(&USBD_Device, 0, sizeof(USBD_Device));
#if TARGET_ID == 0x33000004
// init timeouts and other global fields
os_memset(G_io_app.usb_ep_xfer_len, 0, sizeof(G_io_app.usb_ep_xfer_len));
os_memset(G_io_app.usb_ep_timeouts, 0, sizeof(G_io_app.usb_ep_timeouts));
#endif
if (enabled) {
os_memset(&USBD_Device, 0, sizeof(USBD_Device));
/* Init Device Library */
@ -890,6 +1175,10 @@ void USB_power(unsigned char enabled) {
USBD_RegisterClassForInterface(CCID_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_CCID);
#endif // HAVE_USB_CLASS_CCID
#ifdef HAVE_WEBUSB
USBD_RegisterClassForInterface(WEBUSB_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_WEBUSB);
USBD_LL_PrepareReceive(&USBD_Device, WEBUSB_EPOUT_ADDR , WEBUSB_EPOUT_SIZE);
#endif // HAVE_WEBUSB
/* Start Device Process */
USBD_Start(&USBD_Device);

Loading…
Cancel
Save