diff --git a/.clang-format b/.clang-format index 95b750c..d65f1ce 100644 --- a/.clang-format +++ b/.clang-format @@ -1,119 +1,18 @@ --- -Language: Cpp -# BasedOnStyle: LLVM -AccessModifierOffset: -2 +BasedOnStyle: Google +IndentWidth: 4 +Language: Cpp +ColumnLimit: 100 +PointerAlignment: Right AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: true -AlignConsecutiveDeclarations: true -#AlignConsecutiveMacros: true -AlignEscapedNewlines: Right -AlignOperands: true -AlignTrailingComments: true -#AllowAllArgumentsOnNextLine: false -#AllowAllConstructorInitializersOnNextLine: false +AlignConsecutiveMacros: true AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: false +SortIncludes: false +SpaceAfterCStyleCast: true AllowShortCaseLabelsOnASingleLine: false +AllowAllArgumentsOnNextLine: false +AllowShortBlocksOnASingleLine: Never AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: false -#AllowShortLambdasOnASingleLine: None -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: false -BinPackArguments: true +BinPackArguments: false 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/.gitignore b/.gitignore index 1b26681..6850c09 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,32 @@ -# Glyphs auto-generated -src/glyphs.* - -# Build files -dep -obj -release -bin -debug -build +# Compilation files of the application +build/ + +# Legacy compilation output +bin/ +debug/ + +# Temporary directory with snapshots taken during test runs +tests/snapshots-tmp/ + +# Unit tests and code coverage +unit-tests/build/ +unit-tests/coverage/ +unit-tests/coverage.info + +# Fuzzing +fuzzing/build/ + +# Python +*.pyc[cod] +*.egg +__pycache__/ +*.egg-info/ +.eggs/ +.python-version + +# Doxygen +doc/html +doc/latex + +# Virtual env for sideload (macOS and Windows) +ledger/ diff --git a/README.md b/README.md index 782962c..8b293cd 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,48 @@ -## GnuPG application: blue-app-gnupg +# GnuPG application 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 . +This application implements "The OpenPGP card" specification revision 3.3. +This specification is available in *doc* directory and at . The application supports: - - RSA with key up to 4096 bits - - ECDSA with secp256k1 - - EDDSA with Ed25519 curve - - ECDH with secp256k1 and curve25519 curves +- RSA with key up to 4096 bits +- ECDSA with secp256k1 +- EDDSA with Ed25519 curve +- ECDH with secp256k1 and curve25519 curves This release has known missing parts (see also Add-on) : - * Ledger Blue support - * Seed mode ON/OFF via apdu - +- Ledger Blue support +- Seed mode ON/OFF via apdu ## Installation and Usage -See the full doc at https://github.com/LedgerHQ/blue-app-openpgp-card/blob/master/doc/user/blue-app-openpgp-card.pdf - +See the full doc at ## Add-on The GnuPG application implements the following addon: - - serial modification - - on screen reset - - 3 independent key slots - - seeded key generation -Technical specification is available at https://github.com/LedgerHQ/blue-app-openpgp-card/blob/master/doc/developper/gpgcard3.0-addon.rst +- serial modification +- on screen reset +- 3 independent key slots +- seeded key generation + +Technical specification is available at - ### Key slot "The OpenPGP card" specification specifies: - - 3 asymmetric keys : Signature, Decryption, Authentication - - 1 symmetric key -The blue application allow you to store 3 different key sets, named slot. Each slot contains the above 4 keys. +- 3 asymmetric keys : Signature, Decryption, Authentication +- 1 symmetric key + +The application allows you to store 3 different key sets, named slot. Each slot contains the above 4 keys. You can choose the active slot on the main screen. When installed the default slot is "1". You can change it in settings. - ### seeded key generation A seeded mode is implemented in order to restore private keys on a new token. @@ -51,9 +50,8 @@ In this mode key material is generated from the global token seeded. Please consider SEED mode as experimental. -More details to come... +More details to come... ### On screen reset The application can be reset as if it was fresh installed. In settings, choose reset and confirm. - diff --git a/doc/developper/gpgcard3.0-addon.rst b/doc/developer/gpgcard3.0-addon.rst similarity index 90% rename from doc/developper/gpgcard3.0-addon.rst rename to doc/developer/gpgcard3.0-addon.rst index 9ffa82c..71f0ac3 100644 --- a/doc/developper/gpgcard3.0-addon.rst +++ b/doc/developer/gpgcard3.0-addon.rst @@ -35,7 +35,7 @@ OpenPGP Application manage four keys for cryptographic operation (PSO) plus two for secure channel. The first four keys are defined as follow: - - One asymmetric signature private key (RSA or EC), named 'sig'; + - One asymmetric signature private key (RSA or EC), named 'sig' - One asymmetric decryption private key (RSA or EC), named 'dec' - One asymmetric authentication private key (RSA or EC), named 'aut' - One symmetric decryption private key (AES), named 'sym0' @@ -49,7 +49,7 @@ It's never possible to retrieve private key from the card. This add-on specification propose a solution to derive those keys from the master seed managed by the Ledger Token. -This allow owner to restore a broken token without the needs to keep track of keys +This allows owner to restore a broken token without the needs to keep track of keys outside the card. Moreover this add-on specification propose to manage multiple set of the @@ -69,7 +69,7 @@ This add-on specification propose new type of random generation: Key Backup ~~~~~~~~~~ -A full keybackup mecanism is provided. +A full keybackup mechanism is provided. GPG-ledger @@ -79,7 +79,7 @@ Definitions ----------- - The application is named GPG-ledger - - A keys set is named 'keys slot' + - A keys set is named 'keys slot' How --- @@ -95,7 +95,7 @@ Deterministic key derivation maybe activated in: This activation remains effective until *set off* is selected or the application ends. -The key management remains the same if seed mode is on or off, i.e. key are stored in memory key containers. So their is no perfomance inpact when using seeded keys. +The key management remains the same if seed mode is on or off, i.e. key are stored in memory key containers. So there is no performance impact when using seeded keys. Seeded keys are generated as follow: @@ -133,7 +133,7 @@ Generate RSA key pair as usual. - n = p*q - d = inv(e) mod (p-1)(q-1) -*ECC key genration* : +*ECC key generation* : Generate one seed Sd in step2 with : - i = 1 @@ -188,16 +188,18 @@ For a given length *L* and seed *S*: Key Backup & Restore ~~~~~~~~~~~~~~~~~~~~ -In order to backup/restore private key the commands `put_data` and -`get_data` accept the tag `B6` (signature key), `B8`(encryption key), -`A4` (authentication). +In order to backup/restore private key the commands `put_data` and +`get_data` accept the tags: + - `B6` (signature key) + - `B8`(encryption key) + - `A4` (authentication). -put_data command accept the exact output of get_data. The get_data command +`put_data` command accept the exact output of `get_data`. The `get_data` command return both the public and private key. -For security and confidentiality private key is returned encryped in AES. -The key used is derived according to previously described AES key derivation -with name 'key '. +For security and confidentiality, private key is returned encrypted in AES. +The key used is derived according to previously described AES key derivation +with name 'key'. The data payload is formatted as follow: @@ -227,7 +229,7 @@ APDU Modification Key Slot management ~~~~~~~~~~~~~~~~~~~~ -Key slots are managed by data object 01F1 and 01F2 witch are +Key slots are managed by data object *01F1* and *01F2* witch are manageable by PUT/GET DATA command as for others DO and organized as follow. On application reset, the *01F2* content is set to *Default Slot* value @@ -255,8 +257,6 @@ Byte 3 is endoced as follow: | \- | \- | \- | \- | \- | \- | x | \- | selection by screen | +----+----+----+----+----+----+----+----+-------------------------+ - - *01F2:* @@ -302,7 +302,7 @@ P2 parameter of GENERATE ASYMMETRIC KEY PAIR is set to (hex value): Deterministic random number ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -P1 parameter of GET CHALLENGE is a bits field encoded as follow: +P1 parameter of GET CHALLENGE is a bit-field encoded as follow: +----+-----+----+----+----+----+----+----+-------------------------+ | b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | Meaning | @@ -320,7 +320,7 @@ the length of random bytes to generate. Other minor add-on ------------------ -GnuPG use both fingerprints and serial number to identfy key on card. -So, the put data command is able to modify the AID file with '4F' tag. -In that case the data field shall be four bytes length and shall contain +GnuPG use both fingerprints and serial number to identify key on card. +So, the `put_data` command is able to modify the AID file with '4F' tag. +In that case the data field shall be four bytes length and shall contain the new serial number. '4F' is protected by PW3 (admin) PIN. diff --git a/doc/developper/quick-test.txt b/doc/developer/quick-test.txt similarity index 88% rename from doc/developper/quick-test.txt rename to doc/developer/quick-test.txt index 5558ce7..4a7f189 100644 --- a/doc/developper/quick-test.txt +++ b/doc/developer/quick-test.txt @@ -1,20 +1,30 @@ Step1: ... ----- -Jump into any temp dir +Jump into any temp dir Step2: install nanos ------ +----- Do a fresh install of gpg application 1.1.0 from google app manager Step3: setup conf ----- -Create a 'manual-test' directory - $ mkdir manual-test +Install needed tools if needed (some are optional) + $ sudo apt install scdaemon opensc-pkcs11 pcscd sssd libpam-sss gnutls-bin opensc pcsc-tools + +Check the tools are operational + $ p11-kit list-modules + $ p11tool --list-tokens + $ pkcs15-tool --list-certificates + +Check installation of CCID driver and more particularly its device config: + Edit the file /etc/libccid_Info.plist, and check the Ledger devices. + Please take care, the lists are ordered in the same way. Do not insert elements anywhere! + To add a new Ledger device, check file in doc/developer/user/blue-app-openpgp-card.rst Create a 'manual-test/gnupg' - $ mkdir manual-test/gnupg + $ mkdir -p manual-test/gnupg Create a 'manual-test/gnupg/scdaemon.conf' file with content: reader-port "Ledger Token [Nano S] (0001) 01 00" @@ -76,7 +86,7 @@ Launch gpg NanoS application and: Authentication key: [none] General key info..: [none] - gpg/card> + gpg/card> Then on nanos, goto settings->PIN mode, and select 'Host' Then on nanos, goto settings->PIN mode, and select 'Set as default' @@ -144,8 +154,8 @@ In 'manual-test' directory, ask key generation. Nota that during this phase PIN GnuPG needs to construct a user ID to identify your key. Real name: testkey - Email address: - Comment: + Email address: + Comment: You selected this USER-ID: "testkey" @@ -180,17 +190,17 @@ encrypt Force pin to asked - $ killall gpg-agent scdaemon + $ killall gpg-agent scdaemon decrypt - $ gpg2 --homedir `pwd`/gnupg foo.txt.gpg + $ gpg2 --homedir `pwd`/gnupg foo.txt.gpg gpg: WARNING: unsafe permissions on homedir '/home/cme/Projects/Git/ledgerblue/blue-app-openpgp-card/manual-test/gnupg' gpg: encrypted with 2047-bit RSA key, ID 602FE5EB7BFA4B00, created 2017-10-03 "testkey" File 'foo.txt' exists. Overwrite? (y/N) y -Step7: pin on screen +Step7: pin on screen ------ Restart from Step1, but skip step4 diff --git a/doc/user/blue-app-openpgp-card.rst b/doc/user/blue-app-openpgp-card.rst index 7e350c9..b1ceb0b 100644 --- a/doc/user/blue-app-openpgp-card.rst +++ b/doc/user/blue-app-openpgp-card.rst @@ -3,7 +3,7 @@ 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 + 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. @@ -53,9 +53,9 @@ The application supports: - RSA with key up to 4096 bits - ECDSA with secp256k1, secp256r1, brainpool 256r1 and brainpool 256t1 curves - EDDSA with Ed25519 curve - - ECDH with secp256k1, secp256r1, brainpool 256r1, brainpool 256t1 and + - ECDH with secp256k1, secp256r1, brainpool 256r1, brainpool 256t1 and curve25519 curves - + This release has known missing parts (see also [GPGADD]) : - Ledger Blue support @@ -78,14 +78,14 @@ Use the "Ledger Manager" Chrome App. See https://www.ledgerwallet.com/apps/manag As the "OpenPGP card" application is not fully compliant with UI and documentation guidelines, the application is in developer section: click on "Show developers items" on the bottom right corner to see it. - - Launch the Ledger Manager. See `Ledger Manager `_ - and ` `_ + - Launch the Ledger Manager. See `Ledger Manager `_ + and ` `_ for details about installing and using the manager; - - Connect your Nano S or your Blue, enter your PIN, and stay on the + - Connect your Nano S or your Blue, enter your PIN, and stay on the dashboard; - Click on *show developer items* on the bottom right corner; - Click on the green bottom arrow icon near the Ledger *Open PGP* logo; - - Confirm the installation when required on your device by pressing the + - Confirm the installation when required on your device by pressing the right button above the check mark; - Quit the Ledger Manager @@ -118,7 +118,7 @@ If you are using an old version of CCID, you have to have to add the NanoS to /e - In ifdVendorID add the entry 0x2C97 - In ifdProductID add the entry 0x0001 - In ifdFriendlyName add the entry Ledger Token - + These 3 entries must be added at the end of each list. For the NanoX : @@ -138,7 +138,7 @@ MAC - In ifdVendorID add the entry 0x2C97 - In ifdProductID add the entry 0x0001 - In ifdFriendlyName add the entry Ledger Token - + This 3 entries must be added at the end of each list. 3. [Enable SIP](https://developer.apple.com/library/content/documentation/Security/Conceptual/System_Integrity_Protection_Guide/ConfiguringSystemIntegrityProtection/ConfiguringSystemIntegrityProtection.html) @@ -191,13 +191,13 @@ The full menu layout is : | Confirm only #+ | Trust | Reset -| About +| About | \ *OpenPGP Card* | \ *(c) Ledger SAS* | \ *Spec 3.0* | \ *App 1.0.1* -| Emphasis entries are not selectable and just provide information. +| Emphasis entries are not selectable and just provide information. | A "**#**" after the entry label means default value on reset. | A "**+**" after the entry label means current value. @@ -224,13 +224,13 @@ Select Slot This menu is only available on ``XL`` version A Slot is a set of -three key pairs *Signature, Decryption, Authentication* as defined by gnupg +three key pairs *Signature, Decryption, Authentication* as defined by gnupg specification. Usually a GPG card application only manages a single set. Ledger version enhances -this and allows you to manage three key sets. +this and allows you to manage three key sets. -The *Select Slot* menu allows you to select the slot you want to play with, and +The *Select Slot* menu allows you to select the slot you want to play with, and to set the default slot when the application start. To change the current slot, display the slot you want and select it @@ -245,8 +245,8 @@ Settings Key Template ~~~~~~~~~~~~ -A key template is defined by the OpenGPG card application specification. It -describes the key to be generated with the ``generate`` command in +A key template is defined by the OpenGPG card application specification. It +describes the key to be generated with the ``generate`` command in ``gpg --card-edit`` To set up a new ECC template you have three choices: the ``gpg --edit-card`` @@ -303,10 +303,10 @@ To show the current template use the ``gpg --card-status`` command. **gpg-connect-agent** -This method suppose you have correctly configured your GnuPG tool. +This method suppose you have correctly configured your GnuPG tool. See the dedicated section for that. -In a terminal launch : +In a terminal launch : | ``gpg-connect-agent "SCD SETATTR KEY-ATTR --force 1 " /bye`` | ``gpg-connect-agent "SCD SETATTR KEY-ATTR --force 2 18 " /bye`` @@ -327,7 +327,7 @@ To show the current template use the ``gpg --card-status`` command. **NanoS menu** First under *Choose Key* menu, select the one of three keys for which you want to modify -the template. Then under "Choose Type", select the desired key template. +the template. Then under "Choose Type", select the desired key template. Finally select "Set Template" entry to set it. To show the current template use the ``gpg --card-status`` command. @@ -349,13 +349,13 @@ When the application starts, the seeded mode is always set to *OFF* PIN mode ~~~~~~~~ -Some operations require the user to enter his PIN code. +Some operations require the user to enter his PIN code. The default PIN values are: - user: ``123456`` - admin: ``12345678`` -The PIN entry can be done using four methods, named +The PIN entry can be done using four methods, named "*Host*", "*On Screen*", "*Confirm only*", "*Trust*". After each mode a *+* or *#* symbol may appear to tell which mode is the current one @@ -363,14 +363,14 @@ and which one is the default when the application starts. The default mode can be changed by first selecting the desired mode and then selecting the *Set default" menu. Note that *Trust* can not be set as default mode. -Before you can change the PIN mode, you need to verify the PIN on the client. To do this, +Before you can change the PIN mode, you need to verify the PIN on the client. To do this, run ``gpg --card-edit``, then ``admin`` and finally ``verify`` on you PC. You will then be asked to enter the current PIN. After doing so, you can change the PIN mode on your device. -Note that *On Screen*", "*Confirm only*" and "*Trust*" may not work if the -client application does not support it. In that case the "*Host*" should be +Note that *On Screen*", "*Confirm only*" and "*Trust*" may not work if the +client application does not support it. In that case the "*Host*" should be automatically used by the client in a transparent way. **Host** @@ -393,36 +393,36 @@ letter .. image:: pin_validate.png :align: middle - + If you want to change the previous digit select the **'C'** (Cancel) letter. .. image:: pin_cancel.png :align: middle - + Finally if you want to abort the PIN entry, select the **'A'** (Abort) letter. .. image:: pin_abort.png :align: middle - + **Confirm only** -The user is requested, on the NanoS or Blue screen, to confirm +The user is requested, on the NanoS or Blue screen, to confirm the PIN validation. The PIN value is not required, the user just has -to push the *REJECT* or *OK* button on the device. +to push the *REJECT* or *OK* button on the device. -This is the default mode after application installation. +This is the default mode after application installation. .. image:: pin_confirm.png :align: middle - + **Trust** Act as if the PIN is always validated. This is a dangerous mode which should only be -used in a highly secure environment. +used in a highly secure environment. UIF mode ~~~~~~~~ @@ -438,9 +438,9 @@ When activated, a '+' symbol appears after the operation name. Reset ~~~~~ -Selecting the menu will erase all OpenPGP Card Application data and will +Selecting the menu will erase all OpenPGP Card Application data and will reset the application in its '*just installed*' state. - + Nano S OpenPGP Card application usage @@ -460,8 +460,8 @@ keyring before starting, except if your are sure about what you do. Configuration ~~~~~~~~~~~~~ -In order to use a Ledger device with gpg it is needed to explicitly setup -the reader and the delegated PIN support. +In order to use a Ledger device with gpg it is needed to explicitly setup +the reader and the delegated PIN support. Edit the file ~/.gnupg/scdaemon.conf and add the following lines: | ``reader-port "Ledger Token [Nano S] (0001) 01 00"`` @@ -519,7 +519,7 @@ installation it should look like this: | ``Authentication key: [none]`` | ``General key info..: [none]`` -You can set the user information with the ``gpg --card-edit`` command and +You can set the user information with the ``gpg --card-edit`` command and ``name``, ``url``, ``login``, ``lang``, ``sex`` subcommands. For example if you want to set up your name: @@ -558,9 +558,9 @@ want to set up your name: Notes: - + * Modifying the user information will prompt you to enter ``User PIN``. - * Setting user information is not required for using gpg client. + * Setting user information is not required for using gpg client. Generate new key pair @@ -570,7 +570,7 @@ For generating a new key pair follow those steps: - Select the desired NanoS OpenPGP Card application slot - Setup the desired key template for this slot - - Generate the new key set + - Generate the new key set **Step 1** @@ -586,23 +586,23 @@ Starting from main menu: **Step 2** -The default template for each three keys (*signature*, *decryption*, +The default template for each three keys (*signature*, *decryption*, *authentication*) is ``RSA 2048``. If you want another kind of key you have to set the template before generating keys. -!WARNING!: changing the current template of a key automatically erases +!WARNING!: changing the current template of a key automatically erases the associated key. Starting from main menu: - Select *Settings* menu - - Select *Key template* menu + - Select *Key template* menu - Select *Choose Key...* menu (a) - Scroll and select which key you want to set the new template for - Select *Choose type...* menu - Scroll and select among the supported key types and sizes - Select *Set template* - - Repeat this process from (a) if you want to modify another key + - Repeat this process from (a) if you want to modify another key template - Select *Back* to return to main menu. @@ -610,7 +610,7 @@ Starting from main menu: **Step 3** Once the template has been set, it's possible to generate new key pairs -with ``gpg``. +with ``gpg``. !WARNING!: gpg will generate the three key pairs and will overwrite any key already present in the selected slot. @@ -650,18 +650,18 @@ the three key templates are ``NIST P256``. **Request new key generation without backup** | ``gpg/card>`` *generate* - | ``Make off-card backup of encryption key? (Y/n)`` **n** + | ``Make off-card backup of encryption key? (Y/n)`` **n** **Unlock user level ``81``** - | ``Please unlock the card`` + | ``Please unlock the card`` | ```` | ``Number: 2C97 AFB1142B`` | ``Holder: Cedric Mesnil`` | ```` | ``Use the reader's pinpad for input.`` | `` OK`` - | ``Press any key to continue. `` + | ``Press any key to continue. `` **Set key validity** @@ -676,12 +676,12 @@ the three key templates are ``NIST P256``. | ``Is this correct? (y/N)``*y* **Set user ID** - + | ``GnuPG needs to construct a user ID to identify your key.`` | ```` | ``Real name: Cedric Mesnil`` | ``Email address: cedric@ledger.fr`` - | ``Comment: `` + | ``Comment: `` | ``You selected this USER-ID:`` | `` "Cedric Mesnil "`` | ```` @@ -692,7 +692,7 @@ the three key templates are ``NIST P256``. **Unlock admin level ``83``** - | ``Please enter the Admin PIN `` + | ``Please enter the Admin PIN `` | ```` | ``Number: 2C97 AFB1142B`` | ``Holder: Cedric Mesnil`` @@ -748,9 +748,9 @@ the three key templates are ``NIST P256``. | ``General key info..: pub nistp256/F8A4A3533CBFCAA5 2017-08-22 cedric mesnilCedric Mesnil `` | ``sec> nistp256/F8A4A3533CBFCAA5 created: 2017-08-22 expires: never `` | `` card-no: 2C97 AFB1142B`` - | ``ssb> nistp256/2345A677CE9D8223 created: 2017-08-22 expires: never `` + | ``ssb> nistp256/2345A677CE9D8223 created: 2017-08-22 expires: never `` | `` card-no: 2C97 AFB1142B`` - | ``ssb> nistp256/E13728E913B877E1 created: 2017-08-22 expires: never `` + | ``ssb> nistp256/E13728E913B877E1 created: 2017-08-22 expires: never `` | `` card-no: 2C97 AFB1142B`` **Say goodbye @@ -789,7 +789,7 @@ The key to transfer here is a RSA 4096 bits key: In case of transfer it is not necessary to previously set the template. It will be automatically changed. -When generating a new key, the three keys (*signature*, *decryption*, +When generating a new key, the three keys (*signature*, *decryption*, *authentication*)) are automatically generated. When transferring existing ones, it is possible to choose which one will be moved. @@ -804,7 +804,7 @@ moved. | ``Secret key is available.`` | ```` | ``sec rsa4096/9B93CB47F954FB53`` - | `` created: 2017-04-26 expires: never usage: SC `` + | `` created: 2017-04-26 expires: never usage: SC `` | `` trust: ultimate validity: ultimate`` | ``ssb rsa4096/49EE12B0F5CBDF26`` | `` created: 2017-04-26 expires: never usage: E `` @@ -821,7 +821,7 @@ moved. | `` created: 2017-04-26 expires: never usage: E `` | ``[ultimate] (1). RSA 4096`` -**Move** +**Move** | ``gpg> `` **keytocard** | ``Please select where to store the key:`` @@ -890,8 +890,8 @@ Decrypting and Signing Decrypting and Signing will act exactly the same way as if keys were not on -the card. The only difference is ``gpg`` will request the PIN code instead -of the passphrase. +the card. The only difference is ``gpg`` will request the PIN code instead +of the passphrase. SSH @@ -902,7 +902,7 @@ Overview ~~~~~~~~ In order to use gpg for SSH authentication, an "authentication" is needed. -There are two solutions for that, either generate one on the device +There are two solutions for that, either generate one on the device or add an authentication sub-key to your existing master gpg key. Once done, it is necessary to configure ssh to point to the right key and @@ -914,7 +914,7 @@ Generate new key on device The important thing to keep in mind here is there is no way to tell gpg to only generate the authentication key. So generating this key will also -generate the two other under a new identity and will erase existing keys +generate the two other under a new identity and will erase existing keys on the current slot on the device. Nevertheless, if you want to use a different identity for ssh login, you can use @@ -1021,7 +1021,7 @@ Add sub-key | ``generator a better chance to gain enough entropy.`` | ``sec rsa2048/831415DA94A9A15C`` - | `` created: 2017-08-25 expires: never usage: SC `` + | `` created: 2017-08-25 expires: never usage: SC `` | `` trust: ultimate validity: ultimate`` | ``ssb rsa2048/8E95F2999EEC38C4`` | `` created: 2017-08-25 expires: never usage: E `` @@ -1053,7 +1053,7 @@ Add sub-key | ``ssb rsa2048/8E95F2999EEC38C4`` | `` created: 2017-08-25 expires: never usage: E `` | ``ssb* rsa2048/C20B90E12F68F035`` - | `` created: 2017-08-28 expires: never usage: A `` + | `` created: 2017-08-28 expires: never usage: A `` | ``[ultimate] (1). cedric`` @@ -1074,7 +1074,7 @@ to your .gpg-agent.conf: ``enable-ssh-support`` -Starting with gpg2 it necessary to add some configuration options to make the *pinentry* +Starting with gpg2 it necessary to add some configuration options to make the *pinentry* work properly. Add the following line to ~/.bashrc file: | ``export SSH_AUTH_SOCK=`gpgconf --list-dirs agent-ssh-socket` `` @@ -1093,7 +1093,7 @@ And add the following line to your ~/.gnupg/gpg.conf: ``pinentry-mode loopback`` -Then export your authentication public key. First execute the +Then export your authentication public key. First execute the ``gpg -k --with-subkey-fingerprint --with-keygrip cedric`` command. @@ -1113,7 +1113,7 @@ to .gnupg/sshcontrol file: | ``$ echo 6D60CB58D9D66EE09804E7FE460E865A91F5E41A > .gnupg/sshcontrol`` -Export your authentication key, identifier by its fingerprint, in a SSH compliant format. +Export your authentication key, identifier by its fingerprint, in a SSH compliant format. | ``$ gpg --export-ssh-key 2D0E4FFFAA448AA2770C7F02C20B90E12F68F035`` | ``ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDCIARKh0IZTHld+I6oA8nwrgnCUQE8f`` @@ -1122,8 +1122,8 @@ Export your authentication key, identifier by its fingerprint, in a SSH complian | ``3uEBsaY5PR1Tuko/GwywLyZu0SwfEobl/RPjL7P8rUSc7DTHpQMw8fjJFb4BNvIHAlaVC`` | ``5FwZwkuogygaJdN/44MayHFmOZmzx9CAgYgLpTzen35+CcyhlqCqi+HjNlnHL2DDWd4iR`` | ``d3Y6pY8LjS3xQkECc3Bhedptp17D+H9AVJt openpgp:0x2F68F035`` - -Finally copy the above export (``ssh-rsa AAAAB...Jt openpgp:0x2F68F035``) into the + +Finally copy the above export (``ssh-rsa AAAAB...Jt openpgp:0x2F68F035``) into the ~/.ssh/authorized_keys file on your remote server. @@ -1143,11 +1143,11 @@ Backup and Restore Introduction ~~~~~~~~~~~~ -"The OpenPGP card" specification does not provide any mechanism for backuping you key. +"The OpenPGP card" specification does not provide any mechanism for backuping you key. Thus if you generate your keys on device and loose it, you definitively loose you private key. In order to avoid such extreme panic situation, a backup/restore mechanism is provided. -At any time you can backup a snapshot of your device data, including your private keys. +At any time you can backup a snapshot of your device data, including your private keys. All public data are retrieve in clear form. The private key are stored encrypted with a key derived from your seed, i.e. from your 24 BIP words. @@ -1161,13 +1161,13 @@ The backup/restore tool is located in ``pytools`` directory: | ``optional arguments:`` | `` -h, --help show this help message and exit`` | `` --adm-pin PIN Administrative PIN, if pinpad not used`` - | `` --backup Perfom a full backup except the key`` - | `` --backup-keys Perfom keys encrypted backup`` + | `` --backup Perform a full backup except the key`` + | `` --backup-keys Perform keys encrypted backup`` | `` --file FILE basckup/restore file`` | `` --pinpad PIN validation will be deledated to pinpad`` | `` --reader READER PCSC reader`` | `` --reset Reset the application. All data are erased`` - | `` --restore Perfom a full restore except the key`` + | `` --restore Perform a full restore except the key`` | `` --set-serial SERIAL set the four serial bytes`` | `` --set-fp SIG:DEC:AUT sig:dec:aut fingerprints, 20 bytes each in hexa`` | `` --seed-key Regenerate all keys, based on seed mode`` @@ -1175,20 +1175,20 @@ The backup/restore tool is located in ``pytools`` directory: | `` --user-pin PIN User PIN, if pinpad not used`` -First you must either provide your pin codes or use the pinpad (onscreen pin). This is +First you must either provide your pin codes or use the pinpad (onscreen pin). This is done by giving either ``--adm-pin`` AND ``--user-pin`` or ``--pinpad``. Note that 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`` -If you encounter an error when performing the backup/restore, reload your scdaemon with +If you encounter an error when performing the backup/restore, reload your scdaemon with ``gpgconf --reload scdaemon`` @@ -1198,7 +1198,7 @@ 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 --file my_bck_file_name.pickle`` backup command without private keys: @@ -1207,20 +1207,20 @@ backup command without private keys: full restore command: - + | ``python3 -m gpgcard.gpgcli --restore --pinpad --file my_bck_file_name.pickle`` full restore command with seed key generation: - + | ``python3 -m gpgcard.gpgcli --restore --pinpad --seed-key --file my_bck_file_name.pickle`` Restore without backup ~~~~~~~~~~~~~~~~~~~~~~ -If you have seeded key but do not have done a backup and still have your keyring, there is a -solution to restore at least the key and their related information: serial and fingerprints. +If you have seeded key but do not have done a backup and still have your keyring, there is a +solution to restore at least the key and their related information: serial and fingerprints. All other information such as name, url, ... shall be set manually with ``gpg --card-edit``. @@ -1251,7 +1251,7 @@ Run the command ``gpg --edit-key John``, replace John by your own key id. | | ``gpg> `` | - + The ``usage`` field tells you each key purpose: ``SC`` or ``S`` for signature, ``A`` for authentication, ``E`` for encryption. @@ -1261,7 +1261,7 @@ You should have three or less keys with the same serial. These are the keys we w For each key you also have the key template (rsa2048, rsa3072, rsa4096, ed2559, cv25519) followed by the short fingerprint, e.g. ``ed25519/8451AAF7D43D1095`` -Note the serial and the three key template names: ``FD6C11BE`` , ``ed25519:cv25519:ed25519``. +Note the serial and the three key template names: ``FD6C11BE`` , ``ed25519:cv25519:ed25519``. Take care of the order: ``SC:E:A``. Now type the ``quit`` command. @@ -1281,8 +1281,8 @@ To get the full fingerprint of each key, run (yes twice ``--fingerprint``): | ``sub cv25519 2018-10-10 [E]`` | `` DF15 7BD4 AC3B D1EE 9910 99C8 0953 D871 FC4B 9EA4`` -Assemble the three full fingerprint, corresponding to the one identified previously, -in the the following order ``SC:E:A`` : +Assemble the three full fingerprint, corresponding to the one identified previously, +in the the following order ``SC:E:A`` : ``2C688345BDDA0EDFB24DB4FB8451AAF7D43D1095:DF157BD4AC3BD1EE991099C80953D871FC4B9EA4: CEC59AE6A76614BC3C6D37D9C5A8FB078520ABBB``. @@ -1294,7 +1294,7 @@ If you only have one key to restore you can omit the others, for example to only **Step 1: restore** -Plug you Nano S and run the OpenPGP application. +Plug you Nano S and run the OpenPGP application. Finally run the following command : @@ -1323,19 +1323,19 @@ logout/login **Q:** It does not work at all, HELP ME!!! -**R** Please keep calm and do not cry. +**R** Please keep calm and do not cry. Add the following option to ~/.gnupg/gpg-agent.conf - + | ``debug-level guru`` | ``log-file /tmp/gpgagent.log`` Add the following option to ~/.gnupg/scdaemon.conf - + | ``log-file /tmp/scd.log`` | ``debug-level guru`` | ``debug-all`` -Make a nice issue report under github providing log and and command line you run. +Make a nice issue report under github providing log and and command line you run. **!*WARNING*!** : this may reveal confidential information such as key values. Do your log with a test key. diff --git a/doc/user/blue-app-openpgp-card.template b/doc/user/blue-app-openpgp-card.template index 6e2e0f8..5a5138d 100644 --- a/doc/user/blue-app-openpgp-card.template +++ b/doc/user/blue-app-openpgp-card.template @@ -208,7 +208,7 @@ $endfor$ {\scshape\LARGE OpenPGP Card Application \par} {\scshape \LARGE User Guide \par} \vspace{1cm} - + % {\scshape\Large Ledger SAS \par} \vspace{1cm} \begin{figure}[h] diff --git a/images/LICENSE b/images/LICENSE index ef84e83..9d28341 100644 --- a/images/LICENSE +++ b/images/LICENSE @@ -8,4 +8,3 @@ Thanks to gnupg.org for the original images. Others under this directory are covered by Apache License Version 2.0, - diff --git a/pytools/gpgcard/__init__.py b/pytools/gpgcard/__init__.py index 48b1f69..45940a0 100644 --- a/pytools/gpgcard/__init__.py +++ b/pytools/gpgcard/__init__.py @@ -1,15 +1,14 @@ # 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. # - diff --git a/pytools/gpgcard/backup.py b/pytools/gpgcard/backup.py index 4abcf4e..2ee62d0 100644 --- a/pytools/gpgcard/backup.py +++ b/pytools/gpgcard/backup.py @@ -1,11 +1,11 @@ # 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. diff --git a/pytools/gpgcard/gpgcard.py b/pytools/gpgcard/gpgcard.py index 59dd999..d6d63db 100644 --- a/pytools/gpgcard/gpgcard.py +++ b/pytools/gpgcard/gpgcard.py @@ -847,4 +847,3 @@ class GPGCard() : 'e': tags[0x82], 'd': tags[0x98], } - diff --git a/pytools/gpgcard/gpgcli.py b/pytools/gpgcard/gpgcli.py index 29465bb..cb94d08 100644 --- a/pytools/gpgcard/gpgcli.py +++ b/pytools/gpgcard/gpgcli.py @@ -80,7 +80,7 @@ try: gpgcard.connect(args.reader) print("OK") - print("Verfify PINs...", end='', flush=True) + print("Verify PINs...", end='', flush=True) if args.pinpad: if not gpgcard.verify_pin(0x82, "", True) or not gpgcard.verify_pin(0x83, "", True): error("PIN not verified") @@ -122,7 +122,7 @@ try: 'rsa3072' : "010C00002001", 'rsa4096' : "011000002001", 'nistp256' : "132A8648CE3D030107", - 'ed255519' : "162B06010401DA470F01", + 'ed25519' : "162B06010401DA470F01", 'cv25519' : "122B060104019755010501" } sig,dec,aut = args.set_templates.split(":") diff --git a/pytools/gpgcard/restore.py b/pytools/gpgcard/restore.py index d75b565..382c4a7 100644 --- a/pytools/gpgcard/restore.py +++ b/pytools/gpgcard/restore.py @@ -1,11 +1,11 @@ # 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. diff --git a/src/gpg_api.h b/src/gpg_api.h index 2622005..27852d5 100644 --- a/src/gpg_api.h +++ b/src/gpg_api.h @@ -18,17 +18,17 @@ void USBD_CCID_activate_pinpad(int enabled); -unsigned int gpg_oid2curve(unsigned char *oid, unsigned int len); +unsigned int gpg_oid2curve(unsigned char *oid, unsigned int len); unsigned char *gpg_curve2oid(unsigned int cv, unsigned int *len); -unsigned int gpg_curve2domainlen(unsigned int cv); +unsigned int gpg_curve2domainlen(unsigned int cv); void gpg_init(void); void gpg_init_ux(void); void gpg_install(unsigned char app_state); void gpg_install_slot(gpg_key_slot_t *slot); -int gpg_dispatch(void); +int gpg_dispatch(void); -int gpg_apdu_select_data(unsigned int ref, int reccord); +int gpg_apdu_select_data(unsigned int ref, int record); 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); @@ -38,13 +38,13 @@ 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 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); + 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_select(void); @@ -53,11 +53,11 @@ 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_apdu_mse(); @@ -81,16 +81,16 @@ 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); +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_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); @@ -108,7 +108,7 @@ void io_usb_ccid_set_card_inserted(unsigned int inserted); #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 bb53e2b..b6f61ca 100644 --- a/src/gpg_challenge.c +++ b/src/gpg_challenge.c @@ -20,48 +20,56 @@ #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; - } else { - olen = G_gpg_vstate.io_le; - } - if (olen == 0 || olen > GPG_EXT_CHALLENGE_LENTH) { - THROW(SW_WRONG_LENGTH); - return SW_WRONG_LENGTH; - } + if ((G_gpg_vstate.io_p1 & 0x80) == 0x80) { + olen = G_gpg_vstate.io_p2; + } else { + olen = G_gpg_vstate.io_le; + } + if (olen == 0 || olen > GPG_EXT_CHALLENGE_LENTH) { + 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]; + if ((G_gpg_vstate.io_p1 & 0x82) == 0x82) { + unsigned int path[2]; + unsigned char chain[32]; + unsigned char Sr[32]; - 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'; + 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'; - 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); + 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); - 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); - } else { - cx_rng(G_gpg_vstate.work.io_buffer, olen); - } + cx_sha3_xof_init(&G_gpg_vstate.work.md.sha3, 256, olen); + cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha3, + CX_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); - } - gpg_io_discard(0); - gpg_io_inserted(olen); - return SW_OK; + 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 2409244..14bbd5b 100644 --- a/src/gpg_data.c +++ b/src/gpg_data.c @@ -19,841 +19,920 @@ #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; - return SW_OK; -} - -int gpg_apdu_get_data(unsigned int ref) { - int sw; - - if (G_gpg_vstate.DO_current != ref) { +int gpg_apdu_select_data(unsigned int ref, int record) { G_gpg_vstate.DO_current = ref; - G_gpg_vstate.DO_reccord = 0; - G_gpg_vstate.DO_offset = 0; - } - sw = SW_OK; - - gpg_io_discard(1); - switch (ref) { - /* ----------------- Optional DO for private use ----------------- */ - case 0x0101: - gpg_io_insert((const unsigned char *)N_gpg_pstate->private_DO1.value, N_gpg_pstate->private_DO1.length); - break; - case 0x0102: - gpg_io_insert((const unsigned char *)N_gpg_pstate->private_DO2.value, N_gpg_pstate->private_DO2.length); - break; - case 0x0103: - gpg_io_insert((const unsigned char *)N_gpg_pstate->private_DO3.value, N_gpg_pstate->private_DO3.length); - break; - case 0x0104: - gpg_io_insert((const unsigned char *)N_gpg_pstate->private_DO4.value, N_gpg_pstate->private_DO4.length); - break; - - /* ----------------- Config key slot ----------------- */ - case 0x01F0: - gpg_io_insert((const unsigned char *)N_gpg_pstate->config_slot, 3); - gpg_io_insert_u8(G_gpg_vstate.slot); - break; - case 0x01F1: - gpg_io_insert((const unsigned char *)N_gpg_pstate->config_slot, 3); - break; - case 0x01F2: - gpg_io_insert_u8(G_gpg_vstate.slot); - break; - /* ----------------- Config RSA exponent ----------------- */ - case 0x01F8: - gpg_io_insert((const unsigned char *)N_gpg_pstate->default_RSA_exponent, 4); - break; - - /* ----------------- Application ----------------- */ - /* Full Application identifier */ - case 0x004F: - gpg_io_insert((const unsigned char *)N_gpg_pstate->AID, 10); - gpg_io_insert(G_gpg_vstate.kslot->serial, 4); - gpg_io_insert_u16(0x0000); - break; - /* Historical bytes, */ - case 0x5F52: - gpg_io_insert((const unsigned char *)N_gpg_pstate->histo, 15); - break; - /* Extended length information */ - case 0x7F66: - gpg_io_insert(C_ext_length, sizeof(C_ext_length)); - break; - - /* ----------------- User -----------------*/ - /* Login data */ - case 0x005E: - gpg_io_insert((const unsigned char *)N_gpg_pstate->login.value, N_gpg_pstate->login.length); - break; - /* Uniform resource locator */ - case 0x5F50: - gpg_io_insert((const unsigned char *)N_gpg_pstate->url.value, N_gpg_pstate->url.length); - break; - /* Name, Language, Sex */ - case 0x65: - gpg_io_insert_tlv(0x5B, N_gpg_pstate->name.length, (const unsigned char *)N_gpg_pstate->name.value); - gpg_io_insert_tlv(0x5F2D, N_gpg_pstate->lang.length, (const unsigned char *)N_gpg_pstate->lang.value); - gpg_io_insert_tlv(0x5F35, 1, (const unsigned char *)N_gpg_pstate->sex); - break; - - /* ----------------- aid, histo, ext_length, ... ----------------- */ - case 0x6E: - gpg_io_insert_tlv(0x4F, 16, (const unsigned char *)N_gpg_pstate->AID); - 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, (const unsigned char *)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(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((const unsigned char *)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); - gpg_io_insert_tl(0xC5, 60); - gpg_io_insert(G_gpg_vstate.kslot->sig.fingerprints, 20); - gpg_io_insert(G_gpg_vstate.kslot->dec.fingerprints, 20); - gpg_io_insert(G_gpg_vstate.kslot->aut.fingerprints, 20); - gpg_io_insert_tl(0xC6, 60); - gpg_io_insert(G_gpg_vstate.kslot->sig.CA_fingerprints, 20); - gpg_io_insert(G_gpg_vstate.kslot->dec.CA_fingerprints, 20); - gpg_io_insert(G_gpg_vstate.kslot->aut.CA_fingerprints, 20); - gpg_io_insert_tl(0xCD, 12); - gpg_io_insert(G_gpg_vstate.kslot->sig.date, 4); - 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_set_offset(IO_OFFSET_END); - break; - - /* ----------------- User Interaction Flag (UIF) for PSO:CDS ----------------- */ - case 0x00D6: - gpg_io_insert(G_gpg_vstate.kslot->sig.UIF, 2); - break; - case 0x00D7: - gpg_io_insert(G_gpg_vstate.kslot->dec.UIF, 2); - break; - case 0x00D8: - gpg_io_insert(G_gpg_vstate.kslot->aut.UIF, 2); - break; - - /* ----------------- Security support template ----------------- */ - case 0x7A: - gpg_io_insert_tl(0x93, 3); - gpg_io_insert_u24(G_gpg_vstate.kslot->sig_count); - break; - - /* ----------------- Cardholder certificate ----------------- */ - 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); - break; - case 1: - 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); - break; - default: - sw = SW_RECORD_NOT_FOUND; - } - break; - - /* ----------------- PW Status Bytes ----------------- */ - case 0x00C4: - gpg_io_insert((const unsigned char *)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); - break; - - /* WAT */ - default: - THROW(SW_REFERENCED_DATA_NOT_FOUND); - return 0; - } - - return sw; + G_gpg_vstate.DO_reccord = record; + G_gpg_vstate.DO_offset = 0; + return SW_OK; } -int gpg_apdu_get_next_data(unsigned int ref) { - int sw; - - if ((ref != 0x7F21) || (G_gpg_vstate.DO_current != 0x7F21)) { - return SW_CONDITIONS_NOT_SATISFIED; - } - sw = gpg_apdu_get_data(ref); - if (sw == SW_OK) { - G_gpg_vstate.DO_reccord++; - } - return sw; -} +int gpg_apdu_get_data(unsigned int ref) { + int sw; -int gpg_apdu_put_data(unsigned int ref) { - unsigned int t, l, sw; - unsigned int * ptr_l; - unsigned char *ptr_v; - - G_gpg_vstate.DO_current = ref; - sw = SW_OK; - - switch (ref) { - /* ----------------- Optional DO for private use ----------------- */ - case 0x0101: - ptr_l = (unsigned int *)&N_gpg_pstate->private_DO1.length; - ptr_v = (unsigned char *)N_gpg_pstate->private_DO1.value; - goto WRITE_PRIVATE_DO; - case 0x0102: - ptr_l = (unsigned int *)&N_gpg_pstate->private_DO2.length; - ptr_v = (unsigned char *)N_gpg_pstate->private_DO2.value; - goto WRITE_PRIVATE_DO; - case 0x0103: - ptr_l = (unsigned int *)&N_gpg_pstate->private_DO3.length; - ptr_v = (unsigned char *)N_gpg_pstate->private_DO3.value; - goto WRITE_PRIVATE_DO; - case 0x0104: - ptr_l = (unsigned int *)&N_gpg_pstate->private_DO4.length; - ptr_v = (unsigned char *)N_gpg_pstate->private_DO4.value; - goto WRITE_PRIVATE_DO; - WRITE_PRIVATE_DO: - if (G_gpg_vstate.io_length > GPG_EXT_PRIVATE_DO_LENGTH) { - THROW(SW_WRONG_LENGTH); - return 0; + 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; } - 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; - /* ----------------- Config key slot ----------------- */ - case 0x01F1: - if (G_gpg_vstate.io_length != 3) { - 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); - return 0; - } - gpg_nvm_write((void *)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); - return 0; - } - G_gpg_vstate.slot = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset]; - break; - - /* ----------------- Config RSA exponent ----------------- */ - case 0x01F8: { - unsigned int e; - if (G_gpg_vstate.io_length != 4) { - THROW(SW_WRONG_LENGTH); - return 0; - } - e = gpg_io_fetch_u32(); - nvm_write((void *)&N_gpg_pstate->default_RSA_exponent, &e, sizeof(unsigned int)); - break; - } - - /* ----------------- Serial -----------------*/ - case 0x4f: - if (G_gpg_vstate.io_length != 4) { - THROW(SW_WRONG_LENGTH); - } - nvm_write(G_gpg_vstate.kslot->serial, &G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset], 4); - break; - - /* ----------------- Extended Header list -----------------*/ - case 0x3FFF: { - unsigned int len_e, len_p, len_q; - unsigned int endof, ksz, reset_cnt; - gpg_key_t * keygpg; - // 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); - reset_cnt = 0; - switch (t) { - case 0xB6: - keygpg = &G_gpg_vstate.kslot->sig; - reset_cnt = 0x11111111; - break; - case 0xA4: - keygpg = &G_gpg_vstate.kslot->aut; - break; - case 0xB8: - keygpg = &G_gpg_vstate.kslot->dec; - break; - default: - THROW(SW_REFERENCED_DATA_NOT_FOUND); - return 0; - } - // 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_offset < endof) { - gpg_io_fetch_tl(&t, &l); - switch (t) { - case 0x91: - len_e = l; - break; - case 0x92: - len_p = l; - break; - case 0x93: - len_q = l; - break; - break; - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x99: - break; - default: - THROW(SW_REFERENCED_DATA_NOT_FOUND); - return 0; - } - } - // fecth 5f78 - gpg_io_fetch_tl(&t, &l); - if (t != 0x5f48) { - THROW(SW_REFERENCED_DATA_NOT_FOUND); - return 0; - } + gpg_io_discard(1); + switch (ref) { + /* ----------------- Optional DO for private use ----------------- */ + case 0x0101: + gpg_io_insert((const unsigned char *) N_gpg_pstate->private_DO1.value, + N_gpg_pstate->private_DO1.length); + break; + case 0x0102: + gpg_io_insert((const unsigned char *) N_gpg_pstate->private_DO2.value, + N_gpg_pstate->private_DO2.length); + break; + case 0x0103: + gpg_io_insert((const unsigned char *) N_gpg_pstate->private_DO3.value, + N_gpg_pstate->private_DO3.length); + break; + case 0x0104: + gpg_io_insert((const unsigned char *) N_gpg_pstate->private_DO4.value, + N_gpg_pstate->private_DO4.length); + break; + + /* ----------------- Config key slot ----------------- */ + case 0x01F0: + gpg_io_insert((const unsigned char *) N_gpg_pstate->config_slot, 3); + gpg_io_insert_u8(G_gpg_vstate.slot); + break; + case 0x01F1: + gpg_io_insert((const unsigned char *) N_gpg_pstate->config_slot, 3); + break; + case 0x01F2: + gpg_io_insert_u8(G_gpg_vstate.slot); + break; + /* ----------------- Config RSA exponent ----------------- */ + case 0x01F8: + gpg_io_insert((const unsigned char *) N_gpg_pstate->default_RSA_exponent, 4); + break; + + /* ----------------- Application ----------------- */ + case 0x004F: + /* Full Application identifier */ + gpg_io_insert((const unsigned char *) N_gpg_pstate->AID, 10); + gpg_io_insert(G_gpg_vstate.kslot->serial, 4); + gpg_io_insert_u16(0x0000); + break; + case 0x5F52: + /* Historical bytes */ + gpg_io_insert((const unsigned char *) N_gpg_pstate->histo, 15); + break; + case 0x7F66: + /* Extended length information */ + gpg_io_insert(C_ext_length, sizeof(C_ext_length)); + break; + + /* ----------------- User -----------------*/ + case 0x005E: + /* Login data */ + gpg_io_insert((const unsigned char *) N_gpg_pstate->login.value, + N_gpg_pstate->login.length); + break; + case 0x5F50: + /* Uniform resource locator */ + gpg_io_insert((const unsigned char *) N_gpg_pstate->url.value, + N_gpg_pstate->url.length); + break; + case 0x65: + /* Name, Language, Sex */ + gpg_io_insert_tlv(0x5B, + N_gpg_pstate->name.length, + (const unsigned char *) N_gpg_pstate->name.value); + gpg_io_insert_tlv(0x5F2D, + N_gpg_pstate->lang.length, + (const unsigned char *) N_gpg_pstate->lang.value); + gpg_io_insert_tlv(0x5F35, 1, (const unsigned char *) N_gpg_pstate->sex); + break; + + /* ----------------- aid, histo, ext_length, ... ----------------- */ + case 0x6E: + gpg_io_insert_tlv(0x4F, 16, (const unsigned char *) N_gpg_pstate->AID); + 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, (const unsigned char *) 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(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((const unsigned char *) 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); + gpg_io_insert_tl(0xC5, 60); + gpg_io_insert(G_gpg_vstate.kslot->sig.fingerprints, 20); + gpg_io_insert(G_gpg_vstate.kslot->dec.fingerprints, 20); + gpg_io_insert(G_gpg_vstate.kslot->aut.fingerprints, 20); + gpg_io_insert_tl(0xC6, 60); + gpg_io_insert(G_gpg_vstate.kslot->sig.CA_fingerprints, 20); + gpg_io_insert(G_gpg_vstate.kslot->dec.CA_fingerprints, 20); + gpg_io_insert(G_gpg_vstate.kslot->aut.CA_fingerprints, 20); + gpg_io_insert_tl(0xCD, 12); + gpg_io_insert(G_gpg_vstate.kslot->sig.date, 4); + 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_set_offset(IO_OFFSET_END); + break; + + /* ----------------- User Interaction Flag (UIF) for PSO:CDS ----------------- */ + case 0x00D6: + gpg_io_insert(G_gpg_vstate.kslot->sig.UIF, 2); + break; + case 0x00D7: + gpg_io_insert(G_gpg_vstate.kslot->dec.UIF, 2); + break; + case 0x00D8: + gpg_io_insert(G_gpg_vstate.kslot->aut.UIF, 2); + break; + + /* ----------------- Security support template ----------------- */ + case 0x7A: + gpg_io_insert_tl(0x93, 3); + gpg_io_insert_u24(G_gpg_vstate.kslot->sig_count); + break; + + /* ----------------- Cardholder certificate ----------------- */ + 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); + break; + case 1: + 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); + break; + default: + sw = SW_RECORD_NOT_FOUND; + } + break; + + /* ----------------- PW Status Bytes ----------------- */ + case 0x00C4: + gpg_io_insert((const unsigned char *) 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); + break; + + default: + /* WAT */ + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return 0; + } + + return sw; +} - // --- RSA KEY --- - if (keygpg->attributes.value[0] == 0x01) { - 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: - pkey_size = sizeof(cx_rsa_1024_private_key_t); - pq = G_gpg_vstate.work.rsa.public1024.n; - break; - case 2048 / 8: - pkey_size = sizeof(cx_rsa_2048_private_key_t); - pq = G_gpg_vstate.work.rsa.public2048.n; - break; - case 3072 / 8: - pkey_size = sizeof(cx_rsa_3072_private_key_t); - pq = G_gpg_vstate.work.rsa.public3072.n; - break; - case 4096 / 8: - pkey_size = sizeof(cx_rsa_4096_private_key_t); - pq = G_gpg_vstate.work.rsa.public4096.n; - break; - } - ksz = ksz >> 1; - - // fetch e - e = 0; - switch (len_e) { - case 4: - e = gpg_io_fetch_u32(); - break; - case 3: - e = gpg_io_fetch_u24(); - break; - case 2: - e = gpg_io_fetch_u16(); - break; - case 1: - e = gpg_io_fetch_u8(); - break; - default: - THROW(SW_WRONG_DATA); - return 0; - } - - // 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; - memmove(pq + ksz - len_p, p, len_p); - memset(pq, 0, ksz - len_p); - memmove(pq + 2 * ksz - len_q, q, len_q); - 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); - - // 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)); - } - } - // --- ECC KEY --- - 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); - if (curve == 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; - 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)); - if (reset_cnt) { - reset_cnt = 0; - nvm_write(&G_gpg_vstate.kslot->sig_count, &reset_cnt, sizeof(unsigned int)); - } - } +int gpg_apdu_get_next_data(unsigned int ref) { + int sw; + if ((ref != 0x7F21) || (G_gpg_vstate.DO_current != 0x7F21)) { + return SW_CONDITIONS_NOT_SATISFIED; } - // --- UNSUPPORTED KEY --- - else { - THROW(SW_REFERENCED_DATA_NOT_FOUND); - return 0; - } - break; - } // endof of 3fff - - /* ----------------- User -----------------*/ - /* Name */ - case 0x5B: - if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->name.value)) { - THROW(SW_WRONG_LENGTH); - return 0; - } - gpg_nvm_write((void *)N_gpg_pstate->name.value, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length); - gpg_nvm_write((void *)&N_gpg_pstate->name.length, &G_gpg_vstate.io_length, sizeof(unsigned int)); - break; - /* Login data */ - case 0x5E: - if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->login.value)) { - THROW(SW_WRONG_LENGTH); - return 0; + sw = gpg_apdu_get_data(ref); + if (sw == SW_OK) { + G_gpg_vstate.DO_reccord++; } - gpg_nvm_write((void *)N_gpg_pstate->login.value, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length); - gpg_nvm_write((void *)&N_gpg_pstate->login.length, &G_gpg_vstate.io_length, sizeof(unsigned int)); - break; - /* Language preferences */ - case 0x5F2D: - if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->lang.value)) { - THROW(SW_WRONG_LENGTH); - return 0; - } - gpg_nvm_write((void *)N_gpg_pstate->lang.value, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length); - gpg_nvm_write((void *)&N_gpg_pstate->lang.length, &G_gpg_vstate.io_length, sizeof(unsigned int)); - break; - /* Sex */ - case 0x5F35: - if (G_gpg_vstate.io_length != sizeof(N_gpg_pstate->sex)) { - THROW(SW_WRONG_LENGTH); - return 0; - } - gpg_nvm_write((void *)N_gpg_pstate->sex, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length); - break; - /* Uniform resource locator */ - case 0x5F50: - if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->url.value)) { - THROW(SW_WRONG_LENGTH); - return 0; - } - gpg_nvm_write((void *)N_gpg_pstate->url.value, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length); - gpg_nvm_write((void *)&N_gpg_pstate->url.length, &G_gpg_vstate.io_length, sizeof(unsigned int)); - break; - - /* ----------------- 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); - return 0; - } - 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); - gpg_nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int)); - break; - - /* ----------------- Algorithm attributes ----------------- */ - case 0xC1: - ptr_l = &G_gpg_vstate.kslot->sig.attributes.length; - ptr_v = G_gpg_vstate.kslot->sig.attributes.value; - goto WRITE_ATTRIBUTES; - case 0xC2: - ptr_l = &G_gpg_vstate.kslot->dec.attributes.length; - ptr_v = G_gpg_vstate.kslot->dec.attributes.value; - goto WRITE_ATTRIBUTES; - case 0xC3: - ptr_l = &G_gpg_vstate.kslot->aut.attributes.length; - ptr_v = G_gpg_vstate.kslot->aut.attributes.value; - goto WRITE_ATTRIBUTES; - WRITE_ATTRIBUTES: - if (G_gpg_vstate.io_length > 12) { - THROW(SW_WRONG_LENGTH); - return 0; - } - gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length); - gpg_nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int)); - break; - - /* ----------------- PWS status ----------------- */ - case 0xC4: - gpg_io_fetch_nv((unsigned char *)N_gpg_pstate->PW_status, 1); - break; - - /* ----------------- Fingerprints ----------------- */ - case 0xC7: - ptr_v = G_gpg_vstate.kslot->sig.fingerprints; - goto WRITE_FINGERPRINTS; - case 0xC8: - ptr_v = G_gpg_vstate.kslot->dec.fingerprints; - goto WRITE_FINGERPRINTS; - case 0xC9: - ptr_v = G_gpg_vstate.kslot->aut.fingerprints; - goto WRITE_FINGERPRINTS; - case 0xCA: - ptr_v = G_gpg_vstate.kslot->sig.CA_fingerprints; - goto WRITE_FINGERPRINTS; - case 0xCB: - ptr_v = G_gpg_vstate.kslot->dec.CA_fingerprints; - goto WRITE_FINGERPRINTS; - case 0xCC: - ptr_v = G_gpg_vstate.kslot->aut.CA_fingerprints; - goto WRITE_FINGERPRINTS; - WRITE_FINGERPRINTS: - if (G_gpg_vstate.io_length != 20) { - THROW(SW_WRONG_LENGTH); - return 0; - } - gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, 20); - break; - - /* ----------------- Generation date/time ----------------- */ - case 0xCE: - ptr_v = G_gpg_vstate.kslot->sig.date; - goto WRITE_DATE; - case 0xCF: - ptr_v = G_gpg_vstate.kslot->dec.date; - goto WRITE_DATE; - case 0xD0: - ptr_v = G_gpg_vstate.kslot->aut.date; - goto WRITE_DATE; - WRITE_DATE: - if (G_gpg_vstate.io_length != 4) { - THROW(SW_WRONG_LENGTH); - return 0; - } - gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, 4); - break; - - /* ----------------- AES key ----------------- */ - { - void * pkey; - cx_aes_key_t aes_key; - case 0xD1: - pkey = (void *)&N_gpg_pstate->SM_enc; - goto init_aes_key; - case 0xD2: - pkey = (void *)&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((void *)&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((void *)&N_gpg_pstate->SM_mac, &aes_key, sizeof(cx_aes_key_t)); - break; - } - - /* ----------------- RC ----------------- */ - case 0xD3: { - gpg_pin_t *pin; + return sw; +} - pin = gpg_pin_get_pin(PIN_ID_RC); - if (G_gpg_vstate.io_length == 0) { - gpg_nvm_write(pin, NULL, sizeof(gpg_pin_t)); +int gpg_apdu_put_data(unsigned int ref) { + unsigned int t, l, sw; + unsigned int *ptr_l; + unsigned char *ptr_v; - } 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); - } + G_gpg_vstate.DO_current = ref; sw = SW_OK; - break; - } - - /* ----------------- UIF ----------------- */ - case 0xD6: - ptr_v = G_gpg_vstate.kslot->sig.UIF; - goto WRITE_UIF; - case 0xD7: - ptr_v = G_gpg_vstate.kslot->dec.UIF; - goto WRITE_UIF; - case 0xD8: - ptr_v = G_gpg_vstate.kslot->aut.UIF; - goto WRITE_UIF; - WRITE_UIF: - if (G_gpg_vstate.io_length != 2) { - THROW(SW_WRONG_LENGTH); - return 0; - } - gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, 2); - break; - /* ----------------- WAT ----------------- */ - default: - sw = SW_REFERENCED_DATA_NOT_FOUND; - break; - } + switch (ref) { + /* ----------------- Optional DO for private use ----------------- */ + case 0x0101: + ptr_l = (unsigned int *) &N_gpg_pstate->private_DO1.length; + ptr_v = (unsigned char *) N_gpg_pstate->private_DO1.value; + goto WRITE_PRIVATE_DO; + case 0x0102: + ptr_l = (unsigned int *) &N_gpg_pstate->private_DO2.length; + ptr_v = (unsigned char *) N_gpg_pstate->private_DO2.value; + goto WRITE_PRIVATE_DO; + case 0x0103: + ptr_l = (unsigned int *) &N_gpg_pstate->private_DO3.length; + ptr_v = (unsigned char *) N_gpg_pstate->private_DO3.value; + goto WRITE_PRIVATE_DO; + case 0x0104: + ptr_l = (unsigned int *) &N_gpg_pstate->private_DO4.length; + ptr_v = (unsigned char *) N_gpg_pstate->private_DO4.value; + goto WRITE_PRIVATE_DO; + WRITE_PRIVATE_DO: + if (G_gpg_vstate.io_length > GPG_EXT_PRIVATE_DO_LENGTH) { + 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_l, &G_gpg_vstate.io_length, sizeof(unsigned int)); + sw = SW_OK; + break; + /* ----------------- Config key slot ----------------- */ + case 0x01F1: + if (G_gpg_vstate.io_length != 3) { + 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); + return 0; + } + gpg_nvm_write((void *) 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); + return 0; + } + G_gpg_vstate.slot = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset]; + break; + + /* ----------------- Config RSA exponent ----------------- */ + case 0x01F8: { + unsigned int e; + if (G_gpg_vstate.io_length != 4) { + THROW(SW_WRONG_LENGTH); + return 0; + } + e = gpg_io_fetch_u32(); + nvm_write((void *) &N_gpg_pstate->default_RSA_exponent, &e, sizeof(unsigned int)); + break; + } - gpg_io_discard(1); - return sw; + /* ----------------- Serial -----------------*/ + case 0x4f: + if (G_gpg_vstate.io_length != 4) { + THROW(SW_WRONG_LENGTH); + } + nvm_write(G_gpg_vstate.kslot->serial, + &G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset], + 4); + break; + + /* ----------------- Extended Header list -----------------*/ + case 0x3FFF: { + unsigned int len_e, len_p, len_q; + unsigned int endof, ksz, reset_cnt; + gpg_key_t *keygpg; + // 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); + reset_cnt = 0; + switch (t) { + case 0xB6: + keygpg = &G_gpg_vstate.kslot->sig; + reset_cnt = 0x11111111; + break; + case 0xA4: + keygpg = &G_gpg_vstate.kslot->aut; + break; + case 0xB8: + keygpg = &G_gpg_vstate.kslot->dec; + break; + default: + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return 0; + } + // 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_offset < endof) { + gpg_io_fetch_tl(&t, &l); + switch (t) { + case 0x91: + len_e = l; + break; + case 0x92: + len_p = l; + break; + case 0x93: + len_q = l; + break; + break; + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x99: + break; + default: + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return 0; + } + } + // fecth 5f78 + gpg_io_fetch_tl(&t, &l); + if (t != 0x5f48) { + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return 0; + } + + // --- RSA KEY --- + if (keygpg->attributes.value[0] == 0x01) { + 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: + pkey_size = sizeof(cx_rsa_1024_private_key_t); + pq = G_gpg_vstate.work.rsa.public1024.n; + break; + case 2048 / 8: + pkey_size = sizeof(cx_rsa_2048_private_key_t); + pq = G_gpg_vstate.work.rsa.public2048.n; + break; + case 3072 / 8: + pkey_size = sizeof(cx_rsa_3072_private_key_t); + pq = G_gpg_vstate.work.rsa.public3072.n; + break; + case 4096 / 8: + pkey_size = sizeof(cx_rsa_4096_private_key_t); + pq = G_gpg_vstate.work.rsa.public4096.n; + break; + } + ksz = ksz >> 1; + + // fetch e + e = 0; + switch (len_e) { + case 4: + e = gpg_io_fetch_u32(); + break; + case 3: + e = gpg_io_fetch_u24(); + break; + case 2: + e = gpg_io_fetch_u16(); + break; + case 1: + e = gpg_io_fetch_u8(); + break; + default: + THROW(SW_WRONG_DATA); + return 0; + } + + // 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; + memmove(pq + ksz - len_p, p, len_p); + memset(pq, 0, ksz - len_p); + memmove(pq + 2 * ksz - len_q, q, len_q); + 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); + + // 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)); + } + } + // --- ECC KEY --- + 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); + if (curve == 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; + 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)); + if (reset_cnt) { + reset_cnt = 0; + nvm_write(&G_gpg_vstate.kslot->sig_count, &reset_cnt, sizeof(unsigned int)); + } + } + + } + // --- UNSUPPORTED KEY --- + else { + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return 0; + } + break; + } // endof of 3fff + + /* ----------------- User -----------------*/ + /* Name */ + case 0x5B: + if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->name.value)) { + THROW(SW_WRONG_LENGTH); + return 0; + } + gpg_nvm_write((void *) N_gpg_pstate->name.value, + G_gpg_vstate.work.io_buffer, + G_gpg_vstate.io_length); + gpg_nvm_write((void *) &N_gpg_pstate->name.length, + &G_gpg_vstate.io_length, + sizeof(unsigned int)); + break; + /* Login data */ + case 0x5E: + if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->login.value)) { + THROW(SW_WRONG_LENGTH); + return 0; + } + gpg_nvm_write((void *) N_gpg_pstate->login.value, + G_gpg_vstate.work.io_buffer, + G_gpg_vstate.io_length); + gpg_nvm_write((void *) &N_gpg_pstate->login.length, + &G_gpg_vstate.io_length, + sizeof(unsigned int)); + break; + /* Language preferences */ + case 0x5F2D: + if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->lang.value)) { + THROW(SW_WRONG_LENGTH); + return 0; + } + gpg_nvm_write((void *) N_gpg_pstate->lang.value, + G_gpg_vstate.work.io_buffer, + G_gpg_vstate.io_length); + gpg_nvm_write((void *) &N_gpg_pstate->lang.length, + &G_gpg_vstate.io_length, + sizeof(unsigned int)); + break; + /* Sex */ + case 0x5F35: + if (G_gpg_vstate.io_length != sizeof(N_gpg_pstate->sex)) { + THROW(SW_WRONG_LENGTH); + return 0; + } + gpg_nvm_write((void *) N_gpg_pstate->sex, + G_gpg_vstate.work.io_buffer, + G_gpg_vstate.io_length); + break; + /* Uniform resource locator */ + case 0x5F50: + if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->url.value)) { + THROW(SW_WRONG_LENGTH); + return 0; + } + gpg_nvm_write((void *) N_gpg_pstate->url.value, + G_gpg_vstate.work.io_buffer, + G_gpg_vstate.io_length); + gpg_nvm_write((void *) &N_gpg_pstate->url.length, + &G_gpg_vstate.io_length, + sizeof(unsigned int)); + break; + + /* ----------------- 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); + return 0; + } + 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); + gpg_nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int)); + break; + + /* ----------------- Algorithm attributes ----------------- */ + case 0xC1: + ptr_l = &G_gpg_vstate.kslot->sig.attributes.length; + ptr_v = G_gpg_vstate.kslot->sig.attributes.value; + goto WRITE_ATTRIBUTES; + case 0xC2: + ptr_l = &G_gpg_vstate.kslot->dec.attributes.length; + ptr_v = G_gpg_vstate.kslot->dec.attributes.value; + goto WRITE_ATTRIBUTES; + case 0xC3: + ptr_l = &G_gpg_vstate.kslot->aut.attributes.length; + ptr_v = G_gpg_vstate.kslot->aut.attributes.value; + goto WRITE_ATTRIBUTES; + WRITE_ATTRIBUTES: + if (G_gpg_vstate.io_length > 12) { + THROW(SW_WRONG_LENGTH); + return 0; + } + gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length); + gpg_nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int)); + break; + + /* ----------------- PWS status ----------------- */ + case 0xC4: + gpg_io_fetch_nv((unsigned char *) N_gpg_pstate->PW_status, 1); + break; + + /* ----------------- Fingerprints ----------------- */ + case 0xC7: + ptr_v = G_gpg_vstate.kslot->sig.fingerprints; + goto WRITE_FINGERPRINTS; + case 0xC8: + ptr_v = G_gpg_vstate.kslot->dec.fingerprints; + goto WRITE_FINGERPRINTS; + case 0xC9: + ptr_v = G_gpg_vstate.kslot->aut.fingerprints; + goto WRITE_FINGERPRINTS; + case 0xCA: + ptr_v = G_gpg_vstate.kslot->sig.CA_fingerprints; + goto WRITE_FINGERPRINTS; + case 0xCB: + ptr_v = G_gpg_vstate.kslot->dec.CA_fingerprints; + goto WRITE_FINGERPRINTS; + case 0xCC: + ptr_v = G_gpg_vstate.kslot->aut.CA_fingerprints; + goto WRITE_FINGERPRINTS; + WRITE_FINGERPRINTS: + if (G_gpg_vstate.io_length != 20) { + THROW(SW_WRONG_LENGTH); + return 0; + } + gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, 20); + break; + + /* ----------------- Generation date/time ----------------- */ + case 0xCE: + ptr_v = G_gpg_vstate.kslot->sig.date; + goto WRITE_DATE; + case 0xCF: + ptr_v = G_gpg_vstate.kslot->dec.date; + goto WRITE_DATE; + case 0xD0: + ptr_v = G_gpg_vstate.kslot->aut.date; + goto WRITE_DATE; + WRITE_DATE: + if (G_gpg_vstate.io_length != 4) { + THROW(SW_WRONG_LENGTH); + return 0; + } + gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, 4); + break; + + /* ----------------- AES key ----------------- */ + { + void *pkey; + cx_aes_key_t aes_key; + case 0xD1: + pkey = (void *) &N_gpg_pstate->SM_enc; + goto init_aes_key; + case 0xD2: + pkey = (void *) &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((void *) &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((void *) &N_gpg_pstate->SM_mac, &aes_key, sizeof(cx_aes_key_t)); + break; + } + + /* ----------------- RC ----------------- */ + case 0xD3: { + gpg_pin_t *pin; + + pin = gpg_pin_get_pin(PIN_ID_RC); + 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)) { + 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); + } + sw = SW_OK; + break; + } + + /* ----------------- UIF ----------------- */ + case 0xD6: + ptr_v = G_gpg_vstate.kslot->sig.UIF; + goto WRITE_UIF; + case 0xD7: + ptr_v = G_gpg_vstate.kslot->dec.UIF; + goto WRITE_UIF; + case 0xD8: + ptr_v = G_gpg_vstate.kslot->aut.UIF; + goto WRITE_UIF; + WRITE_UIF: + if (G_gpg_vstate.io_length != 2) { + THROW(SW_WRONG_LENGTH); + return 0; + } + gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, 2); + break; + + /* ----------------- WAT ----------------- */ + default: + sw = SW_REFERENCED_DATA_NOT_FOUND; + break; + } + + gpg_io_discard(1); + return sw; } static void gpg_init_keyenc(cx_aes_key_t *keyenc) { - unsigned char seed[32]; + 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); - cx_aes_init_key(seed, 16, keyenc); + gpg_pso_derive_slot_seed(G_gpg_vstate.slot, seed); + 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 int gpg_apdu_get_key_data(unsigned int ref) { - cx_aes_key_t keyenc; - gpg_key_t * keygpg; - unsigned int len = 0; - gpg_init_keyenc(&keyenc); - - switch (ref) { - case 0x00B6: - keygpg = &G_gpg_vstate.kslot->sig; - break; - case 0x00B8: - keygpg = &G_gpg_vstate.kslot->dec; - break; - case 0x00A4: - keygpg = &G_gpg_vstate.kslot->aut; - break; - default: - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } - - gpg_io_discard(1); - // 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; - gpg_io_insert_u32(4); - gpg_io_insert(keygpg->pub_key.rsa, 4); - - // 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); - 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 19: - case 22: - // 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)); - - // 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); - gpg_io_inserted(len); - gpg_io_set_offset(IO_OFFSET_MARK); - gpg_io_insert_u32(len); - gpg_io_set_offset(IO_OFFSET_END); - break; - - default: - THROW(SW_REFERENCED_DATA_NOT_FOUND); - return SW_REFERENCED_DATA_NOT_FOUND; - } - return SW_OK; + cx_aes_key_t keyenc; + gpg_key_t *keygpg; + unsigned int len = 0; + gpg_init_keyenc(&keyenc); + + switch (ref) { + case 0x00B6: + keygpg = &G_gpg_vstate.kslot->sig; + break; + case 0x00B8: + keygpg = &G_gpg_vstate.kslot->dec; + break; + case 0x00A4: + keygpg = &G_gpg_vstate.kslot->aut; + break; + default: + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } + + gpg_io_discard(1); + // 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; + gpg_io_insert_u32(4); + gpg_io_insert(keygpg->pub_key.rsa, 4); + + // 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); + 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 19: + case 22: + // 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)); + + // 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); + gpg_io_inserted(len); + gpg_io_set_offset(IO_OFFSET_MARK); + gpg_io_insert_u32(len); + gpg_io_set_offset(IO_OFFSET_END); + break; + + default: + 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 - int gpg_apdu_put_key_data(unsigned int ref) { - cx_aes_key_t keyenc; - gpg_key_t * keygpg; - unsigned int len; - unsigned int offset; - gpg_init_keyenc(&keyenc); - - switch (ref) { - case 0xB6: - keygpg = &G_gpg_vstate.kslot->sig; - break; - case 0xB8: - keygpg = &G_gpg_vstate.kslot->dec; - break; - case 0xA4: - keygpg = &G_gpg_vstate.kslot->aut; - break; - default: - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } - - /* 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]) { - // RSA - case 0x01: - // insert pubkey; - len = gpg_io_fetch_u32(); - if (len != 4) { - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } - gpg_io_fetch_nv(keygpg->pub_key.rsa, len); - - // insert privkey - len = gpg_io_fetch_u32(); - 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); - if (len != sizeof(cx_rsa_4096_private_key_t)) { - THROW(SW_WRONG_DATA); - } - gpg_nvm_write((unsigned char *)&keygpg->priv_key.rsa4096, G_gpg_vstate.work.io_buffer, len); - break; - - // 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); - - // insert privkey - len = gpg_io_fetch_u32(); - 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); - if (len != sizeof(cx_ecfp_640_private_key_t)) { - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } - 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; - } - gpg_io_discard(1); - return SW_OK; + cx_aes_key_t keyenc; + gpg_key_t *keygpg; + unsigned int len; + unsigned int offset; + gpg_init_keyenc(&keyenc); + + switch (ref) { + case 0xB6: + keygpg = &G_gpg_vstate.kslot->sig; + break; + case 0xB8: + keygpg = &G_gpg_vstate.kslot->dec; + break; + case 0xA4: + keygpg = &G_gpg_vstate.kslot->aut; + break; + default: + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } + + /* 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]) { + // RSA + case 0x01: + // insert pubkey; + len = gpg_io_fetch_u32(); + if (len != 4) { + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } + gpg_io_fetch_nv(keygpg->pub_key.rsa, len); + + // insert privkey + len = gpg_io_fetch_u32(); + 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); + if (len != sizeof(cx_rsa_4096_private_key_t)) { + THROW(SW_WRONG_DATA); + } + gpg_nvm_write((unsigned char *) &keygpg->priv_key.rsa4096, + G_gpg_vstate.work.io_buffer, + len); + break; + + // 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); + + // insert privkey + len = gpg_io_fetch_u32(); + 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); + if (len != sizeof(cx_ecfp_640_private_key_t)) { + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } + 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; + } + gpg_io_discard(1); + return SW_OK; } diff --git a/src/gpg_dispatch.c b/src/gpg_dispatch.c index 5e27263..d6825b7 100644 --- a/src/gpg_dispatch.c +++ b/src/gpg_dispatch.c @@ -20,407 +20,410 @@ #include "gpg_vars.h" void gpg_check_access_ins() { - unsigned int ref; - - ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; - - switch (G_gpg_vstate.io_ins) { - case INS_EXIT: - if (gpg_pin_is_verified(PIN_ID_PW2)) { - return; - } - break; - #ifdef GPG_LOG - #warning GPG_LOG activated - case INS_GET_LOG: - return; - #endif - - case INS_SELECT: - return; - case INS_GET_DATA: - case INS_GET_NEXT_DATA: - return; - - case INS_VERIFY: - return; - - case INS_CHANGE_REFERENCE_DATA: - return; - - case INS_RESET_RETRY_COUNTER: - if (gpg_pin_is_verified(PIN_ID_PW3) || gpg_pin_is_verified(PIN_ID_RC)) { - return; - } - break; - - case INS_PUT_DATA: - case INS_PUT_DATA_ODD: - return; - - case INS_GEN_ASYM_KEYPAIR: - if (G_gpg_vstate.io_p1 == 0x81) { - return; - } - if (gpg_pin_is_verified(PIN_ID_PW3)) { - return; - } - break; - - case INS_MSE: - return; - - case INS_PSO: - if ((ref == 0x9e9a) && gpg_pin_is_verified(PIN_ID_PW1)) { - // 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 - return; - } - break; - - case INS_INTERNAL_AUTHENTICATE: - if (gpg_pin_is_verified(PIN_ID_PW2)) { - return; - } - break; - - case INS_GET_CHALLENGE: - return; + unsigned int ref; + + ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; + + switch (G_gpg_vstate.io_ins) { + case INS_EXIT: + if (gpg_pin_is_verified(PIN_ID_PW2)) { + return; + } + break; +#ifdef GPG_LOG +#warning GPG_LOG activated + case INS_GET_LOG: + return; +#endif - case INS_TERMINATE_DF: - if (gpg_pin_is_verified(PIN_ID_PW3)) { - return; + case INS_SELECT: + return; + case INS_GET_DATA: + case INS_GET_NEXT_DATA: + return; + + case INS_VERIFY: + return; + + case INS_CHANGE_REFERENCE_DATA: + return; + + case INS_RESET_RETRY_COUNTER: + if (gpg_pin_is_verified(PIN_ID_PW3) || gpg_pin_is_verified(PIN_ID_RC)) { + return; + } + break; + + case INS_PUT_DATA: + case INS_PUT_DATA_ODD: + return; + + case INS_GEN_ASYM_KEYPAIR: + if (G_gpg_vstate.io_p1 == 0x81) { + return; + } + if (gpg_pin_is_verified(PIN_ID_PW3)) { + return; + } + break; + + case INS_MSE: + return; + + case INS_PSO: + if ((ref == 0x9e9a) && gpg_pin_is_verified(PIN_ID_PW1)) { + // 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 + return; + } + break; + + case INS_INTERNAL_AUTHENTICATE: + if (gpg_pin_is_verified(PIN_ID_PW2)) { + return; + } + break; + + case INS_GET_CHALLENGE: + return; + + case INS_TERMINATE_DF: + if (gpg_pin_is_verified(PIN_ID_PW3)) { + return; + } + break; + + case INS_ACTIVATE_FILE: + return; + + default: + THROW(SW_INS_NOT_SUPPORTED); + break; } - break; - - case INS_ACTIVATE_FILE: - return; - - default: - THROW(SW_INS_NOT_SUPPORTED); - break; - } - THROW(SW_CONDITIONS_NOT_SATISFIED); + THROW(SW_CONDITIONS_NOT_SATISFIED); } void gpg_check_access_read_DO() { - unsigned int ref; - - ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; - - switch (ref) { - // ALWAYS - case 0x0101: - case 0x0102: - case 0x01F0: - case 0x01F1: - case 0x01F2: - case 0x01F8: - case 0x006E: - case 0x0065: - case 0x0073: - case 0x007A: - case 0x004F: - case 0x005E: - case 0x005B: - case 0x5F2D: - case 0x5F35: - case 0x5F50: - case 0x5F52: - case 0x7F21: - case 0x0093: - case 0x00C0: - case 0x00C1: - case 0x00C2: - case 0x00C3: - case 0x00C4: - case 0x00C5: - case 0x00C7: - case 0x00C8: - case 0x00C9: - case 0x00C6: - case 0x00CA: - case 0x00CD: - case 0x00CC: - case 0x00CE: - case 0x00CF: - case 0x00D0: - case 0x7F74: - case 0x7F66: - case 0x00D6: - case 0x00D7: - case 0x00D8: - return; - - // PW2 - case 0x0103: - if (gpg_pin_is_verified(PIN_ID_PW2)) { - return; - } - break; - - // PW3 - case 0x00B6: - case 0x00A4: - case 0x00B8: - case 0x0104: - if (gpg_pin_is_verified(PIN_ID_PW3)) { - return; + unsigned int ref; + + ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; + + switch (ref) { + // ALWAYS + case 0x0101: + case 0x0102: + case 0x01F0: + case 0x01F1: + case 0x01F2: + case 0x01F8: + case 0x006E: + case 0x0065: + case 0x0073: + case 0x007A: + case 0x004F: + case 0x005E: + case 0x005B: + case 0x5F2D: + case 0x5F35: + case 0x5F50: + case 0x5F52: + case 0x7F21: + case 0x0093: + case 0x00C0: + case 0x00C1: + case 0x00C2: + case 0x00C3: + case 0x00C4: + case 0x00C5: + case 0x00C7: + case 0x00C8: + case 0x00C9: + case 0x00C6: + case 0x00CA: + case 0x00CD: + case 0x00CC: + case 0x00CE: + case 0x00CF: + case 0x00D0: + case 0x7F74: + case 0x7F66: + case 0x00D6: + case 0x00D7: + case 0x00D8: + return; + + // PW2 + case 0x0103: + if (gpg_pin_is_verified(PIN_ID_PW2)) { + return; + } + break; + + // PW3 + case 0x00B6: + case 0x00A4: + case 0x00B8: + case 0x0104: + if (gpg_pin_is_verified(PIN_ID_PW3)) { + return; + } + break; } - break; - } - THROW(SW_CONDITIONS_NOT_SATISFIED); + THROW(SW_CONDITIONS_NOT_SATISFIED); } char debugbuff[5]; void gpg_check_access_write_DO() { - unsigned int ref; - - ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; - - switch (ref) { - // PW2 - case 0x0101: - case 0x0103: - case 0x01F2: - if (gpg_pin_is_verified(PIN_ID_PW2)) { - return; + unsigned int ref; + + ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; + + switch (ref) { + // PW2 + case 0x0101: + case 0x0103: + case 0x01F2: + if (gpg_pin_is_verified(PIN_ID_PW2)) { + return; + } + break; + + // PW3 + case 0x3FFF: // only used for putkey under PW3 control + case 0x4f: + case 0x0102: + case 0x0104: + case 0x01F1: + case 0x01F8: + case 0x005E: + case 0x005B: + case 0x5F2D: + case 0x5F35: + case 0x5F50: + case 0x5F48: + case 0x7F21: + case 0x00B6: + case 0x00A4: + case 0x00B8: + case 0x00C1: + case 0x00C2: + case 0x00C3: + case 0x00C4: + case 0x00C5: + case 0x00C7: + case 0x00C8: + case 0x00C9: + case 0x00C6: + case 0x00CA: + case 0x00CB: + case 0x00CC: + case 0x00CD: + case 0x00CE: + case 0x00CF: + case 0x00D0: + case 0x00D1: + case 0x00D2: + case 0x00D3: + case 0x00D5: + case 0x00F4: + case 0x00D6: + case 0x00D7: + case 0x00D8: + if (gpg_pin_is_verified(PIN_ID_PW3)) { + return; + } + break; } - break; - - // PW3 - case 0x3FFF: // only used for putkey under PW3 control - case 0x4f: - case 0x0102: - case 0x0104: - case 0x01F1: - case 0x01F8: - case 0x005E: - case 0x005B: - case 0x5F2D: - case 0x5F35: - case 0x5F50: - case 0x5F48: - case 0x7F21: - case 0x00B6: - case 0x00A4: - case 0x00B8: - case 0x00C1: - case 0x00C2: - case 0x00C3: - case 0x00C4: - case 0x00C5: - case 0x00C7: - case 0x00C8: - case 0x00C9: - case 0x00C6: - case 0x00CA: - case 0x00CB: - case 0x00CC: - case 0x00CD: - case 0x00CE: - case 0x00CF: - case 0x00D0: - case 0x00D1: - case 0x00D2: - case 0x00D3: - case 0x00D5: - case 0x00F4: - case 0x00D6: - case 0x00D7: - case 0x00D8: - if (gpg_pin_is_verified(PIN_ID_PW3)) { - return; - } - break; - } - THROW(SW_CONDITIONS_NOT_SATISFIED); + THROW(SW_CONDITIONS_NOT_SATISFIED); } /* assume command is fully received */ int gpg_dispatch() { - unsigned int tag, t, l; - int sw; - - if ((G_gpg_vstate.io_cla != 0x00) && (G_gpg_vstate.io_cla != 0x10) && (G_gpg_vstate.io_cla != 0xEF)) { - THROW(SW_CLA_NOT_SUPPORTED); - return SW_CLA_NOT_SUPPORTED; - } - - tag = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; - - switch (G_gpg_vstate.io_ins) { - #ifdef GPG_LOG - case INS_GET_LOG: - gpg_io_discard(1); - gpg_io_insert(G_gpg_vstate.log_buffer, 32); - return SW_OK; - #endif - - /* --- SELECT --- */ - case INS_SELECT: - sw = gpg_apdu_select(); - return sw; - break; + unsigned int tag, t, l; + int sw; - /* --- ACTIVATE/TERMINATE FILE --- */ - case INS_ACTIVATE_FILE: - gpg_io_discard(0); - if (N_gpg_pstate->histo[7] == STATE_TERMINATE) { - gpg_install(STATE_ACTIVATE); - } - 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); - break; + 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; } - THROW(SW_CONDITIONS_NOT_SATISFIED); - break; - } - /* Other commands allowed if not terminated */ - if (N_gpg_pstate->histo[7] != 0x07) { - THROW(SW_STATE_TERMINATED); - } + tag = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; - /* Process */ - gpg_check_access_ins(); - - switch (G_gpg_vstate.io_ins) { -#ifdef GPG_DEBUG_APDU - case 0x42: - sw = debug_apdu(); - break; + switch (G_gpg_vstate.io_ins) { +#ifdef GPG_LOG + case INS_GET_LOG: + gpg_io_discard(1); + gpg_io_insert(G_gpg_vstate.log_buffer, 32); + return SW_OK; #endif - case INS_EXIT: - os_sched_exit(0); - sw = SW_OK; - break; - - /* --- CHALLENGE --- */ - case INS_GET_CHALLENGE: - sw = gpg_apdu_get_challenge(); - break; - - /* --- DATA --- */ - - case INS_SELECT_DATA: - if ((G_gpg_vstate.io_p1 > 2) || (G_gpg_vstate.io_p2 != 0x04)) { - THROW(SW_WRONG_P1P2); - } - gpg_io_fetch_tl(&t, &l); - if (t != 0x60) { - // TODO add l check - THROW(SW_DATA_INVALID); - } - gpg_io_fetch_tl(&t, &l); - if (t != 0x5C) { - // TODO add l check - THROW(SW_WRONG_DATA); - } - if (l == 1) { - tag = gpg_io_fetch_u8(); - } else if (l == 2) { - tag = gpg_io_fetch_u16(); - } else { - THROW(SW_WRONG_DATA); - } - sw = gpg_apdu_select_data(tag, G_gpg_vstate.io_p1); - break; - - case INS_GET_DATA: - gpg_check_access_read_DO(); - switch (tag) { - case 0x00B6: - case 0x00A4: - case 0x00B8: - sw = gpg_apdu_get_key_data(tag); - break; - default: - sw = gpg_apdu_get_data(tag); - break; + /* --- SELECT --- */ + case INS_SELECT: + sw = gpg_apdu_select(); + return sw; + break; + + /* --- ACTIVATE/TERMINATE FILE --- */ + case INS_ACTIVATE_FILE: + gpg_io_discard(0); + if (N_gpg_pstate->histo[7] == STATE_TERMINATE) { + gpg_install(STATE_ACTIVATE); + } + 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); + break; + } + THROW(SW_CONDITIONS_NOT_SATISFIED); + break; } - break; - - case INS_GET_NEXT_DATA: - gpg_check_access_read_DO(); - sw = gpg_apdu_get_next_data(tag); - break; - - case INS_PUT_DATA_ODD: - case INS_PUT_DATA: - gpg_check_access_write_DO(); - switch (tag) { - case 0x00B6: - case 0x00A4: - case 0x00B8: - sw = gpg_apdu_put_key_data(tag); - break; - default: - sw = gpg_apdu_put_data(tag); - break; - } - break; - - /* --- PIN -- */ - case INS_VERIFY: - 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; + /* Other commands allowed if not terminated */ + if (N_gpg_pstate->histo[7] != STATE_ACTIVATE) { + THROW(SW_STATE_TERMINATED); } - 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 --- */ - case INS_GEN_ASYM_KEYPAIR: - sw = gpg_apdu_gen(); - break; - /* --- MSE --- */ - case INS_MSE: - sw = gpg_apdu_mse(tag); - break; + /* Process */ + gpg_check_access_ins(); - /* --- PSO --- */ - case INS_PSO: - sw = gpg_apdu_pso(); - break; - - case INS_INTERNAL_AUTHENTICATE: - sw = gpg_apdu_internal_authenticate(); - break; + switch (G_gpg_vstate.io_ins) { +#ifdef GPG_DEBUG_APDU + case 0x42: + sw = debug_apdu(); + break; +#endif - default: - THROW(SW_INS_NOT_SUPPORTED); - break; - } + case INS_EXIT: + os_sched_exit(0); + sw = SW_OK; + break; + + /* --- CHALLENGE --- */ + case INS_GET_CHALLENGE: + sw = gpg_apdu_get_challenge(); + break; + + /* --- DATA --- */ + + case INS_SELECT_DATA: + if ((G_gpg_vstate.io_p1 > 2) || (G_gpg_vstate.io_p2 != 0x04)) { + THROW(SW_WRONG_P1P2); + } + gpg_io_fetch_tl(&t, &l); + if (t != 0x60) { + // TODO add l check + THROW(SW_DATA_INVALID); + } + gpg_io_fetch_tl(&t, &l); + if (t != 0x5C) { + // TODO add l check + THROW(SW_WRONG_DATA); + } + if (l == 1) { + tag = gpg_io_fetch_u8(); + } else if (l == 2) { + tag = gpg_io_fetch_u16(); + } else { + THROW(SW_WRONG_DATA); + } + sw = gpg_apdu_select_data(tag, G_gpg_vstate.io_p1); + break; + + case INS_GET_DATA: + gpg_check_access_read_DO(); + switch (tag) { + case 0x00B6: + case 0x00A4: + case 0x00B8: + sw = gpg_apdu_get_key_data(tag); + break; + default: + sw = gpg_apdu_get_data(tag); + break; + } + break; + + case INS_GET_NEXT_DATA: + gpg_check_access_read_DO(); + sw = gpg_apdu_get_next_data(tag); + break; + + case INS_PUT_DATA_ODD: + case INS_PUT_DATA: + gpg_check_access_write_DO(); + switch (tag) { + case 0x00B6: + case 0x00A4: + case 0x00B8: + sw = gpg_apdu_put_key_data(tag); + break; + default: + sw = gpg_apdu_put_data(tag); + break; + } + break; + + /* --- PIN -- */ + case INS_VERIFY: + 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); + + 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 --- */ + case INS_GEN_ASYM_KEYPAIR: + sw = gpg_apdu_gen(); + break; + + /* --- MSE --- */ + case INS_MSE: + sw = gpg_apdu_mse(tag); + break; + + /* --- PSO --- */ + case INS_PSO: + sw = gpg_apdu_pso(); + break; + + case INS_INTERNAL_AUTHENTICATE: + sw = gpg_apdu_internal_authenticate(); + break; + + default: + THROW(SW_INS_NOT_SUPPORTED); + break; + } - return sw; + return sw; } diff --git a/src/gpg_gen.c b/src/gpg_gen.c index 8f99db4..1273d23 100644 --- a/src/gpg_gen.c +++ b/src/gpg_gen.c @@ -23,13 +23,13 @@ * @out seed 32 bytes master seed for given slot */ void gpg_pso_derive_slot_seed(int slot, unsigned char *seed) { - unsigned int path[2]; - unsigned char chain[32]; + unsigned int path[2]; + unsigned char chain[32]; - memset(chain, 0, 32); - path[0] = 0x80475047; - path[1] = slot + 1; - os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 2, seed, chain); + memset(chain, 0, 32); + path[0] = 0x80475047; + path[1] = slot + 1; + os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 2, seed, chain); } /* @in Sn master seed slot number @@ -40,245 +40,265 @@ 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 int idx, unsigned char *Ski, - unsigned int Ski_len) { - unsigned char h[32]; - h[0] = idx >> 8; - h[1] = idx; + unsigned int Ski_len) { + unsigned char h[32]; + 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_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); #ifdef GPG_SHAKE256 - cx_shake256_init(&G_gpg_vstate.work.md.sha3, Ski_len); - cx_sha3_update(&G_gpg_vstate.work.md.sha3, h, 32); - cx_sha3_final(&G_gpg_vstate.work.md.sha3, Ski); + cx_shake256_init(&G_gpg_vstate.work.md.sha3, Ski_len); + cx_sha3_update(&G_gpg_vstate.work.md.sha3, h, 32); + cx_sha3_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_sha3_xof_init(&G_gpg_vstate.work.md.sha3, 256, Ski_len); + cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha3, CX_LAST, h, 32, Ski, Ski_len); #endif } /* assume command is fully received */ int gpg_apdu_gen() { - unsigned int t, l, ksz, reset_cnt; - 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) { - case 0x8000: - case 0x8001: - case 0x8100: - break; - default: - THROW(SW_INCORRECT_P1P2); - return SW_INCORRECT_P1P2; - } + switch ((G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2) { + case 0x8000: + case 0x8001: + case 0x8100: + break; + default: + THROW(SW_INCORRECT_P1P2); + return SW_INCORRECT_P1P2; + } - if (G_gpg_vstate.io_lc != 2) { - THROW(SW_WRONG_LENGTH); - return SW_WRONG_LENGTH; - } + if (G_gpg_vstate.io_lc != 2) { + THROW(SW_WRONG_LENGTH); + return SW_WRONG_LENGTH; + } - gpg_io_fetch_tl(&t, &l); - gpg_io_discard(1); - reset_cnt = 0; - switch (t) { - case 0xB6: - keygpg = &G_gpg_vstate.kslot->sig; - name = (unsigned char *)PIC("sig "); + gpg_io_fetch_tl(&t, &l); + gpg_io_discard(1); reset_cnt = 0; - break; - case 0xA4: - keygpg = &G_gpg_vstate.kslot->aut; - name = (unsigned char *)PIC("aut "); - break; - case 0xB8: - keygpg = &G_gpg_vstate.kslot->dec; - name = (unsigned char *)PIC("dec "); - break; - default: - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } + switch (t) { + case 0xB6: + 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 "); + break; + case 0xB8: + keygpg = &G_gpg_vstate.kslot->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) { - // -- generate keypair --- - case 0x8000: - case 0x8001: - // RSA - if (keygpg->attributes.value[0] == 0x01) { - unsigned char * pq; - cx_rsa_public_key_t * rsa_pub; - cx_rsa_private_key_t *rsa_priv, *pkey; - unsigned int pkey_size; + 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; + cx_rsa_private_key_t *rsa_priv, *pkey; + 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: - pkey_size = sizeof(cx_rsa_1024_private_key_t); - break; - case 2048 / 8: - pkey_size = sizeof(cx_rsa_2048_private_key_t); - break; - case 3072 / 8: - pkey_size = sizeof(cx_rsa_3072_private_key_t); - break; - case 4096 / 8: - pkey_size = sizeof(cx_rsa_4096_private_key_t); - break; - default: - THROW(SW_WRONG_DATA); - } - pq = NULL; - if ((G_gpg_vstate.io_p2 == 0x01) || (G_gpg_vstate.seed_mode)) { - pq = &rsa_pub->n[0]; - unsigned int size; - 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); - } + 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: + pkey_size = sizeof(cx_rsa_2048_private_key_t); + break; + case 3072 / 8: + pkey_size = sizeof(cx_rsa_3072_private_key_t); + break; + case 4096 / 8: + pkey_size = sizeof(cx_rsa_4096_private_key_t); + break; + default: + THROW(SW_WRONG_DATA); + } + pq = NULL; + if ((G_gpg_vstate.io_p2 == 0x01) || (G_gpg_vstate.seed_mode)) { + pq = &rsa_pub->n[0]; + unsigned int size; + 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); + } - cx_rsa_generate_pair(ksz, rsa_pub, rsa_priv, (const unsigned char *)N_gpg_pstate->default_RSA_exponent, 4, pq); + cx_rsa_generate_pair(ksz, + rsa_pub, + rsa_priv, + (const unsigned char *) N_gpg_pstate->default_RSA_exponent, + 4, + pq); - nvm_write(pkey, rsa_priv, pkey_size); - 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)); - } - gpg_io_clear(); + nvm_write(pkey, rsa_priv, pkey_size); + 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)); + } + 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; - keepprivate = 0; - 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_key_seed(seed, name, 1, seed, ksz); - cx_ecfp_init_private_key(curve, seed, ksz, &G_gpg_vstate.work.ecfp.private); - keepprivate = 1; - } + 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; + keepprivate = 0; + 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_key_seed(seed, name, 1, seed, ksz); + 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)); - 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)); - } - gpg_io_clear(); - goto send_ecc_pub; - } - break; + 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)); + } + gpg_io_clear(); + goto send_ecc_pub; + } + break; - // --- read pubkey --- - case 0x8100: - if (keygpg->attributes.value[0] == 0x01) { - /// read RSA - send_rsa_pub: - gpg_io_discard(1); - // 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: - if (keygpg->priv_key.rsa2048.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.rsa2048.n); - break; - case 3072 / 8: - if (keygpg->priv_key.rsa3072.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.rsa3072.n); - break; - case 4096 / 8: - if (keygpg->priv_key.rsa4096.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.rsa4096.n); - break; - } - gpg_io_insert_tlv(0x82, 4, keygpg->pub_key.rsa); + // --- read pubkey --- + case 0x8100: + if (keygpg->attributes.value[0] == 0x01) { + /// read RSA + send_rsa_pub: + gpg_io_discard(1); + // 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: + if (keygpg->priv_key.rsa2048.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.rsa2048.n); + break; + case 3072 / 8: + if (keygpg->priv_key.rsa3072.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.rsa3072.n); + break; + case 4096 / 8: + if (keygpg->priv_key.rsa4096.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.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_set_offset(IO_OFFSET_END); + l = G_gpg_vstate.io_length; + gpg_io_set_offset(IO_OFFSET_MARK); + gpg_io_insert_tl(0x7f49, l); + gpg_io_set_offset(IO_OFFSET_END); - return SW_OK; - } + return SW_OK; + } - 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->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); - return 0; - } - gpg_io_discard(1); - gpg_io_mark(); - curve = gpg_oid2curve(keygpg->attributes.value + 1, keygpg->attributes.length - 1); - if (curve == CX_CURVE_Ed25519) { - 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]; - } - 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); - } - l = G_gpg_vstate.io_length; - gpg_io_set_offset(IO_OFFSET_MARK); - gpg_io_insert_tl(0x7f49, l); - gpg_io_set_offset(IO_OFFSET_END); - return SW_OK; + if (keygpg->pub_key.ecfp256.W_len == 0) { + 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); + if (curve == CX_CURVE_Ed25519) { + 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]; + } + 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); + } + l = G_gpg_vstate.io_length; + gpg_io_set_offset(IO_OFFSET_MARK); + gpg_io_insert_tl(0x7f49, l); + gpg_io_set_offset(IO_OFFSET_END); + return SW_OK; + } + break; } - break; - } - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } diff --git a/src/gpg_init.c b/src/gpg_init.c index 5599161..f79a147 100644 --- a/src/gpg_init.c +++ b/src/gpg_init.c @@ -19,7 +19,7 @@ #include "gpg_api.h" #include "gpg_vars.h" -#define SHORT(x) ((x) >> 8) & 0xFF, (x)&0xFF +#define SHORT(x) ((x) >> 8) & 0xFF, (x) &0xFF /* ----------------------*/ /* -- A Kind of Magic -- */ /* ----------------------*/ @@ -68,115 +68,132 @@ const unsigned char C_OID_BRAINPOOL512R1[9] = { // 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 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)) && (memcmp(oid, C_OID_SECP256R1, len) == 0)) { - return CX_CURVE_SECP256R1; - } - /* - if ( (len == sizeof(C_OID_SECP256K1)) && (memcmp(oid, C_OID_SECP256K1, len)==0) ) { - return CX_CURVE_SECP256K1; - } - - if ( (len == sizeof(C_OID_SECP384R1)) && (memcmp(oid, C_OID_SECP384R1, len)==0) ) { - return CX_CURVE_SECP384R1; - } - if ( (len == sizeof(C_OID_SECP521R1)) && (memcmp(oid, C_OID_SECP521R1, len)==0) ) { - return CX_CURVE_SECP521R1; - } - */ + if ((len == sizeof(C_OID_SECP256R1)) && (memcmp(oid, C_OID_SECP256R1, len) == 0)) { + return CX_CURVE_SECP256R1; + } + /* + if ( (len == sizeof(C_OID_SECP256K1)) && (memcmp(oid, C_OID_SECP256K1, len)==0) ) { + return CX_CURVE_SECP256K1; + } - /* - if ( (len == sizeof(C_OID_BRAINPOOL256R1)) && (memcmp(oid, C_OID_BRAINPOOL256R1, len)==0) ) { - return CX_CURVE_BrainPoolP256R1; - } - if ( (len == sizeof(C_OID_BRAINPOOL384R1)) && (memcmp(oid, C_OID_BRAINPOOL384R1, len)==0) ) { - return CX_CURVE_BrainPoolP384R1; - } - if ( (len == sizeof(C_OID_BRAINPOOL512R1)) && (memcmp(oid, C_OID_BRAINPOOL512R1, len)==0) ) { - return CX_CURVE_BrainPoolP512R1; - } - */ - if ((len == sizeof(C_OID_Ed25519)) && (memcmp(oid, C_OID_Ed25519, len) == 0)) { - return CX_CURVE_Ed25519; - } - - if ((len == sizeof(C_OID_cv25519)) && (memcmp(oid, C_OID_cv25519, len) == 0)) { - return CX_CURVE_Curve25519; - } - - /* - if ( (len == sizeof(C_OID_SECP256K1)) && (memcmp(oid, C_OID_SECP256K1, len)==0) ) { - return CX_CURVE_256K1; - } - if ( (len == sizeof(C_OID_BRAINPOOL256T1)) && (memcmp(oid, C_OID_BRAINPOOL256T1, len)==0) ) { - return CX_CURVE_BrainPoolP256T1; - } - */ - return CX_CURVE_NONE; + if ( (len == sizeof(C_OID_SECP384R1)) && (memcmp(oid, C_OID_SECP384R1, len)==0) ) { + return CX_CURVE_SECP384R1; + } + if ( (len == sizeof(C_OID_SECP521R1)) && (memcmp(oid, C_OID_SECP521R1, len)==0) ) { + return CX_CURVE_SECP521R1; + } + */ + + /* + if ( (len == sizeof(C_OID_BRAINPOOL256R1)) && (memcmp(oid, C_OID_BRAINPOOL256R1, len)==0) ) { + return CX_CURVE_BrainPoolP256R1; + } + if ( (len == sizeof(C_OID_BRAINPOOL384R1)) && (memcmp(oid, C_OID_BRAINPOOL384R1, len)==0) ) { + return CX_CURVE_BrainPoolP384R1; + } + if ( (len == sizeof(C_OID_BRAINPOOL512R1)) && (memcmp(oid, C_OID_BRAINPOOL512R1, len)==0) ) { + return CX_CURVE_BrainPoolP512R1; + } + */ + if ((len == sizeof(C_OID_Ed25519)) && (memcmp(oid, C_OID_Ed25519, len) == 0)) { + return CX_CURVE_Ed25519; + } + + if ((len == sizeof(C_OID_cv25519)) && (memcmp(oid, C_OID_cv25519, len) == 0)) { + return CX_CURVE_Curve25519; + } + + /* + if ( (len == sizeof(C_OID_SECP256K1)) && (memcmp(oid, C_OID_SECP256K1, len)==0) ) { + return CX_CURVE_256K1; + } + if ( (len == sizeof(C_OID_BRAINPOOL256T1)) && (memcmp(oid, C_OID_BRAINPOOL256T1, len)==0) ) { + return CX_CURVE_BrainPoolP256T1; + } + */ + return CX_CURVE_NONE; } 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); - - /* - case CX_CURVE_SECP256K1: - *len = sizeof(C_OID_SECP256K1); - return (unsigned char*)PIC(C_OID_SECP256K1); - - case CX_CURVE_SECP384R1: - *len = sizeof(C_OID_SECP384R1); - return (unsigned char*)PIC(C_OID_SECP384R1); - - case CX_CURVE_SECP521R1: - *len = sizeof(C_OID_SECP521R1); - return (unsigned char*)PIC(C_OID_SECP521R1); - */ - - /* - case CX_CURVE_BrainPoolP256R1: - *len = sizeof(C_OID_SECP256R1); - return (unsigned char*)PIC(C_OID_SECP256R1); - - case CX_CURVE_BrainPoolP384R1: - *len = sizeof(C_OID_SECP384R1); - return (unsigned char*)PIC(C_OID_SECP384R1); - - case CX_CURVE_BrainPoolP512R1: - *len = sizeof(C_OID_SECP521R1); - return (unsigned char*)PIC(C_OID_SECP521R1); - */ - case CX_CURVE_Ed25519: - *len = sizeof(C_OID_Ed25519); - return (unsigned char *)PIC(C_OID_Ed25519); - - case CX_CURVE_Curve25519: - *len = sizeof(C_OID_cv25519); - return (unsigned char *)PIC(C_OID_cv25519); - } - - *len = 0; - return NULL; + switch (cv) { + case CX_CURVE_SECP256R1: + *len = sizeof(C_OID_SECP256R1); + return (unsigned char *) PIC(C_OID_SECP256R1); + + /* + case CX_CURVE_SECP256K1: + *len = sizeof(C_OID_SECP256K1); + return (unsigned char*)PIC(C_OID_SECP256K1); + + case CX_CURVE_SECP384R1: + *len = sizeof(C_OID_SECP384R1); + return (unsigned char*)PIC(C_OID_SECP384R1); + + case CX_CURVE_SECP521R1: + *len = sizeof(C_OID_SECP521R1); + return (unsigned char*)PIC(C_OID_SECP521R1); + */ + + /* + case CX_CURVE_BrainPoolP256R1: + *len = sizeof(C_OID_SECP256R1); + return (unsigned char*)PIC(C_OID_SECP256R1); + + case CX_CURVE_BrainPoolP384R1: + *len = sizeof(C_OID_SECP384R1); + return (unsigned char*)PIC(C_OID_SECP384R1); + + case CX_CURVE_BrainPoolP512R1: + *len = sizeof(C_OID_SECP521R1); + return (unsigned char*)PIC(C_OID_SECP521R1); + */ + case CX_CURVE_Ed25519: + *len = sizeof(C_OID_Ed25519); + return (unsigned char *) PIC(C_OID_Ed25519); + + case CX_CURVE_Curve25519: + *len = sizeof(C_OID_cv25519); + return (unsigned char *) PIC(C_OID_cv25519); + } + + *len = 0; + return NULL; } unsigned int gpg_curve2domainlen(unsigned int cv) { - switch (cv) { - case CX_CURVE_SECP256R1: - case CX_CURVE_Ed25519: - case CX_CURVE_Curve25519: - return 32; - } - return 0; + switch (cv) { + case CX_CURVE_SECP256R1: + case CX_CURVE_Ed25519: + case CX_CURVE_Curve25519: + return 32; + } + return 0; } /* -------------------------------*/ @@ -201,30 +218,49 @@ const unsigned char C_ext_capabilities[10] = { }; -const unsigned char C_ext_length[8] = {0x02, 0x02, SHORT(GPG_APDU_LENGTH), 0x02, 0x02, SHORT(GPG_APDU_LENGTH)}; +const unsigned char C_ext_length[8] = + {0x02, 0x02, SHORT(GPG_APDU_LENGTH), 0x02, 0x02, SHORT(GPG_APDU_LENGTH)}; /* ---------------------*/ /* -- default values -- */ /* ---------------------*/ -const unsigned char C_default_AID[] = {0xD2, 0x76, 0x00, 0x01, 0x24, 0x01, - // 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[] = { + // RID: Registered application provider Identifier + 0xD2, + 0x76, + 0x00, + 0x01, + 0x24, + // PIX: Proprietary application identifier extension + // application + 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 @@ -232,18 +268,22 @@ const unsigned char C_default_AlgoAttr_sig[] = { // RSA 0x01, // Modulus default length 2048 - 0x08, 0x00, + 0x08, + 0x00, // PubExp length 32 - 0x00, 0x20, + 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, + 0x08, + 0x00, // PubExp length 32 - 0x00, 0x20, + 0x00, + 0x20, // std: e,p,q with modulus (n) 0x01}; #endif @@ -296,135 +336,138 @@ const unsigned char C_sha256_PW2[] = { /* ----------------------------------------------------------------------- */ void gpg_init() { - memset(&G_gpg_vstate, 0, sizeof(gpg_v_state_t)); - // first init ? - if (memcmp((void *)(N_gpg_pstate->magic), (void *)C_MAGIC, sizeof(C_MAGIC)) != 0) { - gpg_install(STATE_ACTIVATE); - gpg_nvm_write((void *)(N_gpg_pstate->magic), (void *)C_MAGIC, sizeof(C_MAGIC)); memset(&G_gpg_vstate, 0, sizeof(gpg_v_state_t)); - } - - // key conf - G_gpg_vstate.slot = N_gpg_pstate->config_slot[1]; - G_gpg_vstate.kslot = (gpg_key_slot_t *)&N_gpg_pstate->keys[G_gpg_vstate.slot]; - gpg_mse_reset(); - // pin conf - G_gpg_vstate.pinmode = N_gpg_pstate->config_pin[0]; - // ux conf - gpg_init_ux(); + // first init ? + if (memcmp((void *) (N_gpg_pstate->magic), (void *) C_MAGIC, sizeof(C_MAGIC)) != 0) { + gpg_install(STATE_ACTIVATE); + gpg_nvm_write((void *) (N_gpg_pstate->magic), (void *) C_MAGIC, sizeof(C_MAGIC)); + memset(&G_gpg_vstate, 0, sizeof(gpg_v_state_t)); + } + + // key conf + G_gpg_vstate.slot = N_gpg_pstate->config_slot[1]; + G_gpg_vstate.kslot = (gpg_key_slot_t *) &N_gpg_pstate->keys[G_gpg_vstate.slot]; + gpg_mse_reset(); + // pin conf + G_gpg_vstate.pinmode = N_gpg_pstate->config_pin[0]; + // 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_type = -1; + G_gpg_vstate.ux_key = -1; } /* ----------------------------------------------------------------------- */ /* --- Install/ReInstall GPGapp --- */ /* ----------------------------------------------------------------------- */ void gpg_install_slot(gpg_key_slot_t *slot) { - unsigned char tmp[4]; - unsigned int l; + unsigned char tmp[4]; + unsigned int l; - gpg_nvm_write(slot, 0, sizeof(gpg_key_slot_t)); + gpg_nvm_write(slot, 0, sizeof(gpg_key_slot_t)); - cx_rng(tmp, 4); - gpg_nvm_write((void *)(slot->serial), tmp, 4); + cx_rng(tmp, 4); + gpg_nvm_write((void *) (slot->serial), tmp, 4); - l = sizeof(C_default_AlgoAttr_sig); - gpg_nvm_write((void *)(&slot->sig.attributes.value), (void *)C_default_AlgoAttr_sig, l); - gpg_nvm_write((void *)(&slot->sig.attributes.length), &l, sizeof(unsigned int)); - gpg_nvm_write((void *)(&slot->aut.attributes.value), (void *)C_default_AlgoAttr_sig, l); - gpg_nvm_write((void *)(&slot->aut.attributes.length), &l, sizeof(unsigned int)); + l = sizeof(C_default_AlgoAttr_sig); + gpg_nvm_write((void *) (&slot->sig.attributes.value), (void *) C_default_AlgoAttr_sig, l); + gpg_nvm_write((void *) (&slot->sig.attributes.length), &l, sizeof(unsigned int)); + gpg_nvm_write((void *) (&slot->aut.attributes.value), (void *) C_default_AlgoAttr_sig, l); + gpg_nvm_write((void *) (&slot->aut.attributes.length), &l, sizeof(unsigned int)); - l = sizeof(C_default_AlgoAttr_dec); - gpg_nvm_write((void *)(&slot->dec.attributes.value), (void *)C_default_AlgoAttr_dec, l); - gpg_nvm_write((void *)(&slot->dec.attributes.length), &l, sizeof(unsigned int)); + l = sizeof(C_default_AlgoAttr_dec); + gpg_nvm_write((void *) (&slot->dec.attributes.value), (void *) C_default_AlgoAttr_dec, l); + gpg_nvm_write((void *) (&slot->dec.attributes.length), &l, sizeof(unsigned int)); - tmp[0] = 0x00; - tmp[1] = 0x20; - gpg_nvm_write((void *)(&slot->sig.UIF), &tmp, 2); - gpg_nvm_write((void *)(&slot->dec.UIF), &tmp, 2); - gpg_nvm_write((void *)(&slot->aut.UIF), &tmp, 2); + tmp[0] = 0x00; + tmp[1] = 0x20; + gpg_nvm_write((void *) (&slot->sig.UIF), &tmp, 2); + gpg_nvm_write((void *) (&slot->dec.UIF), &tmp, 2); + gpg_nvm_write((void *) (&slot->aut.UIF), &tmp, 2); } void gpg_install(unsigned char app_state) { - gpg_pin_t pin; - - // full reset data - gpg_nvm_write((void *)(N_gpg_pstate), NULL, sizeof(gpg_nv_state_t)); - - // historical bytes - 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((void *)(N_gpg_pstate->histo), G_gpg_vstate.work.io_buffer, sizeof(C_default_Histo)); - - // AID - memmove(G_gpg_vstate.work.io_buffer, C_default_AID, sizeof(C_default_AID)); - gpg_nvm_write((void *)(N_gpg_pstate->AID), &G_gpg_vstate.work.io_buffer, sizeof(C_default_AID)); - - - if (app_state == STATE_ACTIVATE) { - // default sex: none - G_gpg_vstate.work.io_buffer[0] = 0x39; - gpg_nvm_write((void *)(&N_gpg_pstate->sex), G_gpg_vstate.work.io_buffer, 1); - - // default PW1/PW2: 1 2 3 4 5 6 - memmove(pin.value, C_sha256_PW1, sizeof(C_sha256_PW1)); - pin.length = 6; - pin.counter = 3; - 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 - memmove(pin.value, C_sha256_PW2, sizeof(C_sha256_PW2)); - pin.length = 8; - pin.counter = 3; - pin.ref = PIN_ID_PW3; - gpg_nvm_write((void *)(&N_gpg_pstate->PW3), &pin, sizeof(gpg_pin_t)); - - // PWs status - G_gpg_vstate.work.io_buffer[0] = 1; - G_gpg_vstate.work.io_buffer[1] = GPG_MAX_PW_LENGTH; - G_gpg_vstate.work.io_buffer[2] = GPG_MAX_PW_LENGTH; - G_gpg_vstate.work.io_buffer[3] = GPG_MAX_PW_LENGTH; - gpg_nvm_write((void *)(&N_gpg_pstate->PW_status), G_gpg_vstate.work.io_buffer, 4); - - // config slot - G_gpg_vstate.work.io_buffer[0] = GPG_KEYS_SLOTS; - G_gpg_vstate.work.io_buffer[1] = 0; - G_gpg_vstate.work.io_buffer[2] = 3; // 3: selection by APDU and screen - gpg_nvm_write((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((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++) { - gpg_install_slot((gpg_key_slot_t *)&N_gpg_pstate->keys[s]); + gpg_pin_t pin; + + // full reset data + gpg_nvm_write((void *) (N_gpg_pstate), NULL, sizeof(gpg_nv_state_t)); + + // historical bytes + 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((void *) (N_gpg_pstate->histo), + G_gpg_vstate.work.io_buffer, + sizeof(C_default_Histo)); + + // AID + memmove(G_gpg_vstate.work.io_buffer, C_default_AID, sizeof(C_default_AID)); + gpg_nvm_write((void *) (N_gpg_pstate->AID), + &G_gpg_vstate.work.io_buffer, + sizeof(C_default_AID)); + + if (app_state == STATE_ACTIVATE) { + // default sex: none + G_gpg_vstate.work.io_buffer[0] = 0x39; + gpg_nvm_write((void *) (&N_gpg_pstate->sex), G_gpg_vstate.work.io_buffer, 1); + + // default PW1/PW2: 1 2 3 4 5 6 + memmove(pin.value, C_sha256_PW1, sizeof(C_sha256_PW1)); + pin.length = 6; + pin.counter = 3; + 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 + memmove(pin.value, C_sha256_PW2, sizeof(C_sha256_PW2)); + pin.length = 8; + pin.counter = 3; + pin.ref = PIN_ID_PW3; + gpg_nvm_write((void *) (&N_gpg_pstate->PW3), &pin, sizeof(gpg_pin_t)); + + // PWs status + G_gpg_vstate.work.io_buffer[0] = 1; + G_gpg_vstate.work.io_buffer[1] = GPG_MAX_PW_LENGTH; + G_gpg_vstate.work.io_buffer[2] = GPG_MAX_PW_LENGTH; + G_gpg_vstate.work.io_buffer[3] = GPG_MAX_PW_LENGTH; + gpg_nvm_write((void *) (&N_gpg_pstate->PW_status), G_gpg_vstate.work.io_buffer, 4); + + // config slot + G_gpg_vstate.work.io_buffer[0] = GPG_KEYS_SLOTS; + G_gpg_vstate.work.io_buffer[1] = 0; + G_gpg_vstate.work.io_buffer[2] = 3; // 3: selection by APDU and screen + gpg_nvm_write((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((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++) { + gpg_install_slot((gpg_key_slot_t *) &N_gpg_pstate->keys[s]); + } } - } } +// TODO: Check if needed 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; - cfgDesc = USBD_GetCfgDesc_impl(&length); - nvm_write(cfgDesc + (length - 16), &e, 1); + //unsigned short length = 0; + //uint8_t *cfgDesc = NULL; + unsigned char e; + e = enabled ? 3 : 0; + //cfgDesc = USBD_GetCfgDesc_impl(&length); + //nvm_write(cfgDesc + (length - 16), &e, 1); #else - UNUSED(enabled); + UNUSED(enabled); #endif } diff --git a/src/gpg_io.c b/src/gpg_io.c index 198dbab..edcf085 100644 --- a/src/gpg_io.c +++ b/src/gpg_io.c @@ -30,38 +30,38 @@ /* ----------------------------------------------------------------------- */ 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) { - G_gpg_vstate.io_offset = G_gpg_vstate.io_mark; - } else if (offset < G_gpg_vstate.io_length) { - G_gpg_vstate.io_offset = G_gpg_vstate.io_length; - } else { - THROW(ERROR_IO_OFFSET); - return; - } + if (offset == IO_OFFSET_END) { + G_gpg_vstate.io_offset = G_gpg_vstate.io_length; + } else if (offset == IO_OFFSET_MARK) { + G_gpg_vstate.io_offset = G_gpg_vstate.io_mark; + } else if (offset < G_gpg_vstate.io_length) { + G_gpg_vstate.io_offset = G_gpg_vstate.io_length; + } else { + THROW(ERROR_IO_OFFSET); + return; + } } void gpg_io_mark() { - G_gpg_vstate.io_mark = G_gpg_vstate.io_offset; + 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; + G_gpg_vstate.io_offset += len; + G_gpg_vstate.io_length += 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; - if (clear) { - gpg_io_clear(); - } + G_gpg_vstate.io_length = 0; + G_gpg_vstate.io_offset = 0; + G_gpg_vstate.io_mark = 0; + if (clear) { + gpg_io_clear(); + } } void gpg_io_clear() { - memset(G_gpg_vstate.work.io_buffer, 0, GPG_IO_BUFFER_LENGTH); + memset(G_gpg_vstate.work.io_buffer, 0, GPG_IO_BUFFER_LENGTH); } /* ----------------------------------------------------------------------- */ @@ -69,72 +69,73 @@ 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; - } - 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; + if ((G_gpg_vstate.io_length + sz) > GPG_IO_BUFFER_LENGTH) { + THROW(ERROR_IO_FULL); + return; + } + 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); - memmove(G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, buff, len); - G_gpg_vstate.io_offset += len; + gpg_io_hole(len); + 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) { - 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.io_offset += 4; + 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.io_offset += 4; } 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.io_offset += 3; + 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.io_offset += 3; } 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.io_offset += 2; + 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.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.io_offset += 1; + gpg_io_hole(1); + 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); - } else { - gpg_io_insert_u8(T); - } + if (T & 0xFF00) { + gpg_io_insert_u16(T); + } else { + gpg_io_insert_u8(T); + } } void gpg_io_insert_tl(unsigned int T, unsigned int L) { - gpg_io_insert_t(T); - if (L < 128) { - gpg_io_insert_u8(L); - } else if (L < 256) { - gpg_io_insert_u16(0x8100 | L); - } else { - gpg_io_insert_u8(0x82); - gpg_io_insert_u16(L); - } + gpg_io_insert_t(T); + if (L < 128) { + gpg_io_insert_u8(L); + } else if (L < 256) { + gpg_io_insert_u16(0x8100 | L); + } else { + gpg_io_insert_u8(0x82); + gpg_io_insert_u16(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(V, L); + gpg_io_insert_tl(T, L); + gpg_io_insert(V, L); } /* ----------------------------------------------------------------------- */ @@ -142,87 +143,87 @@ void gpg_io_insert_tlv(unsigned int T, unsigned int L, unsigned char const *V) { /* ----------------------------------------------------------------------- */ 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)); - G_gpg_vstate.io_offset += 4; - return v32; + 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)); - G_gpg_vstate.io_offset += 3; - return v24; + 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)); - G_gpg_vstate.io_offset += 2; - return v16; + 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]; - G_gpg_vstate.io_offset += 1; - return v8; + unsigned int v8; + v8 = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset]; + G_gpg_vstate.io_offset += 1; + return v8; } int gpg_io_fetch_t(unsigned int *T) { - *T = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset]; - G_gpg_vstate.io_offset++; - if ((*T & 0x1F) == 0x1F) { - *T = (*T << 8) | G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset]; + *T = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset]; G_gpg_vstate.io_offset++; - } - return 0; + if ((*T & 0x1F) == 0x1F) { + *T = (*T << 8) | G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset]; + G_gpg_vstate.io_offset++; + } + return 0; } int gpg_io_fetch_l(unsigned int *L) { - *L = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset]; - - if ((*L & 0x80) != 0) { - *L &= 0x7F; - if (*L == 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]; + + if ((*L & 0x80) != 0) { + *L &= 0x7F; + if (*L == 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; + } else { + *L = -1; + } } else { - *L = -1; + G_gpg_vstate.io_offset += 1; } - } else { - G_gpg_vstate.io_offset += 1; - } - return 0; + return 0; } int gpg_io_fetch_tl(unsigned int *T, unsigned int *L) { - gpg_io_fetch_t(T); - gpg_io_fetch_l(L); - return 0; + gpg_io_fetch_t(T); + gpg_io_fetch_l(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); - G_gpg_vstate.io_offset += len; - return 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) { - if (buffer) { - memmove(buffer, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, len); - } - G_gpg_vstate.io_offset += len; - return len; + if (buffer) { + memmove(buffer, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, len); + } + G_gpg_vstate.io_offset += len; + return len; } /* ----------------------------------------------------------------------- */ @@ -232,123 +233,128 @@ int gpg_io_fetch(unsigned char *buffer, int len) { #define MAX_OUT GPG_APDU_LENGTH int gpg_io_do(unsigned int io_flags) { - unsigned int rx = 0; - - // 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 - 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; - 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; - } else { - 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)) { - THROW(SW_COMMAND_NOT_ALLOWED); - return 0; - } + unsigned int rx = 0; + + // if pending input chaining + if (G_gpg_vstate.io_cla & 0x10) { + goto in_chaining; } - 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); - return 0; + 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 + rx = gpg_io_exchange(CHANNEL_APDU | IO_ASYNCH_REPLY, 0); } else { - 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; - } - if (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; - - 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]; - break; - - case INS_GET_CHALLENGE: - if (G_gpg_vstate.io_p1 == 0) { - G_gpg_vstate.io_le = G_io_apdu_buffer[4]; - break; + // --- 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; + 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; + } else { + 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)) { + THROW(SW_COMMAND_NOT_ALLOWED); + return 0; + } + } + 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); + return 0; + } else { + rx = gpg_io_exchange(CHANNEL_APDU, G_gpg_vstate.io_length); + } } - __attribute__((fallthrough)); - 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]; - 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) { - G_io_apdu_buffer[0] = 0x90; - G_io_apdu_buffer[1] = 0x00; - rx = gpg_io_exchange(CHANNEL_APDU, 2); - in_chaining: - if ((rx < 4) || ((G_io_apdu_buffer[0] & 0xEF) != (G_gpg_vstate.io_cla & 0xEF)) || - (G_io_apdu_buffer[1] != G_gpg_vstate.io_ins) || (G_io_apdu_buffer[2] != G_gpg_vstate.io_p1) || - (G_io_apdu_buffer[3] != G_gpg_vstate.io_p2)) { - THROW(SW_COMMAND_NOT_ALLOWED); - return SW_COMMAND_NOT_ALLOWED; + //--- full in chaining --- + if (rx < 4) { + 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_lc = G_io_apdu_buffer[4]; - if ((G_gpg_vstate.io_length + G_gpg_vstate.io_lc) > GPG_IO_BUFFER_LENGTH) { - return 1; + 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]; + break; + + case INS_GET_CHALLENGE: + if (G_gpg_vstate.io_p1 == 0) { + G_gpg_vstate.io_le = G_io_apdu_buffer[4]; + break; + } + + __attribute__((fallthrough)); + 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]; + 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) { + G_io_apdu_buffer[0] = 0x90; + G_io_apdu_buffer[1] = 0x00; + rx = gpg_io_exchange(CHANNEL_APDU, 2); + in_chaining: + if ((rx < 4) || ((G_io_apdu_buffer[0] & 0xEF) != (G_gpg_vstate.io_cla & 0xEF)) || + (G_io_apdu_buffer[1] != G_gpg_vstate.io_ins) || + (G_io_apdu_buffer[2] != G_gpg_vstate.io_p1) || + (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_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; + } + 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; } - 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; + return 0; } diff --git a/src/gpg_main.c b/src/gpg_main.c index 088bb58..65f8d5f 100644 --- a/src/gpg_main.c +++ b/src/gpg_main.c @@ -22,7 +22,6 @@ #include "gpg_vars.h" #include "gpg_ux_nanos.h" -//#include "gpg_ux_blue.h" #include "os_io_seproxyhal.h" #include "string.h" @@ -33,161 +32,161 @@ /* ----------------------------------------------------------------------- */ void gpg_main(void) { - unsigned int io_flags; - io_flags = 0; - for (;;) { - volatile unsigned short sw = 0; - BEGIN_TRY { - TRY { - gpg_io_do(io_flags); - sw = gpg_dispatch(); - } - 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; + unsigned int io_flags; + io_flags = 0; + for (;;) { + volatile unsigned short sw = 0; + BEGIN_TRY { + TRY { + gpg_io_do(io_flags); + sw = gpg_dispatch(); + } + 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 { + if (sw) { + gpg_io_insert_u16(sw); + io_flags = 0; + } else { + io_flags = IO_ASYNCH_REPLY; + } + } } - } - FINALLY { - if (sw) { - gpg_io_insert_u16(sw); - io_flags = 0; - } else { - io_flags = IO_ASYNCH_REPLY; - } - } + END_TRY; } - END_TRY; - } } unsigned char io_event(unsigned char channel) { - UNUSED(channel); - // nothing done with the event, throw an error on the transport layer if - // needed - // can't have more than one tag in the reply, not supported yet. - switch (G_io_seproxyhal_spi_buffer[0]) { - case SEPROXYHAL_TAG_FINGER_EVENT: - UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer); - break; - // power off if long push, else pass to the application callback if any - case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: // for Nano S - UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer); - break; - - // other events are propagated to the UX just in case - default: - UX_DEFAULT_EVENT(); - break; - - case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT: - 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(); - } - }); - break; - } - - // close the event if not done previously (by a display or whatever) - if (!io_seproxyhal_spi_is_status_sent()) { - io_seproxyhal_general_status(); - } - // command has been processed, DO NOT reset the current APDU transport - return 1; + UNUSED(channel); + // nothing done with the event, throw an error on the transport layer if + // needed + // can't have more than one tag in the reply, not supported yet. + switch (G_io_seproxyhal_spi_buffer[0]) { + case SEPROXYHAL_TAG_FINGER_EVENT: + UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer); + break; + // power off if long push, else pass to the application callback if any + case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: // for Nano S + UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer); + break; + + // other events are propagated to the UX just in case + default: + UX_DEFAULT_EVENT(); + break; + + case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT: + UX_DISPLAYED_EVENT({}); + break; + case SEPROXYHAL_TAG_TICKER_EVENT: + UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, { + // only allow display when not locked of overlaid by an OS UX. + if (UX_ALLOWED) { + UX_REDISPLAY(); + } + }); + break; + } + + // close the event if not done previously (by a display or whatever) + if (!io_seproxyhal_spi_is_status_sent()) { + io_seproxyhal_general_status(); + } + // command has been processed, DO NOT reset the current APDU transport + return 1; } unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) { - switch (channel & ~(IO_FLAGS)) { - case CHANNEL_KEYBOARD: - break; - - // multiplexed io exchange over a SPI channel and TLV encapsulated protocol - case CHANNEL_SPI: - if (tx_len) { - io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len); - - if (channel & IO_RESET_AFTER_REPLIED) { - reset(); - } - 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); + switch (channel & ~(IO_FLAGS)) { + case CHANNEL_KEYBOARD: + break; + + // multiplexed io exchange over a SPI channel and TLV encapsulated protocol + case CHANNEL_SPI: + if (tx_len) { + io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len); + + if (channel & IO_RESET_AFTER_REPLIED) { + reset(); + } + 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); + } + + default: + THROW(INVALID_PARAMETER); + return 0; } - - default: - THROW(INVALID_PARAMETER); return 0; - } - return 0; } void app_exit(void) { - BEGIN_TRY_L(exit) { - TRY_L(exit) { - os_sched_exit(-1); - } - FINALLY_L(exit) { + BEGIN_TRY_L(exit) { + TRY_L(exit) { + os_sched_exit(-1); + } + FINALLY_L(exit) { + } } - } - END_TRY_L(exit); + END_TRY_L(exit); } /* -------------------------------------------------------------- */ __attribute__((section(".boot"))) int main(void) { - // exit critical section - __asm volatile("cpsie i"); + // exit critical section + __asm volatile("cpsie i"); - // ensure exception will work as planned - os_boot(); - for (;;) { - UX_INIT(); + // ensure exception will work as planned + os_boot(); + for (;;) { + UX_INIT(); - BEGIN_TRY { - TRY { - // start communication with MCU - io_seproxyhal_init(); + BEGIN_TRY { + TRY { + // start communication with MCU + io_seproxyhal_init(); - USB_power(1); + USB_power(1); #if HAVE_USB_CLASS_CCID - io_usb_ccid_set_card_inserted(1); + io_usb_ccid_set_card_inserted(1); #endif - // set up - gpg_init(); - - // set up initial screen - ui_init(); - - // 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 - continue; - } - CATCH_ALL { - break; - } - FINALLY { - } + // set up + gpg_init(); + + // set up initial screen + ui_init(); + + // 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 + continue; + } + CATCH_ALL { + break; + } + FINALLY { + } + } + END_TRY; } - END_TRY; - } - app_exit(); + app_exit(); } #endif diff --git a/src/gpg_mse.c b/src/gpg_mse.c index c9d2db8..831e338 100644 --- a/src/gpg_mse.c +++ b/src/gpg_mse.c @@ -20,53 +20,54 @@ #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; + if (crt == 0xA4) { + if (ref == 0x02) { + G_gpg_vstate.mse_aut = &G_gpg_vstate.kslot->dec; + } + if (ref == 0x03) { + G_gpg_vstate.mse_aut = &G_gpg_vstate.kslot->aut; + } } - if (ref == 0x03) { - 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; - } - if (ref == 0x03) { - G_gpg_vstate.mse_dec = &G_gpg_vstate.kslot->aut; + if (crt == 0xB8) { + if (ref == 0x02) { + G_gpg_vstate.mse_dec = &G_gpg_vstate.kslot->dec; + } + if (ref == 0x03) { + G_gpg_vstate.mse_dec = &G_gpg_vstate.kslot->aut; + } } - } - return 0; + return 0; } int gpg_mse_reset() { - gpg_mse_set(0xA4, 0x03); - gpg_mse_set(0xB8, 0x02); - return 0; + gpg_mse_set(0xA4, 0x03); + gpg_mse_set(0xB8, 0x02); + return 0; } 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))) { - THROW(SW_INCORRECT_P1P2); - return SW_INCORRECT_P1P2; - } + 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(); - if (crt != 0x8301) { - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } + 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)) { - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } + ref = gpg_io_fetch_u8(); + if ((ref != 0x02) && (ref != 0x03)) { + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } - gpg_mse_set(crt, ref); - gpg_io_discard(1); - return SW_OK; -} \ No newline at end of file + gpg_mse_set(crt, ref); + gpg_io_discard(1); + return SW_OK; +} diff --git a/src/gpg_pin.c b/src/gpg_pin.c index 534c212..80e2295 100644 --- a/src/gpg_pin.c +++ b/src/gpg_pin.c @@ -22,257 +22,266 @@ #include "gpg_ux_nanos.h" gpg_pin_t *gpg_pin_get_pin(int pinref) { - switch (pinref) { - case PIN_ID_PW1: - case PIN_ID_PW2: - return (gpg_pin_t *)&N_gpg_pstate->PW1; - case PIN_ID_PW3: - return (gpg_pin_t *)&N_gpg_pstate->PW3; - case PIN_ID_RC: - return (gpg_pin_t *)&N_gpg_pstate->RC; - } - return NULL; + switch (pinref) { + case PIN_ID_PW1: + case PIN_ID_PW2: + return (gpg_pin_t *) &N_gpg_pstate->PW1; + case PIN_ID_PW3: + return (gpg_pin_t *) &N_gpg_pstate->PW3; + case PIN_ID_RC: + return (gpg_pin_t *) &N_gpg_pstate->RC; + } + return NULL; } static int gpg_pin_get_state_index(unsigned int pinref) { - switch (pinref) { - case PIN_ID_PW1: - return 1; - case PIN_ID_PW2: - return 2; - case PIN_ID_PW3: - return 3; - case PIN_ID_RC: - return 4; - } - return -1; + switch (pinref) { + case PIN_ID_PW1: + return 1; + case PIN_ID_PW2: + return 2; + 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) { - unsigned int counter; - - if (pin->counter == 0) { - return SW_PIN_BLOCKED; - } - - counter = pin->counter - 1; - gpg_nvm_write(&(pin->counter), &counter, sizeof(int)); - cx_sha256_init(&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 (memcmp(G_gpg_vstate.work.md.H, pin->value, 32)) { - return SW_SECURITY_STATUS_NOT_SATISFIED; - } - - counter = 3; - gpg_nvm_write(&(pin->counter), &counter, sizeof(int)); - return SW_OK; + unsigned int counter; + + if (pin->counter == 0) { + return SW_PIN_BLOCKED; + } + + counter = pin->counter - 1; + gpg_nvm_write(&(pin->counter), &counter, sizeof(int)); + cx_sha256_init(&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 (memcmp(G_gpg_vstate.work.md.H, pin->value, 32)) { + return SW_SECURITY_STATUS_NOT_SATISFIED; + } + + counter = 3; + gpg_nvm_write(&(pin->counter), &counter, sizeof(int)); + return SW_OK; } 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); - if (sw == SW_OK) { - gpg_pin_set_verified(pinID, 1); + int sw; + 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); + return; + } + THROW(sw); return; - } - THROW(sw); - return; } 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); - if (sw == SW_OK) { - gpg_pin_set_verified(pinID, 1); - } - return sw; + int sw; + 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); + } + return sw; } void gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len) { - cx_sha256_t sha256; + cx_sha256_t sha256; - gpg_pin_t newpin; + 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; - newpin.counter = 3; + cx_sha256_init(&sha256); + 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)); + gpg_nvm_write(pin, &newpin, sizeof(gpg_pin_t)); } 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; + int idx; + idx = gpg_pin_get_state_index(pinID); + if (idx >= 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; + int idx; + idx = gpg_pin_get_state_index(pinID); + if (idx >= 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; + gpg_pin_t *pin; - pin = gpg_pin_get_pin(G_gpg_vstate.io_p2); - if (pin == NULL) { - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } - - // PINPAD - if (G_gpg_vstate.io_cla == 0xEF) { - if (gpg_pin_is_blocked(pin)) { - THROW(SW_PIN_BLOCKED); - return SW_PIN_BLOCKED; + pin = gpg_pin_get_pin(G_gpg_vstate.io_p2); + if (pin == NULL) { + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } - if (G_gpg_vstate.pinmode == PIN_MODE_SCREEN) { - // Delegate pin check to ui - gpg_io_discard(1); - ui_menu_pinentry_display(0); - return 0; + // PINPAD + if (G_gpg_vstate.io_cla == 0xEF) { + if (gpg_pin_is_blocked(pin)) { + THROW(SW_PIN_BLOCKED); + return SW_PIN_BLOCKED; + } + + if (G_gpg_vstate.pinmode == PIN_MODE_SCREEN) { + // 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 + 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; + } + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } - if (G_gpg_vstate.pinmode == PIN_MODE_CONFIRM) { - // 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; - } - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } - // 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; + // 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, + G_gpg_vstate.io_length); + gpg_io_discard(1); + return SW_OK; } - 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; - } - gpg_io_discard(1); + gpg_io_discard(1); - // 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; + // 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; } - 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); - return SW_OK; - } + // 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; + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } int gpg_apdu_change_ref_data() { - gpg_pin_t *pin; - int len, newlen; + gpg_pin_t *pin; + 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); - - // --- PW1/PW3 pin --- - if (gpg_pin_is_blocked(pin)) { - THROW(SW_PIN_BLOCKED); - return SW_PIN_BLOCKED; - } - // 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 - gpg_io_discard(1); - ui_menu_pinentry_display(0); - return 0; + pin = gpg_pin_get_pin(G_gpg_vstate.io_p2); + if (pin == NULL) { + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } - } - - if (pin->length > 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_set_verified(pin->ref, 0); - 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_io_discard(1); - return SW_OK; -} + // --- PW1/PW3 pin --- + if (gpg_pin_is_blocked(pin)) { + THROW(SW_PIN_BLOCKED); + return SW_PIN_BLOCKED; + } + // avoid any-overflow without giving info + if (G_gpg_vstate.io_length == 0) { + if (G_gpg_vstate.pinmode != PIN_MODE_HOST) { + // Delegate pin change to ui + gpg_io_discard(1); + ui_menu_pinentry_display(0); + return 0; + } + } -int gpg_apdu_reset_retry_counter() { - gpg_pin_t *pin_pw1; - gpg_pin_t *pin_rc; - int rc_len, pw1_len; + if (pin->length > G_gpg_vstate.io_length) { + len = G_gpg_vstate.io_length; + } else { + len = pin->length; + } - pin_pw1 = gpg_pin_get_pin(PIN_ID_PW1); - pin_rc = gpg_pin_get_pin(PIN_ID_RC); + gpg_pin_check_throw(pin, pin->ref, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, len); - 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; + 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; } - rc_len = 0; - pw1_len = G_gpg_vstate.io_length; - } else { - // avoid any-overflow whitout giving info - if (pin_rc->length > G_gpg_vstate.io_length) { - rc_len = G_gpg_vstate.io_length; + gpg_pin_set(pin, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset + len, newlen); + gpg_io_discard(1); + return SW_OK; +} + +int gpg_apdu_reset_retry_counter() { + gpg_pin_t *pin_pw1; + gpg_pin_t *pin_rc; + int rc_len, pw1_len; + + pin_pw1 = gpg_pin_get_pin(PIN_ID_PW1); + 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; + pw1_len = G_gpg_vstate.io_length; } else { - rc_len = pin_rc->length; + // avoid any-overflow without giving info + if (pin_rc->length > 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)) { - 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_io_discard(1); - return SW_OK; + 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_io_discard(1); + return SW_OK; } diff --git a/src/gpg_pso.c b/src/gpg_pso.c index 2e1834b..64fa73b 100644 --- a/src/gpg_pso.c +++ b/src/gpg_pso.c @@ -20,316 +20,401 @@ #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) { - THROW(SW_CONDITIONS_NOT_SATISFIED); - return SW_CONDITIONS_NOT_SATISFIED; - } + // --- 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 - if (ksz < G_gpg_vstate.io_length) { - THROW(SW_WRONG_LENGTH); + // sign + if (ksz < G_gpg_vstate.io_length) { + THROW(SW_WRONG_LENGTH); + } + l = ksz - G_gpg_vstate.io_length; + memmove(G_gpg_vstate.work.io_buffer + l, + G_gpg_vstate.work.io_buffer, + G_gpg_vstate.io_length); + 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; } - l = ksz - G_gpg_vstate.io_length; - memmove(G_gpg_vstate.work.io_buffer + l, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length); - 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, info; - unsigned char * rs; + // --- 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, info; + unsigned char *rs; - key = &sigkey->priv_key.ecfp; + 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 = (unsigned int) 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, &info); - // reencode r,s in MPI format - gpg_io_discard(0); + if (sigkey->attributes.value[0] == 19) { + sz = (unsigned int) 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, + &info); + // reencode r,s in MPI format + gpg_io_discard(0); - rs_len = RS[3]; - rs = &RS[4]; + rs_len = RS[3]; + rs = &RS[4]; - for (i = 0; i < 2; i++) { - if (*rs == 0) { - rs++; - rs_len--; + 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; + } + } 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; - } - } 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); - } #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; + // 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; - unsigned int sz; + unsigned int pso; + unsigned int sz; - 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) { - // --- PSO:CDS --- - case 0x9e9a: - if (G_gpg_vstate.kslot->sig.UIF[0]) { - if ((G_gpg_vstate.UIF_flags) == 0) { - ui_menu_uifconfirm_display(0); - return 0; - } - G_gpg_vstate.UIF_flags = 0; - } - break; - // --- PSO:DEC --- - case 0x8086: - case 0x8680: - if (G_gpg_vstate.kslot->dec.UIF[0]) { - if ((G_gpg_vstate.UIF_flags) == 0) { - ui_menu_uifconfirm_display(0); - return 0; - } - G_gpg_vstate.UIF_flags = 0; + // UIF HANDLE + switch (pso) { + // --- PSO:CDS --- + case 0x9e9a: + if (G_gpg_vstate.kslot->sig.UIF[0]) { + if ((G_gpg_vstate.UIF_flags) == 0) { + ui_menu_uifconfirm_display(0); + return 0; + } + G_gpg_vstate.UIF_flags = 0; + } + break; + // --- PSO:DEC --- + case 0x8086: + case 0x8680: + if (G_gpg_vstate.kslot->dec.UIF[0]) { + if ((G_gpg_vstate.UIF_flags) == 0) { + ui_menu_uifconfirm_display(0); + return 0; + } + G_gpg_vstate.UIF_flags = 0; + } + break; } - break; - } - // --- PSO:ENC --- - 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)); - return sw; - } - // --- PSO:ENC --- - case 0x8680: { - unsigned int msg_len; - cx_aes_key_t *key; - key = &G_gpg_vstate.kslot->AES_dec; - if (!(key->size != 16)) { - 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 - gpg_io_discard(0); - G_gpg_vstate.work.io_buffer[0] = 0x02; - gpg_io_inserted(1 + sz); - return SW_OK; - } + // --- PSO:ENC --- + 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)); + return sw; + } + // --- PSO:ENC --- + case 0x8680: { + unsigned int msg_len; + cx_aes_key_t *key; + key = &G_gpg_vstate.kslot->AES_dec; + if (!(key->size != 16)) { + 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 + gpg_io_discard(0); + G_gpg_vstate.work.io_buffer[0] = 0x02; + gpg_io_inserted(1 + sz); + return SW_OK; + } - // --- PSO:DEC --- - case 0x8086: { - unsigned int msg_len; - unsigned int pad_byte; - pad_byte = gpg_io_fetch_u8(); + // --- PSO:DEC --- + case 0x8086: { + unsigned int msg_len; + unsigned int pad_byte; + pad_byte = gpg_io_fetch_u8(); - switch (pad_byte) { - // --- PSO:DEC:RSA - case 0x00: { - cx_rsa_private_key_t *key; - if (G_gpg_vstate.mse_dec->attributes.value[0] != 0x01) { - 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; - 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 (pad_byte) { + // --- PSO:DEC:RSA + case 0x00: { + cx_rsa_private_key_t *key; + if (G_gpg_vstate.mse_dec->attributes.value[0] != 0x01) { + 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; + 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; + } - 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 - gpg_io_discard(0); - gpg_io_inserted(sz); - return SW_OK; - } + 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 + gpg_io_discard(0); + gpg_io_inserted(sz); + return SW_OK; + } - // --- PSO:DEC:AES - case 0x02: { - cx_aes_key_t *key; - key = &G_gpg_vstate.kslot->AES_dec; - if (!(key->size != 16)) { - 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 - gpg_io_discard(0); - gpg_io_inserted(sz); - return SW_OK; - } + // --- PSO:DEC:AES + case 0x02: { + cx_aes_key_t *key; + key = &G_gpg_vstate.kslot->AES_dec; + if (!(key->size != 16)) { + 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 + gpg_io_discard(0); + gpg_io_inserted(sz); + return SW_OK; + } - // --- PSO:DEC:ECDH - case 0xA6: { - cx_ecfp_private_key_t *key; - unsigned int curve; - if (G_gpg_vstate.mse_dec->attributes.value[0] != 0x12) { - THROW(SW_CONDITIONS_NOT_SATISFIED); - return SW_CONDITIONS_NOT_SATISFIED; - } - key = &G_gpg_vstate.mse_dec->priv_key.ecfp; - gpg_io_fetch_l(&l); - gpg_io_fetch_tl(&t, &l); - if (t != 0x7f49) { - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } - gpg_io_fetch_tl(&t, &l); - if (t != 0x86) { - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } + // --- PSO:DEC:ECDH + case 0xA6: { + cx_ecfp_private_key_t *key; + unsigned int curve; - curve = gpg_oid2curve(G_gpg_vstate.mse_dec->attributes.value + 1, G_gpg_vstate.mse_dec->attributes.length - 1); - if (key->curve != curve) { - THROW(SW_CONDITIONS_NOT_SATISFIED); - return SW_CONDITIONS_NOT_SATISFIED; - } - if (curve == CX_CURVE_Curve25519) { - unsigned int i; + if (G_gpg_vstate.mse_dec->attributes.value[0] != 0x12) { + THROW(SW_CONDITIONS_NOT_SATISFIED); + return SW_CONDITIONS_NOT_SATISFIED; + } + key = &G_gpg_vstate.mse_dec->priv_key.ecfp; + gpg_io_fetch_l(&l); + gpg_io_fetch_tl(&t, &l); + if (t != 0x7f49) { + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } + gpg_io_fetch_tl(&t, &l); + if (t != 0x86) { + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } - 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]; + curve = gpg_oid2curve(G_gpg_vstate.mse_dec->attributes.value + 1, + G_gpg_vstate.mse_dec->attributes.length - 1); + if (key->curve != curve) { + THROW(SW_CONDITIONS_NOT_SATISFIED); + return SW_CONDITIONS_NOT_SATISFIED; + } + if (curve == CX_CURVE_Curve25519) { + 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]; + } + 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 = 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); + } + // send + gpg_io_discard(0); + gpg_io_insert(G_gpg_vstate.work.io_buffer + 128, sz); + return SW_OK; + } + + // --- PSO:DEC:xx NOT SUPPORTED + default: + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return SW_REFERENCED_DATA_NOT_FOUND; + } } - 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); - } - // send - gpg_io_discard(0); - gpg_io_insert(G_gpg_vstate.work.io_buffer + 128, sz); - return SW_OK; - } - // --- PSO:DEC:xx NOT SUPPORTDED - default: - THROW(SW_REFERENCED_DATA_NOT_FOUND); - return SW_REFERENCED_DATA_NOT_FOUND; + //--- PSO:yy NOT SUPPORTED --- + default: + THROW(SW_REFERENCED_DATA_NOT_FOUND); + return SW_REFERENCED_DATA_NOT_FOUND; } - } - - //--- PSO:yy NOT SUPPPORTED --- - 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; } int gpg_apdu_internal_authenticate() { - // --- PSO:AUTH --- - if (G_gpg_vstate.kslot->aut.UIF[0]) { - if ((G_gpg_vstate.UIF_flags) == 0) { - ui_menu_uifconfirm_display(0); - return 0; + // --- PSO:AUTH --- + if (G_gpg_vstate.kslot->aut.UIF[0]) { + if ((G_gpg_vstate.UIF_flags) == 0) { + ui_menu_uifconfirm_display(0); + return 0; + } + G_gpg_vstate.UIF_flags = 0; } - G_gpg_vstate.UIF_flags = 0; - } - 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) { - THROW(SW_WRONG_LENGTH); - return SW_WRONG_LENGTH; + 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) { + THROW(SW_WRONG_LENGTH); + return SW_WRONG_LENGTH; + } } - } - return gpg_sign(G_gpg_vstate.mse_aut); + return gpg_sign(G_gpg_vstate.mse_aut); } diff --git a/src/gpg_ram.c b/src/gpg_ram.c index 5b58016..721d55c 100644 --- a/src/gpg_ram.c +++ b/src/gpg_ram.c @@ -22,21 +22,21 @@ #ifndef TARGET_NANOS #include "ux.h" -ux_state_t G_ux; +ux_state_t G_ux; bolos_ux_params_t G_ux_params; #else -ux_state_t ux; +ux_state_t ux; #endif #ifndef GPG_DEBUG_MAIN unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; #else extern unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; -int apdu_n; +int apdu_n; #endif gpg_v_state_t G_gpg_vstate; #ifdef HAVE_RSA union cx_u G_cx; -#endif // HAVE_RSA +#endif // HAVE_RSA diff --git a/src/gpg_select.c b/src/gpg_select.c index ff6de5a..0285fb1 100644 --- a/src/gpg_select.c +++ b/src/gpg_select.c @@ -21,37 +21,39 @@ const unsigned char C_MF[] = {0x3F, 0x00}; int gpg_apdu_select() { - int sw; + int sw; - // MF - if ((G_gpg_vstate.io_length == 2) && (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) && - (memcmp(G_gpg_vstate.work.io_buffer, (const void *)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) { - 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; + // MF + if ((G_gpg_vstate.io_length == 2) && + (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) && (memcmp(G_gpg_vstate.work.io_buffer, + (const void *) 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) { + 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; + } - gpg_io_discard(0); - if (N_gpg_pstate->histo[7] != 0x07) { - THROW(SW_STATE_TERMINATED); + gpg_io_discard(0); + if (N_gpg_pstate->histo[7] != STATE_ACTIVATE) { + THROW(SW_STATE_TERMINATED); + } + sw = SW_OK; } - sw = SW_OK; - } - // NOT FOUND - else { - THROW(SW_FILE_NOT_FOUND); - return SW_FILE_NOT_FOUND; - } - return sw; + // NOT FOUND + else { + THROW(SW_FILE_NOT_FOUND); + return SW_FILE_NOT_FOUND; + } + return sw; } diff --git a/src/gpg_types.h b/src/gpg_types.h index ec89bf2..27b7bb2 100644 --- a/src/gpg_types.h +++ b/src/gpg_types.h @@ -26,11 +26,11 @@ /* big private DO */ #define GPG_EXT_PRIVATE_DO_LENGTH 512 -/* will be fixed..1024 is not enougth */ +/* will be fixed..1024 is not enough */ #define GPG_EXT_CARD_HOLDER_CERT_LENTH 2560 /* random choice */ #define GPG_EXT_CHALLENGE_LENTH 254 -/* accpet long PW, but less than one sha256 block */ +/* accept long PW, but less than one sha256 block */ #define GPG_MAX_PW_LENGTH 12 #if GPG_MULTISLOT @@ -44,137 +44,137 @@ #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 char value[32]; + 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]; \ - } name +#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); - /* 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; - } 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; - } pub_key; - /* C7 C8 C9 , C5 = C7|C8|C9*/ - unsigned char fingerprints[20]; - /* 7F21 */ - 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 */ - unsigned char date[4]; - /* D6/D7/D8- */ - unsigned char UIF[2]; + /* C1 C2 C3 */ + 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; + } 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; + } pub_key; + /* C7 C8 C9 , C5 = C7|C8|C9*/ + unsigned char fingerprints[20]; + /* 7F21 */ + 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 */ + unsigned char date[4]; + /* D6/D7/D8- */ + unsigned char UIF[2]; } gpg_key_t; typedef struct gpg_key_slot_s { - unsigned char serial[4]; - /* */ - gpg_key_t sig; - gpg_key_t aut; - gpg_key_t dec; - /* -- Security support template -- */ - /* 93 */ - unsigned int sig_count; - /* D5 */ - cx_aes_key_t AES_dec; + unsigned char serial[4]; + /* */ + gpg_key_t sig; + gpg_key_t aut; + gpg_key_t dec; + /* -- Security support template -- */ + /* 93 */ + unsigned int sig_count; + /* D5 */ + cx_aes_key_t AES_dec; } gpg_key_slot_t; struct gpg_nv_state_s { - /* magic */ - unsigned char magic[8]; - - /* pin mode */ - unsigned char config_pin[1]; - - /* 01F1 (01F2 is volatile)*/ - unsigned char config_slot[3]; - /* RSA exponent */ - unsigned char default_RSA_exponent[4]; - - /* 0101 0102 0103 0104 */ - LV(private_DO1, GPG_EXT_PRIVATE_DO_LENGTH); - LV(private_DO2, GPG_EXT_PRIVATE_DO_LENGTH); - LV(private_DO3, GPG_EXT_PRIVATE_DO_LENGTH); - LV(private_DO4, GPG_EXT_PRIVATE_DO_LENGTH); - - /* 5E */ - LV(login, GPG_EXT_PRIVATE_DO_LENGTH); - /* 5F50 */ - LV(url, GPG_EXT_PRIVATE_DO_LENGTH); - - /* -- Cardholder Related Data -- */ - /* 5B */ - LV(name, 39); - /* 5F2D */ - LV(lang, 8); - /* 5F35 */ - unsigned char sex[1]; - - /* -- Application Related Data -- */ - /* 4F */ - unsigned char AID[16]; - /* 5F52 */ - unsigned char histo[15]; - /* 7f66 */ - // unsigned char ext_length_info[8]; - /* C0 */ - // unsigned char ext_capabilities[10]; - - /* C4 */ - unsigned char PW_status[4]; - - /* PINs */ - gpg_pin_t PW1; - gpg_pin_t PW3; - gpg_pin_t RC; - - /* gpg keys */ - gpg_key_slot_t keys[GPG_KEYS_SLOTS]; - - /* --- SM --- */ - /* D1 */ - cx_aes_key_t SM_enc; - /* D2 */ - cx_aes_key_t SM_mac; + /* magic */ + unsigned char magic[8]; + + /* pin mode */ + unsigned char config_pin[1]; + + /* 01F1 (01F2 is volatile)*/ + unsigned char config_slot[3]; + /* RSA exponent */ + unsigned char default_RSA_exponent[4]; + + /* 0101 0102 0103 0104 */ + LV(private_DO1, GPG_EXT_PRIVATE_DO_LENGTH); + LV(private_DO2, GPG_EXT_PRIVATE_DO_LENGTH); + LV(private_DO3, GPG_EXT_PRIVATE_DO_LENGTH); + LV(private_DO4, GPG_EXT_PRIVATE_DO_LENGTH); + + /* 5E */ + LV(login, GPG_EXT_PRIVATE_DO_LENGTH); + /* 5F50 */ + LV(url, GPG_EXT_PRIVATE_DO_LENGTH); + + /* -- Cardholder Related Data -- */ + /* 5B */ + LV(name, 39); + /* 5F2D */ + LV(lang, 8); + /* 5F35 */ + unsigned char sex[1]; + + /* -- Application Related Data -- */ + /* 4F */ + unsigned char AID[16]; + /* 5F52 */ + unsigned char histo[15]; + /* 7f66 */ + // unsigned char ext_length_info[8]; + /* C0 */ + // unsigned char ext_capabilities[10]; + + /* C4 */ + unsigned char PW_status[4]; + + /* PINs */ + gpg_pin_t PW1; + gpg_pin_t PW3; + gpg_pin_t RC; + + /* gpg keys */ + gpg_key_slot_t keys[GPG_KEYS_SLOTS]; + + /* --- SM --- */ + /* D1 */ + cx_aes_key_t SM_enc; + /* D2 */ + cx_aes_key_t SM_mac; }; typedef struct gpg_nv_state_s gpg_nv_state_t; @@ -182,105 +182,106 @@ typedef struct gpg_nv_state_s gpg_nv_state_t; #define GPG_IO_BUFFER_LENGTH (1512) 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; - unsigned char seed_mode; - - 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; - union { - unsigned char io_buffer[GPG_IO_BUFFER_LENGTH]; - struct { - union { - 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_1024_private_key_t private1024; - cx_rsa_2048_private_key_t private2048; - cx_rsa_3072_private_key_t private3072; - cx_rsa_4096_private_key_t private4096; - }; - } rsa; - - struct { - 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; - }; - } ecfp; - - struct { - unsigned char md_buffer[GPG_IO_BUFFER_LENGTH - (32 + MAX(sizeof(cx_sha3_t), sizeof(cx_sha256_t)))]; - unsigned char H[32]; - union { - cx_sha3_t sha3; - cx_sha256_t sha256; - }; - } md; - } work; - - /* data state */ - unsigned short DO_current; - unsigned short DO_reccord; - unsigned short DO_offset; - - /* PINs state */ - unsigned char verified_pin[5]; - unsigned char pinmode; - - /* ux menus */ - char menu[112]; - unsigned char ux_pinentry[12]; - unsigned int ux_key; - unsigned int ux_type; + /* 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; + unsigned char seed_mode; + + 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; + union { + unsigned char io_buffer[GPG_IO_BUFFER_LENGTH]; + struct { + union { + 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_1024_private_key_t private1024; + cx_rsa_2048_private_key_t private2048; + cx_rsa_3072_private_key_t private3072; + cx_rsa_4096_private_key_t private4096; + }; + } rsa; + + struct { + 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; + }; + } ecfp; + + struct { + unsigned char md_buffer[GPG_IO_BUFFER_LENGTH - + (32 + MAX(sizeof(cx_sha3_t), sizeof(cx_sha256_t)))]; + unsigned char H[32]; + union { + cx_sha3_t sha3; + cx_sha256_t sha256; + }; + } md; + } work; + + /* data state */ + unsigned short DO_current; + unsigned short DO_reccord; + unsigned short DO_offset; + + /* PINs state */ + unsigned char verified_pin[5]; + unsigned char pinmode; + + /* ux menus */ + char menu[112]; + unsigned char ux_pinentry[12]; + unsigned int ux_key; + unsigned int ux_type; #ifdef UI_NANO_S - ux_menu_entry_t ui_dogsays[2]; + 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]; + char ux_buff1[32]; + char ux_buff2[32]; + char ux_buff3[32]; + char ux_buff4[32]; + char ux_buff5[32]; #endif - #ifdef GPG_LOG +#ifdef GPG_LOG unsigned char log_buffer[32]; - #endif +#endif #ifdef GPG_DEBUG - unsigned char print; + unsigned char print; #endif }; typedef struct gpg_v_state_s gpg_v_state_t; @@ -290,29 +291,29 @@ typedef struct gpg_v_state_s gpg_v_state_t; #define ERROR(x) ((x) << 16) #define ERROR_IO_OFFSET ERROR(1) -#define ERROR_IO_FULL ERROR(2) +#define ERROR_IO_FULL ERROR(2) /* --- IDentifiers --- */ #define ID_AUTH 1 -#define ID_DEC 2 -#define ID_SIG 3 +#define ID_DEC 2 +#define ID_SIG 3 -#define STATE_ACTIVATE 0x07 +#define STATE_ACTIVATE 0x07 #define STATE_TERMINATE 0x03 -#define IO_OFFSET_END (unsigned int)-1 -#define IO_OFFSET_MARK (unsigned int)-2 +#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_ID_RC 0x84 -#define PIN_MODE_HOST 1 -#define PIN_MODE_SCREEN 2 +#define PIN_MODE_HOST 1 +#define PIN_MODE_SCREEN 2 #define PIN_MODE_CONFIRM 3 -#define PIN_MODE_TRUST 4 +#define PIN_MODE_TRUST 4 /* --- INS --- */ #define INS_EXIT 0x02 @@ -320,73 +321,73 @@ typedef struct gpg_v_state_s gpg_v_state_t; #define INS_GET_LOG 0x04 #endif -#define INS_SELECT 0xa4 -#define INS_TERMINATE_DF 0xe6 +#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_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_PUT_DATA 0xda +#define INS_PUT_DATA_ODD 0xdb -#define INS_VERIFY 0x20 -#define INS_MSE 0x22 +#define INS_VERIFY 0x20 +#define INS_MSE 0x22 #define INS_CHANGE_REFERENCE_DATA 0x24 -#define INS_RESET_RETRY_COUNTER 0x2c +#define INS_RESET_RETRY_COUNTER 0x2c #define INS_GEN_ASYM_KEYPAIR 0x47 -#define INS_PSO 0x2a -//#define INS_COMPUTEDIGSIG 0x2a -//#define INS_DECIPHER 0x2a +#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_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_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_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_STATE_TERMINATED 0x6285 #define SW_MORE_DATA_AVAILABLE 0x6310 #define SW_WRONG_LENGTH 0x6700 -#define SW_LOGICAL_CHANNEL_NOT_SUPPORTED 0x6881 +#define SW_LOGICAL_CHANNEL_NOT_SUPPORTED 0x6881 #define SW_SECURE_MESSAGING_NOT_SUPPORTED 0x6882 -#define SW_LAST_COMMAND_EXPECTED 0x6883 +#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_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_WRONG_P1P2 0x6b00 #define SW_CORRECT_LENGTH_00 0x6c00 #define SW_INS_NOT_SUPPORTED 0x6d00 #define SW_CLA_NOT_SUPPORTED 0x6e00 diff --git a/src/gpg_ux_msg.c b/src/gpg_ux_msg.c index f60d7fd..ea0c4ca 100644 --- a/src/gpg_ux_msg.c +++ b/src/gpg_ux_msg.c @@ -13,24 +13,24 @@ * limitations under the License. */ -const char *const C_TEMPLATE_TYPE = "Key type"; -const char *const C_TEMPLATE_KEY = "Key"; +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_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_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_PIN_USER = "User PIN"; +const char *const C_PIN_ADMIN = "Admin PIN"; -const char *const C_VERIFIED = "Verified"; +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_ALLOWED = "Allowed"; +const char *const C_NOT_ALLOWED = "Not Allowed "; const char *const C_DEFAULT_MODE = "Default mode"; diff --git a/src/gpg_ux_msg.h b/src/gpg_ux_msg.h index 7e4fa32..ade9c3f 100644 --- a/src/gpg_ux_msg.h +++ b/src/gpg_ux_msg.h @@ -39,25 +39,25 @@ extern const char *const C_DEFAULT_MODE; extern const char *const C_UIF_LOCKED; extern const char *const C_UIF_INVALID; -#define PICSTR(x) ((char *)PIC(x)) +#define PICSTR(x) ((char *) PIC(x)) -#define TEMPLATE_TYPE PICSTR(C_TEMPLATE_TYPE) -#define TEMPLATE_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 fcee0d5..a66a583 100644 --- a/src/gpg_ux_nanos.c +++ b/src/gpg_ux_nanos.c @@ -32,62 +32,66 @@ /* ----------------------------------------------------------------------- */ 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); +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_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) { - io_usb_ccid_set_card_inserted(0); - io_usb_ccid_set_card_inserted(1); + io_usb_ccid_set_card_inserted(0); + io_usb_ccid_set_card_inserted(1); } void ui_info(const char *msg1, const char *msg2, const void *menu_display, unsigned int value) { - 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; - - memset(&G_gpg_vstate.ui_dogsays[1], 0, sizeof(ux_menu_entry_t)); - UX_MENU_DISPLAY(0, G_gpg_vstate.ui_dogsays, NULL); + 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; + + 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 ----------------------------- */ @@ -95,375 +99,469 @@ unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int b 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}, - - {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, - NULL}, - - {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, - NULL}, - - {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + // 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}, + + {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, NULL}, + + {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, 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}, - {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + {{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}, }; void ui_menu_uifconfirm_display(unsigned int value) { - UNUSED(value); - UX_DISPLAY(ui_uifconfirm_nanos, (void *)ui_uifconfirm_prepro); + UNUSED(value); + UX_DISPLAY(ui_uifconfirm_nanos, (void *) ui_uifconfirm_prepro); } unsigned int ui_uifconfirm_prepro(const bagl_element_t *element) { - if (element->component.userid == 1) { - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Confirm:"); - return 1; - } - if (element->component.userid == 2) { - unsigned int uif_case = (G_gpg_vstate.io_ins << 16) | (G_gpg_vstate.io_p1 << 8) | (G_gpg_vstate.io_p2); - switch (uif_case) { - case 0x002A9E9A: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Signature"); - return 1; - case 0x002A8680: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Encryption"); - return 1; - case 0x002A8086: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Decryption"); - return 1; - case 0x00880000: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Authentication"); - return 1; + if (element->component.userid == 1) { + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Confirm:"); + return 1; } - } - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Please Cancel"); - return 1; + if (element->component.userid == 2) { + unsigned int uif_case = + (G_gpg_vstate.io_ins << 16) | (G_gpg_vstate.io_p1 << 8) | (G_gpg_vstate.io_p2); + switch (uif_case) { + case 0x002A9E9A: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Signature"); + return 1; + case 0x002A8680: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Encryption"); + return 1; + case 0x002A8086: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Decryption"); + return 1; + case 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; } -unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int button_mask_counter) { - UNUSED(button_mask_counter); - unsigned int sw; +unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, + unsigned int button_mask_counter) { + UNUSED(button_mask_counter); + unsigned int sw; - sw = 0x6985; - switch (button_mask) { - case BUTTON_EVT_RELEASED | BUTTON_LEFT: // CANCEL - gpg_io_discard(1); - gpg_io_insert_u16(sw); - gpg_io_do(IO_RETURN_AFTER_TX); - ui_menu_main_display(0); sw = 0x6985; - break; - - case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // OK - BEGIN_TRY { - TRY { - G_gpg_vstate.UIF_flags = 1; - if (G_gpg_vstate.io_ins == INS_PSO) { - sw = gpg_apdu_pso(); - } else if (G_gpg_vstate.io_ins == INS_INTERNAL_AUTHENTICATE) { - sw = gpg_apdu_internal_authenticate(); - } else { - gpg_io_discard(1); - sw = 0x6985; - } - } - CATCH_OTHER(e) { - gpg_io_discard(1); - if ((e & 0xFFFF0000) || (((e & 0xF000) != 0x6000) && ((e & 0xF000) != 0x9000))) { - gpg_io_insert_u32(e); - sw = 0x6f42; - } else { - sw = e; - } - } - FINALLY { - G_gpg_vstate.UIF_flags = 0; - gpg_io_insert_u16(sw); - gpg_io_do(IO_RETURN_AFTER_TX); - ui_menu_main_display(0); - } - break; + switch (button_mask) { + case BUTTON_EVT_RELEASED | BUTTON_LEFT: // CANCEL + gpg_io_discard(1); + gpg_io_insert_u16(sw); + gpg_io_do(IO_RETURN_AFTER_TX); + ui_menu_main_display(0); + sw = 0x6985; + break; + + case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // OK + BEGIN_TRY { + TRY { + G_gpg_vstate.UIF_flags = 1; + if (G_gpg_vstate.io_ins == INS_PSO) { + sw = gpg_apdu_pso(); + } else if (G_gpg_vstate.io_ins == INS_INTERNAL_AUTHENTICATE) { + sw = gpg_apdu_internal_authenticate(); + } else { + gpg_io_discard(1); + sw = 0x6985; + } + } + CATCH_OTHER(e) { + gpg_io_discard(1); + if ((e & 0xFFFF0000) || + (((e & 0xF000) != 0x6000) && ((e & 0xF000) != 0x9000))) { + gpg_io_insert_u32(e); + sw = 0x6f42; + } else { + sw = e; + } + } + FINALLY { + G_gpg_vstate.UIF_flags = 0; + gpg_io_insert_u16(sw); + gpg_io_do(IO_RETURN_AFTER_TX); + ui_menu_main_display(0); + } + break; + } + END_TRY; } - END_TRY; - } - return 0; + return 0; } /* ------------------------------ 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}, - - {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, - NULL}, - - {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, - NULL}, - - {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + // 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}, + + {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, NULL}, + + {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, 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}, - {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + {{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}, }; void ui_menu_pinconfirm_display(unsigned int value) { - UNUSED(value); - UX_DISPLAY(ui_pinconfirm_nanos, (void *)ui_pinconfirm_prepro); + UNUSED(value); + UX_DISPLAY(ui_pinconfirm_nanos, (void *) ui_pinconfirm_prepro); } 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 == 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); - 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); + return 1; + } } - } - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Please Cancel"); - return 1; + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Please Cancel"); + return 1; } -unsigned int ui_pinconfirm_nanos_button(unsigned int button_mask, unsigned int button_mask_counter) { - UNUSED(button_mask_counter); - unsigned int sw; +unsigned int ui_pinconfirm_nanos_button(unsigned int button_mask, + unsigned int button_mask_counter) { + UNUSED(button_mask_counter); + 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; - break; - - case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // OK - gpg_pin_set_verified(G_gpg_vstate.io_p2, 1); - sw = 0x9000; - break; - default: + 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; + break; + default: + return 0; + } + gpg_io_discard(0); + gpg_io_insert_u16(sw); + gpg_io_do(IO_RETURN_AFTER_TX); + ui_menu_main_display(0); return 0; - } - 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 - {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, - NULL}, - - {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_DOWN}, - NULL}, - - {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_UP}, - NULL}, - - {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + // 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}, + + {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_DOWN}, NULL}, + + {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_UP}, 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}, - {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, + {{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}, }; 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) { - 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); + if (value == 0) { + 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 (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++; + 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] = '-'; + 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; + return 1; } unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int button_mask_counter) { - UNUSED(button_mask_counter); - unsigned int offset = G_gpg_vstate.ux_pinentry[0]; - char digit; - - 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 == '<') { - if (offset > 1) { - offset--; - G_gpg_vstate.ux_pinentry[0] = offset; - } - ui_menu_pinentry_display(1); + UNUSED(button_mask_counter); + unsigned int offset = G_gpg_vstate.ux_pinentry[0]; + char digit; + + 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 == '<') { + 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; } - // 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; + 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]]; - } + unsigned int offset, len, sw; + gpg_pin_t *pin; - 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); + 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 == 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) { + 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_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]) || - (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_insert_u16(sw); 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); + 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]) || + (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; + return 0; } /* ------------------------------- template UX ------------------------------- */ @@ -471,189 +569,192 @@ static unsigned int validate_pin() { #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_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_BPOOL256R1 "Brainpool 256R1" -//#define LABEL_BPOOL384R1 "Brainpool 384R1" -//#define LABEL_BPOOL512R1 "Brainpool 512R1" +// #define LABEL_NISTP384 "NIST P384" +// #define LABEL_NISTP521 "NIST P521" +#define LABEL_SECP256K1 "SECP 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}; +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) { - if (entry == &ui_menu_template[0]) { - switch (G_gpg_vstate.ux_key) { - case 1: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s", LABEL_SIG); - break; - case 2: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s", LABEL_DEC); - break; - 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; - } - if (entry == &ui_menu_template[1]) { - switch (G_gpg_vstate.ux_type) { - case 2048: - 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); - break; - case 4096: - 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); - break; - /* - case CX_CURVE_SECP384R1: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_NISTP384); - break; - case CX_CURVE_SECP521R1: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_NISTP521); - break; - case CX_CURVE_SECP256K1: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_SECP256K1); - break; - */ - /* - case CX_CURVE_BrainPoolP256R1: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOL256R1); - break; - case CX_CURVE_BrainPoolP384R1: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOL384R1); - break; - case CX_CURVE_BrainPoolP512R1: - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOL512R1); - break; - */ - - case CX_CURVE_Ed25519: - 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; +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: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s", LABEL_SIG); + break; + case 2: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s", LABEL_DEC); + break; + 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; + } + if (entry == &ui_menu_template[1]) { + switch (G_gpg_vstate.ux_type) { + case 2048: + 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); + break; + case 4096: + 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); + break; + /* + case CX_CURVE_SECP384R1: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_NISTP384); + break; + case CX_CURVE_SECP521R1: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_NISTP521); + break; + case CX_CURVE_SECP256K1: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_SECP256K1); + break; + */ + /* + case CX_CURVE_BrainPoolP256R1: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOL256R1); + break; + case CX_CURVE_BrainPoolP384R1: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOL384R1); + break; + case CX_CURVE_BrainPoolP512R1: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu)," %s", LABEL_BPOOL512R1); + break; + */ + + case CX_CURVE_Ed25519: + 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) { - UNUSED(value); - LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH); - gpg_key_t * dest; - const char * err; - const unsigned char *oid; - unsigned int oid_len; - err = NULL; - - 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: - // 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 + UNUSED(value); + LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH); + gpg_key_t *dest; + const char *err; + const unsigned char *oid; + unsigned int oid_len; + err = NULL; + + 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: + // 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 + } + oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len); + 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 + memmove(attributes.value + 1, C_OID_cv25519, sizeof(C_OID_cv25519)); + attributes.length = 1 + sizeof(C_OID_cv25519); + } else { + attributes.value[0] = 22; // eddsa + 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; } - oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len); - 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 - memmove(attributes.value + 1, C_OID_cv25519, sizeof(C_OID_cv25519)); - attributes.length = 1 + sizeof(C_OID_cv25519); - } else { - attributes.value[0] = 22; // eddsa - memmove(attributes.value + 1, C_OID_Ed25519, sizeof(C_OID_Ed25519)); - attributes.length = 1 + sizeof(C_OID_Ed25519); + + 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; } - 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; + + 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); + 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); + G_gpg_vstate.ux_key = value; + ui_menu_template_display(0); } const ux_menu_entry_t ui_menu_tmpl_type[] = { @@ -661,53 +762,61 @@ const ux_menu_entry_t ui_menu_tmpl_type[] = { {NULL, ui_menu_tmpl_type_action, 3072, NULL, LABEL_RSA3072, NULL, 0, 0}, {NULL, ui_menu_tmpl_type_action, 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_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); + G_gpg_vstate.ux_type = value; + 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); + 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"); - element->text = G_gpg_vstate.menu; +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; + return element; } void ui_menu_seed_action(unsigned int value) { - G_gpg_vstate.seed_mode = value; - ui_menu_seed_display(0); + G_gpg_vstate.seed_mode = 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}, @@ -720,188 +829,202 @@ const ux_menu_entry_t ui_menu_pinmode[] = { 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; - element->component.height = 32; +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; + } } - } - return element; + return element; } void ui_menu_pinmode_action(unsigned int value) { - unsigned char s; - 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; - } - // set new mode - s = G_gpg_vstate.pinmode; - 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 = 3; - } - //#warning USBD_CCID_activate_pinpad commented - USBD_CCID_activate_pinpad(s); - } - } 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; + unsigned char s; + 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; + } + // set new mode + s = G_gpg_vstate.pinmode; + 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 = 3; + } + // #warning USBD_CCID_activate_pinpad commented + USBD_CCID_activate_pinpad(s); + } + } 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; } - G_gpg_vstate.pinmode = value; - } - // redisplay first entry of the idle menu - ui_menu_pinmode_display(0); + // redisplay first entry of the idle menu + 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]; - uif[0] = 0; - uif[1] = 0; - switch (entry->userid) { - case 1: - *uif = G_gpg_vstate.kslot->sig.UIF[0] ? '+' : ' '; - break; - case 2: - *uif = G_gpg_vstate.kslot->dec.UIF[0] ? '+' : ' '; - break; - case 3: - *uif = G_gpg_vstate.kslot->aut.UIF[0] ? '+' : ' '; - break; - } - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s %s", (char *)PIC(entry->line1), uif); - element->text = G_gpg_vstate.menu; - element->component.height = 32; +const bagl_element_t *ui_menu_uifmode_preprocessor(const ux_menu_entry_t *entry, + bagl_element_t *element) { + if (element->component.userid == 0x20) { + if ((entry->userid >= 1) && (entry->userid <= 3)) { + unsigned char uif[2]; + uif[0] = 0; + uif[1] = 0; + switch (entry->userid) { + case 1: + *uif = G_gpg_vstate.kslot->sig.UIF[0] ? '+' : ' '; + break; + case 2: + *uif = G_gpg_vstate.kslot->dec.UIF[0] ? '+' : ' '; + break; + case 3: + *uif = G_gpg_vstate.kslot->aut.UIF[0] ? '+' : ' '; + break; + } + snprintf(G_gpg_vstate.menu, + sizeof(G_gpg_vstate.menu), + "%s %s", + (char *) PIC(entry->line1), + uif); + element->text = G_gpg_vstate.menu; + element->component.height = 32; + } } - } - return element; + return element; } void ui_menu_uifmode_action(unsigned int value) { - unsigned char *uif; - unsigned char new_uif; - switch (value) { - case 1: - uif = &G_gpg_vstate.kslot->sig.UIF[0]; - break; - case 2: - uif = &G_gpg_vstate.kslot->dec.UIF[0]; - break; - case 3: - uif = &G_gpg_vstate.kslot->aut.UIF[0]; - break; - default: - ui_info(INVALID_SELECTION, NULL, ui_menu_uifmode_display, 0); - return; - } - if (uif[0] == 0) { - new_uif = 1; - gpg_nvm_write(&uif[0], &new_uif, 1); - } else if (uif[0] == 1) { - new_uif = 0; - gpg_nvm_write(&uif[0], &new_uif, 1); - } else /*if (uif[0] == 2 )*/ { - ui_info(UIF_LOCKED, NULL, ui_menu_uifmode_display, 0); - return; - } - ui_menu_uifmode_display(value); + 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) { - UNUSED(value); - unsigned char magic[4]; - 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(); - ui_menu_main_display(0); + UNUSED(value); + unsigned char magic[4]; + 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(); + ui_menu_main_display(0); } /* ------------------------------ RESET KEY SLOT ----------------------------- */ void ui_menu_reset_slot_action(unsigned int value); -const ux_menu_entry_t ui_menu_reset_slot[] = {{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_slot_action, 0, NULL, "Yes", NULL, 0, 0}, - UX_MENU_END}; +const ux_menu_entry_t ui_menu_reset_slot[] = { + {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_slot_action, 0, NULL, "Yes", NULL, 0, 0}, + UX_MENU_END}; void ui_menu_reset_slot_action(unsigned int value) { - UNUSED(value); - gpg_install_slot(G_gpg_vstate.kslot); - ui_menu_main_display(0); + UNUSED(value); + gpg_install_slot(G_gpg_vstate.kslot); + ui_menu_main_display(0); } - /* ------------------------------- 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 App", NULL, 0, 0}, - {ui_menu_reset_slot, NULL, 0, NULL, "Reset Slot", 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 App", NULL, 0, 0}, + {ui_menu_reset_slot, NULL, 0, NULL, "Reset Slot", NULL, 0, 0}, + {NULL, ui_menu_main_display, 2, &C_badge_back, "Back", NULL, 61, 40}, + UX_MENU_END}; /* --------------------------------- SLOT UX --------------------------------- */ @@ -910,122 +1033,134 @@ const ux_menu_entry_t ui_menu_settings[] = {{NULL, ui_menu_template_display, 0, #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) { - unsigned int 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*/); - element->text = G_gpg_vstate.menu; +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 (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*/); + element->text = G_gpg_vstate.menu; + } } - } - return element; + return element; } 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); - 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(); + unsigned char s; + + 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(); + } } - } - // redisplay first entry of the idle menu - ui_menu_slot_display(value); + // redisplay first entry of the idle menu + ui_menu_slot_display(value); } #endif /* --------------------------------- 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(OPENPGP_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}, +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}, + {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, (void*)os_sched_exit, 0, &C_icon_dashboard, "Quit app", NULL, 50, 29}, - UX_MENU_END}; -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) { - memset(G_gpg_vstate.menu, 0, sizeof(G_gpg_vstate.menu)); - memmove(G_gpg_vstate.menu, N_gpg_pstate->name.value, 12); - if (G_gpg_vstate.menu[0] == 0) { - memmove(G_gpg_vstate.menu, "", 9); - } else { - for (int i = 0; i < 12; i++) { - if (G_gpg_vstate.menu[i] == 0x3c) { - G_gpg_vstate.menu[i] = ' '; - } + {ui_menu_settings, NULL, 0, NULL, "Settings", NULL, 0, 0}, + {ui_menu_info, NULL, 0, NULL, "About", NULL, 0, 0}, + {NULL, (void *) os_sched_exit, 0, &C_icon_dashboard, "Quit app", NULL, 50, 29}, + UX_MENU_END}; +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) { + memset(G_gpg_vstate.menu, 0, sizeof(G_gpg_vstate.menu)); + memmove(G_gpg_vstate.menu, N_gpg_pstate->name.value, 12); + if (G_gpg_vstate.menu[0] == 0) { + memmove(G_gpg_vstate.menu, "", 9); + } else { + for (int i = 0; i < 12; i++) { + if (G_gpg_vstate.menu[i] == 0x3c) { + G_gpg_vstate.menu[i] = ' '; + } + } + } } - } - } - 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]); - memset(G_gpg_vstate.menu, 0, sizeof(G_gpg_vstate.menu)); + 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]); + memset(G_gpg_vstate.menu, 0, sizeof(G_gpg_vstate.menu)); #if GPG_MULTISLOT - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "ID: %x / %d", serial, G_gpg_vstate.slot + 1); + snprintf(G_gpg_vstate.menu, + sizeof(G_gpg_vstate.menu), + "ID: %x / %d", + serial, + G_gpg_vstate.slot + 1); #else - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "ID: %x", serial); + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "ID: %x", serial); #endif + } + element->text = G_gpg_vstate.menu; } - element->text = G_gpg_vstate.menu; - } - return element; + 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 - UX_CALLBACK_SET_INTERVAL(1000); + 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); + io_seproxyhal_display_default((bagl_element_t *) element); } #endif diff --git a/src/gpg_ux_nanos.h b/src/gpg_ux_nanos.h index cf33333..1236858 100644 --- a/src/gpg_ux_nanos.h +++ b/src/gpg_ux_nanos.h @@ -22,4 +22,4 @@ void ui_main_display(unsigned int value); void ui_menu_pinconfirm_display(unsigned int value); void ui_menu_pinentry_display(unsigned int value); void ui_menu_uifconfirm_display(unsigned int value); -#endif \ No newline at end of file +#endif diff --git a/src/gpg_ux_nanox.c b/src/gpg_ux_nanox.c index db085a2..0a914b8 100644 --- a/src/gpg_ux_nanox.c +++ b/src/gpg_ux_nanox.c @@ -49,46 +49,49 @@ void ui_menu_slot_action(unsigned int value); void ui_menu_main_display(unsigned int value); -void ui_menu_pinconfirm_action(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(); +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) +#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); + 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_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) { - UNUSED(menu_display); - UNUSED(value); - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s. %s", msg1, msg2); - ux_flow_init(0, ux_flow_popup, NULL); + UNUSED(menu_display); + UNUSED(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); +void ui_menu_uifconfirm_predisplay(void); UX_STEP_NOCB_INIT(ux_menu_uifconfirm_1_step, nnn, @@ -99,80 +102,84 @@ UX_STEP_CB(ux_menu_uifconfirm_2_step, pb, ui_uifconfirm_action(0), {&C_icon_cros 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); +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"); - } + 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); + 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; + 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); + } } - } - CATCH_OTHER(e) { + END_TRY; + } else { 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); - } + sw = 0x6985; } - 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; + 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); +void ui_menu_pinconfirm_predisplay(void); +void ui_menu_pinconfirm_display(unsigned int value); UX_STEP_NOCB_INIT(ux_menu_pinconfirm_1_step, nnn, @@ -195,246 +202,300 @@ UX_STEP_CB(ux_menu_pinconfirm_3_step, "Yes", }); -UX_FLOW(ux_flow_pinconfirm, &ux_menu_pinconfirm_1_step, &ux_menu_pinconfirm_2_step, &ux_menu_pinconfirm_3_step); +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"); - } + 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) { - UNUSED(value); - ux_flow_init(0, ux_flow_pinconfirm, NULL); + UNUSED(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); + unsigned int sw; + 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; + 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 + // type userid x y w h str rad fill fg bg + // font_id icon_id // clear screen {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 64, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL}, // left/rights icons {{BAGL_ICON, 0x00, 0, 30, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0, 0}, - (const char *)&C_icon_down}, + (const char *) &C_icon_down}, {{BAGL_ICON, 0x00, 120, 30, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0, 0}, - (const char *)&C_icon_up}, + (const char *) &C_icon_up}, // 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}, + {{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}, // 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} -}; + {{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}}; 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) { - 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); + if (value == 0) { + 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 (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++; + 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] = '-'; + 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; + 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]; - char digit; + unsigned int offset = G_gpg_vstate.ux_pinentry[0]; + char digit; UNUSED(button_mask_counter); - 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; + 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 == '<') { + 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; } - 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 == '<') { - 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; + return 0; } // >= 0 static unsigned int validate_pin() { - unsigned int offset, len, sw; - gpg_pin_t * 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); + 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 == 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]) || - (memcmp(G_gpg_vstate.work.io_buffer + offset + 1, G_gpg_vstate.work.io_buffer + offset + 1 + len + 1, - len) != 0)) { + 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_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_insert_u16(sw); 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); + 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]) || + (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; + return 0; } /* ------------------------------- template UX ------------------------------- */ @@ -442,56 +503,63 @@ static unsigned int validate_pin() { #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" +#define LABEL_RSA2048 "RSA 2048" +#define LABEL_RSA3072 "RSA 3072" +#define LABEL_RSA4096 "RSA 4096" +#define LABEL_SECP256K1 "SECP 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; + 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); + 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, +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 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; + 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); + 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_KEY G_gpg_vstate.ux_buff1 #define KEY_TYPE G_gpg_vstate.ux_buff2 void ui_menu_templet_action(); @@ -515,7 +583,10 @@ UX_STEP_CB_INIT(ux_menu_template_2_step, 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_3_step, + nnbnn, + ui_menu_tmpl_set_action(0), + {NULL, NULL, "Set Template", NULL, NULL}); UX_STEP_CB(ux_menu_template_4_step, pb, @@ -532,121 +603,121 @@ UX_FLOW(ux_flow_template, &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; - } + 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); + 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; + LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH); + gpg_key_t *dest; + const char *err; + const unsigned char *oid; + unsigned int oid_len; + err = NULL; UNUSED(value); - 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 + 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); + 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 + memmove(attributes.value + 1, C_OID_cv25519, sizeof(C_OID_cv25519)); + attributes.length = 1 + sizeof(C_OID_cv25519); + } else { + attributes.value[0] = 22; // eddsa + 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; } - oid = gpg_curve2oid(G_gpg_vstate.ux_type, &oid_len); - 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 - memmove(attributes.value + 1, C_OID_cv25519, sizeof(C_OID_cv25519)); - attributes.length = 1 + sizeof(C_OID_cv25519); - } else { - attributes.value[0] = 22; // eddsa - memmove(attributes.value + 1, C_OID_Ed25519, sizeof(C_OID_Ed25519)); - attributes.length = 1 + sizeof(C_OID_Ed25519); + + 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; } - 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; + + 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); + ui_info(INVALID_SELECTION, err, ui_menu_template_display, 0); } #undef KEY_KEY @@ -687,21 +758,21 @@ UX_STEP_CB(ux_menu_seedmode_2_step, 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"); + 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); + ui_flow_display(ux_flow_seedmode, value); } void ui_menu_seed_action(unsigned int value) { - UNUSED(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); + UNUSED(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 @@ -765,23 +836,31 @@ UX_FLOW(ux_flow_pinmode, &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)" : ""); + 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); + ui_flow_display(ux_flow_pinmode, value); } #undef ONHST_BUFF @@ -790,67 +869,67 @@ void ui_menu_pinmode_display(unsigned int value) { #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; + 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; } - } else { + // redisplay active pin mode entry 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; + 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; } - 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 ------------------------------ */ @@ -888,16 +967,20 @@ UX_STEP_CB(ux_menu_uif_4_step, "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); +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"); + 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); + ui_flow_display(ux_flow_uif, value); } #undef SIG_BUFF @@ -905,117 +988,124 @@ void ui_menu_uifmode_display(unsigned int value) { #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); + 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_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); + ux_flow_init(value, ux_flow_reset, NULL); } void ui_menu_reset_action(unsigned int value) { - UNUSED(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); + UNUSED(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); } /* ------------------------------ RESET SLOT UX ------------------------------ */ void ui_menu_reset_slot_action(unsigned int value); -UX_STEP_CB(ux_menu_reset_slot_1_step, bnn, ui_menu_settings_display(4), {"Ooops, NO!", "Do not reset", "the key slot"}); +UX_STEP_CB(ux_menu_reset_slot_1_step, + bnn, + ui_menu_settings_display(4), + {"Ooops, NO!", "Do not reset", "the key slot"}); UX_STEP_CB(ux_menu_reset_slot_2_step, bn, ui_menu_reset_slot_action(0), {"YES!", "Reset the slot"}); UX_FLOW(ux_flow_reset_slot, &ux_menu_reset_slot_1_step, &ux_menu_reset_slot_2_step); void ui_menu_reset_slot_display(unsigned int value) { - ux_flow_init(value, ux_flow_reset_slot, NULL); + ux_flow_init(value, ux_flow_reset_slot, NULL); } void ui_menu_reset_slot_action(unsigned int value) { - UNUSED(value); - gpg_install_slot(G_gpg_vstate.kslot); - ui_menu_main_display(0); + UNUSED(value); + gpg_install_slot(G_gpg_vstate.kslot); + 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 *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; + 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; - } + 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); + ux_menulist_init_select(G_ux.stack_count - 1, settings_getter, settings_selector, value); } /* --------------------------------- SLOT UX --------------------------------- */ @@ -1032,15 +1122,30 @@ void ui_menu_slot_predisplay(void); #define SLOT2 G_gpg_vstate.ux_buff2 #define SLOT3 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_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_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_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_slot_4_step, + bn, + ui_menu_slot_action(128), + {"Set selected Slot", "as default slot"}); - UX_STEP_CB(ux_menu_slot_5_step, +UX_STEP_CB(ux_menu_slot_5_step, pn, ui_menu_main_display(1), { @@ -1056,16 +1161,25 @@ UX_FLOW(ux_flow_slot, &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 ? "+" : " "); + 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); + ui_flow_display(ux_flow_slot, value); } #undef SLOT1 @@ -1073,27 +1187,27 @@ void ui_menu_slot_display(unsigned int value) { #undef SLOT3 void ui_menu_slot_action(unsigned int value) { - unsigned char s; - - if (value == 128) { - s = G_gpg_vstate.slot; - gpg_nvm_write((void *) &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 = (gpg_key_slot_t *) &N_gpg_pstate->keys[G_gpg_vstate.slot]; - gpg_mse_reset(); - ui_CCID_reset(); + unsigned char s; + + if (value == 128) { + s = G_gpg_vstate.slot; + gpg_nvm_write((void *) &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 = (gpg_key_slot_t *) &N_gpg_pstate->keys[G_gpg_vstate.slot]; + gpg_mse_reset(); + ui_CCID_reset(); + } } - } - ui_menu_slot_display(G_gpg_vstate.slot); + ui_menu_slot_display(G_gpg_vstate.slot); } #endif /* --------------------------------- INFO UX --------------------------------- */ -#define STR(x) #x +#define STR(x) #x #define XSTR(x) STR(x) UX_STEP_NOCB(ux_menu_info_1_step, @@ -1116,8 +1230,8 @@ UX_STEP_CB(ux_menu_info_2_step, UX_FLOW(ux_flow_info, &ux_menu_info_1_step, &ux_menu_info_2_step); void ui_menu_info_display(unsigned int value) { - UNUSED(value); - ux_flow_init(0, ux_flow_info, NULL); + UNUSED(value); + ux_flow_init(0, ux_flow_info, NULL); } #undef STR @@ -1155,47 +1269,51 @@ UX_FLOW(ux_flow_main, &ux_menu_main_5_step); void ui_menu_main_predisplay() { - memset(G_gpg_vstate.ux_buff1, 0, sizeof(G_gpg_vstate.ux_buff1)); - memmove(G_gpg_vstate.ux_buff1, (void *)(N_gpg_pstate->name.value), 20); - if (G_gpg_vstate.ux_buff1[0] == 0) { - 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] = ' '; - } + memset(G_gpg_vstate.ux_buff1, 0, sizeof(G_gpg_vstate.ux_buff1)); + memmove(G_gpg_vstate.ux_buff1, (void *) (N_gpg_pstate->name.value), 20); + if (G_gpg_vstate.ux_buff1[0] == 0) { + 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]); - memset(G_gpg_vstate.ux_buff2, 0, sizeof(G_gpg_vstate.ux_buff2)); + 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]); + 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); + 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); + 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(); - } + // reserve a display stack slot if none yet + if (G_ux.stack_count == 0) { + ux_stack_push(); + } - ui_flow_display(ux_flow_main, value); + ui_flow_display(ux_flow_main, value); } /* --- INIT --- */ void ui_init(void) { - ui_menu_main_display(0); + ui_menu_main_display(0); } void io_seproxyhal_display(const bagl_element_t *element) { - io_seproxyhal_display_default((bagl_element_t *)element); + io_seproxyhal_display_default((bagl_element_t *) element); } ///----- -#endif // UI_NANOX +#endif // UI_NANOX diff --git a/src/gpg_vars.h b/src/gpg_vars.h index 282d8dd..a497c8a 100644 --- a/src/gpg_vars.h +++ b/src/gpg_vars.h @@ -36,10 +36,10 @@ extern gpg_v_state_t G_gpg_vstate; #ifndef TARGET_NANOS extern const gpg_nv_state_t N_state_pic; -#define N_gpg_pstate ((volatile gpg_nv_state_t *)PIC(&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)) +#define N_gpg_pstate ((WIDE gpg_nv_state_t *) PIC(&N_state_pic)) #endif #ifdef GPG_DEBUG_MAIN @@ -51,5 +51,5 @@ extern ux_state_t ux; #ifdef HAVE_RSA #include "cx_ram.h" extern union cx_u G_cx; -#endif // HAVE_RSA +#endif // HAVE_RSA #endif