From 72df4f7d2062e2f48c86967bb6205510ad706456 Mon Sep 17 00:00:00 2001 From: cslashm Date: Fri, 14 Jun 2019 10:38:37 +0200 Subject: [PATCH] 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 --- .clang-format | 119 +++ Makefile | 88 +- README.md | 6 +- doc/user/blue-app-openpgp-card.rst | 13 +- glyphs/icon_back.gif | Bin 0 -> 1123 bytes glyphs/icon_certificate.gif | Bin 0 -> 1133 bytes glyphs/icon_coggle.gif | Bin 0 -> 1128 bytes glyphs/icon_crossmark.gif | Bin 0 -> 1131 bytes glyphs/icon_dashboard_x.gif | Bin 0 -> 1126 bytes glyphs/icon_down.gif | Bin 0 -> 1100 bytes glyphs/icon_left.gif | Bin 0 -> 1101 bytes glyphs/icon_pgp.gif | Bin 0 -> 83 bytes glyphs/icon_right.gif | Bin 0 -> 1100 bytes glyphs/icon_up.gif | Bin 0 -> 1100 bytes glyphs/icon_validate_14.gif | Bin 0 -> 1125 bytes glyphs/icon_warning.gif | Bin 0 -> 1130 bytes images/icon_pgp_nanox.gif | Bin 0 -> 83 bytes pytools/gpgcard/gpgcard.py | 25 +- pytools/gpgcard/gpgcli.py | 5 +- script.ld | 167 ---- src/glyphs.c | 30 - src/glyphs.h | 30 - src/gpg_api.h | 115 +-- src/gpg_challenge.c | 44 +- src/gpg_data.c | 475 ++++++----- src/gpg_dispatch.c | 166 ++-- src/gpg_gen.c | 216 +++-- src/gpg_init.c | 310 ++++--- src/gpg_io.c | 216 +++-- src/gpg_main.c | 42 +- src/gpg_mse.c | 26 +- src/gpg_nvram.c | 4 + src/gpg_pin.c | 159 ++-- src/gpg_pso.c | 345 ++++---- src/gpg_ram.c | 18 +- src/gpg_select.c | 24 +- src/gpg_types.h | 350 ++++---- src/gpg_ux_blue.c | 8 +- src/gpg_ux_msg.c | 35 +- src/gpg_ux_msg.h | 70 +- src/gpg_ux_nanos.c | 992 ++++++++++++----------- src/gpg_ux_nanos.h | 1 - src/gpg_ux_nanox.c | 1198 ++++++++++++++++++++++++++++ src/gpg_vars.h | 11 +- src/sdk/usbd_ccid_cmd.c | 5 +- src/sdk/usbd_ccid_if.c | 10 +- src/sdk/usbd_hid_impl.h | 18 + src/sdk/usbd_impl.c | 345 +++++++- 48 files changed, 3511 insertions(+), 2175 deletions(-) create mode 100644 .clang-format create mode 100644 glyphs/icon_back.gif create mode 100644 glyphs/icon_certificate.gif create mode 100644 glyphs/icon_coggle.gif create mode 100644 glyphs/icon_crossmark.gif create mode 100644 glyphs/icon_dashboard_x.gif create mode 100644 glyphs/icon_down.gif create mode 100644 glyphs/icon_left.gif create mode 100644 glyphs/icon_pgp.gif create mode 100644 glyphs/icon_right.gif create mode 100644 glyphs/icon_up.gif create mode 100644 glyphs/icon_validate_14.gif create mode 100644 glyphs/icon_warning.gif create mode 100644 images/icon_pgp_nanox.gif delete mode 100644 script.ld delete mode 100644 src/glyphs.c delete mode 100644 src/glyphs.h create mode 100644 src/gpg_ux_nanox.c diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..95b750c --- /dev/null +++ b/.clang-format @@ -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 +... + diff --git a/Makefile b/Makefile index 499dd0c..29de45c 100644 --- a/Makefile +++ b/Makefile @@ -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,8 +164,15 @@ 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 @@ -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 + diff --git a/README.md b/README.md index 204edee..782962c 100644 --- a/README.md +++ b/README.md @@ -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) : diff --git a/doc/user/blue-app-openpgp-card.rst b/doc/user/blue-app-openpgp-card.rst index 5045d0a..f8c5f8e 100644 --- a/doc/user/blue-app-openpgp-card.rst +++ b/doc/user/blue-app-openpgp-card.rst @@ -1130,7 +1130,8 @@ using ``--xx-pin`` may compromise your pin codes. Then you must precise if you want a backup or a restore with ``--backup`` or ``--restore`` 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. +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 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/glyphs/icon_back.gif b/glyphs/icon_back.gif new file mode 100644 index 0000000000000000000000000000000000000000..ff043615c0ccfe858bfc3f3805647aaee5a499bb GIT binary patch literal 1123 zcmZ?wbhEHbh+i z#(Mch>H3D2mX`VkM*2oZxP`3=Lf^oD9vKom`v^ z4IGV}EX^$3V0vBhlS^|`^GaZPQxJOHaOwpmh};68%`T}$nPsUdZbkXI3Sf_0W#V>= zGfwlMdQ)(_#RaEceV}9XLD7p8-7q0w8Uiuli5JL$C;!wuV45!iCT_<6|Nj2@{p;tC z@87({PcxqRv3h4bgmo;iK$ z#u35cm<%;FYmM&SmXyJnS^XAT( zJ!|HS>C>i8nLKIYg#NzXp6;&Bj`p_Jmgc6$hWfhNn(C^`it@73lH#Jmg8aPPob0U3 zjP$hBl;otug!s7FnCPg;i14t`kl>)e0DnJUA8#*D4|g|LV6Zqk*xT9KSX)_In46iJ z7#kTH=@}C@U!{$jiyfNJ~jdh>MAe2nz`c@bmHVaC32Tu(PqUFf%a% wONgH=z;c3tK?g*D$_@r5iJtzIs~KwUGz+zPEiKD<-x8T<*15Dbij~0{0O2}{jsO4v literal 0 HcmV?d00001 diff --git a/glyphs/icon_certificate.gif b/glyphs/icon_certificate.gif new file mode 100644 index 0000000000000000000000000000000000000000..89b529f792aeb77c8cc3b4d4782d8280b3c6c204 GIT binary patch literal 1133 zcmZ?wbhEHbh+i z#(Mch>H3D2mX`VkM*2oZxP`3=Lf^oD9vKom`v^ z4IGV}EX^$3V0vBhlS^|`^GaZPQxJOHaOwpmh};68%`T}$nPsUdZbkXI3Sf_0W#V>= zGfwlMdQ)(_#RaEceV}9XLD7p8-7q0w8Uiuli5JL$C;!wuV45!iCT_<6|Nj2@{p;tC z@87({PcxqRv3h4bgmo;iK$ z#u35cm<%;FYmM&SmXyJnS^XAT( zJ!|HS>C>i8nLKIYg#NzXp6;&Bj`p_Jmgc6$hWfhNn(C^`it@73lH#Jmg8aPPob0U3 zjP$hBl;otug!s7FnCPg;i14t`kl>)e0DnJUA8#*D4|g|LV6Zqk*xT9KSX)_In46iJ z7#kTH=@}C@U!{$jiyfNJ~jdh>MAe2nz`c@bmHVaC32Tu(PqUFf%a% zONgH=z;c3tK?g*D$_@r5rJnxG17}|h+i z#(Mch>H3D2mX`VkM*2oZx= z8BX({dQ)(_1?YGj{?G?HMjsTtNYM=w0;VAl6P|d19C-3i%>$zB`;K7M%r?(Lh`uU@`*{_N?K$B!O9xPR~No!hr=-nf44>XplvE?zi)?(CV< zr%s+Ye(dOx!-ozY*uQV@p5424?%2L<>z2)%Hf~tIZta@Yt5&X9zHI4|#fug$m_Kjs zoY}Kx&X_)J>XgZoCQj(@>+R|8>g;H5Yi((6YHX;ltF5W7s;nq4D=jH5DlEv)%gxEo z%FIYlOHD~mN=%54i;annii`*k3k?Yl3Jmb~^Y!ue^7L?bb9Hfca&)k_v$e6dva~Qa zGc_?bGBnWF)78<|($r8_Q&mw`QdE$ala-N{l9Uh^6BQ8_5)|O)h+i z#(Mch>H3D2mX`VkM*2oZxP`3=Lf^oD9vKom`v^ z4IGV}EX^$3V0vBhlS^|`^GaZPQxJMxaOwpmh};68%`T}$nPsUdZbkXI3Sf_0W#V>= zBTn<6dQ)(_#R;cgeV}9XLD7p8-7q0w8Uiuli5JL$C;!wuV45!iCT_<6|Nj2@{p;tC z@87({PcxqRv3h4bgmo;iK$ z#u35cm<%;FYmM&SmXyJnS^XAT( zJ!|HS>C>i8nLKIYg#NzXp6;&Bj`p_Jmgc6$hWfhNn(C^`it@73lH#Jmg8aPPob0U3 zjP$hBl;otug!s7FnCPg;i14t`kl>)e0DnJUA8#*D4|g|LU=%qz*xT9KSX)_In46iJ z7#kTH=@}C@U!{$jiyfNJ~jdh>MAe2nz`c@bmHVaC32Tu(PqUFf%a% zONgH=z;c3tK?g*D$_@r5g`R%S3EQ{LsG1P=G9yPZ?_TW!_O_JIo#INXvMrLH1~M>M F0{{d^jh+i z#(Mch>H3D2mX`VkM*2oZx= z5l-`({PcxqRv3h4bgmo;iK$ z#u35cm<%;FYmM&SmXyJnS^XAT( zJ!|HS>C>i8nLKIYg#NzXp6;&Bj`p_Jmgc6$hWfhNn(C^`it@73lH#Jmg8aPPob0U3 zjP$hBl;otug!s7FnCPg;i14t`kl>)e0DnJUA8#*D4|g|L7iT9&2YWkP8*3{|3v)A5 z6JsMo1ARSR9c?X54RtkD6=fww1$jAH8EGj=32`w|5n&-g0e(JS9&Rp94t6$H7G@?! zUc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*btCX0MpOk6^Wap-qB64UF}T4Rno+txOE8OpFwuK*`RgC?(A*$i)q66_97Elu=SrV5P5L zUS6(Ou9shwu5V~*X{m2uq;F)T3sj(6T$u;-oo-&SvJ%j-AOl=di<65o3raHc^Aw8G ztP+#*OG|8(lob9$J&;=fH#M(V59}GeYG-AXPsowK%`DC^;3VTp46jft7PnYGO%#QAmD%4lD=*GV)9Ei!<^I z6r7#GL8hSLo0y!L2NcundS0ve;2nVDi`Y;NgdWMu4QWZ>pz zXy|I@XlQBVYUE;UXz6Nc_}|je8K&7KKe;qFHLnDwIR&BF8LAmYFGwpWEr5aq7{EoD zWvMA{Mftf3V1HX>!rg-I6icj50lNgEH3i8fKwls^#1W@feV|kH(V`kA1WZ04CM4AY z(t84%^TORUA=Po(!~qs&z(JU`qar2$B!L7a`@1}1N-;w-Lrew&K=vgZQZhY z)5ZeMTG_VdAT{+S(zE>X{jm6Nr?&Zaj`McQIQehVWA};$o%uI|73_73^0#s@+FtPL0rFC}Ia4}c|0Jk%O AU;qFB literal 0 HcmV?d00001 diff --git a/glyphs/icon_left.gif b/glyphs/icon_left.gif new file mode 100644 index 0000000000000000000000000000000000000000..524226ba11247d9c5f797801400fd630071a049a GIT binary patch literal 1101 zcmZ?wbhEHbWMN=u_`m=H|NsA2{K*1lD*orL$SqJvNi0bO(*Nx%3KEmEQ%e+*Qqwc@ zY?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*btCX0MpOk6^Wap-qB64UF}T4Rno+txOE8OpFwuK*`RgC?(A*$i)q66_97Elu=SrV5P5L zUS6(Ou9shwu5V~*X{m2uq;F)T3sj(6T$u;-oo-&SvJ%j-AOl=di<65o3raHc^Aw8G ztP+#*OG|8(lob9$J&;=fH#M(V59}GeYG-AXPsowK%`DC^;3VTp46jft7PnYGO%#QAmD%4lD=*GV)9Ei!<^I z6r7#GL8hSLo0y!L2NcundS0ve;2nVDkcY~W;U?r3IeWZ>*# zXy|I@XlQBVYUE;UXz6Nc_}|je8K&7KKe;qFHLnDwIR&BF45}GLFGwpWEr5aq7{EoD zWvMA{Mftf3V1HX>!rg-I6l1JT0lNgEH3i8fKwls^!~~~SeV|kH(V`kA1WZ04CM4AY z(t84%^TORUA=Po(!~qs&z(JU`qar2$B!L7a`@1}1N-;w-Lrew&K=vgZQZhY z)5ZeMTG_VdAT{+S(zE>X{jm6Nr?&Zaj`McQIQehVWA};$o%uI|73_73^0#s@+FmbdLb7tJW=fuch4FGsN BgIfRq literal 0 HcmV?d00001 diff --git a/glyphs/icon_pgp.gif b/glyphs/icon_pgp.gif new file mode 100644 index 0000000000000000000000000000000000000000..732270e4453448e49ebfad0ab37b4187464da9e7 GIT binary patch literal 83 zcmZ?wbhEHb6_GT#!5ilS)f}<-s-25&{Z+LsCyE eZ2zyzuTmCUGV|KhP0PLebS)3+-;iKsum%7_rWgeP literal 0 HcmV?d00001 diff --git a/glyphs/icon_right.gif b/glyphs/icon_right.gif new file mode 100644 index 0000000000000000000000000000000000000000..15ff3cf5994421fbd6e7d593aae8e438310f33ed GIT binary patch literal 1100 zcmZ?wbhEHbWMN=u_`m=H|NsA2{K*1lD*orL$SqJvNi0bO(*Nx%3KEmEQ%e+*Qqwc@ zY?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*btCX0MpOk6^Wap-qB64UF}T4Rno+txOE8OpFwuK*`RgC?(A*$i)q66_97Elu=SrV5P5L zUS6(Ou9shwu5V~*X{m2uq;F)T3sj(6T$u;-oo-&SvJ%j-AOl=di<65o3raHc^Aw8G ztP+#*OG|8(lob9$J&;=fH#M(V59}GeYG-AXPsowK%`DC^;3VTp46jft7PnYGO%#QAmD%4lD=*GV)9Ei!<^I z6r7#GL8hSLo0y!L2NcundS0ve;2nVDkcY~W;U?r3IcWZ>*# zXy|I@XlQBVYUE;UXz6Nc_}|je8K&7KKe;qFHLnDwIR&BF2&x%HFGwpWEr5aq7{EoD zWvMA{Mftf3V1HX>!rg-A6jL{>P64|FqBRA{B|u*wIm7^`R(+sT^wFXkCIn1AASNW$ z0@Eju15Nk;OB7P`fT_I*n5-H9|NHyr_phHnzJL4r<@2Wx@87+B^ZM1x7tfzPee(Fx z!w2{8-Mw@B*3BE&uU)-z`O?J;=g*xzbNbZD6UUDoJ#zTa!2|pE?cK9`*UlZ=w{6|B zdDF%X>({MavwGFa70Z_`U9x!5!Ugl^&7CuQ*322xr%jzQdD6rQ{e8VX-Cdm>?QN|s z%}tFB^>wv1)m4=h1nAc$w`R`@o}*+(NU2R;bEa6!9jrm z{(inb-d>&_?ryFw&Q6XF_I9>5)>f7l=4PfQ#zuw)`g*!L+FF_#>T0Sg%1Vj~@^Z2= z(o&KV;$osA!a{-q{CvDTJltHI9PDhYEX+)d3=BG;5&~3eFfg(6@U>OF>g8gv1_1YR Bf|mdQ literal 0 HcmV?d00001 diff --git a/glyphs/icon_up.gif b/glyphs/icon_up.gif new file mode 100644 index 0000000000000000000000000000000000000000..4e13c064f7605feb2e6e04a48a3133e5c95912cb GIT binary patch literal 1100 zcmZ?wbhEHbWM^Pu_`m=H|NsA2{K*1lD*orL$SqJvNi0bO(*Nx%3KEmEQ%e+*Qqwc@ zY?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*btCX0MpOk6^Wap-qB64UF}T4Rno+txOE8OpFwuK*`RgC?(A*$i)q66_97Elu=SrV5P5L zUS6(Ou9shwu5V~*X{m2uq;F)T3sj(6T$u;-oo-&SvJ%j-AOl=di<65o3raHc^Aw8G ztP+#*OG|8(lob9$J&;=fH#M(V59}GeYG-AXPsowK%`DC^;3VTp46jft7PnYGO%#QAmD%4lD=*GV)9Ei!<^I z6r7#GL8hSLo0y!L2NcundS0ve;2nVDi`Y;NgdWMu4SWZ>pz zXy|I@XlQBVYUE;UXz6Nc_}|je8K&7KKe;qFHLnDwIR&oS!~m)pMK4GzC@p}31Q@_Y znPsUdZbkXI3SfU*Wy0Np?i3fSP64|FqBRA{B|u*w9AfN>Q>#AEDf(zp4HE(;9}p9g zYJuq!$bqK&|0N2kdBD_O1WeY9|Ns5{^ZVD&AK$-y{qp(KhxhN^zIpxX<%{Rfo<4c} z=;4F=_wL@gee33p>({PcxqRv3h4bgmo;iK$#u35cm<%;FYmM&SmXyJnS^XAT(J!|HS>C>i8nLKIYg#NzXp6;&Bj`p_J zmgc6$hWfhNn(C^`it@73lH#Jmg8aPPob0U3jP$hBl;otug!s7FnCPg;i14t`kl>)e z0DnJUA8#*D4|g|L7iT9&2YWkP8*3{|3v)A56JsMo1ARSR9c?X54RtkD6=fww1$jAH z8EGj=32`w|5n&-g0e(JS9v*HkP7Zc9Ru*O^Mg|5QPzeDlH5i!KTar5~xYlqnSOWmI C)q;Qk literal 0 HcmV?d00001 diff --git a/glyphs/icon_validate_14.gif b/glyphs/icon_validate_14.gif new file mode 100644 index 0000000000000000000000000000000000000000..ccb5cabe38d16ff857d540b64742e4b8346a6949 GIT binary patch literal 1125 zcmZ?wbhEHbh+i z#(Mch>H3D2mX`VkM*2oZx= z0Z#LvdQ)(_#So`neV}9XLD7p8-7q0w8Uiuli5JL$C;!wuV45!iCT_<6|Nj2@{p;tC z@87({PcxqRv3h4bgmo;iK$ z#u35cm<%;FYmM&SmXyJnS^XAT( zJ!|HS>C>i8nLKIYg#NzXp6;&Bj`p_Jmgc6$hWfhNn(C^`it@73lH#Jmg8aPPob0U3 zjP$hBl;otug!s7FnCPg;i14t`kl>)e0DnJUA8#*D4|g|L7iT9&2YWkP8*3{|3v)A5 z6JsMo1ARSR9c?X54RtkD6=fww1$jAH8EGj=32`w|5n&-g0e(JS9&Rp94t6$H7G@?! zUh+i z#(Mch>H3D2mX`VkM*2oZxP`3=Lf^oD9vKom`v^ z4IGV}EX^$3V0vBhlS^|`^GaZPQxJMhaOwpmh};68%`T}$nPsUdZbkXI3Sf_0W#V>= zAx`t4dQ)(_#R#WfeV}9XLD7p8-7q0w8Uiuli5JL$C;!wuV45!iCT_<6|Nj2@{p;tC z@87({PcxqRv3h4bgmo;iK$ z#u35cm<%;FYmM&SmXyJnS^XAT( zJ!|HS>C>i8nLKIYg#NzXp6;&Bj`p_Jmgc6$hWfhNn(C^`it@73lH#Jmg8aPPob0U3 zjP$hBl;otug!s7FnCPg;i14t`kl>)e0DnJUA8#*D4|g|L7iT9&2YWkP8*3{|3v)A5 z6JsMo1ARSR9c?X54RtkD6=fww1$jAH8EGj=32`w|5n&-g0e(JS9&Rp94t6$H7G@?! zU6_GT#!5ilS)f}<-s-25&{Z+LsCyE eZ2zyzuTmCUGV|KhP0PLebS)3+-;iKsum%7_rWgeP literal 0 HcmV?d00001 diff --git a/pytools/gpgcard/gpgcard.py b/pytools/gpgcard/gpgcard.py index 6fbf7b5..c763f81 100644 --- a/pytools/gpgcard/gpgcard.py +++ b/pytools/gpgcard/gpgcard.py @@ -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) @@ -397,7 +414,7 @@ class GPGCard() : self.sig_date, self.dec_date, self.aut_date, self.cardholder_cert, self.UIF_SIG, self.UIF_DEC, self.UIF_AUT, - self.sig_key, self.dec_key, self.aut_key) = pickle.load(f) + self.sig_key, self.dec_key, self.aut_key) = pickle.load(f) self.set_all() return True diff --git a/pytools/gpgcard/gpgcli.py b/pytools/gpgcard/gpgcli.py index d34bbc4..8a6d230 100644 --- a/pytools/gpgcard/gpgcli.py +++ b/pytools/gpgcard/gpgcli.py @@ -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") diff --git a/script.ld b/script.ld deleted file mode 100644 index 60b4ced..0000000 --- a/script.ld +++ /dev/null @@ -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) } - -} diff --git a/src/glyphs.c b/src/glyphs.c deleted file mode 100644 index 4e68e9a..0000000 --- a/src/glyphs.c +++ /dev/null @@ -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 diff --git a/src/glyphs.h b/src/glyphs.h deleted file mode 100644 index b94b06b..0000000 --- a/src/glyphs.h +++ /dev/null @@ -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 diff --git a/src/gpg_api.h b/src/gpg_api.h index f6fe7d8..2dc64ea 100644 --- a/src/gpg_api.h +++ b/src/gpg_api.h @@ -14,81 +14,92 @@ */ #ifndef GPG_API_H -#define GPG_API_H +#define GPG_API_H void USBD_CCID_activate_pinpad(int enabled); -unsigned int gpg_oid2curve(unsigned char* oid, unsigned int len); -unsigned char* gpg_curve2oid(unsigned int cv, unsigned int *len); +unsigned int gpg_oid2curve(unsigned char *oid, unsigned int len); +unsigned char *gpg_curve2oid(unsigned int cv, unsigned int *len); unsigned int gpg_curve2domainlen(unsigned int cv); void gpg_init(void); void gpg_init_ux(void); -int gpg_install(unsigned char app_state) ; +int gpg_install(unsigned char app_state); int gpg_dispatch(void); -int gpg_apdu_select_data(unsigned int ref, int reccord) ; -int gpg_apdu_get_data(unsigned int ref) ; -int gpg_apdu_get_next_data(unsigned int ref) ; -int gpg_apdu_put_data(unsigned int ref) ; -int gpg_apdu_get_key_data(unsigned int ref); -int gpg_apdu_put_key_data(unsigned int ref); +int gpg_apdu_select_data(unsigned int ref, int reccord); +int gpg_apdu_get_data(unsigned int ref); +int gpg_apdu_get_next_data(unsigned int ref); +int gpg_apdu_put_data(unsigned int ref); +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 ); -int gpg_apdu_get_challenge(void) ; +int gpg_apdu_gen(void); +int gpg_apdu_get_challenge(void); -int gpg_apdu_select(void) ; +int gpg_apdu_select(void); -int gpg_apdu_verify(void) ; -int gpg_apdu_change_ref_data(void) ; -int gpg_apdu_reset_retry_counter(void) ; +int gpg_apdu_verify(void); +int gpg_apdu_change_ref_data(void); +int gpg_apdu_reset_retry_counter(void); gpg_pin_t *gpg_pin_get_pin(int id); -int gpg_pin_is_blocked(gpg_pin_t *pin); -int gpg_pin_is_verified(int pinID); -int gpg_pin_set_verified(int pinID, int verified); -int gpg_pin_check(gpg_pin_t *pin, int pinID,unsigned char *pin_val, unsigned int pin_len); -void gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len); +int gpg_pin_is_blocked(gpg_pin_t *pin); +int gpg_pin_is_verified(int pinID); +int gpg_pin_set_verified(int pinID, int verified); +int gpg_pin_check(gpg_pin_t *pin, int pinID, unsigned char *pin_val, unsigned int pin_len); +void gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len); -int gpg_mse_reset(); +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 ---- */ /* ----------------------------------------------------------------------- */ -void gpg_io_discard(int clear) ; +void gpg_io_discard(int clear); void gpg_io_clear(void); -void gpg_io_set_offset(unsigned int offset) ; -void gpg_io_mark(void) ; -void gpg_io_rewind(void) ; -void gpg_io_hole(unsigned int sz) ; +void gpg_io_set_offset(unsigned int offset); +void gpg_io_mark(void); +void gpg_io_rewind(void); +void gpg_io_hole(unsigned int sz); void gpg_io_inserted(unsigned int len); -void gpg_io_insert(unsigned char const * buffer, unsigned int len) ; -void gpg_io_insert_u32(unsigned int v32) ; -void gpg_io_insert_u24(unsigned int v24) ; -void gpg_io_insert_u16(unsigned int v16) ; -void gpg_io_insert_u8(unsigned int v8) ; -void gpg_io_insert_t(unsigned int T) ; -void gpg_io_insert_tl(unsigned int T, unsigned int L) ; -void gpg_io_insert_tlv(unsigned int T, unsigned int L, unsigned char const *V) ; - -void gpg_io_fetch_buffer(unsigned char * buffer, unsigned int len) ; -unsigned int gpg_io_fetch_u32(void) ; -unsigned int gpg_io_fetch_u24(void) ; -unsigned int gpg_io_fetch_u16(void) ; -unsigned int gpg_io_fetch_u8(void) ; -int gpg_io_fetch_t(unsigned int *T) ; -int gpg_io_fetch_l(unsigned int *L) ; -int gpg_io_fetch_tl(unsigned int *T, unsigned int *L) ; -int gpg_io_fetch_nv(unsigned char* buffer, int len) ; -int gpg_io_fetch(unsigned char* buffer, int len) ; - -int gpg_io_do(unsigned int io_flags) ; +void gpg_io_insert(unsigned char const *buffer, unsigned int len); +void gpg_io_insert_u32(unsigned int v32); +void gpg_io_insert_u24(unsigned int v24); +void gpg_io_insert_u16(unsigned int v16); +void gpg_io_insert_u8(unsigned int v8); +void gpg_io_insert_t(unsigned int T); +void gpg_io_insert_tl(unsigned int T, unsigned int L); +void gpg_io_insert_tlv(unsigned int T, unsigned int L, unsigned char const *V); + +void gpg_io_fetch_buffer(unsigned char *buffer, unsigned int len); +unsigned int gpg_io_fetch_u32(void); +unsigned int gpg_io_fetch_u24(void); +unsigned int gpg_io_fetch_u16(void); +unsigned int gpg_io_fetch_u8(void); +int gpg_io_fetch_t(unsigned int *T); +int gpg_io_fetch_l(unsigned int *L); +int gpg_io_fetch_tl(unsigned int *T, unsigned int *L); +int gpg_io_fetch_nv(unsigned char *buffer, int len); +int gpg_io_fetch(unsigned char *buffer, int len); + +int gpg_io_do(unsigned int io_flags); /* ----------------------------------------------------------------------- */ /* --- TMP ---- */ @@ -99,12 +110,12 @@ void io_usb_ccid_set_card_inserted(unsigned int inserted); /* --- DEBUG ---- */ /* ----------------------------------------------------------------------- */ #ifdef GPG_DEBUG - +#error "UNSUPPORTDED: to be fixed" #include "gpg_debug.h" #else -#define gpg_nvm_write nvm_write +#define gpg_nvm_write nvm_write #define gpg_io_exchange io_exchange #endif diff --git a/src/gpg_challenge.c b/src/gpg_challenge.c index 7144574..2b92e94 100644 --- a/src/gpg_challenge.c +++ b/src/gpg_challenge.c @@ -20,10 +20,10 @@ #include "gpg_vars.h" int gpg_apdu_get_challenge() { - unsigned int olen,hlen; + unsigned int olen, hlen; - if ((G_gpg_vstate.io_p1&0x80) == 0x80) { - olen = G_gpg_vstate.io_p2; + if ((G_gpg_vstate.io_p1 & 0x80) == 0x80) { + olen = G_gpg_vstate.io_p2; } else { olen = G_gpg_vstate.io_le; } @@ -31,36 +31,36 @@ int gpg_apdu_get_challenge() { THROW(SW_WRONG_LENGTH); return SW_WRONG_LENGTH; } - - if ((G_gpg_vstate.io_p1&0x82) == 0x82) { - unsigned int path[2]; - unsigned char chain[32]; - unsigned char Sr[32]; - os_memset(chain, 0, 32); + if ((G_gpg_vstate.io_p1 & 0x82) == 0x82) { + unsigned int path[2]; + unsigned char chain[32]; + unsigned char Sr[32]; + + os_memset(chain, 0, 32); 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'; + os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 2, Sr, chain); + chain[0] = 'r'; + chain[1] = 'n'; + chain[2] = 'd'; - cx_sha256_init(&G_gpg_vstate.work.md.sha256); + cx_sha256_init(&G_gpg_vstate.work.md.sha256); cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256, 0, Sr, 32, NULL, 0); cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256, 0, 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, - G_gpg_vstate.work.io_buffer,olen); + 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); } - if ((G_gpg_vstate.io_p1&0x81) == 0x81) { - cx_math_next_prime(G_gpg_vstate.work.io_buffer,olen); - } + if ((G_gpg_vstate.io_p1 & 0x81) == 0x81) { + cx_math_next_prime(G_gpg_vstate.work.io_buffer, olen); + } gpg_io_discard(0); gpg_io_inserted(olen); return SW_OK; diff --git a/src/gpg_data.c b/src/gpg_data.c index d2f9927..d47b790 100644 --- a/src/gpg_data.c +++ b/src/gpg_data.c @@ -19,22 +19,20 @@ #include "gpg_api.h" #include "gpg_vars.h" -int gpg_apdu_select_data(unsigned int ref, int reccord) { - G_gpg_vstate.DO_current = ref; - G_gpg_vstate.DO_reccord = reccord; - G_gpg_vstate.DO_offset = 0; +int gpg_apdu_select_data(unsigned int ref, int reccord) { + G_gpg_vstate.DO_current = ref; + G_gpg_vstate.DO_reccord = reccord; + G_gpg_vstate.DO_offset = 0; return SW_OK; } -int gpg_apdu_get_data(unsigned int ref) { +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; - G_gpg_vstate.DO_offset = 0; + G_gpg_vstate.DO_offset = 0; } sw = SW_OK; @@ -54,11 +52,11 @@ int gpg_apdu_get_data(unsigned int ref) { gpg_io_insert(N_gpg_pstate->private_DO4.value, N_gpg_pstate->private_DO4.length); break; - /* ----------------- Config key slot ----------------- */ + /* ----------------- Config key slot ----------------- */ case 0x01F0: gpg_io_insert(N_gpg_pstate->config_slot, 3); gpg_io_insert_u8(G_gpg_vstate.slot); - break; + break; case 0x01F1: gpg_io_insert(N_gpg_pstate->config_slot, 3); break; @@ -67,10 +65,10 @@ int gpg_apdu_get_data(unsigned int ref) { break; /* ----------------- Config RSA exponent ----------------- */ case 0x01F8: - gpg_io_insert(N_gpg_pstate->default_RSA_exponent,4); + gpg_io_insert(N_gpg_pstate->default_RSA_exponent, 4); break; - /* ----------------- Application ----------------- */ + /* ----------------- Application ----------------- */ /* Full Application identifier */ case 0x004F: gpg_io_insert(N_gpg_pstate->AID, 10); @@ -97,28 +95,26 @@ int gpg_apdu_get_data(unsigned int ref) { break; /* Name, Language, Sex */ case 0x65: - gpg_io_insert_tlv(0x5B, N_gpg_pstate->name.length, N_gpg_pstate->name.value); + gpg_io_insert_tlv(0x5B, N_gpg_pstate->name.length, N_gpg_pstate->name.value); gpg_io_insert_tlv(0x5F2D, N_gpg_pstate->lang.length, N_gpg_pstate->lang.value); - gpg_io_insert_tlv(0x5F35, 1, N_gpg_pstate->sex); + gpg_io_insert_tlv(0x5F35, 1, N_gpg_pstate->sex); break; /* ----------------- aid, histo, ext_length, ... ----------------- */ case 0x6E: - gpg_io_insert_tlv(0x4F, 16, N_gpg_pstate->AID); - os_memmove(G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset-6, G_gpg_vstate.kslot->serial, 4); + gpg_io_insert_tlv(0x4F, 16, N_gpg_pstate->AID); + os_memmove(G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset - 6, G_gpg_vstate.kslot->serial, 4); gpg_io_insert_tlv(0x5F52, 15, N_gpg_pstate->histo); gpg_io_insert_tlv(0x7F66, sizeof(C_ext_length), C_ext_length); 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); gpg_io_insert_tl(0xC4, 7); - gpg_io_insert(N_gpg_pstate->PW_status,4); + gpg_io_insert(N_gpg_pstate->PW_status, 4); gpg_io_insert_u8(N_gpg_pstate->PW1.counter); gpg_io_insert_u8(N_gpg_pstate->RC.counter); gpg_io_insert_u8(N_gpg_pstate->PW3.counter); @@ -135,7 +131,7 @@ int gpg_apdu_get_data(unsigned int ref) { gpg_io_insert(G_gpg_vstate.kslot->dec.date, 4); gpg_io_insert(G_gpg_vstate.kslot->aut.date, 4); gpg_io_set_offset(IO_OFFSET_MARK); - gpg_io_insert_tl(0x73, G_gpg_vstate.io_length- G_gpg_vstate.io_offset); + gpg_io_insert_tl(0x73, G_gpg_vstate.io_length - G_gpg_vstate.io_offset); gpg_io_set_offset(IO_OFFSET_END); break; @@ -152,7 +148,7 @@ int gpg_apdu_get_data(unsigned int ref) { /* ----------------- Security support template ----------------- */ case 0x7A: - gpg_io_insert_tl(0x93,3); + gpg_io_insert_tl(0x93, 3); gpg_io_insert_u24(G_gpg_vstate.kslot->sig_count); break; @@ -160,22 +156,22 @@ int gpg_apdu_get_data(unsigned int ref) { case 0x7F21: switch (G_gpg_vstate.DO_reccord) { case 0: - gpg_io_insert(G_gpg_vstate.kslot->aut.CA.value,G_gpg_vstate.kslot->aut.CA.length); + gpg_io_insert(G_gpg_vstate.kslot->aut.CA.value, G_gpg_vstate.kslot->aut.CA.length); break; case 1: - gpg_io_insert(G_gpg_vstate.kslot->dec.CA.value,G_gpg_vstate.kslot->dec.CA.length); + gpg_io_insert(G_gpg_vstate.kslot->dec.CA.value, G_gpg_vstate.kslot->dec.CA.length); break; case 2: - gpg_io_insert(G_gpg_vstate.kslot->sig.CA.value,G_gpg_vstate.kslot->sig.CA.length); + gpg_io_insert(G_gpg_vstate.kslot->sig.CA.value, G_gpg_vstate.kslot->sig.CA.length); break; - default : + default: sw = SW_RECORD_NOT_FOUND; } break; /* ----------------- PW Status Bytes ----------------- */ case 0x00C4: - gpg_io_insert(N_gpg_pstate->PW_status,4); + gpg_io_insert(N_gpg_pstate->PW_status, 4); gpg_io_insert_u8(N_gpg_pstate->PW1.counter); gpg_io_insert_u8(N_gpg_pstate->RC.counter); gpg_io_insert_u8(N_gpg_pstate->PW3.counter); @@ -190,7 +186,7 @@ int gpg_apdu_get_data(unsigned int ref) { return sw; } -int gpg_apdu_get_next_data(unsigned int ref) { +int gpg_apdu_get_next_data(unsigned int ref) { int sw; if ((ref != 0x7F21) || (G_gpg_vstate.DO_current != 0x7F21)) { @@ -204,15 +200,15 @@ int gpg_apdu_get_next_data(unsigned int ref) { } int gpg_apdu_put_data(unsigned int ref) { - unsigned int t,l,sw; - unsigned int *ptr_l; - unsigned char *ptr_v; + unsigned int t, l, sw; + unsigned int * ptr_l; + unsigned char *ptr_v; G_gpg_vstate.DO_current = ref; - sw = SW_OK; + sw = SW_OK; switch (ref) { - /* ----------------- Optional DO for private use ----------------- */ + /* ----------------- Optional DO for private use ----------------- */ case 0x0101: ptr_l = &N_gpg_pstate->private_DO1.length; ptr_v = N_gpg_pstate->private_DO1.value; @@ -234,7 +230,7 @@ int gpg_apdu_put_data(unsigned int ref) { THROW(SW_WRONG_LENGTH); return 0; } - gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, G_gpg_vstate.io_length); + gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, G_gpg_vstate.io_length); gpg_nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int)); sw = SW_OK; break; @@ -244,23 +240,22 @@ int gpg_apdu_put_data(unsigned int ref) { THROW(SW_WRONG_LENGTH); return 0; } - if ((G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset +0] != GPG_KEYS_SLOTS) || - (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset +1] >= GPG_KEYS_SLOTS) || - (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset +2] > 3)) { - THROW(SW_WRONG_DATA); + if ((G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] != GPG_KEYS_SLOTS) || + (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 1] >= GPG_KEYS_SLOTS) || + (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 2] > 3)) { + THROW(SW_WRONG_DATA); return 0; } - gpg_nvm_write(N_gpg_pstate->config_slot, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,3); + gpg_nvm_write(N_gpg_pstate->config_slot, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, 3); break; - + case 0x01F2: if ((N_gpg_pstate->config_slot[2] & 2) == 0) { 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)) { - THROW(SW_WRONG_DATA); + } + 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; } G_gpg_vstate.slot = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset]; @@ -272,12 +267,11 @@ int gpg_apdu_put_data(unsigned int ref) { if (G_gpg_vstate.io_length != 4) { THROW(SW_WRONG_LENGTH); return 0; - } - e = gpg_io_fetch_u32(); + } + e = gpg_io_fetch_u32(); nvm_write(&N_gpg_pstate->default_RSA_exponent, &e, sizeof(unsigned int)); break; } - /* ----------------- Serial -----------------*/ case 0x4f: @@ -289,46 +283,48 @@ int gpg_apdu_put_data(unsigned int ref) { /* ----------------- Extended Header list -----------------*/ case 0x3FFF: { - unsigned int len_e,len_p,len_q; - unsigned int endof,ksz,reset_cnt; - gpg_key_t *keygpg; - unsigned int dh; - //fecth 4D - gpg_io_fetch_tl(&t,&l); - if (t!=0x4D) { + unsigned int len_e, len_p, len_q; + unsigned int endof, ksz, reset_cnt; + gpg_key_t * keygpg; + unsigned int dh; + // fecth 4D + gpg_io_fetch_tl(&t, &l); + if (t != 0x4D) { THROW(SW_REFERENCED_DATA_NOT_FOUND); return 0; } - //fecth B8/B6/A4 - gpg_io_fetch_tl(&t,&l); - dh = 0; + // fecth B8/B6/A4 + gpg_io_fetch_tl(&t, &l); + dh = 0; reset_cnt = 0; - switch(t) { + switch (t) { case 0xB6: - keygpg = &G_gpg_vstate.kslot->sig; + keygpg = &G_gpg_vstate.kslot->sig; reset_cnt = 0x11111111; break; case 0xA4: - keygpg = &G_gpg_vstate.kslot->aut; + keygpg = &G_gpg_vstate.kslot->aut; break; case 0xB8: - keygpg = &G_gpg_vstate.kslot->dec; - dh = 0x11; + keygpg = &G_gpg_vstate.kslot->dec; + dh = 0x11; break; default: THROW(SW_REFERENCED_DATA_NOT_FOUND); return 0; } - //fecth 7f78 - gpg_io_fetch_tl(&t,&l); - if (t!=0x7f48) { + // fecth 7f78 + gpg_io_fetch_tl(&t, &l); + if (t != 0x7f48) { THROW(SW_REFERENCED_DATA_NOT_FOUND); return 0; } - len_e = 0; len_p = 0; len_q = 0; - endof = G_gpg_vstate.io_offset+l; - while (G_gpg_vstate.io_offsetattributes.value[0] == 0x01) { - unsigned int e; - unsigned char *p,*q,*pq; - cx_rsa_public_key_t *rsa_pub; + unsigned int e; + unsigned char * p, *q, *pq; + cx_rsa_public_key_t * rsa_pub; cx_rsa_private_key_t *rsa_priv, *pkey; - unsigned int pkey_size; - //check length - ksz = (keygpg->attributes.value[1]<<8)|keygpg->attributes.value[2]; - ksz = ksz >> 3; - rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa.public; - rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa.private; - pkey = &keygpg->priv_key.rsa; - switch(ksz) { - case 1024/8: + unsigned int pkey_size; + // check length + ksz = (keygpg->attributes.value[1] << 8) | keygpg->attributes.value[2]; + ksz = ksz >> 3; + rsa_pub = (cx_rsa_public_key_t *)&G_gpg_vstate.work.rsa.public; + rsa_priv = (cx_rsa_private_key_t *)&G_gpg_vstate.work.rsa.private; + pkey = &keygpg->priv_key.rsa; + switch (ksz) { + case 1024 / 8: pkey_size = sizeof(cx_rsa_1024_private_key_t); - pq = G_gpg_vstate.work.rsa.public1024.n; + pq = G_gpg_vstate.work.rsa.public1024.n; break; - case 2048/8: + case 2048 / 8: pkey_size = sizeof(cx_rsa_2048_private_key_t); - pq = G_gpg_vstate.work.rsa.public2048.n; + pq = G_gpg_vstate.work.rsa.public2048.n; break; - case 3072/8: + case 3072 / 8: pkey_size = sizeof(cx_rsa_3072_private_key_t); - pq = G_gpg_vstate.work.rsa.public3072.n; + pq = G_gpg_vstate.work.rsa.public3072.n; break; - case 4096/8: + case 4096 / 8: pkey_size = sizeof(cx_rsa_4096_private_key_t); - pq = G_gpg_vstate.work.rsa.public4096.n; + pq = G_gpg_vstate.work.rsa.public4096.n; break; } - ksz = ksz>>1; - - - //fetch e + ksz = ksz >> 1; + + // fetch e e = 0; - switch(len_e) { + switch (len_e) { case 4: e = gpg_io_fetch_u32(); break; @@ -404,65 +399,64 @@ int gpg_apdu_put_data(unsigned int ref) { case 2: e = gpg_io_fetch_u16(); break; - case 1: + case 1: e = gpg_io_fetch_u8(); break; default: THROW(SW_WRONG_DATA); - return 0; + return 0; } - //move p,q over pub key, this only work because adr < adr

- if ( (len_p > ksz )|| (len_q > ksz)) { + // move p,q over pub key, this only work because adr < adr

+ if ((len_p > ksz) || (len_q > ksz)) { THROW(SW_WRONG_DATA); return 0; } p = G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset; q = p + len_p; - os_memmove(pq+ksz-len_p, p, len_p); - os_memset(pq, 0, ksz-len_p); - os_memmove(pq+2*ksz-len_q, q, len_q); - os_memset(pq+ksz, 0, ksz-len_q); - - //regenerate RSA private key + os_memmove(pq + ksz - len_p, p, len_p); + os_memset(pq, 0, ksz - len_p); + os_memmove(pq + 2 * ksz - len_q, q, len_q); + os_memset(pq + ksz, 0, ksz - len_q); + + // regenerate RSA private key unsigned char _e[4]; - _e[0] = e>>24; - _e[1] = e>>16; - _e[2] = e>>8; - _e[3] = e>>0; - cx_rsa_generate_pair(ksz<<1, rsa_pub, rsa_priv, _e, 4, pq); + _e[0] = e >> 24; + _e[1] = e >> 16; + _e[2] = e >> 8; + _e[3] = e >> 0; + cx_rsa_generate_pair(ksz << 1, rsa_pub, rsa_priv, _e, 4, pq); - //write keys + // write keys nvm_write(&keygpg->pub_key.rsa, rsa_pub->e, 4); nvm_write(pkey, rsa_priv, pkey_size); if (reset_cnt) { reset_cnt = 0; - nvm_write(&G_gpg_vstate.kslot->sig_count,&reset_cnt,sizeof(unsigned int)); + nvm_write(&G_gpg_vstate.kslot->sig_count, &reset_cnt, sizeof(unsigned int)); } } // --- ECC KEY --- - else if ((keygpg->attributes.value[0] == 19) || - (keygpg->attributes.value[0] == 18) || - (keygpg->attributes.value[0] == 22) ) { + else if ((keygpg->attributes.value[0] == 19) || (keygpg->attributes.value[0] == 18) || + (keygpg->attributes.value[0] == 22)) { unsigned int curve; - ksz = 0; - curve = gpg_oid2curve(&keygpg->attributes.value[1], keygpg->attributes.length-1); + ksz = 0; + curve = gpg_oid2curve(&keygpg->attributes.value[1], keygpg->attributes.length - 1); if (curve == 0) { - THROW(SW_WRONG_DATA); - return 0; + THROW(SW_WRONG_DATA); + return 0; } ksz = gpg_curve2domainlen(curve); if (ksz == len_p) { G_gpg_vstate.work.ecfp.private.curve = curve; G_gpg_vstate.work.ecfp.private.d_len = ksz; - os_memmove(G_gpg_vstate.work.ecfp.private.d, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,ksz); + os_memmove(G_gpg_vstate.work.ecfp.private.d, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, ksz); cx_ecfp_generate_pair(curve, &G_gpg_vstate.work.ecfp.public, &G_gpg_vstate.work.ecfp.private, 1); - nvm_write(&keygpg->pub_key.ecfp, &G_gpg_vstate.work.ecfp.public, sizeof(cx_ecfp_public_key_t)); - nvm_write(&keygpg->priv_key.ecfp, &G_gpg_vstate.work.ecfp.private, sizeof(cx_ecfp_private_key_t)); + nvm_write(&keygpg->pub_key.ecfp, &G_gpg_vstate.work.ecfp.public, sizeof(cx_ecfp_public_key_t)); + nvm_write(&keygpg->priv_key.ecfp, &G_gpg_vstate.work.ecfp.private, sizeof(cx_ecfp_private_key_t)); if (reset_cnt) { reset_cnt = 0; - nvm_write(&G_gpg_vstate.kslot->sig_count,&reset_cnt,sizeof(unsigned int)); + nvm_write(&G_gpg_vstate.kslot->sig_count, &reset_cnt, sizeof(unsigned int)); } } @@ -473,10 +467,9 @@ int gpg_apdu_put_data(unsigned int ref) { return 0; } break; - } //endof of 3fff - + } // endof of 3fff - /* ----------------- User -----------------*/ + /* ----------------- User -----------------*/ /* Name */ case 0x5B: if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->name.value)) { @@ -495,7 +488,7 @@ int gpg_apdu_put_data(unsigned int ref) { gpg_nvm_write(N_gpg_pstate->login.value, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length); gpg_nvm_write(&N_gpg_pstate->login.length, &G_gpg_vstate.io_length, sizeof(unsigned int)); break; - /* Language preferences */ + /* Language preferences */ case 0x5F2D: if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->lang.value)) { THROW(SW_WRONG_LENGTH); @@ -514,7 +507,7 @@ int gpg_apdu_put_data(unsigned int ref) { break; /* Uniform resource locator */ case 0x5F50: - if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->url.value)) { + if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->url.value)) { THROW(SW_WRONG_LENGTH); return 0; } @@ -524,26 +517,26 @@ int gpg_apdu_put_data(unsigned int ref) { /* ----------------- Cardholder certificate ----------------- */ case 0x7F21: - ptr_v = NULL; - switch ( G_gpg_vstate.DO_reccord) { - case 0: - ptr_l = &G_gpg_vstate.kslot->aut.CA.length; - ptr_v = G_gpg_vstate.kslot->aut.CA.value; - goto WRITE_CA; - case 1: - ptr_l = &G_gpg_vstate.kslot->sig.CA.length; - ptr_v = G_gpg_vstate.kslot->sig.CA.value; - goto WRITE_CA; - case 2: - ptr_l = &G_gpg_vstate.kslot->dec.CA.length; - ptr_v = G_gpg_vstate.kslot->dec.CA.value; - goto WRITE_CA; - default: - THROW(SW_REFERENCED_DATA_NOT_FOUND); + ptr_v = NULL; + switch (G_gpg_vstate.DO_reccord) { + case 0: + ptr_l = &G_gpg_vstate.kslot->aut.CA.length; + ptr_v = G_gpg_vstate.kslot->aut.CA.value; + goto WRITE_CA; + case 1: + ptr_l = &G_gpg_vstate.kslot->sig.CA.length; + ptr_v = G_gpg_vstate.kslot->sig.CA.value; + goto WRITE_CA; + case 2: + ptr_l = &G_gpg_vstate.kslot->dec.CA.length; + ptr_v = G_gpg_vstate.kslot->dec.CA.value; + goto WRITE_CA; + default: + THROW(SW_REFERENCED_DATA_NOT_FOUND); return 0; - } - WRITE_CA: - if (G_gpg_vstate.io_length > GPG_EXT_CARD_HOLDER_CERT_LENTH) { + } + WRITE_CA: + if (G_gpg_vstate.io_length > GPG_EXT_CARD_HOLDER_CERT_LENTH) { THROW(SW_WRONG_LENGTH); } gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length); @@ -564,7 +557,7 @@ int gpg_apdu_put_data(unsigned int ref) { ptr_v = G_gpg_vstate.kslot->aut.attributes.value; goto WRITE_ATTRIBUTES; WRITE_ATTRIBUTES: - if (G_gpg_vstate.io_length > 12) { + if (G_gpg_vstate.io_length > 12) { THROW(SW_WRONG_LENGTH); return 0; } @@ -585,7 +578,7 @@ int gpg_apdu_put_data(unsigned int ref) { ptr_v = G_gpg_vstate.kslot->dec.fingerprints; goto WRITE_FINGERPRINTS; case 0xC9: - ptr_v =G_gpg_vstate.kslot->aut.fingerprints; + ptr_v = G_gpg_vstate.kslot->aut.fingerprints; goto WRITE_FINGERPRINTS; case 0xCA: ptr_v = G_gpg_vstate.kslot->sig.CA_fingerprints; @@ -624,30 +617,29 @@ int gpg_apdu_put_data(unsigned int ref) { /* ----------------- AES key ----------------- */ { - void *pkey; - cx_aes_key_t aes_key; - case 0xD1: - pkey = &N_gpg_pstate->SM_enc; - goto init_aes_key; - case 0xD2: - pkey = &N_gpg_pstate->SM_mac; - goto init_aes_key; - case 0xD5: - pkey = &G_gpg_vstate.kslot->AES_dec; - goto init_aes_key; - init_aes_key: - cx_aes_init_key(G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length, &aes_key); - gpg_nvm_write(pkey, &aes_key, sizeof(cx_aes_key_t)); - break; - + void * pkey; + cx_aes_key_t aes_key; + case 0xD1: + pkey = &N_gpg_pstate->SM_enc; + goto init_aes_key; + case 0xD2: + pkey = &N_gpg_pstate->SM_mac; + goto init_aes_key; + case 0xD5: + pkey = &G_gpg_vstate.kslot->AES_dec; + goto init_aes_key; + init_aes_key: + cx_aes_init_key(G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length, &aes_key); + 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); - gpg_nvm_write(&N_gpg_pstate->SM_enc, &aes_key, sizeof(cx_aes_key_t)); - cx_aes_init_key(G_gpg_vstate.work.io_buffer+16, G_gpg_vstate.io_length, &aes_key); - gpg_nvm_write(&N_gpg_pstate->SM_mac, &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); + gpg_nvm_write(&N_gpg_pstate->SM_enc, &aes_key, sizeof(cx_aes_key_t)); + cx_aes_init_key(G_gpg_vstate.work.io_buffer + 16, G_gpg_vstate.io_length, &aes_key); + gpg_nvm_write(&N_gpg_pstate->SM_mac, &aes_key, sizeof(cx_aes_key_t)); + break; } /* ----------------- RC ----------------- */ @@ -658,20 +650,16 @@ 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; + sw = SW_OK; break; } - + /* ----------------- UIF ----------------- */ case 0xD6: ptr_v = G_gpg_vstate.kslot->sig.UIF; @@ -679,10 +667,10 @@ int gpg_apdu_put_data(unsigned int ref) { case 0xD7: ptr_v = G_gpg_vstate.kslot->dec.UIF; goto WRITE_UIF; - case 0xD8: + case 0xD8: ptr_v = G_gpg_vstate.kslot->aut.UIF; - goto WRITE_UIF; - WRITE_UIF: + goto WRITE_UIF; + WRITE_UIF: if (G_gpg_vstate.io_length != 2) { THROW(SW_WRONG_LENGTH); return 0; @@ -690,7 +678,7 @@ int gpg_apdu_put_data(unsigned int ref) { gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, 2); break; - /* ----------------- WAT ----------------- */ + /* ----------------- WAT ----------------- */ default: sw = SW_REFERENCED_DATA_NOT_FOUND; break; @@ -698,27 +686,25 @@ int gpg_apdu_put_data(unsigned int ref) { gpg_io_discard(1); return sw; - - } static void gpg_init_keyenc(cx_aes_key_t *keyenc) { unsigned char seed[32]; gpg_pso_derive_slot_seed(G_gpg_vstate.slot, seed); - gpg_pso_derive_key_seed(seed, (unsigned char*)PIC("key "), 1, seed, 16); + gpg_pso_derive_key_seed(seed, (unsigned char *)PIC("key "), 1, seed, 16); cx_aes_init_key(seed, 16, keyenc); } -//cmd -//resp TID API COMPAT len_pub len_priv priv +// cmd +// resp TID API COMPAT len_pub len_priv priv int gpg_apdu_get_key_data(unsigned int ref) { cx_aes_key_t keyenc; - gpg_key_t *keygpg; + gpg_key_t * keygpg; unsigned int len = 0; gpg_init_keyenc(&keyenc); - - switch(ref) { + + switch (ref) { case 0x00B6: keygpg = &G_gpg_vstate.kslot->sig; break; @@ -734,43 +720,40 @@ int gpg_apdu_get_key_data(unsigned int ref) { } gpg_io_discard(1); - //clear part + // clear part 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 - //insert pubkey; + // encrypted part + switch (keygpg->attributes.value[0]) { + case 0x01: // RSA + // insert pubkey; gpg_io_insert_u32(4); gpg_io_insert(keygpg->pub_key.rsa, 4); - //insert privkey + // insert privkey gpg_io_mark(); - 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); + 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); gpg_io_set_offset(IO_OFFSET_MARK); gpg_io_insert_u32(len); gpg_io_set_offset(IO_OFFSET_END); break; - case 18: //ECC + case 18: // ECC case 19: case 22: - //insert pubkey; + // insert pubkey; gpg_io_insert_u32(sizeof(cx_ecfp_640_public_key_t)); - gpg_io_insert((unsigned char*)&keygpg->pub_key.ecfp640, sizeof(cx_ecfp_640_public_key_t)); + gpg_io_insert((unsigned char *)&keygpg->pub_key.ecfp640, sizeof(cx_ecfp_640_public_key_t)); - //insert privkey + // insert privkey gpg_io_mark(); - 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); + 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); gpg_io_set_offset(IO_OFFSET_MARK); gpg_io_insert_u32(len); @@ -778,23 +761,22 @@ int gpg_apdu_get_key_data(unsigned int ref) { break; default: - THROW(SW_REFERENCED_DATA_NOT_FOUND); - return SW_REFERENCED_DATA_NOT_FOUND; + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return SW_REFERENCED_DATA_NOT_FOUND; } return SW_OK; } -//cmd TID API COMPAT len_pub len_priv priv -//resp - +// cmd TID API COMPAT len_pub len_priv priv +// resp - int gpg_apdu_put_key_data(unsigned int ref) { cx_aes_key_t keyenc; - gpg_key_t *keygpg; + gpg_key_t * keygpg; unsigned int len; unsigned int offset; - gpg_init_keyenc(&keyenc); - switch(ref) { + switch (ref) { case 0xB6: keygpg = &G_gpg_vstate.kslot->sig; break; @@ -809,16 +791,17 @@ int gpg_apdu_put_key_data(unsigned int ref) { return SW_WRONG_DATA; } - /* unsigned int target_id = */ + /* unsigned int target_id = */ gpg_io_fetch_u32(); /* unsigned int cx_apilevel = */ gpg_io_fetch_u32(); /* unsigned int cx_compat_apilevel = */ gpg_io_fetch_u32(); - switch(keygpg->attributes.value[0]) { - case 0x01: //RSA - //insert pubkey; + switch (keygpg->attributes.value[0]) { + // RSA + case 0x01: + // insert pubkey; len = gpg_io_fetch_u32(); if (len != 4) { THROW(SW_WRONG_DATA); @@ -826,55 +809,53 @@ int gpg_apdu_put_key_data(unsigned int ref) { } gpg_io_fetch_nv(keygpg->pub_key.rsa, len); - //insert privkey + // insert privkey len = gpg_io_fetch_u32(); - if (len > (G_gpg_vstate.io_length-G_gpg_vstate.io_offset)) { + if (len > (G_gpg_vstate.io_length - G_gpg_vstate.io_offset)) { THROW(SW_WRONG_DATA); } 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); + THROW(SW_WRONG_DATA); } - gpg_nvm_write((unsigned char*)&keygpg->priv_key.rsa4096, G_gpg_vstate.work.io_buffer, len); + gpg_nvm_write((unsigned char *)&keygpg->priv_key.rsa4096, G_gpg_vstate.work.io_buffer, len); break; - case 18: //ECC - case 19: - case 22: - //insert pubkey; + // 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)) { THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } - gpg_io_fetch_nv((unsigned char*)&keygpg->pub_key.ecfp640, len); + gpg_io_fetch_nv((unsigned char *)&keygpg->pub_key.ecfp640, len); - //insert privkey + // insert privkey len = gpg_io_fetch_u32(); - if (len > (G_gpg_vstate.io_length-G_gpg_vstate.io_offset)) { + if (len > (G_gpg_vstate.io_length - G_gpg_vstate.io_offset)) { THROW(SW_WRONG_DATA); } 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; + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } - gpg_nvm_write((unsigned char*)&keygpg->priv_key.ecfp640, G_gpg_vstate.work.io_buffer, len); + gpg_nvm_write((unsigned char *)&keygpg->priv_key.ecfp640, G_gpg_vstate.work.io_buffer, len); break; default: - THROW(SW_REFERENCED_DATA_NOT_FOUND); - return SW_REFERENCED_DATA_NOT_FOUND; + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return SW_REFERENCED_DATA_NOT_FOUND; } gpg_io_discard(1); return SW_OK; diff --git a/src/gpg_dispatch.c b/src/gpg_dispatch.c index 356b87f..7c61990 100644 --- a/src/gpg_dispatch.c +++ b/src/gpg_dispatch.c @@ -19,12 +19,10 @@ #include "gpg_api.h" #include "gpg_vars.h" - - void gpg_check_access_ins() { unsigned int ref; - - ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ; + + ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; switch (G_gpg_vstate.io_ins) { case INS_EXIT: @@ -42,7 +40,7 @@ void gpg_check_access_ins() { case INS_VERIFY: return; - case INS_CHANGE_REFERENCE_DATA: + case INS_CHANGE_REFERENCE_DATA: return; case INS_RESET_RETRY_COUNTER: @@ -61,22 +59,22 @@ void gpg_check_access_ins() { } if (gpg_pin_is_verified(PIN_ID_PW3)) { return; - } + } break; - + case INS_MSE: - return ; + return; case INS_PSO: if ((ref == 0x9e9a) && gpg_pin_is_verified(PIN_ID_PW1)) { - //pso:sign + // pso:sign if (N_gpg_pstate->PW_status[0] == 0) { gpg_pin_set_verified(PIN_ID_PW1, 0); } return; } - if (((ref == 0x8086 )||(ref == 0x8680)) && gpg_pin_is_verified(PIN_ID_PW2)) { - //pso:dec/enc + if (((ref == 0x8086) || (ref == 0x8680)) && gpg_pin_is_verified(PIN_ID_PW2)) { + // pso:dec/enc return; } break; @@ -85,7 +83,7 @@ void gpg_check_access_ins() { if (gpg_pin_is_verified(PIN_ID_PW2)) { return; } - break; + break; case INS_GET_CHALLENGE: return; @@ -108,11 +106,11 @@ void gpg_check_access_ins() { void gpg_check_access_read_DO() { unsigned int ref; - - ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ; - switch(ref) { - //ALWAYS + ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; + + switch (ref) { + // ALWAYS case 0x0101: case 0x0102: case 0x01F0: @@ -155,23 +153,23 @@ void gpg_check_access_read_DO() { case 0x00D8: return; - //PW2 + // PW2 case 0x0103: if (gpg_pin_is_verified(PIN_ID_PW2)) { return; } break; - //PW3 + // PW3 case 0x00B6: case 0x00A4: case 0x00B8: case 0x0104: - if (gpg_pin_is_verified(PIN_ID_PW3)) { + if (gpg_pin_is_verified(PIN_ID_PW3)) { return; } break; - } + } THROW(SW_CONDITIONS_NOT_SATISFIED); } @@ -180,24 +178,24 @@ char debugbuff[5]; void gpg_check_access_write_DO() { unsigned int ref; - gpg_pin_t *pin_pw2, *pin_pw3; + gpg_pin_t * pin_pw2, *pin_pw3; pin_pw2 = gpg_pin_get_pin(PIN_ID_PW2); pin_pw3 = gpg_pin_get_pin(PIN_ID_PW3); - ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ; + ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; - switch(ref) { - //PW2 + switch (ref) { + // PW2 case 0x0101: - case 0x0103: + case 0x0103: case 0x01F2: if (gpg_pin_is_verified(PIN_ID_PW2)) { return; } break; - - //PW3 - case 0x3FFF: //only used for putkey under PW3 control + + // PW3 + case 0x3FFF: // only used for putkey under PW3 control case 0x4f: case 0x0102: case 0x0104: @@ -240,26 +238,22 @@ void gpg_check_access_write_DO() { if (gpg_pin_is_verified(PIN_ID_PW3)) { return; } - break; - } + break; + } THROW(SW_CONDITIONS_NOT_SATISFIED); } - - /* assume command is fully received */ int gpg_dispatch() { - unsigned int tag,t,l; - int sw; + 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; } - tag = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ; + tag = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; switch (G_gpg_vstate.io_ins) { /* --- SELECT --- */ @@ -274,21 +268,20 @@ int gpg_dispatch() { if (N_gpg_pstate->histo[7] == STATE_TERMINATE) { gpg_install(STATE_ACTIVATE); } - return(SW_OK); + return (SW_OK); break; case INS_TERMINATE_DF: gpg_io_discard(0); if (gpg_pin_is_verified(PIN_ID_PW3) || (N_gpg_pstate->PW3.counter == 0)) { gpg_install(STATE_TERMINATE); - return(SW_OK); + return (SW_OK); break; } THROW(SW_CONDITIONS_NOT_SATISFIED); 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(); @@ -322,19 +313,19 @@ int gpg_dispatch() { if ((G_gpg_vstate.io_p1 > 2) || (G_gpg_vstate.io_p2 != 0x04)) { THROW(SW_WRONG_P1P2); } - gpg_io_fetch_tl(&t,&l); + gpg_io_fetch_tl(&t, &l); if (t != 0x60) { - //TODO add l check + // TODO add l check THROW(SW_DATA_INVALID); } - gpg_io_fetch_tl(&t,&l); + gpg_io_fetch_tl(&t, &l); if (t != 0x5C) { - //TODO add l check + // TODO add l check THROW(SW_WRONG_DATA); } if (l == 1) { tag = gpg_io_fetch_u8(); - } else if (l == 2) { + } else if (l == 2) { tag = gpg_io_fetch_u16(); } else { THROW(SW_WRONG_DATA); @@ -344,10 +335,10 @@ int gpg_dispatch() { case INS_GET_DATA: gpg_check_access_read_DO(); - switch(tag) { - case 0x00B6: - case 0x00A4: - case 0x00B8: + switch (tag) { + case 0x00B6: + case 0x00A4: + case 0x00B8: sw = gpg_apdu_get_key_data(tag); break; default: @@ -361,14 +352,13 @@ int gpg_dispatch() { sw = gpg_apdu_get_next_data(tag); break; - - case INS_PUT_DATA_ODD: - case INS_PUT_DATA: + case INS_PUT_DATA_ODD: + case INS_PUT_DATA: gpg_check_access_write_DO(); - switch(tag) { - case 0x00B6: - case 0x00A4: - case 0x00B8: + switch (tag) { + case 0x00B6: + case 0x00A4: + case 0x00B8: sw = gpg_apdu_put_key_data(tag); break; default: @@ -379,55 +369,47 @@ 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) - ) { - sw = gpg_apdu_change_ref_data(); - break; - } - THROW(SW_INCORRECT_P1P2); + 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) ) - ) { - sw = gpg_apdu_reset_retry_counter(); - break; - } - THROW(SW_INCORRECT_P1P2); - - /* --- Key Management --- */ + 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; + } + THROW(SW_INCORRECT_P1P2); + + /* --- Key Management --- */ case INS_GEN_ASYM_KEYPAIR: - sw = gpg_apdu_gen(); - break; + sw = gpg_apdu_gen(); + break; - /* --- MSE --- */ + /* --- MSE --- */ case INS_MSE: - sw = gpg_apdu_mse(tag); - break; - - /* --- PSO --- */ + sw = gpg_apdu_mse(tag); + break; + + /* --- PSO --- */ case INS_PSO: - sw = gpg_apdu_pso(); - break; + sw = gpg_apdu_pso(); + break; case INS_INTERNAL_AUTHENTICATE: - sw = gpg_apdu_internal_authenticate(); - break; + sw = gpg_apdu_internal_authenticate(); + break; default: - THROW( SW_INS_NOT_SUPPORTED); + THROW(SW_INS_NOT_SUPPORTED); break; } diff --git a/src/gpg_gen.c b/src/gpg_gen.c index e10437c..2e618cf 100644 --- a/src/gpg_gen.c +++ b/src/gpg_gen.c @@ -22,15 +22,15 @@ /* @in slot slot num [0 ; GPG_KEYS_SLOTS[ * @out seed 32 bytes master seed for given slot */ -void gpg_pso_derive_slot_seed(int slot, unsigned char *seed) { - unsigned int path[2]; +void gpg_pso_derive_slot_seed(int slot, unsigned char *seed) { + unsigned int path[2]; unsigned char chain[32]; - os_memset(chain, 0, 32); + os_memset(chain, 0, 32); path[0] = 0x80475047; - path[1] = slot+1; - os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 2 , seed, chain); -} + path[1] = slot + 1; + os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 2, seed, chain); +} /* @in Sn master seed slot number * @in key_name key name: 'sig ', 'auth ', 'dec ' @@ -38,31 +38,37 @@ 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[0] = idx >> 8; h[1] = idx; cx_sha256_init(&G_gpg_vstate.work.md.sha256); - cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha256, 0, Sn, 32, NULL, 0); - cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha256, 0, (unsigned char *)key_name, 4, NULL, 0); - cx_hash((cx_hash_t*)&G_gpg_vstate.work.md.sha256, CX_LAST, h , 2, h,32); - + cx_hash((cx_hash_t *)&G_gpg_vstate.work.md.sha256, 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); + 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; - gpg_key_t *keygpg; - unsigned char seed[66]; - unsigned char* name; + unsigned int t, l, ksz, reset_cnt; + gpg_key_t * keygpg; + unsigned char seed[66]; + unsigned char *name; - switch ((G_gpg_vstate.io_p1<<8)|G_gpg_vstate.io_p2) { + switch ((G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2) { case 0x8000: case 0x8001: case 0x8100: @@ -72,76 +78,75 @@ int gpg_apdu_gen() { return SW_INCORRECT_P1P2; } - if (G_gpg_vstate.io_lc != 2){ + if (G_gpg_vstate.io_lc != 2) { THROW(SW_WRONG_LENGTH); return SW_WRONG_LENGTH; } - gpg_io_fetch_tl(&t,&l); + gpg_io_fetch_tl(&t, &l); gpg_io_discard(1); reset_cnt = 0; - switch(t) { + switch (t) { case 0xB6: - keygpg = &G_gpg_vstate.kslot->sig; - name = (unsigned char*)PIC("sig "); + keygpg = &G_gpg_vstate.kslot->sig; + name = (unsigned char *)PIC("sig "); reset_cnt = 0; break; case 0xA4: keygpg = &G_gpg_vstate.kslot->aut; - name = (unsigned char*)PIC("aut "); + name = (unsigned char *)PIC("aut "); break; case 0xB8: keygpg = &G_gpg_vstate.kslot->dec; - name = (unsigned char*)PIC("dec "); + name = (unsigned char *)PIC("dec "); break; default: THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } - switch ((G_gpg_vstate.io_p1<<8)|G_gpg_vstate.io_p2) { + switch ((G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2) { // -- generate keypair --- case 0x8000: case 0x8001: // RSA if (keygpg->attributes.value[0] == 0x01) { - - unsigned char *pq; - cx_rsa_public_key_t *rsa_pub; + unsigned char * pq; + cx_rsa_public_key_t * rsa_pub; cx_rsa_private_key_t *rsa_priv, *pkey; - unsigned int pkey_size; + unsigned int pkey_size; - ksz = (keygpg->attributes.value[1]<<8)|keygpg->attributes.value[2]; - ksz = ksz >> 3; - rsa_pub = (cx_rsa_public_key_t*)&G_gpg_vstate.work.rsa.public; - rsa_priv = (cx_rsa_private_key_t*)&G_gpg_vstate.work.rsa.private; - pkey = &keygpg->priv_key.rsa; - switch(ksz) { - case 1024/8: + ksz = (keygpg->attributes.value[1] << 8) | keygpg->attributes.value[2]; + ksz = ksz >> 3; + rsa_pub = (cx_rsa_public_key_t *)&G_gpg_vstate.work.rsa.public; + rsa_priv = (cx_rsa_private_key_t *)&G_gpg_vstate.work.rsa.private; + pkey = &keygpg->priv_key.rsa; + switch (ksz) { + case 1024 / 8: pkey_size = sizeof(cx_rsa_1024_private_key_t); break; - case 2048/8: + case 2048 / 8: pkey_size = sizeof(cx_rsa_2048_private_key_t); break; - case 3072/8: + case 3072 / 8: pkey_size = sizeof(cx_rsa_3072_private_key_t); break; - case 4096/8: + case 4096 / 8: pkey_size = sizeof(cx_rsa_4096_private_key_t); break; } pq = NULL; - if ((G_gpg_vstate.io_p2 == 0x01) || (G_gpg_vstate.seed_mode)){ - pq = &rsa_pub->n[0]; + if ((G_gpg_vstate.io_p2 == 0x01) || (G_gpg_vstate.seed_mode)) { + pq = &rsa_pub->n[0]; unsigned int size; - size = ksz>>1; + size = ksz >> 1; gpg_pso_derive_slot_seed(G_gpg_vstate.slot, seed); - gpg_pso_derive_key_seed(seed, name, 1, pq, size); - gpg_pso_derive_key_seed(seed, name, 2, pq+size, size); - *pq |= 0x80; - *(pq+size) |= 0x80; - cx_math_next_prime(pq,size); - cx_math_next_prime(pq+size,size); + gpg_pso_derive_key_seed(seed, name, 1, pq, size); + gpg_pso_derive_key_seed(seed, name, 2, pq + size, size); + *pq |= 0x80; + *(pq + size) |= 0x80; + cx_math_next_prime(pq, size); + cx_math_next_prime(pq + size, size); } cx_rsa_generate_pair(ksz, rsa_pub, rsa_priv, N_gpg_pstate->default_RSA_exponent, 4, pq); @@ -150,41 +155,36 @@ int gpg_apdu_gen() { nvm_write(&keygpg->pub_key.rsa[0], rsa_pub->e, 4); if (reset_cnt) { reset_cnt = 0; - nvm_write(&G_gpg_vstate.kslot->sig_count,&reset_cnt,sizeof(unsigned int)); + nvm_write(&G_gpg_vstate.kslot->sig_count, &reset_cnt, sizeof(unsigned int)); } gpg_io_clear(); goto send_rsa_pub; - } // ECC - if ((keygpg->attributes.value[0] == 18) || - (keygpg->attributes.value[0] == 19) || - (keygpg->attributes.value[0] == 22) ){ - unsigned int curve,keepprivate; + if ((keygpg->attributes.value[0] == 18) || (keygpg->attributes.value[0] == 19) || + (keygpg->attributes.value[0] == 22)) { + unsigned int curve, keepprivate; keepprivate = 0; - curve = gpg_oid2curve(keygpg->attributes.value+1, keygpg->attributes.length-1); + curve = gpg_oid2curve(keygpg->attributes.value + 1, keygpg->attributes.length - 1); if (curve == CX_CURVE_NONE) { THROW(SW_REFERENCED_DATA_NOT_FOUND); return SW_REFERENCED_DATA_NOT_FOUND; } if ((G_gpg_vstate.io_p2 == 0x01) || (G_gpg_vstate.seed_mode)) { ksz = gpg_curve2domainlen(curve); - gpg_pso_derive_slot_seed(G_gpg_vstate.slot, seed); + gpg_pso_derive_slot_seed(G_gpg_vstate.slot, seed); gpg_pso_derive_key_seed(seed, name, 1, seed, ksz); - cx_ecfp_init_private_key(curve,seed, ksz, &G_gpg_vstate.work.ecfp.private); + cx_ecfp_init_private_key(curve, seed, ksz, &G_gpg_vstate.work.ecfp.private); keepprivate = 1; } - 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)); + 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) { reset_cnt = 0; - nvm_write(&G_gpg_vstate.kslot->sig_count,&reset_cnt,sizeof(unsigned int)); + nvm_write(&G_gpg_vstate.kslot->sig_count, &reset_cnt, sizeof(unsigned int)); } gpg_io_clear(); goto send_ecc_pub; @@ -197,88 +197,86 @@ int gpg_apdu_gen() { /// read RSA send_rsa_pub: gpg_io_discard(1); - //check length - ksz = (keygpg->attributes.value[1]<<8)|keygpg->attributes.value[2]; - ksz = ksz>>3; + // check length + ksz = (keygpg->attributes.value[1] << 8) | keygpg->attributes.value[2]; + ksz = ksz >> 3; gpg_io_mark(); - switch(ksz) { - case 1024/8: - if (keygpg->priv_key.rsa1024.size == 0) { - THROW (SW_REFERENCED_DATA_NOT_FOUND); - return SW_REFERENCED_DATA_NOT_FOUND; - } - gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->priv_key.rsa1024.n); - break; - case 2048/8: + switch (ksz) { + case 1024 / 8: + if (keygpg->priv_key.rsa1024.size == 0) { + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return SW_REFERENCED_DATA_NOT_FOUND; + } + gpg_io_insert_tlv(0x81, ksz, (unsigned char *)&keygpg->priv_key.rsa1024.n); + break; + case 2048 / 8: if (keygpg->priv_key.rsa2048.size == 0) { - THROW (SW_REFERENCED_DATA_NOT_FOUND); + THROW(SW_REFERENCED_DATA_NOT_FOUND); return SW_REFERENCED_DATA_NOT_FOUND; } - gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->priv_key.rsa2048.n); + gpg_io_insert_tlv(0x81, ksz, (unsigned char *)&keygpg->priv_key.rsa2048.n); break; - case 3072/8: + case 3072 / 8: if (keygpg->priv_key.rsa3072.size == 0) { - THROW (SW_REFERENCED_DATA_NOT_FOUND); + THROW(SW_REFERENCED_DATA_NOT_FOUND); return SW_REFERENCED_DATA_NOT_FOUND; } - gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->priv_key.rsa3072.n); + gpg_io_insert_tlv(0x81, ksz, (unsigned char *)&keygpg->priv_key.rsa3072.n); break; - case 4096/8: + case 4096 / 8: if (keygpg->priv_key.rsa4096.size == 0) { - THROW (SW_REFERENCED_DATA_NOT_FOUND); + THROW(SW_REFERENCED_DATA_NOT_FOUND); return SW_REFERENCED_DATA_NOT_FOUND; } - gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->priv_key.rsa4096.n); + gpg_io_insert_tlv(0x81, ksz, (unsigned char *)&keygpg->priv_key.rsa4096.n); break; } gpg_io_insert_tlv(0x82, 4, keygpg->pub_key.rsa); - + l = G_gpg_vstate.io_length; gpg_io_set_offset(IO_OFFSET_MARK); - gpg_io_insert_tl(0x7f49,l); + gpg_io_insert_tl(0x7f49, l); gpg_io_set_offset(IO_OFFSET_END); - + return SW_OK; } - - if ((keygpg->attributes.value[0] == 18) || - (keygpg->attributes.value[0] == 19) || - (keygpg->attributes.value[0] == 22) ){ + + if ((keygpg->attributes.value[0] == 18) || (keygpg->attributes.value[0] == 19) || + (keygpg->attributes.value[0] == 22)) { unsigned int curve; /// read ECC send_ecc_pub: - + if (keygpg->pub_key.ecfp256.W_len == 0) { - THROW (SW_REFERENCED_DATA_NOT_FOUND); + THROW(SW_REFERENCED_DATA_NOT_FOUND); return 0; } gpg_io_discard(1); gpg_io_mark(); - curve = gpg_oid2curve(keygpg->attributes.value+1, keygpg->attributes.length-1); + curve = gpg_oid2curve(keygpg->attributes.value + 1, keygpg->attributes.length - 1); if (curve == CX_CURVE_Ed25519) { - os_memmove(G_gpg_vstate.work.io_buffer+128, keygpg->pub_key.ecfp256.W,keygpg->pub_key.ecfp256.W_len); - cx_edward_compress_point(CX_CURVE_Ed25519, G_gpg_vstate.work.io_buffer+128, 65); - gpg_io_insert_tlv(0x86, 32, G_gpg_vstate.work.io_buffer+129); //129: discard 02 + os_memmove(G_gpg_vstate.work.io_buffer + 128, keygpg->pub_key.ecfp256.W, keygpg->pub_key.ecfp256.W_len); + cx_edward_compress_point(CX_CURVE_Ed25519, G_gpg_vstate.work.io_buffer + 128, 65); + gpg_io_insert_tlv(0x86, 32, G_gpg_vstate.work.io_buffer + 129); // 129: discard 02 } else if (curve == CX_CURVE_Curve25519) { - unsigned int i,len; - len = keygpg->pub_key.ecfp256.W_len-1; - for (i = 0; i <=len; i++) { - G_gpg_vstate.work.io_buffer[128+i] = keygpg->pub_key.ecfp256.W[len-i]; + unsigned int i, len; + len = keygpg->pub_key.ecfp256.W_len - 1; + for (i = 0; i <= len; i++) { + G_gpg_vstate.work.io_buffer[128 + i] = keygpg->pub_key.ecfp256.W[len - i]; } - gpg_io_insert_tlv(0x86, 32, G_gpg_vstate.work.io_buffer+128); + gpg_io_insert_tlv(0x86, 32, G_gpg_vstate.work.io_buffer + 128); } else { - gpg_io_insert_tlv(0x86, keygpg->pub_key.ecfp256.W_len, (unsigned char*)&keygpg->pub_key.ecfp256.W ); + gpg_io_insert_tlv(0x86, keygpg->pub_key.ecfp256.W_len, (unsigned char *)&keygpg->pub_key.ecfp256.W); } l = G_gpg_vstate.io_length; gpg_io_set_offset(IO_OFFSET_MARK); - gpg_io_insert_tl(0x7f49,l); + gpg_io_insert_tl(0x7f49, l); gpg_io_set_offset(IO_OFFSET_END); return SW_OK; } break; - } - + THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } diff --git a/src/gpg_init.c b/src/gpg_init.c index a7773c4..ff005e2 100644 --- a/src/gpg_init.c +++ b/src/gpg_init.c @@ -20,23 +20,18 @@ #include "gpg_vars.h" #include "usbd_impl.h" -#define SHORT(x) ((x)>>8)&0xFF, (x)&0xFF +#define SHORT(x) ((x) >> 8) & 0xFF, (x)&0xFF /* ----------------------*/ /* -- 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 -}; +// secp256r1 / NIST P256 /ansi-x9.62 : 1.2.840.10045.3.1.7 +const unsigned char C_OID_SECP256R1[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}; /* //secp384r1 / NIST P384 /ansi-x9.62 :1.3.132.0.34 const unsigned char C_OID_SECP384R1[5] = { @@ -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] = { @@ -73,19 +67,18 @@ const unsigned char C_OID_BRAINPOOL512R1[9] = { }; */ -//Ed25519/curve25519: 1.3.6.1.4.1.11591.15.1 +// Ed25519/curve25519: 1.3.6.1.4.1.11591.15.1 const unsigned char C_OID_Ed25519[9] = { - 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01, + 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01, }; -//Ed25519/curve25519: 1.3.6.1.4.1.11591.15.1 +// Ed25519/curve25519: 1.3.6.1.4.1.11591.15.1 const unsigned char C_OID_cv25519[10] = { - 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01, + 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01, }; -unsigned int gpg_oid2curve(unsigned char* oid, unsigned int len) { - - if ( (len == sizeof(C_OID_SECP256R1)) && (os_memcmp(oid, C_OID_SECP256R1, len)==0) ) { +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; } /* @@ -112,11 +105,11 @@ unsigned int gpg_oid2curve(unsigned char* oid, unsigned int len) { return CX_CURVE_BrainPoolP512R1; } */ - if ( (len == sizeof(C_OID_Ed25519)) && (os_memcmp(oid, C_OID_Ed25519, len)==0) ) { + if ((len == sizeof(C_OID_Ed25519)) && (os_memcmp(oid, C_OID_Ed25519, len) == 0)) { return CX_CURVE_Ed25519; } - if ( (len == sizeof(C_OID_cv25519)) && (os_memcmp(oid, C_OID_cv25519, len)==0) ) { + if ((len == sizeof(C_OID_cv25519)) && (os_memcmp(oid, C_OID_cv25519, len) == 0)) { return CX_CURVE_Curve25519; } @@ -131,12 +124,11 @@ unsigned int gpg_oid2curve(unsigned char* oid, unsigned int len) { return CX_CURVE_NONE; } - -unsigned char* gpg_curve2oid(unsigned int cv, unsigned int *len) { +unsigned char *gpg_curve2oid(unsigned int cv, unsigned int *len) { switch (cv) { case CX_CURVE_SECP256R1: *len = sizeof(C_OID_SECP256R1); - return (unsigned char*)PIC(C_OID_SECP256R1); + return (unsigned char *)PIC(C_OID_SECP256R1); /* case CX_CURVE_SECP256K1: @@ -146,7 +138,7 @@ unsigned char* gpg_curve2oid(unsigned int cv, unsigned int *len) { case CX_CURVE_SECP384R1: *len = sizeof(C_OID_SECP384R1); return (unsigned char*)PIC(C_OID_SECP384R1); - + case CX_CURVE_SECP521R1: *len = sizeof(C_OID_SECP521R1); return (unsigned char*)PIC(C_OID_SECP521R1); @@ -156,22 +148,22 @@ unsigned char* gpg_curve2oid(unsigned int cv, unsigned int *len) { case CX_CURVE_BrainPoolP256R1: *len = sizeof(C_OID_SECP256R1); return (unsigned char*)PIC(C_OID_SECP256R1); - + case CX_CURVE_BrainPoolP384R1: *len = sizeof(C_OID_SECP384R1); return (unsigned char*)PIC(C_OID_SECP384R1); - + case CX_CURVE_BrainPoolP512R1: *len = sizeof(C_OID_SECP521R1); return (unsigned char*)PIC(C_OID_SECP521R1); */ case CX_CURVE_Ed25519: *len = sizeof(C_OID_Ed25519); - return (unsigned char*)PIC(C_OID_Ed25519); + return (unsigned char *)PIC(C_OID_Ed25519); case CX_CURVE_Curve25519: *len = sizeof(C_OID_cv25519); - return (unsigned char*)PIC(C_OID_cv25519); + return (unsigned char *)PIC(C_OID_cv25519); } *len = 0; @@ -181,7 +173,7 @@ unsigned char* gpg_curve2oid(unsigned int cv, unsigned int *len) { unsigned int gpg_curve2domainlen(unsigned int cv) { switch (cv) { case CX_CURVE_SECP256R1: - case CX_CURVE_Ed25519: + case CX_CURVE_Ed25519: case CX_CURVE_Curve25519: return 32; } @@ -193,80 +185,68 @@ unsigned int gpg_curve2domainlen(unsigned int cv) { /* -------------------------------*/ const unsigned char C_ext_capabilities[10] = { - //-SM, +getchallenge, +keyimport, +PWchangeable, +privateDO, +algAttrChangeable, +AES, -KDF - 0x7E, - // No SM, - 0x00, - //max challenge - SHORT(GPG_EXT_CHALLENGE_LENTH), - //max cert holder length - SHORT(GPG_EXT_CARD_HOLDER_CERT_LENTH), - //maximum do length - SHORT(GPG_EXT_PRIVATE_DO_LENGTH), - //PIN block formart 2 not supported - 0x00, - //MSE - 0x01 + //-SM, +getchallenge, +keyimport, +PWchangeable, +privateDO, +algAttrChangeable, +AES, -KDF + 0x7E, + // No SM, + 0x00, + // max challenge + SHORT(GPG_EXT_CHALLENGE_LENTH), + // max cert holder length + SHORT(GPG_EXT_CARD_HOLDER_CERT_LENTH), + // maximum do length + SHORT(GPG_EXT_PRIVATE_DO_LENGTH), + // PIN block formart 2 not supported + 0x00, + // MSE + 0x01 }; -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, - //version - 0x03, 0x03, - //manufacturer - 0x2C, 0x97, - //serial - 0x00, 0x00, 0x00, 0x00, - //RFU - 0x00,0x00 -}; - -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 -}; - +const unsigned char C_default_AID[] = {0xD2, 0x76, 0x00, 0x01, 0x24, 0x01, + // version + 0x03, 0x03, + // manufacturer + 0x2C, 0x97, + // serial + 0x00, 0x00, 0x00, 0x00, + // RFU + 0x00, 0x00}; + +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}; // Default template: RSA2048 010800002001 / 010800002001 #if 1 -const unsigned char C_default_AlgoAttr_sig[] = { - // RSA - 0x01, - // Modulus default length 2048 - 0x08, 0x00, - // PubExp length 32 - 0x00, 0x20, - // std: e,p,q with modulus (n) - 0x01 -}; -const unsigned char C_default_AlgoAttr_dec[] = { - // RSA - 0x01, - // Modulus default length 2048 - 0x08, 0x00, - // PubExp length 32 - 0x00, 0x20, - // std: e,p,q with modulus (n) - 0x01 -}; +const unsigned char C_default_AlgoAttr_sig[] = { + // RSA + 0x01, + // Modulus default length 2048 + 0x08, 0x00, + // PubExp length 32 + 0x00, 0x20, + // std: e,p,q with modulus (n) + 0x01}; +const unsigned char C_default_AlgoAttr_dec[] = { + // RSA + 0x01, + // Modulus default length 2048 + 0x08, 0x00, + // PubExp length 32 + 0x00, 0x20, + // std: e,p,q with modulus (n) + 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,148 +283,143 @@ 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) { + // first init ? + 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)); } - //key conf + // key conf G_gpg_vstate.slot = N_gpg_pstate->config_slot[1]; G_gpg_vstate.kslot = &N_gpg_pstate->keys[G_gpg_vstate.slot]; gpg_mse_reset(); - //pin conf + // pin conf G_gpg_vstate.pinmode = N_gpg_pstate->config_pin[0]; - //ux conf + // ux conf gpg_init_ux(); } void gpg_init_ux() { G_gpg_vstate.ux_type = -1; - G_gpg_vstate.ux_key = -1; + G_gpg_vstate.ux_key = -1; } /* ----------------------------------------------------------------------- */ /* --- Install/ReInstall GPGapp --- */ /* ----------------------------------------------------------------------- */ int gpg_install(unsigned char app_state) { - gpg_pin_t pin; + gpg_pin_t pin; unsigned int l; - //full reset data - gpg_nvm_write(N_gpg_pstate, NULL, sizeof(gpg_nv_state_t)); + // full reset data + 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)); + // 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 + // 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; skeys[s].serial, G_gpg_vstate.work.io_buffer+4*s, 4); + // 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((void *)(N_gpg_pstate->keys[s].serial), G_gpg_vstate.work.io_buffer + 4 * s, 4); } if (app_state == STATE_ACTIVATE) { - - //default sex: none + // 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)); + // 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)); + pin.ref = PIN_ID_PW1; + 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)); + // 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)); + pin.ref = PIN_ID_PW3; + gpg_nvm_write((void *)(&N_gpg_pstate->PW3), &pin, sizeof(gpg_pin_t)); - //PWs status + // 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 + // 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); - - //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); - - //config pin + G_gpg_vstate.work.io_buffer[2] = 3; // 3: selection by APDU and screen + 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((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) - - for (int s = 0; s< GPG_KEYS_SLOTS; s++) { + + // default key template: RSA 2048) + + for (int s = 0; s < GPG_KEYS_SLOTS; s++) { unsigned char uif[2]; 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)); + l = sizeof(C_default_AlgoAttr_sig); + 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) { +#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; - e = enabled?3:0; - length = 0; + uint8_t * cfgDesc; + unsigned char e; + e = enabled ? 3 : 0; + length = 0; cfgDesc = USBD_GetCfgDesc_impl(&length); - nvm_write(cfgDesc+(length-16), &e,1); + nvm_write(cfgDesc + (length - 16), &e, 1); +#endif } diff --git a/src/gpg_io.c b/src/gpg_io.c index c674d3c..0364822 100644 --- a/src/gpg_io.c +++ b/src/gpg_io.c @@ -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 ; + 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; @@ -60,14 +54,14 @@ void gpg_io_inserted(unsigned int len) { void gpg_io_discard(int clear) { G_gpg_vstate.io_length = 0; G_gpg_vstate.io_offset = 0; - G_gpg_vstate.io_mark = 0; + G_gpg_vstate.io_mark = 0; if (clear) { gpg_io_clear(); } } void gpg_io_clear() { - os_memset(G_gpg_vstate.work.io_buffer, 0 , GPG_IO_BUFFER_LENGTH); + os_memset(G_gpg_vstate.work.io_buffer, 0, GPG_IO_BUFFER_LENGTH); } /* ----------------------------------------------------------------------- */ @@ -77,54 +71,52 @@ void gpg_io_clear() { void gpg_io_hole(unsigned int sz) { if ((G_gpg_vstate.io_length + sz) > GPG_IO_BUFFER_LENGTH) { THROW(ERROR_IO_FULL); - return ; + 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); + 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.io_length += sz; } void gpg_io_insert(unsigned char const *buff, unsigned int len) { gpg_io_hole(len); - os_memmove(G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, buff, len); + os_memmove(G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, buff, len); G_gpg_vstate.io_offset += len; } -void gpg_io_insert_u32(unsigned int v32) { +void gpg_io_insert_u32(unsigned int v32) { gpg_io_hole(4); - G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+0] = v32>>24; - G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+1] = v32>>16; - 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.work.io_buffer[G_gpg_vstate.io_offset + 0] = v32 >> 24; + G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 1] = v32 >> 16; + 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) { +void gpg_io_insert_u24(unsigned int v24) { gpg_io_hole(3); - G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+0] = v24>>16; - G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+1] = v24>>8; - G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+2] = v24>>0; + G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] = v24 >> 16; + G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 1] = v24 >> 8; + G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 2] = v24 >> 0; G_gpg_vstate.io_offset += 3; } -void gpg_io_insert_u16(unsigned int v16) { +void gpg_io_insert_u16(unsigned int v16) { gpg_io_hole(2); - G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+0] = v16>>8; - G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+1] = v16>>0; + G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] = v16 >> 8; + G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 1] = v16 >> 0; G_gpg_vstate.io_offset += 2; } void gpg_io_insert_u8(unsigned int v8) { gpg_io_hole(1); - G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+0] = v8; + G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] = v8; G_gpg_vstate.io_offset += 1; } void gpg_io_insert_t(unsigned int T) { - if (T &0xFF00) { - gpg_io_insert_u16(T); + if (T & 0xFF00) { + gpg_io_insert_u16(T); } else { - gpg_io_insert_u8(T); + gpg_io_insert_u8(T); } } @@ -133,7 +125,7 @@ void gpg_io_insert_tl(unsigned int T, unsigned int L) { if (L < 128) { gpg_io_insert_u8(L); } else if (L < 256) { - gpg_io_insert_u16(0x8100|L); + gpg_io_insert_u16(0x8100 | L); } else { gpg_io_insert_u8(0x82); gpg_io_insert_u16(L); @@ -141,46 +133,44 @@ void gpg_io_insert_tl(unsigned int T, unsigned int L) { } void gpg_io_insert_tlv(unsigned int T, unsigned int L, unsigned char const *V) { - gpg_io_insert_tl(T,L); + gpg_io_insert_tl(T, L); 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) | - (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+1] << 16) | - (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+2] << 8) | - (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+3] << 0) ); + unsigned int v32; + v32 = ((G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] << 24) | + (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 1] << 16) | + (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 2] << 8) | + (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 3] << 0)); G_gpg_vstate.io_offset += 4; return v32; } unsigned int gpg_io_fetch_u24() { - unsigned int v24; - v24 = ( (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+0] << 16) | - (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] << 0) ); + unsigned int v24; + v24 = ((G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] << 16) | + (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] << 0)); G_gpg_vstate.io_offset += 3; return v24; } unsigned int gpg_io_fetch_u16() { - unsigned int v16; - v16 = ( (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+0] << 8) | - (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+1] << 0) ); + unsigned int v16; + v16 = ((G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] << 8) | + (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 1] << 0)); G_gpg_vstate.io_offset += 2; return v16; } unsigned int gpg_io_fetch_u8() { - unsigned int v8; - v8 = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset] ; + unsigned int v8; + v8 = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset]; G_gpg_vstate.io_offset += 1; return v8; } @@ -201,16 +191,17 @@ int gpg_io_fetch_l(unsigned int *L) { if ((*L & 0x80) != 0) { *L &= 0x7F; if (*L == 1) { - *L = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+1]; + *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] ; - G_gpg_vstate.io_offset += 3 ; + *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; } } else { - G_gpg_vstate.io_offset += 1 ; + G_gpg_vstate.io_offset += 1; } return 0; } @@ -221,20 +212,19 @@ int gpg_io_fetch_tl(unsigned int *T, unsigned int *L) { return 0; } -int gpg_io_fetch_nv(unsigned char* buffer, int len) { - gpg_nvm_write(buffer, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, len); +int gpg_io_fetch_nv(unsigned char *buffer, int len) { + gpg_nvm_write(buffer, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, len); G_gpg_vstate.io_offset += len; return len; } -int gpg_io_fetch(unsigned char* buffer, int len) { +int gpg_io_fetch(unsigned char *buffer, int len) { if (buffer) { - os_memmove(buffer, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, len); + os_memmove(buffer, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, len); } G_gpg_vstate.io_offset += len; return len; } - /* ----------------------------------------------------------------------- */ /* REAL IO */ /* ----------------------------------------------------------------------- */ @@ -244,125 +234,119 @@ int gpg_io_fetch(unsigned char* buffer, int len) { int gpg_io_do(unsigned int io_flags) { unsigned int rx = 0; - //if pending input chaining + // if pending input chaining if (G_gpg_vstate.io_cla & 0x10) { goto in_chaining; } if (io_flags & IO_ASYNCH_REPLY) { // if IO_ASYNCH_REPLY has been set, - // gpg_io_exchange will return when IO_RETURN_AFTER_TX will set in ui + // gpg_io_exchange will return when IO_RETURN_AFTER_TX will set in ui rx = gpg_io_exchange(CHANNEL_APDU | IO_ASYNCH_REPLY, 0); } else { // --- full out chaining --- G_gpg_vstate.io_offset = 0; - while(G_gpg_vstate.io_length > MAX_OUT) { - unsigned int tx,xx; - //send chunk - tx = MAX_OUT-2; - os_memmove(G_io_apdu_buffer, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, tx); + while (G_gpg_vstate.io_length > MAX_OUT) { + unsigned int tx, xx; + // send chunk + tx = MAX_OUT - 2; + os_memmove(G_io_apdu_buffer, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, tx); G_gpg_vstate.io_length -= tx; G_gpg_vstate.io_offset += tx; G_io_apdu_buffer[tx] = 0x61; - if (G_gpg_vstate.io_length > MAX_OUT-2) { - xx = MAX_OUT-2; + if (G_gpg_vstate.io_length > MAX_OUT - 2) { + xx = MAX_OUT - 2; } else { - xx = G_gpg_vstate.io_length-2; + xx = G_gpg_vstate.io_length - 2; } - 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) || - (G_io_apdu_buffer[3] != 0x00) ) { + 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) || + (G_io_apdu_buffer[3] != 0x00)) { THROW(SW_COMMAND_NOT_ALLOWED); return 0; } } - os_memmove(G_io_apdu_buffer, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, G_gpg_vstate.io_length); - + os_memmove(G_io_apdu_buffer, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, G_gpg_vstate.io_length); + if (io_flags & IO_RETURN_AFTER_TX) { - rx = gpg_io_exchange(CHANNEL_APDU |IO_RETURN_AFTER_TX, G_gpg_vstate.io_length); + rx = gpg_io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, G_gpg_vstate.io_length); return 0; } else { - rx = gpg_io_exchange(CHANNEL_APDU, G_gpg_vstate.io_length); + rx = gpg_io_exchange(CHANNEL_APDU, G_gpg_vstate.io_length); } } //--- full in chaining --- if (rx < 4) { - THROW(SW_COMMAND_NOT_ALLOWED); - return SW_COMMAND_NOT_ALLOWED; + THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } if (rx == 4) { - G_io_apdu_buffer[4]=0; - rx = 4; + G_io_apdu_buffer[4] = 0; + rx = 4; } G_gpg_vstate.io_offset = 0; G_gpg_vstate.io_length = 0; - G_gpg_vstate.io_cla = G_io_apdu_buffer[0]; - G_gpg_vstate.io_ins = G_io_apdu_buffer[1]; - G_gpg_vstate.io_p1 = G_io_apdu_buffer[2]; - G_gpg_vstate.io_p2 = G_io_apdu_buffer[3]; - G_gpg_vstate.io_lc = 0; - G_gpg_vstate.io_le = 0; + G_gpg_vstate.io_cla = G_io_apdu_buffer[0]; + G_gpg_vstate.io_ins = G_io_apdu_buffer[1]; + G_gpg_vstate.io_p1 = G_io_apdu_buffer[2]; + G_gpg_vstate.io_p2 = G_io_apdu_buffer[3]; + G_gpg_vstate.io_lc = 0; + G_gpg_vstate.io_le = 0; switch (G_gpg_vstate.io_ins) { case INS_GET_DATA: case INS_GET_RESPONSE: case INS_TERMINATE_DF: case INS_ACTIVATE_FILE: - G_gpg_vstate.io_le = G_io_apdu_buffer[4]; + G_gpg_vstate.io_le = G_io_apdu_buffer[4]; break; - + case INS_GET_CHALLENGE: if (G_gpg_vstate.io_p1 == 0) { break; } - case INS_VERIFY: - case INS_CHANGE_REFERENCE_DATA: - if (G_io_apdu_buffer[4] == 0) { - break; - } - goto _default; + case INS_VERIFY: + case INS_CHANGE_REFERENCE_DATA: + if (G_io_apdu_buffer[4] == 0) { + break; + } + goto _default; default: _default: - G_gpg_vstate.io_lc = G_io_apdu_buffer[4]; - os_memmove(G_gpg_vstate.work.io_buffer, G_io_apdu_buffer+5, G_gpg_vstate.io_lc); - G_gpg_vstate.io_length = G_gpg_vstate.io_lc; + G_gpg_vstate.io_lc = G_io_apdu_buffer[4]; + os_memmove(G_gpg_vstate.work.io_buffer, G_io_apdu_buffer + 5, G_gpg_vstate.io_lc); + G_gpg_vstate.io_length = G_gpg_vstate.io_lc; break; } - while(G_gpg_vstate.io_cla & 0x10) { - + 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); + 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) || - (G_io_apdu_buffer[3] != G_gpg_vstate.io_p2) ) { + 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; } if (rx == 4) { - G_io_apdu_buffer[4]=0; - rx = 4; + G_io_apdu_buffer[4] = 0; + rx = 4; } G_gpg_vstate.io_cla = G_io_apdu_buffer[0]; G_gpg_vstate.io_lc = G_io_apdu_buffer[4]; if ((G_gpg_vstate.io_length + G_gpg_vstate.io_lc) > GPG_IO_BUFFER_LENGTH) { return 1; } - os_memmove(G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_length, G_io_apdu_buffer+5, G_gpg_vstate.io_lc); - G_gpg_vstate.io_length += G_gpg_vstate.io_lc; + os_memmove(G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_length, G_io_apdu_buffer + 5, G_gpg_vstate.io_lc); + G_gpg_vstate.io_length += G_gpg_vstate.io_lc; } - return 0; } diff --git a/src/gpg_main.c b/src/gpg_main.c index 78bb5e2..cd3ee69 100644 --- a/src/gpg_main.c +++ b/src/gpg_main.c @@ -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,11 +86,10 @@ unsigned char io_event(unsigned char channel) { UX_DISPLAYED_EVENT({}); break; case SEPROXYHAL_TAG_TICKER_EVENT: - 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(); + 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(); } }); break; @@ -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,39 +146,36 @@ __attribute__((section(".boot"))) int main(void) { // exit critical section __asm volatile("cpsie i"); - // ensure exception will work as planned os_boot(); - for(;;) { + for (;;) { UX_INIT(); BEGIN_TRY { TRY { - - //start communication with MCU + // 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 + // set up gpg_init(); - - //set up initial screen - ui_init(); - + // set up initial screen + ui_init(); - //start the application - //the first exchange will: + // start the application + // the first exchange will: // - display the initial screen // - send the ATR // - receive the first command gpg_main(); } CATCH(EXCEPTION_IO_RESET) { - // reset IO and UX + // reset IO and UX continue; } CATCH_ALL { diff --git a/src/gpg_mse.c b/src/gpg_mse.c index d3cc88c..c9d2db8 100644 --- a/src/gpg_mse.c +++ b/src/gpg_mse.c @@ -20,29 +20,26 @@ #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; + G_gpg_vstate.mse_aut = &G_gpg_vstate.kslot->dec; } if (ref == 0x03) { - G_gpg_vstate.mse_aut = &G_gpg_vstate.kslot->aut; + G_gpg_vstate.mse_aut = &G_gpg_vstate.kslot->aut; } } if (crt == 0xB8) { if (ref == 0x02) { - G_gpg_vstate.mse_dec = &G_gpg_vstate.kslot->dec; + G_gpg_vstate.mse_dec = &G_gpg_vstate.kslot->dec; } if (ref == 0x03) { - G_gpg_vstate.mse_dec = &G_gpg_vstate.kslot->aut; + G_gpg_vstate.mse_dec = &G_gpg_vstate.kslot->aut; } } return 0; } - - int gpg_mse_reset() { gpg_mse_set(0xA4, 0x03); gpg_mse_set(0xB8, 0x02); @@ -50,29 +47,26 @@ int gpg_mse_reset() { } int gpg_apdu_mse() { - int crt,ref; - + 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; } - crt = gpg_io_fetch_u16(); + crt = gpg_io_fetch_u16(); if (crt != 0x8301) { THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } - ref = gpg_io_fetch_u8(); - if ((ref != 0x02) && (ref != 0x03)) { + ref = gpg_io_fetch_u8(); + if ((ref != 0x02) && (ref != 0x03)) { THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } - gpg_mse_set(crt,ref); + gpg_mse_set(crt, ref); gpg_io_discard(1); return SW_OK; - } \ No newline at end of file diff --git a/src/gpg_nvram.c b/src/gpg_nvram.c index a697c9c..1c81d1f 100644 --- a/src/gpg_nvram.c +++ b/src/gpg_nvram.c @@ -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 diff --git a/src/gpg_pin.c b/src/gpg_pin.c index 4ed7aa2..fdfe903 100644 --- a/src/gpg_pin.c +++ b/src/gpg_pin.c @@ -23,8 +23,8 @@ gpg_pin_t *gpg_pin_get_pin(int pinref) { switch (pinref) { - case PIN_ID_PW1 : - case PIN_ID_PW2 : + case PIN_ID_PW1: + case PIN_ID_PW2: return &N_gpg_pstate->PW1; case PIN_ID_PW3: return &N_gpg_pstate->PW3; @@ -34,37 +34,33 @@ gpg_pin_t *gpg_pin_get_pin(int pinref) { return NULL; } - - -static int gpg_pin_get_state_index(unsigned int pinref) { +static int gpg_pin_get_state_index(unsigned int pinref) { switch (pinref) { - case PIN_ID_PW1 : + case PIN_ID_PW1: return 1; - case PIN_ID_PW2 : + case PIN_ID_PW2: return 2; - case PIN_ID_PW3 : - return 3; - case PIN_ID_RC : + case PIN_ID_PW3: + 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; +static int gpg_pin_check_internal(gpg_pin_t *pin, unsigned char *pin_val, int pin_len) { unsigned int counter; - if (pin->counter == 0) { return SW_PIN_BLOCKED; } - counter = pin->counter-1; + 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,26 +69,24 @@ 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); + gpg_pin_set_verified(pinID, 0); + sw = gpg_pin_check_internal(pin, pin_val, pin_len); if (sw == SW_OK) { - gpg_pin_set_verified(pinID,1); + gpg_pin_set_verified(pinID, 1); return; } THROW(sw); 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); + gpg_pin_set_verified(pinID, 0); + sw = gpg_pin_check_internal(pin, pin_val, pin_len); if (sw == SW_OK) { - gpg_pin_set_verified(pinID,1); + gpg_pin_set_verified(pinID, 1); } return sw; } @@ -103,8 +97,8 @@ void gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len) { gpg_pin_t newpin; cx_sha256_init(&sha256); - cx_hash((cx_hash_t*)&sha256, CX_LAST, pin_val, pin_len, newpin.value, 32); - newpin.length = pin_len; + cx_hash((cx_hash_t *)&sha256, CX_LAST, pin_val, pin_len, newpin.value, 32); + newpin.length = pin_len; newpin.counter = 3; gpg_nvm_write(pin, &newpin, sizeof(gpg_pin_t)); @@ -114,27 +108,25 @@ int gpg_pin_set_verified(int pinID, int verified) { int idx; idx = gpg_pin_get_state_index(pinID); if (idx >= 0) { - G_gpg_vstate.verified_pin[idx]=verified; - return verified; - } - return 0; + G_gpg_vstate.verified_pin[idx] = verified; + return verified; + } + return 0; } int gpg_pin_is_verified(int pinID) { int idx; idx = gpg_pin_get_state_index(pinID); if (idx >= 0) { - return G_gpg_vstate.verified_pin[idx]; - } - return 0; + return G_gpg_vstate.verified_pin[idx]; + } + return 0; } - int gpg_pin_is_blocked(gpg_pin_t *pin) { - return pin->counter == 0; + return pin->counter == 0; } - int gpg_apdu_verify() { gpg_pin_t *pin; @@ -143,8 +135,8 @@ int gpg_apdu_verify() { THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } - - //PINPAD + + // PINPAD if (G_gpg_vstate.io_cla == 0xEF) { if (gpg_pin_is_blocked(pin)) { THROW(SW_PIN_BLOCKED); @@ -152,34 +144,33 @@ int gpg_apdu_verify() { } if (G_gpg_vstate.pinmode == PIN_MODE_SCREEN) { - //Delegate pin check to ui + // Delegate pin check to ui gpg_io_discard(1); ui_menu_pinentry_display(0); return 0; } if (G_gpg_vstate.pinmode == PIN_MODE_CONFIRM) { - //Delegate pin check to ui + // Delegate pin check to ui gpg_io_discard(1); ui_menu_pinconfirm_display(0); return 0; } if (G_gpg_vstate.pinmode == PIN_MODE_TRUST) { - gpg_pin_set_verified(G_gpg_vstate.io_p2,1); - gpg_io_discard(1); - return SW_OK; + gpg_pin_set_verified(G_gpg_vstate.io_p2, 1); + gpg_io_discard(1); + return SW_OK; } THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } - //NORMAL CHECK - if ((G_gpg_vstate.io_p1==0) && G_gpg_vstate.io_length) { + // NORMAL CHECK + if ((G_gpg_vstate.io_p1 == 0) && G_gpg_vstate.io_length) { if (gpg_pin_is_blocked(pin)) { 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; @@ -187,75 +178,66 @@ int gpg_apdu_verify() { gpg_io_discard(1); - //STATUS REQUEST - if ((G_gpg_vstate.io_p1==0) && G_gpg_vstate.io_length==0) { + // STATUS REQUEST + if ((G_gpg_vstate.io_p1 == 0) && G_gpg_vstate.io_length == 0) { if (gpg_pin_is_verified(G_gpg_vstate.io_p2)) { return SW_OK; } return 0x63C0 | pin->counter; } - //RESET REQUEST - if ((G_gpg_vstate.io_p1==0xFF) && G_gpg_vstate.io_length==0) { - gpg_pin_set_verified(G_gpg_vstate.io_p2,0); + // RESET REQUEST + if ((G_gpg_vstate.io_p1 == 0xFF) && G_gpg_vstate.io_length == 0) { + gpg_pin_set_verified(G_gpg_vstate.io_p2, 0); return SW_OK; } THROW(SW_WRONG_DATA); return SW_WRONG_DATA; - } int gpg_apdu_change_ref_data() { gpg_pin_t *pin; - int len, newlen; - + int len, newlen; + pin = gpg_pin_get_pin(G_gpg_vstate.io_p2); if (pin == NULL) { THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } - gpg_pin_set_verified(pin->ref,0); - - - + gpg_pin_set_verified(pin->ref, 0); // --- PW1/PW3 pin --- if (gpg_pin_is_blocked(pin)) { THROW(SW_PIN_BLOCKED); return SW_PIN_BLOCKED; } - //avoid any-overflow whitout giving info + // avoid any-overflow whitout giving info if (G_gpg_vstate.io_length == 0) { if (G_gpg_vstate.pinmode != PIN_MODE_HOST) { - //Delegate pin change to ui + // Delegate pin change to ui gpg_io_discard(1); ui_menu_pinentry_display(0); return 0; - } + } } if (pin->length > G_gpg_vstate.io_length) { - len = G_gpg_vstate.io_length; + len = G_gpg_vstate.io_length; } else { 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)) || - ((pin->ref == PIN_ID_PW3) && (newlen < 8)) ) { + newlen = G_gpg_vstate.io_length - len; + 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; } @@ -264,40 +246,35 @@ int gpg_apdu_reset_retry_counter() { gpg_pin_t *pin_pw1; gpg_pin_t *pin_pw3; gpg_pin_t *pin_rc; - int rc_len, pw1_len; + int rc_len, pw1_len; pin_pw1 = gpg_pin_get_pin(PIN_ID_PW1); pin_pw3 = gpg_pin_get_pin(PIN_ID_PW3); - pin_rc = gpg_pin_get_pin(PIN_ID_RC); + pin_rc = gpg_pin_get_pin(PIN_ID_RC); if (G_gpg_vstate.io_p1 == 2) { if (!gpg_pin_is_verified(PIN_ID_PW3)) { THROW(SW_SECURITY_STATUS_NOT_SATISFIED); return SW_SECURITY_STATUS_NOT_SATISFIED; } - rc_len = 0; + rc_len = 0; pw1_len = G_gpg_vstate.io_length; } else { - - //avoid any-overflow whitout giving info + // avoid any-overflow whitout giving info if (pin_rc->length > G_gpg_vstate.io_length) { - rc_len = G_gpg_vstate.io_length; + rc_len = G_gpg_vstate.io_length; } else { 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); + 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); } - if ((pw1_len > GPG_MAX_PW_LENGTH) ||(pw1_len < 6)) { + 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; } diff --git a/src/gpg_pso.c b/src/gpg_pso.c index 004878b..3259e7c 100644 --- a/src/gpg_pso.c +++ b/src/gpg_pso.c @@ -20,152 +20,133 @@ #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) { - gpg_pin_set_verified(PIN_ID_PW1,0); + if (N_gpg_pstate->PW_status[0] == 0) { + gpg_pin_set_verified(PIN_ID_PW1, 0); } } static int gpg_sign(gpg_key_t *sigkey) { - // --- RSA - if (sigkey->attributes.value[0] == 1) { - cx_rsa_private_key_t *key; - unsigned int ksz,l; - ksz = (sigkey->attributes.value[1]<<8) | sigkey->attributes.value[2]; - ksz = ksz>>3; - switch(ksz) { - case 1024/8: - key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa1024; - break; - case 2048/8: - key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa2048; - break; - case 3072/8: - key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa3072; - break; - case 4096/8: - key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa4096; - break; - } - if (key->size != ksz) { + // --- RSA + if (sigkey->attributes.value[0] == 1) { + cx_rsa_private_key_t *key; + unsigned int ksz, l; + ksz = (sigkey->attributes.value[1] << 8) | sigkey->attributes.value[2]; + ksz = ksz >> 3; + switch (ksz) { + case 1024 / 8: + key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa1024; + break; + case 2048 / 8: + key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa2048; + break; + case 3072 / 8: + key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa3072; + break; + case 4096 / 8: + key = (cx_rsa_private_key_t *)&sigkey->priv_key.rsa4096; + break; + } + if (key->size != ksz) { + THROW(SW_CONDITIONS_NOT_SATISFIED); + return SW_CONDITIONS_NOT_SATISFIED; + } + + // 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_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); + // send + gpg_io_discard(0); + gpg_io_inserted(ksz); + gpg_pso_reset_PW1(); + return SW_OK; + } + // --- ECDSA/EdDSA + 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; + + key = &sigkey->priv_key.ecfp; + +// sign +#define RS (G_gpg_vstate.work.io_buffer + (GPG_IO_BUFFER_LENGTH - 256)) + if (sigkey->attributes.value[0] == 19) { + sz = gpg_curve2domainlen(key->curve); + if ((sz == 0) || (key->d_len != sz)) { THROW(SW_CONDITIONS_NOT_SATISFIED); return SW_CONDITIONS_NOT_SATISFIED; } - - //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_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); - //send + 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); - gpg_io_inserted(ksz); - gpg_pso_reset_PW1(); - return SW_OK; - } - // --- ECDSA/EdDSA - 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; - key = &sigkey->priv_key.ecfp; + rs_len = RS[3]; + rs = &RS[4]; - //sign - #define RS (G_gpg_vstate.work.io_buffer+(GPG_IO_BUFFER_LENGTH-256)) - if (sigkey->attributes.value[0] == 19) { - sz = gpg_curve2domainlen(key->curve); - if ((sz == 0) || (key->d_len != sz)) { - THROW(SW_CONDITIONS_NOT_SATISFIED); - return SW_CONDITIONS_NOT_SATISFIED; - } - sz = cx_ecdsa_sign(key, - 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); - - rs_len = RS[3]; - rs = &RS[4]; - - for (i = 0; i<2; i++) { - if (*rs == 0) { - rs++; - rs_len--; - } - gpg_io_insert_u8(0); - gpg_io_insert(rs,rs_len); - rs = rs+rs_len; - rs_len = rs[1]; - rs += 2; + for (i = 0; i < 2; i++) { + if (*rs == 0) { + rs++; + rs_len--; } - } 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, - NULL); - gpg_io_discard(0); - gpg_io_insert(RS, sz); + gpg_io_insert_u8(0); + gpg_io_insert(rs, rs_len); + rs = rs + rs_len; + rs_len = rs[1]; + rs += 2; } - #undef RS - - //send - gpg_pso_reset_PW1(); - return SW_OK; + } 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, + NULL); + gpg_io_discard(0); + gpg_io_insert(RS, sz); } - // --- PSO:CDS NOT SUPPORTED - THROW(SW_REFERENCED_DATA_NOT_FOUND); - return SW_REFERENCED_DATA_NOT_FOUND; +#undef RS + + // send + gpg_pso_reset_PW1(); + return SW_OK; + } + // --- PSO:CDS NOT SUPPORTED + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return SW_REFERENCED_DATA_NOT_FOUND; } int gpg_apdu_pso() { - unsigned int t,l,ksz; + unsigned int t, l, ksz; unsigned int pso; - pso = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ; + pso = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; - //UIF HANDLE - switch(pso) { + // UIF HANDLE + switch (pso) { // --- PSO:CDS --- - case 0x9e9a: + case 0x9e9a: if (G_gpg_vstate.kslot->sig.UIF[0]) { - if ((G_gpg_vstate.UIF_flags)==0) { + if ((G_gpg_vstate.UIF_flags) == 0) { ui_menu_uifconfirm_display(0); return 0; - } + } G_gpg_vstate.UIF_flags = 0; } break; // --- PSO:DEC --- - case 0x8086: - case 0x8680: + case 0x8086: + case 0x8680: if (G_gpg_vstate.kslot->dec.UIF[0]) { - if ((G_gpg_vstate.UIF_flags)==0) { + if ((G_gpg_vstate.UIF_flags) == 0) { ui_menu_uifconfirm_display(0); return 0; } @@ -175,35 +156,33 @@ int gpg_apdu_pso() { } // --- PSO:ENC --- - switch(pso) { + switch (pso) { // --- PSO:CDS --- case 0x9e9a: { unsigned int cnt; - int sw; - sw = gpg_sign(&G_gpg_vstate.kslot->sig); - cnt = G_gpg_vstate.kslot->sig_count+1; - nvm_write(&G_gpg_vstate.kslot->sig_count,&cnt,sizeof(unsigned int)); + int sw; + sw = gpg_sign(&G_gpg_vstate.kslot->sig); + cnt = G_gpg_vstate.kslot->sig_count + 1; + nvm_write(&G_gpg_vstate.kslot->sig_count, &cnt, sizeof(unsigned int)); return sw; } // --- PSO:ENC --- case 0x8680: { - unsigned int msg_len; + unsigned int msg_len; cx_aes_key_t *key; - unsigned int sz; + unsigned int sz; key = &G_gpg_vstate.kslot->AES_dec; if (!(key->size != 16)) { - THROW(SW_CONDITIONS_NOT_SATISFIED+5); + THROW(SW_CONDITIONS_NOT_SATISFIED + 5); 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, - G_gpg_vstate.work.io_buffer+1, GPG_IO_BUFFER_LENGTH-1); - //send + 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); G_gpg_vstate.work.io_buffer[0] = 0x02; - gpg_io_inserted(1+sz); + gpg_io_inserted(1 + sz); return SW_OK; } @@ -214,7 +193,7 @@ int gpg_apdu_pso() { unsigned int sz; pad_byte = gpg_io_fetch_u8(); - switch(pad_byte) { + switch (pad_byte) { // --- PSO:DEC:RSA case 0x00: { cx_rsa_private_key_t *key; @@ -222,35 +201,32 @@ int gpg_apdu_pso() { THROW(SW_CONDITIONS_NOT_SATISFIED); return SW_CONDITIONS_NOT_SATISFIED; } - ksz = (G_gpg_vstate.mse_dec->attributes.value[1]<<8) | G_gpg_vstate.mse_dec->attributes.value[2]; - ksz = ksz>>3; + ksz = (G_gpg_vstate.mse_dec->attributes.value[1] << 8) | G_gpg_vstate.mse_dec->attributes.value[2]; + ksz = ksz >> 3; key = NULL; - switch(ksz) { - case 1024/8: - key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa1024; - break; - case 2048/8: - key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa2048; - break; - case 3072/8: - key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa3072; - break; - case 4096/8: - key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa4096; - break; + switch (ksz) { + case 1024 / 8: + key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa1024; + break; + case 2048 / 8: + key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa2048; + break; + case 3072 / 8: + key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa3072; + break; + case 4096 / 8: + key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->priv_key.rsa4096; + break; } - + if ((key == NULL) || (key->size != ksz)) { THROW(SW_CONDITIONS_NOT_SATISFIED); 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, - G_gpg_vstate.work.io_buffer,ksz); - //send + 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); gpg_io_inserted(sz); return SW_OK; @@ -259,18 +235,16 @@ int gpg_apdu_pso() { // --- PSO:DEC:AES case 0x02: { cx_aes_key_t *key; - unsigned int sz; + unsigned int sz; key = &G_gpg_vstate.kslot->AES_dec; if (!(key->size != 16)) { - THROW(SW_CONDITIONS_NOT_SATISFIED+5); + THROW(SW_CONDITIONS_NOT_SATISFIED + 5); 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); - //send + 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); return SW_OK; @@ -279,8 +253,8 @@ int gpg_apdu_pso() { // --- PSO:DEC:ECDH case 0xA6: { cx_ecfp_private_key_t *key; - unsigned int sz; - unsigned int curve; + unsigned int sz; + unsigned int curve; if (G_gpg_vstate.mse_dec->attributes.value[0] != 0x12) { THROW(SW_CONDITIONS_NOT_SATISFIED); return SW_CONDITIONS_NOT_SATISFIED; @@ -297,46 +271,41 @@ int gpg_apdu_pso() { THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } - - curve = gpg_oid2curve(G_gpg_vstate.mse_dec->attributes.value+1, G_gpg_vstate.mse_dec->attributes.length-1); + + curve = gpg_oid2curve(G_gpg_vstate.mse_dec->attributes.value + 1, G_gpg_vstate.mse_dec->attributes.length - 1); if (key->curve != curve) { THROW(SW_CONDITIONS_NOT_SATISFIED); - return SW_CONDITIONS_NOT_SATISFIED; + return SW_CONDITIONS_NOT_SATISFIED; } if (curve == CX_CURVE_Curve25519) { unsigned int i; - - for (i = 0; i <=31; i++) { - G_gpg_vstate.work.io_buffer[512+i] = (G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset)[31-i]; + + for (i = 0; i <= 31; i++) { + 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); - for (i = 0; i <=31; i++) { - G_gpg_vstate.work.io_buffer[128+i] = G_gpg_vstate.work.io_buffer[287-i]; + 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, - G_gpg_vstate.work.io_buffer+128, 160); + 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 + // send gpg_io_discard(0); - gpg_io_insert( G_gpg_vstate.work.io_buffer+128,sz); + gpg_io_insert(G_gpg_vstate.work.io_buffer + 128, sz); return SW_OK; } // --- PSO:DEC:xx NOT SUPPORTDED - default: + default: THROW(SW_REFERENCED_DATA_NOT_FOUND); return SW_REFERENCED_DATA_NOT_FOUND; - } + } } - + //--- PSO:yy NOT SUPPPORTED --- default: THROW(SW_REFERENCED_DATA_NOT_FOUND); @@ -346,11 +315,10 @@ int gpg_apdu_pso() { return SW_REFERENCED_DATA_NOT_FOUND; } - int gpg_apdu_internal_authenticate() { - // --- PSO:AUTH --- + // --- PSO:AUTH --- if (G_gpg_vstate.kslot->aut.UIF[0]) { - if ((G_gpg_vstate.UIF_flags)==0) { + if ((G_gpg_vstate.UIF_flags) == 0) { ui_menu_uifconfirm_display(0); return 0; } @@ -358,10 +326,11 @@ 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; - } - } + } + } return gpg_sign(G_gpg_vstate.mse_aut); } diff --git a/src/gpg_ram.c b/src/gpg_ram.c index d536d5e..1185f01 100644 --- a/src/gpg_ram.c +++ b/src/gpg_ram.c @@ -18,19 +18,21 @@ #include "gpg_types.h" #include "gpg_api.h" #include "gpg_vars.h" - #include "os_io_seproxyhal.h" +#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]; -ux_state_t ux; - #else extern unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; -int apdu_n; - +int apdu_n; #endif - -gpg_v_state_t G_gpg_vstate; - +gpg_v_state_t G_gpg_vstate; diff --git a/src/gpg_select.c b/src/gpg_select.c index 6c36ac5..be9ce51 100644 --- a/src/gpg_select.c +++ b/src/gpg_select.c @@ -13,7 +13,6 @@ * limitations under the License. */ - #include "os.h" #include "cx.h" #include "gpg_types.h" @@ -24,24 +23,23 @@ const unsigned char C_MF[] = {0x3F, 0x00}; 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) ) { + // MF + if ((G_gpg_vstate.io_length == 2) && (os_memcmp(G_gpg_vstate.work.io_buffer, C_MF, G_gpg_vstate.io_length) == 0)) { gpg_io_discard(0); sw = SW_OK; - } - //AID APP - else if ( (G_gpg_vstate.io_length == 6) && - (os_memcmp(G_gpg_vstate.work.io_buffer, N_gpg_pstate->AID, G_gpg_vstate.io_length) == 0) ) { + } + // AID APP + else if ((G_gpg_vstate.io_length == 6) && + (os_memcmp(G_gpg_vstate.work.io_buffer, N_gpg_pstate->AID, G_gpg_vstate.io_length) == 0)) { G_gpg_vstate.DO_current = 0; G_gpg_vstate.DO_reccord = 0; G_gpg_vstate.DO_offset = 0; - if ( G_gpg_vstate.selected == 0) { + if (G_gpg_vstate.selected == 0) { G_gpg_vstate.verified_pin[0] = 0; G_gpg_vstate.verified_pin[1] = 0; G_gpg_vstate.verified_pin[2] = 0; - G_gpg_vstate.verified_pin[3] = 0; - G_gpg_vstate.verified_pin[4] = 0; + G_gpg_vstate.verified_pin[3] = 0; + G_gpg_vstate.verified_pin[4] = 0; } gpg_io_discard(0); @@ -49,8 +47,8 @@ int gpg_apdu_select() { THROW(SW_STATE_TERMINATED); } sw = SW_OK; - } - //NOT FOUND + } + // NOT FOUND else { THROW(SW_FILE_NOT_FOUND); return SW_FILE_NOT_FOUND; diff --git a/src/gpg_types.h b/src/gpg_types.h index b3c6233..ac93877 100644 --- a/src/gpg_types.h +++ b/src/gpg_types.h @@ -17,96 +17,96 @@ #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 - +#define GPG_APDU_LENGTH 0xFE /* big private DO */ -#define GPG_EXT_PRIVATE_DO_LENGTH 512 +#define GPG_EXT_PRIVATE_DO_LENGTH 512 /* will be fixed..1024 is not enougth */ -#define GPG_EXT_CARD_HOLDER_CERT_LENTH 2560 +#define GPG_EXT_CARD_HOLDER_CERT_LENTH 2560 /* random choice */ -#define GPG_EXT_CHALLENGE_LENTH 254 +#define GPG_EXT_CHALLENGE_LENTH 254 /* accpet long PW, but less than one sha256 block */ -#define GPG_MAX_PW_LENGTH 12 +#define GPG_MAX_PW_LENGTH 12 #if GPG_MULTISLOT -#define GPG_KEYS_SLOTS 3 +#define GPG_KEYS_SLOTS 3 #else -#define GPG_KEYS_SLOTS 1 +#define GPG_KEYS_SLOTS 1 #endif -#define GPG_KEY_ATTRIBUTES_LENGTH 12 +#define GPG_KEY_ATTRIBUTES_LENGTH 12 #define GPG_RSA_DEFAULT_PUB 0x00010001U struct gpg_pin_s { - unsigned int ref; - //initial pin length, 0 means not set - unsigned int length; - unsigned int counter; - //only store sha256 of PIN/RC + unsigned int ref; + // initial pin length, 0 means not set + unsigned int length; + unsigned int counter; + // only store sha256 of PIN/RC unsigned char value[32]; }; typedef struct gpg_pin_s gpg_pin_t; - - -#define LV(name,maxlen) \ - struct { \ - unsigned int length; \ - unsigned char value[maxlen]; \ +#define LV(name, maxlen) \ + struct { \ + unsigned int length; \ + unsigned char value[maxlen]; \ } name typedef struct gpg_lv_s { - unsigned int length; - unsigned char value[]; + unsigned int length; + unsigned char value[]; } gpg_lv_t; typedef struct gpg_key_s { /* C1 C2 C3 */ - LV(attributes,GPG_KEY_ATTRIBUTES_LENGTH); + LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH); /* key value */ /* WARN: changing the cx__t structures breaks backup/restore. Adapt backup/restore code * to ensure backward compatibility. - */ + */ union { - cx_rsa_private_key_t rsa; - cx_rsa_1024_private_key_t rsa1024; - cx_rsa_2048_private_key_t rsa2048; - cx_rsa_3072_private_key_t rsa3072; - cx_rsa_4096_private_key_t rsa4096; - - cx_ecfp_private_key_t ecfp; - cx_ecfp_256_private_key_t ecfp256; - cx_ecfp_384_private_key_t ecfp384; - cx_ecfp_512_private_key_t ecfp512; - cx_ecfp_640_private_key_t ecfp640; + cx_rsa_private_key_t rsa; + cx_rsa_1024_private_key_t rsa1024; + cx_rsa_2048_private_key_t rsa2048; + cx_rsa_3072_private_key_t rsa3072; + cx_rsa_4096_private_key_t rsa4096; + + cx_ecfp_private_key_t ecfp; + cx_ecfp_256_private_key_t ecfp256; + cx_ecfp_384_private_key_t ecfp384; + cx_ecfp_512_private_key_t ecfp512; + cx_ecfp_640_private_key_t ecfp640; } priv_key; union { - unsigned char rsa[4]; - cx_ecfp_public_key_t ecfp; - cx_ecfp_256_public_key_t ecfp256; - cx_ecfp_384_public_key_t ecfp384; - cx_ecfp_512_public_key_t ecfp512; - cx_ecfp_640_public_key_t ecfp640; + unsigned char rsa[4]; + cx_ecfp_public_key_t ecfp; + cx_ecfp_256_public_key_t ecfp256; + cx_ecfp_384_public_key_t ecfp384; + cx_ecfp_512_public_key_t ecfp512; + cx_ecfp_640_public_key_t ecfp640; } pub_key; /* C7 C8 C9 , C5 = C7|C8|C9*/ unsigned char fingerprints[20]; /* 7F21 */ - LV(CA,GPG_EXT_CARD_HOLDER_CERT_LENTH); + LV(CA, GPG_EXT_CARD_HOLDER_CERT_LENTH); /* C7 C8 C9, C6 = C7|C8|C9*/ unsigned char CA_fingerprints[20]; - /* CE CF D0, CD = CE|CF|D0 */ + /* CE CF D0, CD = CE|CF|D0 */ unsigned char date[4]; /* D6/D7/D8- */ unsigned char UIF[2]; } gpg_key_t; - -typedef struct gpg_key_slot_s{ +typedef struct gpg_key_slot_s { unsigned char serial[4]; /* */ gpg_key_t sig; @@ -120,7 +120,6 @@ typedef struct gpg_key_slot_s{ } gpg_key_slot_t; - struct gpg_nv_state_s { /* magic */ unsigned char magic[8]; @@ -146,21 +145,21 @@ struct gpg_nv_state_s { /* -- Cardholder Related Data -- */ /* 5B */ - LV(name,39); + LV(name, 39); /* 5F2D */ LV(lang, 8); /* 5F35 */ unsigned char sex[1]; /* -- Application Related Data -- */ - /* 4F */ + /* 4F */ unsigned char AID[16]; /* 5F52 */ unsigned char histo[15]; /* 7f66 */ - //unsigned char ext_length_info[8]; + // unsigned char ext_length_info[8]; /* C0 */ - //unsigned char ext_capabilities[10]; + // unsigned char ext_capabilities[10]; /* C4 */ unsigned char PW_status[4]; @@ -178,7 +177,7 @@ struct gpg_nv_state_s { cx_aes_key_t SM_enc; /* D2 */ cx_aes_key_t SM_mac; -} ; +}; typedef struct gpg_nv_state_s gpg_nv_state_t; @@ -188,37 +187,37 @@ struct gpg_v_state_s { /* app state */ unsigned char selected; unsigned char slot; /* DO 01F2 */ - gpg_key_slot_t *kslot; - gpg_key_t *mse_aut; - gpg_key_t *mse_dec; + gpg_key_slot_t *kslot; + gpg_key_t * mse_aut; + gpg_key_t * mse_dec; unsigned char seed_mode; - unsigned char UIF_flags; + unsigned char UIF_flags; /* io state*/ - unsigned char io_cla; - unsigned char io_ins; - unsigned char io_p1; - unsigned char io_p2; - unsigned char io_lc; - unsigned char io_le; - unsigned short io_length; - unsigned short io_offset; - unsigned short io_mark; + unsigned char io_cla; + unsigned char io_ins; + unsigned char io_p1; + unsigned char io_p2; + unsigned char io_lc; + unsigned char io_le; + unsigned short io_length; + unsigned short io_offset; + unsigned short io_mark; union { unsigned char io_buffer[GPG_IO_BUFFER_LENGTH]; struct { union { - cx_rsa_public_key_t public; + cx_rsa_public_key_t public; cx_rsa_1024_public_key_t public1024; cx_rsa_2048_public_key_t public2048; cx_rsa_3072_public_key_t public3072; cx_rsa_4096_public_key_t public4096; }; union { - cx_rsa_private_key_t private; + cx_rsa_private_key_t private; cx_rsa_1024_private_key_t private1024; cx_rsa_2048_private_key_t private2048; cx_rsa_3072_private_key_t private3072; @@ -227,26 +226,27 @@ struct gpg_v_state_s { } rsa; struct { - union{ - cx_ecfp_public_key_t public; - cx_ecfp_256_public_key_t public256; - cx_ecfp_384_public_key_t public384; - cx_ecfp_512_public_key_t public512; - cx_ecfp_640_public_key_t public640; + union { + cx_ecfp_public_key_t public; + cx_ecfp_256_public_key_t public256; + cx_ecfp_384_public_key_t public384; + cx_ecfp_512_public_key_t public512; + cx_ecfp_640_public_key_t public640; }; union { - cx_ecfp_private_key_t private; - cx_ecfp_256_private_key_t private256; - cx_ecfp_384_private_key_t private384; - cx_ecfp_512_private_key_t private512; - cx_ecfp_640_private_key_t private640; + cx_ecfp_private_key_t private; + cx_ecfp_256_private_key_t private256; + cx_ecfp_384_private_key_t private384; + cx_ecfp_512_private_key_t private512; + cx_ecfp_640_private_key_t private640; }; - }ecfp; + } 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_sha3_t sha3; cx_sha256_t sha256; }; } md; @@ -266,124 +266,128 @@ struct gpg_v_state_s { unsigned char ux_pinentry[12]; unsigned int ux_key; unsigned int ux_type; - ux_menu_entry_t ui_dogsays[2] ; + +#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; #endif -} ; -typedef struct gpg_v_state_s gpg_v_state_t; +}; +typedef struct gpg_v_state_s gpg_v_state_t; /* --- Errors --- */ -#define ERROR(x) ((x)<<16) +#define ERROR(x) ((x) << 16) -#define ERROR_IO_OFFSET ERROR(1) -#define ERROR_IO_FULL ERROR(2) +#define ERROR_IO_OFFSET ERROR(1) +#define ERROR_IO_FULL ERROR(2) /* --- IDentifiers --- */ +#define ID_AUTH 1 +#define ID_DEC 2 +#define ID_SIG 3 -#define ID_AUTH 1 -#define ID_DEC 2 -#define ID_SIG 3 - +#define STATE_ACTIVATE 0x07 +#define STATE_TERMINATE 0x03 -#define STATE_ACTIVATE 0x07 -#define STATE_TERMINATE 0x03 - -#define IO_OFFSET_END (unsigned int)-1 -#define IO_OFFSET_MARK (unsigned int)-2 - -#define PIN_ID_PW1 0x81 -#define PIN_ID_PW2 0x82 -#define PIN_ID_PW3 0x83 -#define PIN_ID_RC 0x84 - -#define PIN_MODE_HOST 1 -#define PIN_MODE_SCREEN 2 -#define PIN_MODE_CONFIRM 3 -#define PIN_MODE_TRUST 4 +#define IO_OFFSET_END (unsigned int)-1 +#define IO_OFFSET_MARK (unsigned int)-2 +#define PIN_ID_PW1 0x81 +#define PIN_ID_PW2 0x82 +#define PIN_ID_PW3 0x83 +#define PIN_ID_RC 0x84 +#define PIN_MODE_HOST 1 +#define PIN_MODE_SCREEN 2 +#define PIN_MODE_CONFIRM 3 +#define PIN_MODE_TRUST 4 /* --- INS --- */ -#define INS_EXIT 0x02 +#define INS_EXIT 0x02 -#define INS_SELECT 0xa4 -#define INS_TERMINATE_DF 0xe6 -#define INS_ACTIVATE_FILE 0x44 +#define INS_SELECT 0xa4 +#define INS_TERMINATE_DF 0xe6 +#define INS_ACTIVATE_FILE 0x44 -#define INS_SELECT_DATA 0xa5 -#define INS_GET_DATA 0xca -#define INS_GET_NEXT_DATA 0xcc -#define INS_PUT_DATA 0xda -#define INS_PUT_DATA_ODD 0xdb +#define INS_SELECT_DATA 0xa5 +#define INS_GET_DATA 0xca +#define INS_GET_NEXT_DATA 0xcc +#define INS_PUT_DATA 0xda +#define INS_PUT_DATA_ODD 0xdb -#define INS_VERIFY 0x20 -#define INS_MSE 0x22 -#define INS_CHANGE_REFERENCE_DATA 0x24 -#define INS_RESET_RETRY_COUNTER 0x2c +#define INS_VERIFY 0x20 +#define INS_MSE 0x22 +#define INS_CHANGE_REFERENCE_DATA 0x24 +#define INS_RESET_RETRY_COUNTER 0x2c -#define INS_GEN_ASYM_KEYPAIR 0x47 -#define INS_PSO 0x2a +#define INS_GEN_ASYM_KEYPAIR 0x47 +#define INS_PSO 0x2a //#define INS_COMPUTEDIGSIG 0x2a //#define INS_DECIPHER 0x2a -#define INS_INTERNAL_AUTHENTICATE 0x88 - -#define INS_GET_CHALLENGE 0x84 -#define INS_GET_RESPONSE 0xc0 +#define INS_INTERNAL_AUTHENTICATE 0x88 +#define INS_GET_CHALLENGE 0x84 +#define INS_GET_RESPONSE 0xc0 /* --- IO constants --- */ -#define OFFSET_CLA 0 -#define OFFSET_INS 1 -#define OFFSET_P1 2 -#define OFFSET_P2 3 -#define OFFSET_P3 4 -#define OFFSET_CDATA 5 -#define OFFSET_EXT_CDATA 7 - - -#define SW_OK 0x9000 -#define SW_ALGORITHM_UNSUPPORTED 0x9484 - -#define SW_BYTES_REMAINING_00 0x6100 - -#define SW_WARNING_STATE_UNCHANGED 0x6200 -#define SW_STATE_TERMINATED 0x6285 - -#define SW_MORE_DATA_AVAILABLE 0x6310 - -#define SW_WRONG_LENGTH 0x6700 - -#define SW_LOGICAL_CHANNEL_NOT_SUPPORTED 0x6881 -#define SW_SECURE_MESSAGING_NOT_SUPPORTED 0x6882 -#define SW_LAST_COMMAND_EXPECTED 0x6883 -#define SW_COMMAND_CHAINING_NOT_SUPPORTED 0x6884 - -#define SW_SECURITY_STATUS_NOT_SATISFIED 0x6982 -#define SW_FILE_INVALID 0x6983 -#define SW_PIN_BLOCKED 0x6983 -#define SW_DATA_INVALID 0x6984 -#define SW_CONDITIONS_NOT_SATISFIED 0x6985 -#define SW_COMMAND_NOT_ALLOWED 0x6986 -#define SW_APPLET_SELECT_FAILED 0x6999 - -#define SW_WRONG_DATA 0x6a80 -#define SW_FUNC_NOT_SUPPORTED 0x6a81 -#define SW_FILE_NOT_FOUND 0x6a82 -#define SW_RECORD_NOT_FOUND 0x6a83 -#define SW_FILE_FULL 0x6a84 -#define SW_INCORRECT_P1P2 0x6a86 -#define SW_REFERENCED_DATA_NOT_FOUND 0x6a88 - -#define SW_WRONG_P1P2 0x6b00 -#define SW_CORRECT_LENGTH_00 0x6c00 -#define SW_INS_NOT_SUPPORTED 0x6d00 -#define SW_CLA_NOT_SUPPORTED 0x6e00 - -#define SW_UNKNOWN 0x6f00 - +#define OFFSET_CLA 0 +#define OFFSET_INS 1 +#define OFFSET_P1 2 +#define OFFSET_P2 3 +#define OFFSET_P3 4 +#define OFFSET_CDATA 5 +#define OFFSET_EXT_CDATA 7 + +#define SW_OK 0x9000 +#define SW_ALGORITHM_UNSUPPORTED 0x9484 + +#define SW_BYTES_REMAINING_00 0x6100 + +#define SW_WARNING_STATE_UNCHANGED 0x6200 +#define SW_STATE_TERMINATED 0x6285 + +#define SW_MORE_DATA_AVAILABLE 0x6310 + +#define SW_WRONG_LENGTH 0x6700 + +#define SW_LOGICAL_CHANNEL_NOT_SUPPORTED 0x6881 +#define SW_SECURE_MESSAGING_NOT_SUPPORTED 0x6882 +#define SW_LAST_COMMAND_EXPECTED 0x6883 +#define SW_COMMAND_CHAINING_NOT_SUPPORTED 0x6884 + +#define SW_SECURITY_STATUS_NOT_SATISFIED 0x6982 +#define SW_FILE_INVALID 0x6983 +#define SW_PIN_BLOCKED 0x6983 +#define SW_DATA_INVALID 0x6984 +#define SW_CONDITIONS_NOT_SATISFIED 0x6985 +#define SW_COMMAND_NOT_ALLOWED 0x6986 +#define SW_APPLET_SELECT_FAILED 0x6999 + +#define SW_WRONG_DATA 0x6a80 +#define SW_FUNC_NOT_SUPPORTED 0x6a81 +#define SW_FILE_NOT_FOUND 0x6a82 +#define SW_RECORD_NOT_FOUND 0x6a83 +#define SW_FILE_FULL 0x6a84 +#define SW_INCORRECT_P1P2 0x6a86 +#define SW_REFERENCED_DATA_NOT_FOUND 0x6a88 + +#define SW_WRONG_P1P2 0x6b00 +#define SW_CORRECT_LENGTH_00 0x6c00 +#define SW_INS_NOT_SUPPORTED 0x6d00 +#define SW_CLA_NOT_SUPPORTED 0x6e00 + +#define SW_UNKNOWN 0x6f00 #endif diff --git a/src/gpg_ux_blue.c b/src/gpg_ux_blue.c index 6d64451..56e741d 100644 --- a/src/gpg_ux_blue.c +++ b/src/gpg_ux_blue.c @@ -14,25 +14,21 @@ * 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 --- */ /* ----------------------------------------------------------------------- */ -/* screeen size: - blue; 320x480 +/* screeen size: + blue; 320x480 nanoS: 128x32 */ #if 0 diff --git a/src/gpg_ux_msg.c b/src/gpg_ux_msg.c index c684890..f60d7fd 100644 --- a/src/gpg_ux_msg.c +++ b/src/gpg_ux_msg.c @@ -13,26 +13,25 @@ * limitations under the License. */ -const char * const C_TEMPLATE_TYPE = "Key type"; -const char * const C_TEMPLATE_KEY = "Key"; -const char * const C_INVALID_SELECTION = "Invalid selection"; +const char *const C_TEMPLATE_TYPE = "Key type"; +const char *const C_TEMPLATE_KEY = "Key"; +const char *const C_INVALID_SELECTION = "Invalid selection"; -const char * const C_OK = "OK"; -const char * const C_NOK = "NOK"; +const char *const C_OK = "OK"; +const char *const C_NOK = "NOK"; -const char * const C_WRONG_PIN = "PIN Incorrect"; -const char * const C_RIGHT_PIN = "PIN Correct"; -const char * const C_PIN_CHANGED = "PIN changed"; -const char * const C_PIN_DIFFERS = "2 PINs differs"; -const char * const C_PIN_USER = "User PIN"; -const char * const C_PIN_ADMIN = "Admin PIN"; +const char *const C_WRONG_PIN = "PIN Incorrect"; +const char *const C_RIGHT_PIN = "PIN Correct"; +const char *const C_PIN_CHANGED = "PIN changed"; +const char *const C_PIN_DIFFERS = "2 PINs differs"; +const char *const C_PIN_USER = "User PIN"; +const char *const C_PIN_ADMIN = "Admin PIN"; -const char * const C_VERIFIED = "Verified"; -const char * const C_NOT_VERIFIED = "Not Verified"; -const char * const C_ALLOWED = "Allowed"; -const char * const C_NOT_ALLOWED = "Not Allowed "; +const char *const C_VERIFIED = "Verified"; +const char *const C_NOT_VERIFIED = "Not Verified"; +const char *const C_ALLOWED = "Allowed"; +const char *const C_NOT_ALLOWED = "Not Allowed "; -const char * const C_DEFAULT_MODE = "Default mode"; +const char *const C_DEFAULT_MODE = "Default mode"; - -const char * const C_UIF_LOCKED = "UIF locked"; +const char *const C_UIF_LOCKED = "UIF locked"; diff --git a/src/gpg_ux_msg.h b/src/gpg_ux_msg.h index 38847a6..7e4fa32 100644 --- a/src/gpg_ux_msg.h +++ b/src/gpg_ux_msg.h @@ -16,48 +16,48 @@ #ifndef GPG_UX_MSG_H #define GPG_UX_MSG_H -extern const char * const C_TEMPLATE_TYPE; -extern const char * const C_TEMPLATE_KEY; -extern const char * const C_INVALID_SELECTION; +extern const char *const C_TEMPLATE_TYPE; +extern const char *const C_TEMPLATE_KEY; +extern const char *const C_INVALID_SELECTION; -extern const char * const C_OK; -extern const char * const C_NOK; +extern const char *const C_OK; +extern const char *const C_NOK; -extern const char * const C_WRONG_PIN; -extern const char * const C_RIGHT_PIN; -extern const char * const C_PIN_CHANGED; -extern const char * const C_PIN_DIFFERS ; -extern const char * const C_PIN_USER; -extern const char * const C_PIN_ADMIN; +extern const char *const C_WRONG_PIN; +extern const char *const C_RIGHT_PIN; +extern const char *const C_PIN_CHANGED; +extern const char *const C_PIN_DIFFERS; +extern const char *const C_PIN_USER; +extern const char *const C_PIN_ADMIN; -extern const char * const C_VERIFIED; -extern const char * const C_NOT_VERIFIED; -extern const char * const C_NOT_ALLOWED; +extern const char *const C_VERIFIED; +extern const char *const C_NOT_VERIFIED; +extern const char *const C_NOT_ALLOWED; -extern const char * const C_DEFAULT_MODE; +extern const char *const C_DEFAULT_MODE; -extern const char * const C_UIF_LOCKED; -extern const char * const C_UIF_INVALID; +extern const char *const C_UIF_LOCKED; +extern const char *const C_UIF_INVALID; -#define PICSTR(x) ((char*)PIC(x)) +#define PICSTR(x) ((char *)PIC(x)) -#define TEMPLATE_TYPE PICSTR(C_TEMPLATE_TYPE) -#define TEMPLATE_KEY PICSTR(C_TEMPLATE_KEY) +#define TEMPLATE_TYPE PICSTR(C_TEMPLATE_TYPE) +#define TEMPLATE_KEY PICSTR(C_TEMPLATE_KEY) #define INVALID_SELECTION PICSTR(C_INVALID_SELECTION) -#define OK PICSTR(C_OK) -#define NOK PICSTR(C_NOK) -#define WRONG_PIN PICSTR(C_WRONG_PIN) -#define RIGHT_PIN PICSTR(C_RIGHT_PIN) -#define PIN_CHANGED PICSTR(C_PIN_CHANGED) -#define PIN_DIFFERS PICSTR(C_PIN_DIFFERS) -#define PIN_USER PICSTR(C_PIN_USER) -#define PIN_ADMIN PICSTR(C_PIN_ADMIN) -#define VERIFIED PICSTR(C_VERIFIED) -#define NOT_VERIFIED PICSTR(C_NOT_VERIFIED) -#define ALLOWED PICSTR(C_ALLOWED) -#define NOT_ALLOWED PICSTR(C_NOT_ALLOWED) -#define DEFAULT_MODE PICSTR(C_DEFAULT_MODE) -#define UIF_LOCKED PICSTR(C_UIF_LOCKED) -#define UIF_INVALID PICSTR(C_UIF_INVALID) +#define OK PICSTR(C_OK) +#define NOK PICSTR(C_NOK) +#define WRONG_PIN PICSTR(C_WRONG_PIN) +#define RIGHT_PIN PICSTR(C_RIGHT_PIN) +#define PIN_CHANGED PICSTR(C_PIN_CHANGED) +#define PIN_DIFFERS PICSTR(C_PIN_DIFFERS) +#define PIN_USER PICSTR(C_PIN_USER) +#define PIN_ADMIN PICSTR(C_PIN_ADMIN) +#define VERIFIED PICSTR(C_VERIFIED) +#define NOT_VERIFIED PICSTR(C_NOT_VERIFIED) +#define ALLOWED PICSTR(C_ALLOWED) +#define NOT_ALLOWED PICSTR(C_NOT_ALLOWED) +#define DEFAULT_MODE PICSTR(C_DEFAULT_MODE) +#define UIF_LOCKED PICSTR(C_UIF_LOCKED) +#define UIF_INVALID PICSTR(C_UIF_INVALID) #endif diff --git a/src/gpg_ux_nanos.c b/src/gpg_ux_nanos.c index 72ded9f..710a609 100644 --- a/src/gpg_ux_nanos.c +++ b/src/gpg_ux_nanos.c @@ -13,7 +13,7 @@ * limitations under the License. */ - +#ifdef UI_NANO_S #include "os.h" #include "cx.h" @@ -27,54 +27,51 @@ #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); -void ui_menu_tmpl_set_action(unsigned int value) ; +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); +void ui_menu_tmpl_set_action(unsigned int value); const ux_menu_entry_t ui_menu_tmpl_key[]; -void ui_menu_tmpl_key_action(unsigned int value); +void ui_menu_tmpl_key_action(unsigned int value); const ux_menu_entry_t ui_menu_tmpl_type[]; -void ui_menu_tmpl_type_action(unsigned int value); +void ui_menu_tmpl_type_action(unsigned int value); const ux_menu_entry_t ui_menu_seed[]; -void ui_menu_seed_display(unsigned int value); -const bagl_element_t* ui_menu_seed_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element) ; -void ui_menu_seed_action(unsigned int value) ; +void ui_menu_seed_display(unsigned int value); +const bagl_element_t *ui_menu_seed_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element); +void ui_menu_seed_action(unsigned int value); -const ux_menu_entry_t ui_menu_reset[] ; -void ui_menu_reset_action(unsigned int value); +const ux_menu_entry_t ui_menu_reset[]; +void ui_menu_reset_action(unsigned int value); #if GPG_MULTISLOT const ux_menu_entry_t ui_menu_slot[]; -void ui_menu_slot_display(unsigned int value); -const bagl_element_t* ui_menu_slot_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element); -void ui_menu_slot_action(unsigned int value); +void ui_menu_slot_display(unsigned int value); +const bagl_element_t *ui_menu_slot_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element); +void ui_menu_slot_action(unsigned int value); #endif -const ux_menu_entry_t ui_menu_settings[] ; +const ux_menu_entry_t ui_menu_settings[]; const ux_menu_entry_t ui_menu_main[]; -void ui_menu_main_display(unsigned int value) ; -const bagl_element_t* ui_menu_main_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element); +void ui_menu_main_display(unsigned int value); +const bagl_element_t *ui_menu_main_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element); const bagl_element_t ui_pinconfirm_nanos[]; -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) ; - +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); -unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int button_mask_counter); -unsigned int ui_pinentry_prepro(const bagl_element_t* element) ; -static unsigned int validate_pin(); +void ui_menu_pinentry_display(unsigned int value); +void ui_menu_pinentry_action(unsigned int value); +unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int button_mask_counter); +unsigned int ui_pinentry_prepro(const bagl_element_t *element); +static unsigned int validate_pin(); /* ------------------------------- Helpers UX ------------------------------- */ void ui_CCID_reset(void) { @@ -82,65 +79,74 @@ void ui_CCID_reset(void) { io_usb_ccid_set_card_inserted(1); } -void ui_info(const char* msg1, const char* msg2, const void *menu_display, unsigned int value) { +void ui_info(const char *msg1, const char *msg2, const void *menu_display, unsigned int value) { os_memset(&G_gpg_vstate.ui_dogsays[0], 0, sizeof(ux_menu_entry_t)); G_gpg_vstate.ui_dogsays[0].callback = menu_display; G_gpg_vstate.ui_dogsays[0].userid = value; G_gpg_vstate.ui_dogsays[0].line1 = msg1; G_gpg_vstate.ui_dogsays[0].line2 = msg2; - os_memset(&G_gpg_vstate.ui_dogsays[1],0, sizeof(ux_menu_entry_t)); + os_memset(&G_gpg_vstate.ui_dogsays[1], 0, sizeof(ux_menu_entry_t)); 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); +unsigned int ui_uifconfirm_prepro(const bagl_element_t *element); const bagl_element_t ui_uifconfirm_nanos[] = { - // type userid x y w h str rad fill fg bg font_id icon_id - { {BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, - NULL, - 0, - 0, 0, - NULL, NULL, NULL}, - - { {BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS }, - NULL, - 0, - 0, 0, - NULL, NULL, NULL }, - - { {BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK }, - NULL, - 0, - 0, 0, - NULL, NULL, NULL }, - - { {BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, - G_gpg_vstate.menu, - 0, - 0, 0, - NULL, NULL, NULL }, - { {BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, - G_gpg_vstate.menu, - 0, - 0, 0, - NULL, NULL, NULL }, + // type userid x y w h str rad fill fg bg font_id icon_id + {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL, 0, 0, 0, NULL, NULL, NULL}, + + {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, + BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + G_gpg_vstate.menu, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, + BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + G_gpg_vstate.menu, + 0, + 0, + 0, + NULL, + NULL, + NULL}, }; void ui_menu_uifconfirm_display(unsigned int value) { - UX_DISPLAY(ui_uifconfirm_nanos, (void*)ui_uifconfirm_prepro); + UX_DISPLAY(ui_uifconfirm_nanos, (void *)ui_uifconfirm_prepro); } -unsigned int ui_uifconfirm_prepro(const bagl_element_t* element) { +unsigned int ui_uifconfirm_prepro(const bagl_element_t *element) { if (element->component.userid == 1) { snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Confirm:"); return 1; } if (element->component.userid == 2) { - unsigned int uif_case = (G_gpg_vstate.io_ins<<16)|(G_gpg_vstate.io_p1<<8)|(G_gpg_vstate.io_p2); + unsigned int uif_case = (G_gpg_vstate.io_ins << 16) | (G_gpg_vstate.io_p1 << 8) | (G_gpg_vstate.io_p2); switch (uif_case) { case 0x002A9E9A: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Signature"); @@ -154,7 +160,7 @@ unsigned int ui_uifconfirm_prepro(const bagl_element_t* element) { case 0x00880000: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Authentication"); return 1; - } + } } snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Please Cancel"); return 1; @@ -164,16 +170,16 @@ unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int b unsigned int sw; sw = 0x6985; - switch(button_mask) { - case BUTTON_EVT_RELEASED|BUTTON_LEFT: // CANCEL + switch (button_mask) { + case BUTTON_EVT_RELEASED | BUTTON_LEFT: // CANCEL gpg_io_discard(1); - gpg_io_insert_u16(sw); + gpg_io_insert_u16(sw); gpg_io_do(IO_RETURN_AFTER_TX); ui_menu_main_display(0); - sw = 0x6985; + sw = 0x6985; break; - case BUTTON_EVT_RELEASED|BUTTON_RIGHT: // OK + case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // OK BEGIN_TRY { TRY { G_gpg_vstate.UIF_flags = 1; @@ -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 { @@ -198,13 +203,13 @@ unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int b } FINALLY { G_gpg_vstate.UIF_flags = 0; - gpg_io_insert_u16(sw); + gpg_io_insert_u16(sw); gpg_io_do(IO_RETURN_AFTER_TX); ui_menu_main_display(0); } break; - - } END_TRY; + } + END_TRY; } return 0; } @@ -212,51 +217,62 @@ unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int b /* ------------------------------ PIN CONFIRM UX ----------------------------- */ 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_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS }, - NULL, - 0, - 0, 0, - NULL, NULL, NULL }, - - { {BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK }, - NULL, - 0, - 0, 0, - NULL, NULL, NULL }, - - { {BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, - G_gpg_vstate.menu, - 0, - 0, 0, - NULL, NULL, NULL }, - { {BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, - G_gpg_vstate.menu, - 0, - 0, 0, - NULL, NULL, NULL }, + // type userid x y w h str rad fill fg bg font_id icon_id + {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL, 0, 0, 0, NULL, NULL, NULL}, + + {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, + BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + G_gpg_vstate.menu, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, + BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + G_gpg_vstate.menu, + 0, + 0, + 0, + NULL, + NULL, + NULL}, }; void ui_menu_pinconfirm_display(unsigned int value) { - UX_DISPLAY(ui_pinconfirm_nanos, (void*)ui_pinconfirm_prepro); + UX_DISPLAY(ui_pinconfirm_nanos, (void *)ui_pinconfirm_prepro); } -unsigned int ui_pinconfirm_prepro(const bagl_element_t* element) { +unsigned int ui_pinconfirm_prepro(const bagl_element_t *element) { if (element->component.userid == 1) { 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), "Confirm PIN"); return 1; - } + } } 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); + 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); return 1; } } @@ -268,15 +284,15 @@ unsigned int ui_pinconfirm_nanos_button(unsigned int button_mask, unsigned int b unsigned int sw; sw = 0x6985; - switch(button_mask) { - case BUTTON_EVT_RELEASED|BUTTON_LEFT: // CANCEL - gpg_pin_set_verified(G_gpg_vstate.io_p2,0); - sw = 0x6985; + switch (button_mask) { + case BUTTON_EVT_RELEASED | BUTTON_LEFT: // CANCEL + gpg_pin_set_verified(G_gpg_vstate.io_p2, 0); + sw = 0x6985; break; - case BUTTON_EVT_RELEASED|BUTTON_RIGHT: // OK - gpg_pin_set_verified(G_gpg_vstate.io_p2,1); - sw = 0x9000; + case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // OK + gpg_pin_set_verified(G_gpg_vstate.io_p2, 1); + sw = 0x9000; break; default: return 0; @@ -287,176 +303,187 @@ unsigned int ui_pinconfirm_nanos_button(unsigned int button_mask, unsigned int b ui_menu_main_display(0); return 0; } - -/* ------------------------------- PIN ENTRY UX ------------------------------ */ +/* ------------------------------- 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_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_DOWN }, - NULL, - 0, - 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 }, - - { {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 }, - G_gpg_vstate.menu, - 0, - 0, 0, - NULL, NULL, NULL }, + // type userid x y w h str rad fill fg bg font_id icon_id + {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL, 0, 0, 0, NULL, NULL, NULL}, + + {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_DOWN}, + NULL, + 0, + 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}, + + {{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}, + G_gpg_vstate.menu, + 0, + 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) { os_memset(G_gpg_vstate.ux_pinentry, 0, sizeof(G_gpg_vstate.ux_pinentry)); - G_gpg_vstate.ux_pinentry[0]=1; - G_gpg_vstate.ux_pinentry[1]=5; + G_gpg_vstate.ux_pinentry[0] = 1; + G_gpg_vstate.ux_pinentry[1] = 5; } - UX_DISPLAY(ui_pinentry_nanos, (void*)ui_pinentry_prepro); + UX_DISPLAY(ui_pinentry_nanos, (void *)ui_pinentry_prepro); } -unsigned int ui_pinentry_prepro(const bagl_element_t* element) { +unsigned int ui_pinentry_prepro(const bagl_element_t *element) { if (element->component.userid == 1) { - if (G_gpg_vstate.io_ins == 0x24) { - switch (G_gpg_vstate.io_p1) { + 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"); + 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 - 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]]; +#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]]; } - #else - for (i = 1; i< G_gpg_vstate.ux_pinentry[0]; i++) { - G_gpg_vstate.menu[i] = '*'; +#else + for (i = 1; i < G_gpg_vstate.ux_pinentry[0]; i++) { + G_gpg_vstate.menu[i] = '*'; } - G_gpg_vstate.menu[i] = C_pin_digit[G_gpg_vstate.ux_pinentry[i]]; + G_gpg_vstate.menu[i] = C_pin_digit[G_gpg_vstate.ux_pinentry[i]]; i++; - #endif - for (; i<= GPG_MAX_PW_LENGTH;i++) { +#endif + for (; i <= GPG_MAX_PW_LENGTH; i++) { G_gpg_vstate.menu[i] = '-'; } - G_gpg_vstate.menu[i] = 0; + G_gpg_vstate.menu[i] = 0; } - + return 1; } unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int button_mask_counter) { unsigned int offset = G_gpg_vstate.ux_pinentry[0]; - unsigned m_pinentry; - char digit ; + unsigned m_pinentry; + char digit; m_pinentry = 1; - switch(button_mask) { - case BUTTON_EVT_RELEASED|BUTTON_LEFT: // Down - if (G_gpg_vstate.ux_pinentry[offset]) { - G_gpg_vstate.ux_pinentry[offset]--; - } else { - G_gpg_vstate.ux_pinentry[offset] = sizeof(C_pin_digit)-1; - } - ui_menu_pinentry_display(1); - break; - - case BUTTON_EVT_RELEASED|BUTTON_RIGHT: //up + switch (button_mask) { + case BUTTON_EVT_RELEASED | BUTTON_LEFT: // Down + if (G_gpg_vstate.ux_pinentry[offset]) { + G_gpg_vstate.ux_pinentry[offset]--; + } else { + G_gpg_vstate.ux_pinentry[offset] = sizeof(C_pin_digit) - 1; + } + ui_menu_pinentry_display(1); + break; + + case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // up G_gpg_vstate.ux_pinentry[offset]++; if (G_gpg_vstate.ux_pinentry[offset] == sizeof(C_pin_digit)) { G_gpg_vstate.ux_pinentry[offset] = 0; } ui_menu_pinentry_display(1); break; - - case BUTTON_EVT_RELEASED|BUTTON_LEFT|BUTTON_RIGHT: - digit = C_pin_digit[G_gpg_vstate.ux_pinentry[offset]]; - //next digit + + case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT: + digit = C_pin_digit[G_gpg_vstate.ux_pinentry[offset]]; + // next digit if ((digit >= '0') && (digit <= '9')) { - offset ++; + offset++; G_gpg_vstate.ux_pinentry[0] = offset; - if (offset == GPG_MAX_PW_LENGTH+1) { - validate_pin(); + if (offset == GPG_MAX_PW_LENGTH + 1) { + validate_pin(); } else { G_gpg_vstate.ux_pinentry[offset] = 5; ui_menu_pinentry_display(1); } - } - //cancel digit + } + // cancel digit else if (digit == 'C') { - if (offset > 1) { + if (offset > 1) { offset--; G_gpg_vstate.ux_pinentry[0] = offset; } ui_menu_pinentry_display(1); - } - //validate pin + } + // validate pin else if (digit == 'V') { - G_gpg_vstate.ux_pinentry[0] = offset-1; + G_gpg_vstate.ux_pinentry[0] = offset - 1; validate_pin(); } - //cancel input without check - else { //(digit == 'A') + // cancel input without check + else { //(digit == 'A') gpg_io_discard(0); gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED); gpg_io_do(IO_RETURN_AFTER_TX); ui_menu_main_display(0); - } + } } - return 0; + return 0; } // >= 0 static unsigned int validate_pin() { unsigned int offset, len, sw; - gpg_pin_t *pin; + 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]]; + 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]]; } - if (G_gpg_vstate.io_ins == 0x20) { + if (G_gpg_vstate.io_ins == 0x20) { pin = gpg_pin_get_pin(G_gpg_vstate.io_p2); - sw = gpg_pin_check(pin, G_gpg_vstate.io_p2, (unsigned char*)(G_gpg_vstate.menu+1), G_gpg_vstate.ux_pinentry[0]); + sw = gpg_pin_check(pin, G_gpg_vstate.io_p2, (unsigned char *)(G_gpg_vstate.menu + 1), G_gpg_vstate.ux_pinentry[0]); gpg_io_discard(1); gpg_io_insert_u16(sw); gpg_io_do(IO_RETURN_AFTER_TX); if (sw != SW_OK) { - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %d tries remaining", pin->counter ); + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %d tries remaining", pin->counter); ui_info(WRONG_PIN, G_gpg_vstate.menu, ui_menu_main_display, 0); } else { ui_menu_main_display(0); @@ -466,33 +493,35 @@ static unsigned int validate_pin() { if (G_gpg_vstate.io_ins == 0x24) { if (G_gpg_vstate.io_p1 <= 2) { gpg_io_insert_u8(G_gpg_vstate.ux_pinentry[0]); - gpg_io_insert((unsigned char*)(G_gpg_vstate.menu+1), G_gpg_vstate.ux_pinentry[0]); + gpg_io_insert((unsigned char *)(G_gpg_vstate.menu + 1), G_gpg_vstate.ux_pinentry[0]); G_gpg_vstate.io_p1++; } 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); - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %d tries remaining", pin->counter ); - ui_info(WRONG_PIN, NULL, ui_menu_main_display, 0); + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %d tries remaining", pin->counter); + ui_info(WRONG_PIN, NULL, ui_menu_main_display, 0); return 0; } - 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)) { + 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)) { gpg_io_discard(1); gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED); gpg_io_do(IO_RETURN_AFTER_TX); ui_info(PIN_DIFFERS, NULL, ui_menu_main_display, 0); } else { - gpg_pin_set(gpg_pin_get_pin(G_gpg_vstate.io_p2), G_gpg_vstate.work.io_buffer+offset+ 1, len); + gpg_pin_set(gpg_pin_get_pin(G_gpg_vstate.io_p2), G_gpg_vstate.work.io_buffer + offset + 1, len); gpg_io_discard(1); - gpg_io_insert_u16(SW_OK); + gpg_io_insert_u16(SW_OK); gpg_io_do(IO_RETURN_AFTER_TX); - //ui_info(PIN_CHANGED, NULL, ui_menu_main_display, 0); + // ui_info(PIN_CHANGED, NULL, ui_menu_main_display, 0); ui_menu_main_display(0); } return 0; @@ -504,67 +533,65 @@ static unsigned int validate_pin() { } /* ------------------------------- template UX ------------------------------- */ -#define LABEL_SIG "Signature" -#define LABEL_AUT "Authentication" -#define LABEL_DEC "Decryption" +#define LABEL_SIG "Signature" +#define LABEL_AUT "Authentication" +#define LABEL_DEC "Decryption" -#define LABEL_RSA2048 "RSA 2048" -#define LABEL_RSA3072 "RSA 3072" -#define LABEL_RSA4096 "RSA 4096" -#define LABEL_NISTP256 "NIST P256" +#define LABEL_RSA2048 "RSA 2048" +#define LABEL_RSA3072 "RSA 3072" +#define LABEL_RSA4096 "RSA 4096" +#define LABEL_NISTP256 "NIST P256" //#define LABEL_NISTP384 "NIST P384" //#define LABEL_NISTP521 "NIST P521" -#define LABEL_SECP256K1 "SEPC 256K1" +#define LABEL_SECP256K1 "SEPC 256K1" //#define LABEL_BPOOL256R1 "Brainpool 256R1" //#define LABEL_BPOOL384R1 "Brainpool 384R1" //#define LABEL_BPOOL512R1 "Brainpool 512R1" -#define LABEL_Ed25519 "Ed25519" - -const ux_menu_entry_t ui_menu_template[] = { - {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 -}; +#define LABEL_Ed25519 "Ed25519" + +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}; void ui_menu_template_display(unsigned int value) { - UX_MENU_DISPLAY(value, ui_menu_template, ui_menu_template_preprocessor); + UX_MENU_DISPLAY(value, ui_menu_template, ui_menu_template_preprocessor); } -const bagl_element_t* ui_menu_template_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element) { - if(element->component.userid==0x20) { +const bagl_element_t *ui_menu_template_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element) { + if (element->component.userid == 0x20) { if (entry == &ui_menu_template[0]) { - switch(G_gpg_vstate.ux_key) { - case 1: + switch (G_gpg_vstate.ux_key) { + case 1: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s", LABEL_SIG); break; - case 2: + case 2: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s", LABEL_DEC); break; - case 3: + case 3: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s", LABEL_AUT); break; default: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Choose key..."); break; } - element->text = G_gpg_vstate.menu; + element->text = G_gpg_vstate.menu; } if (entry == &ui_menu_template[1]) { - switch(G_gpg_vstate.ux_type) { + switch (G_gpg_vstate.ux_type) { case 2048: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_RSA2048); + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_RSA2048); break; case 3072: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_RSA3072); + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_RSA3072); break; case 4096: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_RSA4096); + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_RSA4096); break; case CX_CURVE_SECP256R1: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_NISTP256); + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_NISTP256); break; /* case CX_CURVE_SECP384R1: @@ -590,69 +617,66 @@ const bagl_element_t* ui_menu_template_preprocessor(const ux_menu_entry_t* entry */ case CX_CURVE_Ed25519: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_Ed25519); + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %s", LABEL_Ed25519); break; default: snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Choose type..."); break; - } + } element->text = G_gpg_vstate.menu; } } - return element; + return element; } - - - -void ui_menu_tmpl_set_action(unsigned int value) { - LV(attributes,GPG_KEY_ATTRIBUTES_LENGTH); - gpg_key_t* dest; - const char* err; +void ui_menu_tmpl_set_action(unsigned int value) { + LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH); + gpg_key_t * dest; + const char * err; const unsigned char *oid; - unsigned int oid_len; + unsigned int oid_len; err = NULL; - + os_memset(&attributes, 0, sizeof(attributes)); switch (G_gpg_vstate.ux_type) { case 2048: case 3072: case 4096: attributes.value[0] = 0x01; - attributes.value[1] = (G_gpg_vstate.ux_type>>8) &0xFF; - attributes.value[2] = G_gpg_vstate.ux_type&0xFF; + attributes.value[1] = (G_gpg_vstate.ux_type >> 8) & 0xFF; + attributes.value[2] = G_gpg_vstate.ux_type & 0xFF; attributes.value[3] = 0x00; attributes.value[4] = 0x20; attributes.value[5] = 0x01; - attributes.length = 6; + attributes.length = 6; break; case CX_CURVE_SECP256R1: - //case CX_CURVE_SECP256K1: - //case CX_CURVE_SECP384R1: - //case CX_CURVE_SECP521R1: - //case CX_CURVE_BrainPoolP256R1: - //case CX_CURVE_BrainPoolP384R1: - //case CX_CURVE_BrainPoolP512R1: - if (G_gpg_vstate.ux_key == 2) { - attributes.value[0] = 18; //ecdh + // case CX_CURVE_SECP256K1: + // case CX_CURVE_SECP384R1: + // case CX_CURVE_SECP521R1: + // case CX_CURVE_BrainPoolP256R1: + // case CX_CURVE_BrainPoolP384R1: + // case CX_CURVE_BrainPoolP512R1: + if (G_gpg_vstate.ux_key == 2) { + attributes.value[0] = 18; // ecdh } else { - attributes.value[0] = 19; //ecdsa + attributes.value[0] = 19; // ecdsa } oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len); - os_memmove(attributes.value+1, oid, sizeof(oid_len)); - attributes.length = 1+oid_len; + os_memmove(attributes.value + 1, oid, sizeof(oid_len)); + attributes.length = 1 + oid_len; break; - case CX_CURVE_Ed25519: + case CX_CURVE_Ed25519: if (G_gpg_vstate.ux_key == 2) { - attributes.value[0] = 18; //ecdh - os_memmove(attributes.value+1, C_OID_cv25519, sizeof(C_OID_cv25519)); - attributes.length = 1+sizeof(C_OID_cv25519); + attributes.value[0] = 18; // ecdh + os_memmove(attributes.value + 1, C_OID_cv25519, sizeof(C_OID_cv25519)); + attributes.length = 1 + sizeof(C_OID_cv25519); } else { - attributes.value[0] = 22; //eddsa - os_memmove(attributes.value+1, C_OID_Ed25519, sizeof(C_OID_Ed25519)); - attributes.length = 1+sizeof(C_OID_Ed25519); + attributes.value[0] = 22; // eddsa + os_memmove(attributes.value + 1, C_OID_Ed25519, sizeof(C_OID_Ed25519)); + attributes.length = 1 + sizeof(C_OID_Ed25519); } break; @@ -662,7 +686,7 @@ void ui_menu_tmpl_set_action(unsigned int value) { } dest = NULL; - switch(G_gpg_vstate.ux_key) { + switch (G_gpg_vstate.ux_key) { case 1: dest = &G_gpg_vstate.kslot->sig; break; @@ -676,7 +700,7 @@ void ui_menu_tmpl_set_action(unsigned int value) { err = TEMPLATE_KEY; goto ERROR; } - + gpg_nvm_write(dest, NULL, sizeof(gpg_key_t)); gpg_nvm_write(&dest->attributes, &attributes, sizeof(attributes)); ui_info(OK, NULL, ui_menu_template_display, 0); @@ -684,65 +708,57 @@ 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}, - {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 -}; +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}; 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}, - {NULL, ui_menu_tmpl_type_action, 4096, NULL, LABEL_RSA4096, NULL, 0, 0}, - {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256R1, NULL, LABEL_NISTP256, NULL, 0, 0}, -// {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP384R1, NULL, LABEL_NISTP384, NULL, 0, 0}, -// {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP521R1, NULL, LABEL_NISTP521, NULL, 0, 0}, -// {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256K1, NULL, LABEL_SECP256K1, NULL, 0, 0}, -// {NULL, ui_menu_tmpl_type_action, CX_CURVE_BrainPoolP256R1, NULL, LABEL_BPOOL256R1, NULL, 0, 0}, -// {NULL, ui_menu_tmpl_type_action, CX_CURVE_BrainPoolP384R1, NULL, LABEL_BPOOL384R1, NULL, 0, 0}, -// {NULL, ui_menu_tmpl_type_action, CX_CURVE_BrainPoolP512R1, NULL, LABEL_BPOOL512R1, NULL, 0, 0}, - {NULL, ui_menu_tmpl_type_action, CX_CURVE_Ed25519, NULL, LABEL_Ed25519, NULL, 0, 0}, - {ui_menu_template, NULL, 0, &C_badge_back, "Back", NULL, 61, 40}, - UX_MENU_END -}; + {NULL, ui_menu_tmpl_type_action, 2048, NULL, LABEL_RSA2048, NULL, 0, 0}, + {NULL, ui_menu_tmpl_type_action, 3072, NULL, LABEL_RSA3072, NULL, 0, 0}, + {NULL, ui_menu_tmpl_type_action, 4096, NULL, LABEL_RSA4096, NULL, 0, 0}, + {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256R1, NULL, LABEL_NISTP256, NULL, 0, 0}, + // {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP384R1, NULL, LABEL_NISTP384, NULL, 0, 0}, + // {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP521R1, NULL, LABEL_NISTP521, NULL, 0, 0}, + // {NULL, ui_menu_tmpl_type_action, CX_CURVE_SECP256K1, NULL, LABEL_SECP256K1, NULL, 0, 0}, + // {NULL, ui_menu_tmpl_type_action, CX_CURVE_BrainPoolP256R1, NULL, LABEL_BPOOL256R1, NULL, 0, 0}, + // {NULL, ui_menu_tmpl_type_action, CX_CURVE_BrainPoolP384R1, NULL, LABEL_BPOOL384R1, NULL, 0, 0}, + // {NULL, ui_menu_tmpl_type_action, CX_CURVE_BrainPoolP512R1, NULL, LABEL_BPOOL512R1, NULL, 0, 0}, + {NULL, ui_menu_tmpl_type_action, CX_CURVE_Ed25519, NULL, LABEL_Ed25519, NULL, 0, 0}, + {ui_menu_template, NULL, 0, &C_badge_back, "Back", NULL, 61, 40}, + UX_MENU_END}; void ui_menu_tmpl_type_action(unsigned int value) { G_gpg_vstate.ux_type = value; - ui_menu_template_display(1); + ui_menu_template_display(1); } /* --------------------------------- SEED UX --------------------------------- */ -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 -}; +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}; void ui_menu_seed_display(unsigned int value) { UX_MENU_DISPLAY(value, ui_menu_seed, ui_menu_seed_preprocessor); } -const bagl_element_t* ui_menu_seed_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element) { - if(element->component.userid==0x20) { - if (entry == &ui_menu_seed[0]) { - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "< %s >", G_gpg_vstate.seed_mode?"ON":"OFF"); +const bagl_element_t *ui_menu_seed_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element) { + if (element->component.userid == 0x20) { + if (entry == &ui_menu_seed[0]) { + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "< %s >", G_gpg_vstate.seed_mode ? "ON" : "OFF"); element->text = G_gpg_vstate.menu; - } + } } return element; } @@ -752,37 +768,34 @@ 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); -const bagl_element_t* ui_menu_pinmode_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element); -void ui_menu_pinmode_action(unsigned int value); +void ui_menu_pinmode_display(unsigned int value); +const bagl_element_t *ui_menu_pinmode_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element); +void ui_menu_pinmode_action(unsigned int value); const ux_menu_entry_t ui_menu_pinmode[] = { - {NULL, NULL, -1, NULL, "Choose:", NULL, 0, 0}, - {NULL, ui_menu_pinmode_action, 0x8000|PIN_MODE_HOST, NULL, "Host", NULL, 0, 0}, - {NULL, ui_menu_pinmode_action, 0x8000|PIN_MODE_SCREEN, NULL, "On Screen", NULL, 0, 0}, - {NULL, ui_menu_pinmode_action, 0x8000|PIN_MODE_CONFIRM, NULL, "Confirm only", NULL, 0, 0}, - {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 -}; + {NULL, NULL, -1, NULL, "Choose:", NULL, 0, 0}, + {NULL, ui_menu_pinmode_action, 0x8000 | PIN_MODE_HOST, NULL, "Host", NULL, 0, 0}, + {NULL, ui_menu_pinmode_action, 0x8000 | PIN_MODE_SCREEN, NULL, "On Screen", NULL, 0, 0}, + {NULL, ui_menu_pinmode_action, 0x8000 | PIN_MODE_CONFIRM, NULL, "Confirm only", NULL, 0, 0}, + {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}; void ui_menu_pinmode_display(unsigned int value) { - UX_MENU_DISPLAY(value, ui_menu_pinmode, ui_menu_pinmode_preprocessor); + UX_MENU_DISPLAY(value, ui_menu_pinmode, ui_menu_pinmode_preprocessor); } -const bagl_element_t* ui_menu_pinmode_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element) { - 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), - id == N_gpg_pstate->config_pin[0] ? "#" : " ", /* default */ - id == G_gpg_vstate.pinmode ? "+" : " " /* selected*/); - element->text = G_gpg_vstate.menu; +const bagl_element_t *ui_menu_pinmode_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element) { + 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), + id == N_gpg_pstate->config_pin[0] ? "#" : " ", /* default */ + id == G_gpg_vstate.pinmode ? "+" : " " /* selected*/); + element->text = G_gpg_vstate.menu; element->component.height = 32; } } @@ -791,47 +804,45 @@ const bagl_element_t* ui_menu_pinmode_preprocessor(const ux_menu_entry_t* entry void ui_menu_pinmode_action(unsigned int value) { unsigned char s; - value = value&0x7FFF; + value = value & 0x7FFF; if (value == 128) { if (G_gpg_vstate.pinmode != N_gpg_pstate->config_pin[0]) { if (G_gpg_vstate.pinmode == PIN_MODE_TRUST) { - ui_info(DEFAULT_MODE, NOT_ALLOWED, ui_menu_pinmode_display,0); - return; + ui_info(DEFAULT_MODE, NOT_ALLOWED, ui_menu_pinmode_display, 0); + return; } - //set new mode + // set new mode s = G_gpg_vstate.pinmode; - gpg_nvm_write(&N_gpg_pstate->config_pin[0], &s,1); - //disactivate pinpad if any + gpg_nvm_write(&N_gpg_pstate->config_pin[0], &s, 1); + // disactivate pinpad if any if (G_gpg_vstate.pinmode == PIN_MODE_HOST) { - s = 0; - } else { + s = 0; + } else { s = 3; } //#warning USBD_CCID_activate_pinpad commented USBD_CCID_activate_pinpad(s); } - } - else { + } else { switch (value) { case PIN_MODE_HOST: case PIN_MODE_SCREEN: case PIN_MODE_CONFIRM: if (!gpg_pin_is_verified(PIN_ID_PW2)) { - ui_info(PIN_USER, NOT_VERIFIED, ui_menu_pinmode_display,0); - return; + ui_info(PIN_USER, NOT_VERIFIED, ui_menu_pinmode_display, 0); + return; } break; - - + case PIN_MODE_TRUST: if (!gpg_pin_is_verified(PIN_ID_PW3)) { - ui_info(PIN_ADMIN, NOT_VERIFIED, ui_menu_pinmode_display,0); + ui_info(PIN_ADMIN, NOT_VERIFIED, ui_menu_pinmode_display, 0); return; } break; default: - ui_info(INVALID_SELECTION, NULL, ui_menu_pinmode_display,0); - return; + ui_info(INVALID_SELECTION, NULL, ui_menu_pinmode_display, 0); + return; } G_gpg_vstate.pinmode = value; } @@ -839,47 +850,42 @@ 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}, - {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 -}; +void ui_menu_uifmode_display(unsigned int value); +const bagl_element_t *ui_menu_uifmode_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element); +void ui_menu_uifmode_action(unsigned int value); + +const ux_menu_entry_t ui_menu_uifmode[] = {{NULL, NULL, -1, NULL, "Activate (+) for:", NULL, 0, 0}, + {NULL, ui_menu_uifmode_action, 1, NULL, "Signature", NULL, 0, 0}, + {NULL, ui_menu_uifmode_action, 2, NULL, "Decryption", NULL, 0, 0}, + {NULL, ui_menu_uifmode_action, 3, NULL, "Authentication", NULL, 0, 0}, + {ui_menu_settings, NULL, 0, &C_badge_back, "Back", NULL, 61, 40}, + UX_MENU_END}; void ui_menu_uifmode_display(unsigned int value) { - UX_MENU_DISPLAY(value, ui_menu_uifmode, ui_menu_uifmode_preprocessor); + UX_MENU_DISPLAY(value, ui_menu_uifmode, ui_menu_uifmode_preprocessor); } -const bagl_element_t* ui_menu_uifmode_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element) { - if (element->component.userid==0x20) { - if ((entry->userid >= 1) && (entry->userid<=3)) { - unsigned char uif[2] ; +const bagl_element_t *ui_menu_uifmode_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element) { + if (element->component.userid == 0x20) { + if ((entry->userid >= 1) && (entry->userid <= 3)) { + unsigned char uif[2]; uif[0] = 0; uif[1] = 0; switch (entry->userid) { - case 1: - *uif = G_gpg_vstate.kslot->sig.UIF[0]?'+':' '; + case 1: + *uif = G_gpg_vstate.kslot->sig.UIF[0] ? '+' : ' '; break; - case 2: - *uif = G_gpg_vstate.kslot->dec.UIF[0]?'+':' '; + case 2: + *uif = G_gpg_vstate.kslot->dec.UIF[0] ? '+' : ' '; break; - case 3: - *uif = G_gpg_vstate.kslot->aut.UIF[0]?'+':' '; + case 3: + *uif = G_gpg_vstate.kslot->aut.UIF[0] ? '+' : ' '; break; } - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s %s", - (char*)PIC(entry->line1), uif); - element->text = G_gpg_vstate.menu; + 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; } } @@ -887,47 +893,48 @@ const bagl_element_t* ui_menu_uifmode_preprocessor(const ux_menu_entry_t* entry } void ui_menu_uifmode_action(unsigned int value) { - unsigned char *uif; - unsigned char new_uif; - switch (value) { - case 1: - uif = &G_gpg_vstate.kslot->sig.UIF[0]; - break; - case 2: - uif = &G_gpg_vstate.kslot->dec.UIF[0]; - break; - case 3: - uif = &G_gpg_vstate.kslot->aut.UIF[0]; - break; - default: - ui_info(INVALID_SELECTION, NULL, ui_menu_uifmode_display,0); - return; - } - if (uif[0] == 0) { - new_uif = 1; - gpg_nvm_write(&uif[0], &new_uif, 1); - } else if (uif[0] == 1) { - new_uif = 0; - gpg_nvm_write(&uif[0], &new_uif, 1) ; - } else /*if (uif[0] == 2 )*/ { - ui_info(UIF_LOCKED, NULL, ui_menu_uifmode_display,0); - return; - } + unsigned char *uif; + unsigned char new_uif; + switch (value) { + case 1: + uif = &G_gpg_vstate.kslot->sig.UIF[0]; + break; + case 2: + uif = &G_gpg_vstate.kslot->dec.UIF[0]; + break; + case 3: + uif = &G_gpg_vstate.kslot->aut.UIF[0]; + break; + default: + ui_info(INVALID_SELECTION, NULL, ui_menu_uifmode_display, 0); + return; + } + if (uif[0] == 0) { + new_uif = 1; + gpg_nvm_write(&uif[0], &new_uif, 1); + } else if (uif[0] == 1) { + new_uif = 0; + gpg_nvm_write(&uif[0], &new_uif, 1); + } else /*if (uif[0] == 2 )*/ { + ui_info(UIF_LOCKED, NULL, ui_menu_uifmode_display, 0); + return; + } ui_menu_uifmode_display(value); } /* -------------------------------- RESET UX --------------------------------- */ -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 -}; +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}; 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}, - {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 -}; - +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}; /* --------------------------------- SLOT UX --------------------------------- */ @@ -953,33 +957,29 @@ 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}, - {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 -}; -void ui_menu_slot_display(unsigned int value) { - UX_MENU_DISPLAY(value, ui_menu_slot, ui_menu_slot_preprocessor); +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}; +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) { +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) { - for (slot = 1; slot <= 3; slot ++) { + if (element->component.userid == 0x20) { + for (slot = 1; slot <= 3; slot++) { if (entry == &ui_menu_slot[slot]) { break; } } if (slot != 4) { - 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*/); + 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; } } @@ -990,17 +990,16 @@ void ui_menu_slot_action(unsigned int value) { if (value == 128) { s = G_gpg_vstate.slot; - gpg_nvm_write(&N_gpg_pstate->config_slot[1], &s,1); - value = s+1; - } - else { - s = (unsigned char)(value-1); - if (s!= G_gpg_vstate.slot) { - G_gpg_vstate.slot = s; - G_gpg_vstate.kslot = &N_gpg_pstate->keys[G_gpg_vstate.slot]; - gpg_mse_reset(); - ui_CCID_reset(); - } + gpg_nvm_write(&N_gpg_pstate->config_slot[1], &s, 1); + value = s + 1; + } else { + s = (unsigned char)(value - 1); + if (s != G_gpg_vstate.slot) { + G_gpg_vstate.slot = s; + G_gpg_vstate.kslot = &N_gpg_pstate->keys[G_gpg_vstate.slot]; + gpg_mse_reset(); + ui_CCID_reset(); + } } // redisplay first entry of the idle menu ui_menu_slot_display(value); @@ -1009,79 +1008,72 @@ void ui_menu_slot_action(unsigned int value) { /* --------------------------------- INFO UX --------------------------------- */ -#define STR(x) #x +#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}, - {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, ui_menu_main_display, 3, &C_badge_back, "Back", NULL, 61, 40}, - UX_MENU_END -}; +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(OPENPGP_VERSION), NULL, 0, 0}, + {NULL, ui_menu_main_display, 3, &C_badge_back, "Back", NULL, 61, 40}, + UX_MENU_END}; #undef STR #undef XSTR /* --------------------------------- MAIN UX --------------------------------- */ -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}, +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 -}; -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) { + {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}; +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]) { - if(element->component.userid==0x21) { - os_memset(G_gpg_vstate.menu, 0, sizeof(G_gpg_vstate.menu)); + if (element->component.userid == 0x21) { + os_memset(G_gpg_vstate.menu, 0, sizeof(G_gpg_vstate.menu)); os_memmove(G_gpg_vstate.menu, N_gpg_pstate->name.value, 12); if (G_gpg_vstate.menu[0] == 0) { os_memmove(G_gpg_vstate.menu, "", 9); } else { - for (int i = 0; i<12; i++) { + for (int i = 0; i < 12; i++) { if (G_gpg_vstate.menu[i] == 0x3c) { G_gpg_vstate.menu[i] = ' '; } } } } - if(element->component.userid==0x22) { + 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); +#if GPG_MULTISLOT + 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; } return element; } void ui_menu_main_display(unsigned int value) { - UX_MENU_DISPLAY(value, ui_menu_main, ui_menu_main_preprocessor); + UX_MENU_DISPLAY(value, ui_menu_main, ui_menu_main_preprocessor); } void ui_init(void) { - ui_menu_main_display(0); - // setup the first screen changing + ui_menu_main_display(0); + // setup the first screen changing UX_CALLBACK_SET_INTERVAL(1000); } void io_seproxyhal_display(const bagl_element_t *element) { io_seproxyhal_display_default((bagl_element_t *)element); } + +#endif \ No newline at end of file diff --git a/src/gpg_ux_nanos.h b/src/gpg_ux_nanos.h index ba41bf4..cf33333 100644 --- a/src/gpg_ux_nanos.h +++ b/src/gpg_ux_nanos.h @@ -14,7 +14,6 @@ * limitations under the License. */ - #ifndef GPG_UX_NANOS_H #define GPG_UX_NANOS_H diff --git a/src/gpg_ux_nanox.c b/src/gpg_ux_nanox.c new file mode 100644 index 0000000..36df94f --- /dev/null +++ b/src/gpg_ux_nanox.c @@ -0,0 +1,1198 @@ +/* Copyright 2017 Cedric Mesnil , Ledger SAS + * + * 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. + */ + +#ifdef UI_NANO_X + +#include "os.h" +#include "cx.h" +#include "gpg_types.h" +#include "gpg_api.h" +#include "gpg_vars.h" + +#include "gpg_ux_msg.h" +#include "os_io_seproxyhal.h" +#include "usbd_ccid_impl.h" +#include "string.h" +#include "glyphs.h" + +/* ----------------------------------------------------------------------- */ +/* --- NanoS UI layout --- */ +/* ----------------------------------------------------------------------- */ +void ui_menu_settings_display(unsigned int value); + +void ui_menu_template_display(unsigned int value); +void ui_menu_tmpl_set_action(unsigned int value); +void ui_menu_tmpl_key_action(unsigned int value); +void ui_menu_tmpl_type_action(unsigned int value); + +void ui_menu_seed_display(unsigned int value); +void ui_menu_seed_action(unsigned int value); + +void ui_menu_reset_action(unsigned int value); + +#if GPG_MULTISLOT +void ui_menu_slot_display(unsigned int value); +void ui_menu_slot_action(unsigned int value); +#endif + +void ui_menu_main_display(unsigned int value); + +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); +unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int button_mask_counter); +unsigned int ui_pinentry_prepro(const bagl_element_t *element); +static unsigned int validate_pin(); + +/* ------------------------------- Helpers UX ------------------------------- */ +#define ui_flow_display(f, i) \ + if ((i) < ARRAYLEN(f)) \ + ux_flow_init(0, f, f[i]); \ + else \ + ux_flow_init(0, f, NULL) + +void ui_CCID_reset(void) { +#ifdef HAVE_USB_CLASS_CCID + io_usb_ccid_set_card_inserted(0); + io_usb_ccid_set_card_inserted(1); +#endif +} + +UX_STEP_CB(ux_menu_popup_1_step, bnnn_paging, ui_menu_main_display(0), {.title = "Info", .text = G_gpg_vstate.menu}); + +UX_FLOW(ux_flow_popup, &ux_menu_popup_1_step); + +void ui_info(const char *msg1, const char *msg2, const void *menu_display, unsigned int value) { + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s. %s", msg1, msg2); + ux_flow_init(0, ux_flow_popup, NULL); +}; + +/* ------------------------------ UIF CONFIRM UX ----------------------------- */ + +unsigned int ui_uifconfirm_action(unsigned int value); +void ui_menu_uifconfirm_predisplay(void); + +UX_STEP_NOCB_INIT(ux_menu_uifconfirm_1_step, + nnn, + ui_menu_uifconfirm_predisplay(), + {"Confirm operation", G_gpg_vstate.menu, ""}); + +UX_STEP_CB(ux_menu_uifconfirm_2_step, pb, ui_uifconfirm_action(0), {&C_icon_crossmark, "No"}); + +UX_STEP_CB(ux_menu_uifconfirm_3_step, pb, ui_uifconfirm_action(1), {&C_icon_validate_14, "Yes"}); + +UX_FLOW(ux_flow_uifconfirm, &ux_menu_uifconfirm_1_step, &ux_menu_uifconfirm_3_step, &ux_menu_uifconfirm_2_step); + +void ui_menu_uifconfirm_predisplay() { + unsigned int uif_case = (G_gpg_vstate.io_ins << 16) | (G_gpg_vstate.io_p1 << 8) | (G_gpg_vstate.io_p2); + switch (uif_case) { + case 0x002A9E9A: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Signature"); + break; + case 0x002A8680: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Encryption"); + break; + case 0x002A8086: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Decryption"); + break; + case 0x00880000: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Authentication"); + break; + default: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Please Cancel"); + } +} + +void ui_menu_uifconfirm_display(unsigned int value) { + ui_flow_display(ux_flow_uifconfirm, value); +} + +unsigned int ui_uifconfirm_action(unsigned int value) { + unsigned int sw; + + sw = 0x6985; + if (value == 1) { + BEGIN_TRY { + TRY { + G_gpg_vstate.UIF_flags = 1; + if (G_gpg_vstate.io_ins == INS_PSO) { + sw = gpg_apdu_pso(); + } else if (G_gpg_vstate.io_ins == INS_INTERNAL_AUTHENTICATE) { + sw = gpg_apdu_internal_authenticate(); + } else { + gpg_io_discard(1); + sw = 0x6985; + } + } + CATCH_OTHER(e) { + gpg_io_discard(1); + if ((e & 0xFFFF0000) || (((e & 0xF000) != 0x6000) && ((e & 0xF000) != 0x9000))) { + gpg_io_insert_u32(e); + sw = 0x6f42; + } else { + sw = e; + } + } + FINALLY { + G_gpg_vstate.UIF_flags = 0; + gpg_io_insert_u16(sw); + gpg_io_do(IO_RETURN_AFTER_TX); + ui_menu_main_display(0); + } + } + END_TRY; + } else { + gpg_io_discard(1); + gpg_io_insert_u16(sw); + gpg_io_do(IO_RETURN_AFTER_TX); + ui_menu_main_display(0); + sw = 0x6985; + } + return 0; +} + +/* ------------------------------ PIN CONFIRM UX ----------------------------- */ +unsigned int ui_pinconfirm_action(unsigned int value); +void ui_menu_pinconfirm_predisplay(void); +void ui_menu_pinconfirm_display(unsigned int value); + +UX_STEP_NOCB_INIT(ux_menu_pinconfirm_1_step, + nnn, + ui_menu_pinconfirm_predisplay(), + {"Confirm PIN", G_gpg_vstate.menu, ""}); + +UX_STEP_CB(ux_menu_pinconfirm_2_step, + pb, + ui_pinconfirm_action(0), + { + &C_icon_crossmark, + "No", + }); + +UX_STEP_CB(ux_menu_pinconfirm_3_step, + pb, + ui_pinconfirm_action(1), + { + &C_icon_validate_14, + "Yes", + }); + +UX_FLOW(ux_flow_pinconfirm, &ux_menu_pinconfirm_1_step, &ux_menu_pinconfirm_2_step, &ux_menu_pinconfirm_3_step); + +void ui_menu_pinconfirm_predisplay() { + 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); + } else { + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Please Cancel"); + } +} + +void ui_menu_pinconfirm_display(unsigned int value) { + ux_flow_init(0, ux_flow_pinconfirm, NULL); +} + +unsigned int ui_pinconfirm_action(unsigned int value) { + unsigned int sw; + + sw = 0x6985; + if (value == 1) { + gpg_pin_set_verified(G_gpg_vstate.io_p2, 1); + sw = 0x9000; + } else { + gpg_pin_set_verified(G_gpg_vstate.io_p2, 0); + sw = 0x6985; + } + gpg_io_discard(0); + gpg_io_insert_u16(sw); + gpg_io_do(IO_RETURN_AFTER_TX); + ui_menu_main_display(0); + return 0; +} + +/* ------------------------------- 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 + + // clrar screen + {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 64, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL, 0, 0, 0, NULL, NULL, NULL}, + + // left/rights icons + {{BAGL_ICON, 0x00, 0, 30, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0, 0}, + (const char *)&C_icon_down, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_ICON, 0x00, 120, 30, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0, 0}, + (const char *)&C_icon_up, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // PIN text identifier + {{BAGL_LABELINE, 0x01, 10, 25, 117, 15, 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}, + + // PIN Value + {{BAGL_LABELINE, 0x02, 10, 45, 117, 15, 0, 0, 0, 0xFFFFFF, 0x000000, + BAGL_FONT_OPEN_SANS_LIGHT_16px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + G_gpg_vstate.menu, + 0, + 0, + 0, + NULL, + NULL, + NULL}, +}; +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) { + os_memset(G_gpg_vstate.ux_pinentry, 0, sizeof(G_gpg_vstate.ux_pinentry)); + G_gpg_vstate.ux_pinentry[0] = 1; + G_gpg_vstate.ux_pinentry[1] = 5; + } + UX_DISPLAY(ui_pinentry_nanos, (void *)ui_pinentry_prepro); +} + +unsigned int ui_pinentry_prepro(const bagl_element_t *element) { + if (element->component.userid == 1) { + 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"); + break; + case 1: + 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"); + break; + default: + 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) { + unsigned int i; + G_gpg_vstate.menu[0] = ' '; +#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]]; + } +#else + for (i = 1; i < G_gpg_vstate.ux_pinentry[0]; i++) { + G_gpg_vstate.menu[i] = '*'; + } + G_gpg_vstate.menu[i] = C_pin_digit[G_gpg_vstate.ux_pinentry[i]]; + i++; +#endif + for (; i <= GPG_MAX_PW_LENGTH; i++) { + G_gpg_vstate.menu[i] = '-'; + } + G_gpg_vstate.menu[i] = 0; + } + + return 1; +} + +unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int button_mask_counter) { + unsigned int offset = G_gpg_vstate.ux_pinentry[0]; + unsigned m_pinentry; + char digit; + + m_pinentry = 1; + + switch (button_mask) { + case BUTTON_EVT_RELEASED | BUTTON_LEFT: // Down + if (G_gpg_vstate.ux_pinentry[offset]) { + G_gpg_vstate.ux_pinentry[offset]--; + } else { + G_gpg_vstate.ux_pinentry[offset] = sizeof(C_pin_digit) - 1; + } + ui_menu_pinentry_display(1); + break; + + case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // up + G_gpg_vstate.ux_pinentry[offset]++; + if (G_gpg_vstate.ux_pinentry[offset] == sizeof(C_pin_digit)) { + G_gpg_vstate.ux_pinentry[offset] = 0; + } + ui_menu_pinentry_display(1); + break; + + case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT: + digit = C_pin_digit[G_gpg_vstate.ux_pinentry[offset]]; + // next digit + if ((digit >= '0') && (digit <= '9')) { + offset++; + G_gpg_vstate.ux_pinentry[0] = offset; + if (offset == GPG_MAX_PW_LENGTH + 1) { + validate_pin(); + } else { + G_gpg_vstate.ux_pinentry[offset] = 5; + ui_menu_pinentry_display(1); + } + } + // cancel digit + else if (digit == 'C') { + if (offset > 1) { + offset--; + G_gpg_vstate.ux_pinentry[0] = offset; + } + ui_menu_pinentry_display(1); + } + // validate pin + else if (digit == 'V') { + G_gpg_vstate.ux_pinentry[0] = offset - 1; + validate_pin(); + } + // cancel input without check + else { //(digit == 'A') + gpg_io_discard(0); + gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED); + gpg_io_do(IO_RETURN_AFTER_TX); + ui_menu_main_display(0); + } + break; + } + return 0; +} +// >= 0 +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]]; + } + + if (G_gpg_vstate.io_ins == 0x20) { + pin = gpg_pin_get_pin(G_gpg_vstate.io_p2); + sw = gpg_pin_check(pin, G_gpg_vstate.io_p2, (unsigned char *)(G_gpg_vstate.menu + 1), G_gpg_vstate.ux_pinentry[0]); + gpg_io_discard(1); + gpg_io_insert_u16(sw); + gpg_io_do(IO_RETURN_AFTER_TX); + if (sw != SW_OK) { + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %d tries remaining", pin->counter); + ui_info(WRONG_PIN, G_gpg_vstate.menu, ui_menu_main_display, 0); + } else { + ui_menu_main_display(0); + } + } + + if (G_gpg_vstate.io_ins == 0x24) { + if (G_gpg_vstate.io_p1 <= 2) { + gpg_io_insert_u8(G_gpg_vstate.ux_pinentry[0]); + gpg_io_insert((unsigned char *)(G_gpg_vstate.menu + 1), G_gpg_vstate.ux_pinentry[0]); + G_gpg_vstate.io_p1++; + } + 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) { + gpg_io_discard(1); + gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED); + gpg_io_do(IO_RETURN_AFTER_TX); + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %d tries remaining", pin->counter); + ui_info(WRONG_PIN, NULL, ui_menu_main_display, 0); + return 0; + } + 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)) { + gpg_io_discard(1); + gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED); + gpg_io_do(IO_RETURN_AFTER_TX); + ui_info(PIN_DIFFERS, NULL, ui_menu_main_display, 0); + } else { + gpg_pin_set(gpg_pin_get_pin(G_gpg_vstate.io_p2), G_gpg_vstate.work.io_buffer + offset + 1, len); + gpg_io_discard(1); + gpg_io_insert_u16(SW_OK); + gpg_io_do(IO_RETURN_AFTER_TX); + // ui_info(PIN_CHANGED, NULL, ui_menu_main_display, 0); + ui_menu_main_display(0); + } + return 0; + } else { + ui_menu_pinentry_display(0); + } + } + return 0; +} + +/* ------------------------------- template UX ------------------------------- */ +#define LABEL_SIG "Signature" +#define LABEL_AUT "Authentication" +#define LABEL_DEC "Decryption" + +#define LABEL_RSA2048 "RSA 2048" +#define LABEL_RSA3072 "RSA 3072" +#define LABEL_RSA4096 "RSA 4096" +#define LABEL_SECP256K1 "SEPC 256K1" +#define LABEL_Ed25519 "Ed25519" + +const char *const tmpl_key_getter_values[] = {LABEL_SIG, LABEL_DEC, LABEL_AUT}; + +const unsigned int tmpl_key_getter_values_map[] = {1, 2, 3}; + +const char *tmpl_key_getter(unsigned int idx) { + if (idx < ARRAYLEN(tmpl_key_getter_values)) { + return tmpl_key_getter_values[idx]; + } + return NULL; +} + +void tmpl_key_selector(unsigned int idx) { + if (idx < ARRAYLEN(tmpl_key_getter_values)) { + idx = tmpl_key_getter_values_map[idx]; + } else { + idx = 0; + } + G_gpg_vstate.ux_key = idx; + ui_menu_template_display(0); +} + +const char *const tmpl_type_getter_values[] = {LABEL_RSA2048, LABEL_RSA3072, LABEL_RSA4096, LABEL_SECP256K1, + LABEL_Ed25519}; + +const unsigned int tmpl_type_getter_values_map[] = {2048, 3072, 4096, CX_CURVE_SECP256R1, CX_CURVE_Ed25519}; + +const char *tmpl_type_getter(unsigned int idx) { + if (idx < ARRAYLEN(tmpl_type_getter_values)) { + return tmpl_type_getter_values[idx]; + } + return NULL; +} + +void tmpl_type_selector(unsigned int idx) { + if (idx < ARRAYLEN(tmpl_type_getter_values)) { + idx = tmpl_type_getter_values_map[idx]; + } else { + idx = 0; + } + G_gpg_vstate.ux_type = idx; + ui_menu_template_display(1); +} + +#define KEY_KEY G_gpg_vstate.ux_buff1 +#define KEY_TYPE G_gpg_vstate.ux_buff2 + +void ui_menu_templet_action(); +void ui_menu_template_predisplay(void); + +UX_STEP_CB_INIT(ux_menu_template_1_step, + bn, + ui_menu_template_predisplay(), + ux_menulist_init(G_ux.stack_count - 1, tmpl_key_getter, tmpl_key_selector), + { + "Key", + KEY_KEY, + }); + +UX_STEP_CB_INIT(ux_menu_template_2_step, + bn, + ui_menu_template_predisplay(), + ux_menulist_init(G_ux.stack_count - 1, tmpl_type_getter, tmpl_type_selector), + { + "Type", + KEY_TYPE, + }); + +UX_STEP_CB(ux_menu_template_3_step, nnbnn, ui_menu_tmpl_set_action(0), {NULL, NULL, "Set Template", NULL, NULL}); + +UX_STEP_CB(ux_menu_template_4_step, + pb, + ui_menu_settings_display(0), + { + &C_icon_back, + "Back", + }); + +UX_FLOW(ux_flow_template, + &ux_menu_template_1_step, + &ux_menu_template_2_step, + &ux_menu_template_3_step, + &ux_menu_template_4_step); + +void ui_menu_template_predisplay() { + switch (G_gpg_vstate.ux_key) { + case 1: + snprintf(KEY_KEY, sizeof(KEY_KEY), "%s", LABEL_SIG); + break; + case 2: + snprintf(KEY_KEY, sizeof(KEY_KEY), "%s", LABEL_DEC); + break; + case 3: + snprintf(KEY_KEY, sizeof(KEY_KEY), "%s", LABEL_AUT); + break; + default: + snprintf(KEY_KEY, sizeof(KEY_KEY), "Choose key..."); + break; + } + + switch (G_gpg_vstate.ux_type) { + case 2048: + snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_RSA2048); + break; + case 3072: + snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_RSA3072); + break; + case 4096: + snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_RSA4096); + break; + case CX_CURVE_SECP256R1: + snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_SECP256K1); + break; + case CX_CURVE_Ed25519: + snprintf(KEY_TYPE, sizeof(KEY_TYPE), " %s", LABEL_Ed25519); + break; + default: + snprintf(KEY_TYPE, sizeof(KEY_TYPE), "Choose type..."); + break; + } +} + +void ui_menu_template_display(unsigned int value) { + ui_flow_display(ux_flow_template, value); +} + +void ui_menu_tmpl_set_action(unsigned int value) { + LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH); + gpg_key_t * dest; + const char * err; + const unsigned char *oid; + unsigned int oid_len; + err = NULL; + + os_memset(&attributes, 0, sizeof(attributes)); + switch (G_gpg_vstate.ux_type) { + case 2048: + case 3072: + case 4096: + attributes.value[0] = 0x01; + attributes.value[1] = (G_gpg_vstate.ux_type >> 8) & 0xFF; + attributes.value[2] = G_gpg_vstate.ux_type & 0xFF; + attributes.value[3] = 0x00; + attributes.value[4] = 0x20; + attributes.value[5] = 0x01; + attributes.length = 6; + break; + + case CX_CURVE_SECP256R1: + if (G_gpg_vstate.ux_key == 2) { + attributes.value[0] = 18; // ecdh + } else { + attributes.value[0] = 19; // ecdsa + } + oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len); + os_memmove(attributes.value + 1, oid, sizeof(oid_len)); + attributes.length = 1 + oid_len; + break; + + case CX_CURVE_Ed25519: + if (G_gpg_vstate.ux_key == 2) { + attributes.value[0] = 18; // ecdh + os_memmove(attributes.value + 1, C_OID_cv25519, sizeof(C_OID_cv25519)); + attributes.length = 1 + sizeof(C_OID_cv25519); + } else { + attributes.value[0] = 22; // eddsa + os_memmove(attributes.value + 1, C_OID_Ed25519, sizeof(C_OID_Ed25519)); + attributes.length = 1 + sizeof(C_OID_Ed25519); + } + break; + + default: + err = TEMPLATE_TYPE; + goto ERROR; + } + + dest = NULL; + switch (G_gpg_vstate.ux_key) { + case 1: + dest = &G_gpg_vstate.kslot->sig; + break; + case 2: + dest = &G_gpg_vstate.kslot->dec; + break; + case 3: + dest = &G_gpg_vstate.kslot->aut; + break; + default: + err = TEMPLATE_KEY; + goto ERROR; + } + + gpg_nvm_write(dest, NULL, sizeof(gpg_key_t)); + gpg_nvm_write(&dest->attributes, &attributes, sizeof(attributes)); + ui_info(OK, NULL, ui_menu_template_display, 0); + return; + +ERROR: + ui_info(INVALID_SELECTION, err, ui_menu_template_display, 0); +} + +#undef KEY_KEY +#undef KEY_TYPE + +#undef LABEL_SIG +#undef LABEL_AUT +#undef LABEL_DEC + +#undef LABEL_RSA2048 +#undef LABEL_RSA3072 +#undef LABEL_RSA4096 +#undef LABEL_NISTP256 +#undef LABEL_SECP256K1 +#undef LABEL_Ed25519 + +/* --------------------------------- SEED UX --------------------------------- */ +#define CUR_SEED_MODE G_gpg_vstate.ux_buff1 + +void ui_menu_seed_action(unsigned int); +void ui_menu_seedmode_display(unsigned int); +void ui_menu_seedmode_predisplay(void); + +UX_STEP_CB_INIT(ux_menu_seedmode_1_step, + bn, + ui_menu_seedmode_predisplay(), + ui_menu_seed_action(0), + {"Toggle seed mode", CUR_SEED_MODE}); + +UX_STEP_CB(ux_menu_seedmode_2_step, + pb, + ui_menu_settings_display(1), + { + &C_icon_back, + "Back", + }); + +UX_FLOW(ux_flow_seedmode, &ux_menu_seedmode_1_step, &ux_menu_seedmode_2_step); + +void ui_menu_seedmode_predisplay() { + snprintf(CUR_SEED_MODE, sizeof(CUR_SEED_MODE), "%s", G_gpg_vstate.seed_mode ? "ON" : "OFF"); +} + +void ui_menu_seedmode_display(unsigned int value) { + ui_flow_display(ux_flow_seedmode, value); +} + +void ui_menu_seed_action(unsigned int value) { + if (G_gpg_vstate.seed_mode) { + G_gpg_vstate.seed_mode = 0; + } else { + G_gpg_vstate.seed_mode = 1; + } + ui_menu_seedmode_display(0); +} + +#undef CUR_SEED_MODE + +/* ------------------------------- PIN MODE UX ------------------------------ */ +void ui_menu_pinmode_action(unsigned int value); +void ui_menu_pinmode_display(unsigned int value); +void ui_menu_pinmode_predisplay(void); + +#define ONHST_BUFF G_gpg_vstate.ux_buff1 +#define ONSCR_BUFF G_gpg_vstate.ux_buff2 +#define CONFI_BUFF G_gpg_vstate.ux_buff3 +#define TRUST_BUFF G_gpg_vstate.ux_buff4 + +UX_STEP_CB_INIT(ux_menu_pinmode_1_step, + bnn, + ui_menu_pinmode_predisplay(), + ui_menu_pinmode_action(PIN_MODE_HOST), + {"On Host", ONHST_BUFF, ONHST_BUFF + 5}); + +UX_STEP_CB_INIT(ux_menu_pinmode_2_step, + bnn, + ui_menu_pinmode_predisplay(), + ui_menu_pinmode_action(PIN_MODE_SCREEN), + {"On Screen", ONSCR_BUFF, ONSCR_BUFF + 5}); + +UX_STEP_CB_INIT(ux_menu_pinmode_3_step, + bnn, + ui_menu_pinmode_predisplay(), + ui_menu_pinmode_action(PIN_MODE_CONFIRM), + {"Confirm Only", CONFI_BUFF, CONFI_BUFF + 5}); + +UX_STEP_CB_INIT(ux_menu_pinmode_4_step, + bnn, + ui_menu_pinmode_predisplay(), + ui_menu_pinmode_action(PIN_MODE_TRUST), + {"Trust", TRUST_BUFF, TRUST_BUFF + 5}); + +UX_STEP_CB(ux_menu_pinmode_6_step, + pb, + ui_menu_pinmode_action(128), + { + &C_icon_validate_14, + "Set as Default", + }); + +UX_STEP_CB(ux_menu_pinmode_7_step, + pb, + ui_menu_settings_display(2), + { + &C_icon_back, + "Back", + }); + +UX_FLOW(ux_flow_pinmode, + &ux_menu_pinmode_1_step, + &ux_menu_pinmode_2_step, + &ux_menu_pinmode_3_step, + &ux_menu_pinmode_4_step, + &ux_menu_pinmode_6_step, + &ux_menu_pinmode_7_step); + +void ui_menu_pinmode_predisplay() { + snprintf(ONHST_BUFF, 5, "%s", PIN_MODE_HOST == G_gpg_vstate.pinmode ? "ON" : "OFF"); + snprintf(ONSCR_BUFF, 5, "%s", PIN_MODE_SCREEN == G_gpg_vstate.pinmode ? "ON" : "OFF"); + snprintf(CONFI_BUFF, 5, "%s", PIN_MODE_CONFIRM == G_gpg_vstate.pinmode ? "ON" : "OFF"); + snprintf(TRUST_BUFF, 5, "%s", PIN_MODE_TRUST == G_gpg_vstate.pinmode ? "ON" : "OFF"); + + snprintf(ONHST_BUFF + 5, sizeof(ONHST_BUFF) - 5, "%s", + PIN_MODE_HOST == N_gpg_pstate->config_pin[0] ? "(Default)" : ""); + snprintf(ONSCR_BUFF + 5, sizeof(ONSCR_BUFF) - 5, "%s", + PIN_MODE_SCREEN == N_gpg_pstate->config_pin[0] ? "(Default)" : ""); + snprintf(CONFI_BUFF + 5, sizeof(CONFI_BUFF) - 5, "%s", + PIN_MODE_CONFIRM == N_gpg_pstate->config_pin[0] ? "(Default)" : ""); + snprintf(TRUST_BUFF + 5, sizeof(TRUST_BUFF) - 5, "%s", + PIN_MODE_TRUST == N_gpg_pstate->config_pin[0] ? "(Default)" : ""); +} + +void ui_menu_pinmode_display(unsigned int value) { + ui_flow_display(ux_flow_pinmode, value); +} + +#undef ONHST_BUFF +#undef ONSCR_BUFF +#undef CONFI_BUFF +#undef TRUST_BUFF + +void ui_menu_pinmode_action(unsigned int value) { + unsigned char s; + if (value == 128) { + if (G_gpg_vstate.pinmode != N_gpg_pstate->config_pin[0]) { + if (G_gpg_vstate.pinmode == PIN_MODE_TRUST) { + ui_info(DEFAULT_MODE, NOT_ALLOWED, ui_menu_pinmode_display, 0); + return; + } + // set new mode + s = G_gpg_vstate.pinmode; + gpg_nvm_write((void *)(&N_gpg_pstate->config_pin[0]), &s, 1); + // disactivate pinpad if any + if (G_gpg_vstate.pinmode == PIN_MODE_HOST) { + s = 0; + } else { + s = 3; + } + //#warning USBD_CCID_activate_pinpad commented + USBD_CCID_activate_pinpad(s); + value = G_gpg_vstate.pinmode; + } + } else { + switch (value) { + case PIN_MODE_HOST: + case PIN_MODE_SCREEN: + case PIN_MODE_CONFIRM: + if (!gpg_pin_is_verified(PIN_ID_PW2)) { + ui_info(PIN_USER, NOT_VERIFIED, ui_menu_pinmode_display, 0); + return; + } + break; + + case PIN_MODE_TRUST: + if (!gpg_pin_is_verified(PIN_ID_PW3)) { + ui_info(PIN_ADMIN, NOT_VERIFIED, ui_menu_pinmode_display, 0); + return; + } + break; + default: + ui_info(INVALID_SELECTION, NULL, ui_menu_pinmode_display, 0); + return; + } + G_gpg_vstate.pinmode = value; + } + // redisplay active pin mode entry + switch (value) { + case PIN_MODE_HOST: + ui_menu_pinmode_display(0); + break; + case PIN_MODE_SCREEN: + ui_menu_pinmode_display(1); + break; + case PIN_MODE_CONFIRM: + ui_menu_pinmode_display(2); + break; + case PIN_MODE_TRUST: + ui_menu_pinmode_display(3); + break; + default: + ui_menu_pinmode_display(0); + break; + } +} + +/* ------------------------------- UIF MODE UX ------------------------------ */ + +void ui_menu_uifmode_action(unsigned int value); +void ui_menu_uifmode_predisplay(void); + +#define SIG_BUFF G_gpg_vstate.ux_buff1 +#define DEC_BUFF G_gpg_vstate.ux_buff2 +#define AUT_BUFF G_gpg_vstate.ux_buff3 + +UX_STEP_CB_INIT(ux_menu_uif_1_step, + bn, + ui_menu_uifmode_predisplay(), + ui_menu_uifmode_action(0), + {"UIF for Signature", SIG_BUFF}); + +UX_STEP_CB_INIT(ux_menu_uif_2_step, + bn, + ui_menu_uifmode_predisplay(), + ui_menu_uifmode_action(1), + {"UIF for Decryption", DEC_BUFF}); + +UX_STEP_CB_INIT(ux_menu_uif_3_step, + bn, + ui_menu_uifmode_predisplay(), + ui_menu_uifmode_action(2), + {"UIF for Authentication", AUT_BUFF}); + +UX_STEP_CB(ux_menu_uif_4_step, + pb, + ui_menu_settings_display(3), + { + &C_icon_back, + "Back", + }); + +UX_FLOW(ux_flow_uif, &ux_menu_uif_1_step, &ux_menu_uif_2_step, &ux_menu_uif_3_step, &ux_menu_uif_4_step); + +void ui_menu_uifmode_predisplay() { + snprintf(SIG_BUFF, sizeof(SIG_BUFF), "%s", G_gpg_vstate.kslot->sig.UIF[0] ? "ON" : "OFF"); + snprintf(DEC_BUFF, sizeof(DEC_BUFF), "%s", G_gpg_vstate.kslot->dec.UIF[0] ? "ON" : "OFF"); + snprintf(AUT_BUFF, sizeof(AUT_BUFF), "%s", G_gpg_vstate.kslot->aut.UIF[0] ? "ON" : "OFF"); +} + +void ui_menu_uifmode_display(unsigned int value) { + ui_flow_display(ux_flow_uif, value); +} + +#undef SIG_BUFF +#undef DEC_BUFF +#undef AUT_BUFF + +void ui_menu_uifmode_action(unsigned int value) { + unsigned char *uif; + unsigned char new_uif; + switch (value) { + case 0: + uif = &G_gpg_vstate.kslot->sig.UIF[0]; + break; + case 1: + uif = &G_gpg_vstate.kslot->dec.UIF[0]; + break; + case 2: + uif = &G_gpg_vstate.kslot->aut.UIF[0]; + break; + default: + ui_info(INVALID_SELECTION, NULL, ui_menu_uifmode_display, 0); + return; + } + if (uif[0] == 0) { + new_uif = 1; + gpg_nvm_write(&uif[0], &new_uif, 1); + } else if (uif[0] == 1) { + new_uif = 0; + gpg_nvm_write(&uif[0], &new_uif, 1); + } else /*if (uif[0] == 2 )*/ { + ui_info(UIF_LOCKED, NULL, ui_menu_uifmode_display, 0); + return; + } + ui_menu_uifmode_display(value); +} + +/* -------------------------------- RESET UX --------------------------------- */ + +void ui_menu_reset_action(unsigned int value); + +UX_STEP_CB(ux_menu_reset_1_step, bnn, ui_menu_settings_display(4), {"Ooops, NO!", "Do not reset", "the application"}); + +UX_STEP_CB(ux_menu_reset_2_step, bn, ui_menu_reset_action(0), {"YES!", "Reset the application"}); + +UX_FLOW(ux_flow_reset, &ux_menu_reset_1_step, &ux_menu_reset_2_step); + +void ui_menu_reset_display(unsigned int value) { + ux_flow_init(value, ux_flow_reset, NULL); +} + +void ui_menu_reset_action(unsigned int value) { + unsigned char magic[4]; + magic[0] = 0; + magic[1] = 0; + magic[2] = 0; + magic[3] = 0; + gpg_nvm_write((void *)(N_gpg_pstate->magic), magic, 4); + gpg_init(); + ui_CCID_reset(); + ui_menu_main_display(0); +} + +/* ------------------------------- SETTINGS UX ------------------------------- */ + +const char *const settings_getter_values[] = {"Key template", "Seed mode", "PIN mode", "UIF mode", "Reset", "Back"}; + +const char *settings_getter(unsigned int idx) { + if (idx < ARRAYLEN(settings_getter_values)) { + return settings_getter_values[idx]; + } + return NULL; +} + +void settings_selector(unsigned int idx) { + switch (idx) { + case 0: + ui_menu_template_display(0); + break; + case 1: + ui_menu_seedmode_display(0); + break; + case 2: + ui_menu_pinmode_display(0); + break; + case 3: + ui_menu_uifmode_display(0); + break; + case 4: + ui_menu_reset_display(0); + break; + default: + ui_menu_main_display(1); + break; + } +} +void ui_menu_settings_display(unsigned int value) { + ux_menulist_init_select(G_ux.stack_count - 1, settings_getter, settings_selector, value); +} + +/* --------------------------------- SLOT UX --------------------------------- */ + +#if GPG_MULTISLOT +#if GPG_KEYS_SLOTS != 3 +#error menu definition not correct for current value of GPG_KEYS_SLOTS +#endif + +void ui_menu_slot_action(unsigned int value); +void ui_menu_slot_predisplay(void); + +#define SIG_BUFF G_gpg_vstate.ux_buff1 +#define DEC_BUFF G_gpg_vstate.ux_buff2 +#define AUT_BUFF G_gpg_vstate.ux_buff3 + +UX_STEP_CB_INIT(ux_menu_slot_1_step, bn, ui_menu_slot_predisplay(), ui_menu_slot_action(1), {"Select Slot", SLOT1}); + +UX_STEP_CB_INIT(ux_menu_slot_2_step, bn, ui_menu_slot_predisplay(), ui_menu_slot_action(2), {"Select Slot", SLOT2}); + +UX_STEP_CB_INIT(ux_menu_slot_3_step, bn, ui_menu_slot_predisplay(), ui_menu_slot_action(3), {"Select Slot", SLOT3}); + +UX_STEP_CB(ux_menu_slot_4_step, bn, ui_menu_slot_action(128), {"Set selected Slot", "as default slot"}); + +UX_STEP_CB(ux_menu_uif_5_step, + bn, + ui_menu_settings_display(0), + { + &C_icon_back, + "Back", + }); + +UX_FLOW(ux_flow_slot, + &ux_menu_slot_1_step, + &ux_menu_slot_2_step, + &ux_menu_slot_3_step, + &ux_menu_slot_4_step &ux_menu_slot_5_step); + +void ui_menu_slot_predisplay() { + snprintf(SLOT1, sizeof(SLOT1), "1 %s %s", 1 == N_gpg_pstate->config_slot[1] + 1 ? "#" : " ", + 1 == G_gpg_vstate.slot + 1 ? "+" : " "); + snprintf(SLOT2, sizeof(SLOT2), "2 %s %s", 2 == N_gpg_pstate->config_slot[1] + 1 ? "#" : " ", + 2 == G_gpg_vstate.slot + 1 ? "+" : " "); + snprintf(SLOT3, sizeof(SLOT3), "3 %s %s", 3 == N_gpg_pstate->config_slot[1] + 1 ? "#" : " ", + 3 == G_gpg_vstate.slot + 1 ? "+" : " "); +} + +void ui_menu_slot_display(unsigned int value) { + ui_flow_display(ux_flow_slot, value); +} + +#undef SLOT1 +#undef SLOT2 +#undef SLOT3 + +void ui_menu_slot_action(unsigned int value) { + unsigned char s; + + if (value == 128) { + s = G_gpg_vstate.slot; + gpg_nvm_write(&N_gpg_pstate->config_slot[1], &s, 1); + } else { + s = (unsigned char)(value - 1); + if (s != G_gpg_vstate.slot) { + G_gpg_vstate.slot = s; + G_gpg_vstate.kslot = &N_gpg_pstate->keys[G_gpg_vstate.slot]; + gpg_mse_reset(); + ui_CCID_reset(); + } + } + ui_menu_slot_display(G_gpg_vstate.slot); +} +#endif + +/* --------------------------------- INFO UX --------------------------------- */ + +#define STR(x) #x +#define XSTR(x) STR(x) + +UX_STEP_NOCB(ux_menu_info_1_step, + bnnn, + { + "OpenPGP Card", + "(c) Ledger SAS", + "Spec " XSTR(SPEC_VERSION), + "App " XSTR(OPENPGP_VERSION), + }); + +UX_STEP_CB(ux_menu_info_2_step, + pb, + ui_menu_main_display(0), + { + &C_icon_back, + "Back", + }); + +UX_FLOW(ux_flow_info, &ux_menu_info_1_step, &ux_menu_info_2_step); + +void ui_menu_info_display(unsigned int value) { + ux_flow_init(0, ux_flow_info, NULL); +} + +#undef STR +#undef XSTR + +/* --------------------------------- MAIN UX --------------------------------- */ +void ui_menu_main_predisplay(void); + +UX_STEP_NOCB_INIT(ux_menu_main_1_step, + pnn, + ui_menu_main_predisplay(), + { + &C_icon_pgp, + G_gpg_vstate.ux_buff1, + G_gpg_vstate.ux_buff2, + }); + +#if GPG_MULTISLOT +UX_STEP_CB(ux_menu_main_2_step, pb, ui_menu_slot_display(0), {&C_icon_coggle, "Select Slot"}); +#endif + +UX_STEP_CB(ux_menu_main_3_step, pb, ui_menu_settings_display(0), {&C_icon_coggle, "Settings"}); + +UX_STEP_CB(ux_menu_main_4_step, pb, ui_menu_info_display(0), {&C_icon_certificate, "About"}); + +UX_STEP_CB(ux_menu_main_5_step, pb, os_sched_exit(0), {&C_icon_dashboard_x, "Quit app"}); + +UX_FLOW(ux_flow_main, + &ux_menu_main_1_step, +#if GPG_MULTISLOT + &ux_menu_main_2_step, +#endif + &ux_menu_main_3_step, + &ux_menu_main_4_step, + &ux_menu_main_5_step); + +void ui_menu_main_predisplay() { + os_memset(G_gpg_vstate.ux_buff1, 0, sizeof(G_gpg_vstate.ux_buff1)); + os_memmove(G_gpg_vstate.ux_buff1, (void *)(N_gpg_pstate->name.value), 20); + if (G_gpg_vstate.ux_buff1[0] == 0) { + os_memmove(G_gpg_vstate.ux_buff1, "", 9); + } else { + for (int i = 0; i < 12; i++) { + if (G_gpg_vstate.ux_buff1[i] == 0x3c) { + G_gpg_vstate.ux_buff1[i] = ' '; + } + } + } + + 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]); + os_memset(G_gpg_vstate.ux_buff2, 0, sizeof(G_gpg_vstate.ux_buff2)); +#if GPG_MULTISLOT + snprintf(G_gpg_vstate.ux_buff2, sizeof(G_gpg_vstate.ux_buff2), "ID: %x / %d", serial, G_gpg_vstate.slot + 1); +#else + snprintf(G_gpg_vstate.ux_buff2, sizeof(G_gpg_vstate.ux_buff2), "ID: %x", serial); +#endif +} + +void ui_menu_main_display(unsigned int value) { + // reserve a display stack slot if none yet + if (G_ux.stack_count == 0) { + ux_stack_push(); + } + + ui_flow_display(ux_flow_main, value); +} +/* --- INIT --- */ + +void ui_init(void) { + ui_menu_main_display(0); +} + +void io_seproxyhal_display(const bagl_element_t *element) { + io_seproxyhal_display_default((bagl_element_t *)element); +} + +///----- + +#endif // UI_NANOX \ No newline at end of file diff --git a/src/gpg_vars.h b/src/gpg_vars.h index 4d7679d..ec19b37 100644 --- a/src/gpg_vars.h +++ b/src/gpg_vars.h @@ -31,10 +31,15 @@ extern const unsigned char C_OID_BRAINPOOL256T1[9]; extern const unsigned char C_OID_Ed25519[9]; extern const unsigned char C_OID_cv25519[10]; -extern gpg_v_state_t G_gpg_vstate; -extern gpg_nv_state_t N_state_pic; -#define N_gpg_pstate ((WIDE gpg_nv_state_t *)PIC(&N_state_pic)) +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; diff --git a/src/sdk/usbd_ccid_cmd.c b/src/sdk/usbd_ccid_cmd.c index 1558d3d..37bb1dc 100755 --- a/src/sdk/usbd_ccid_cmd.c +++ b/src/sdk/usbd_ccid_cmd.c @@ -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 -------------------------------------------------------------*/ diff --git a/src/sdk/usbd_ccid_if.c b/src/sdk/usbd_ccid_if.c index d659ed4..528832f 100755 --- a/src/sdk/usbd_ccid_if.c +++ b/src/sdk/usbd_ccid_if.c @@ -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; diff --git a/src/sdk/usbd_hid_impl.h b/src/sdk/usbd_hid_impl.h index 8d69655..de19ca2 100644 --- a/src/sdk/usbd_hid_impl.h +++ b/src/sdk/usbd_hid_impl.h @@ -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 diff --git a/src/sdk/usbd_impl.c b/src/sdk/usbd_impl.c index 9c82900..8b1600e 100644 --- a/src/sdk/usbd_impl.c +++ b/src/sdk/usbd_impl.c @@ -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);