├── .drone.yml ├── .envrc ├── .gitignore ├── .gitmodules ├── .vscode ├── .gitignore ├── jcardsim_fido2.1.cfg ├── jcardsim_fido2.cfg ├── jcardsim_ndef.cfg ├── jcardsim_spark.cfg ├── jcardsim_tesla.cfg ├── jcardsim_totp.cfg ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── docs ├── 1-technology.md ├── 2-hardware.md ├── 3-dev-setup.md ├── 4-android.md ├── 5-otp-naming.md ├── 6-algorithms.md ├── 7-aid-list.md ├── README.md ├── applets │ ├── 1-pgp.md │ ├── 2-totp-hotp.md │ ├── 3-hmac-sha1.md │ ├── 4-ndef.md │ ├── 5-u2f.md │ ├── 6-fido2.md │ └── 8-bip32.md ├── img │ └── javacards.jpeg └── notes │ └── command_surface.md ├── eclipse-formatter.xml ├── flake.lock ├── flake.nix └── scripts ├── algscan.sh ├── clean-all.sh ├── clean ├── FIDO2Applet.sh ├── SatochipApplet.sh ├── Satodime-Applet.sh ├── Seedkeeper-Applet.sh ├── SmartPGP.sh ├── apex-fido2.sh ├── apex-ndef.sh ├── apex-spark.sh ├── apex-tesla.sh ├── apex-totp.sh ├── flexsecure-ykhmac.sh ├── javacard-memory.sh ├── openjavacard-ndef.sh ├── status-keycard.sh └── u2f-javacard.sh ├── compile-all.sh ├── compile ├── FIDO2Applet.sh ├── SatochipApplet.sh ├── Satodime-Applet.sh ├── Seedkeeper-Applet.sh ├── SmartPGP.sh ├── apex-fido2.sh ├── apex-ndef.sh ├── apex-spark.sh ├── apex-tesla.sh ├── apex-totp.sh ├── flexsecure-ykhmac.sh ├── javacard-memory.sh ├── openjavacard-ndef.sh ├── res │ ├── SatochipApplet.build.xml │ ├── Satodime-Applet.build.xml │ ├── Seedkeeper-Applet.build.xml │ ├── SmartPGP.build.xml │ ├── compile.sh │ ├── openjavacard-ndef.build.xml │ ├── u2f-javacard.build.xml │ └── version.py ├── status-keycard.sh └── u2f-javacard.sh ├── docker-build-image.sh ├── docker-run-image.sh ├── jcardsim.sh ├── test-all.sh └── test ├── FIDO2Applet.bats ├── SmartPGP.default.bats ├── SmartPGP.large.bats ├── apex-fido2.bats ├── apex-ndef.bats ├── apex-spark.bats ├── apex-totp.bats ├── flexsecure-ykhmac.bats ├── openjavacard-ndef.bats ├── res ├── FIDO.common.sh ├── FIDO2Applet.jcardsim.cfg ├── NDEF.common.sh ├── SmartPGP.common.sh ├── SmartPGP.generate.ECC.expect ├── SmartPGP.generate.RSA.expect ├── SmartPGP.import.expect ├── SmartPGP.jcardsim.cfg ├── apex-fido2.jcardsim.cfg ├── apex-ndef.jcardsim.cfg ├── apex-spark.jcardsim.cfg ├── apex-totp.jcardsim.cfg ├── common.sh ├── flexsecure-ykhmac.jcardsim.cfg ├── flexsecure-ykhmac.testdb.kdbx ├── ndef_encode.py ├── openjavacard-ndef.jcardsim.cfg └── u2f-javacard.jcardsim.cfg └── u2f-javacard.bats /.drone.yml: -------------------------------------------------------------------------------- 1 | 2 | kind: pipeline 3 | name: default 4 | 5 | clone: 6 | disable: true 7 | 8 | workspace: 9 | path: /app/src 10 | 11 | volumes: 12 | - name: cache 13 | temp: {} 14 | 15 | steps: 16 | - name: clone 17 | image: alpine/git 18 | commands: 19 | - git clone https://github.com/DangerousThings/flexsecure-applets . 20 | - git -c submodule."smartcard-ci".update=none -c submodule."applets/apex-fido2".update=none -c submodule."applets/apex-tesla".update=none -c submodule."applets/apex-ndef".update=none -c submodule."applets/apex-spark".update=none submodule update --init --recursive 21 | - name: build 22 | image: vivokey/smartcard-ci 23 | commands: 24 | - /app/src/scripts/compile-all.sh 25 | volumes: 26 | - name: cache 27 | path: /tmp 28 | - name: test 29 | image: vivokey/smartcard-ci 30 | commands: 31 | - /app/src/scripts/test-all.sh 32 | volumes: 33 | - name: cache 34 | path: /tmp 35 | - name: publish 36 | image: plugins/github-release 37 | settings: 38 | api_key: 39 | from_secret: github_api_key 40 | files: /app/src/bin/* 41 | when: 42 | branch: 43 | - master 44 | event: 45 | - tag 46 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | use flake -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | .direnv 3 | cpipe -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "applets/flexsecure-ykhmac"] 2 | path = applets/flexsecure-ykhmac 3 | url = https://github.com/DangerousThings/flexsecure-ykhmac.git 4 | [submodule "applets/apex-totp"] 5 | path = applets/apex-totp 6 | url = https://github.com/VivoKey/apex-totp.git 7 | [submodule "applets/SmartPGP"] 8 | path = applets/SmartPGP 9 | url = https://github.com/ANSSI-FR/SmartPGP 10 | [submodule "applets/openjavacard-ndef"] 11 | path = applets/openjavacard-ndef 12 | url = https://github.com/OpenJavaCard/openjavacard-ndef 13 | [submodule "smartcard-ci"] 14 | path = smartcard-ci 15 | url = https://github.com/DangerousThings/smartcard-ci.git 16 | [submodule "applets/u2f-javacard"] 17 | path = applets/u2f-javacard 18 | url = https://github.com/darconeous/u2f-javacard.git 19 | [submodule "applets/apex-fido2"] 20 | path = applets/apex-fido2 21 | url = https://github.com/VivoKey/apex-fido2 22 | [submodule "applets/javacard-memory"] 23 | path = applets/javacard-memory 24 | url = https://github.com/DangerousThings/javacard-memory.git 25 | [submodule "applets/status-keycard"] 26 | path = applets/status-keycard 27 | url = https://github.com/status-im/status-keycard.git 28 | [submodule "applets/apex-tesla"] 29 | path = applets/apex-tesla 30 | url = https://github.com/VivoKey/apex-tesla.git 31 | [submodule "applets/apex-ndef"] 32 | path = applets/apex-ndef 33 | url = https://github.com/VivoKey/apex-ndef.git 34 | [submodule "applets/FIDO2Applet"] 35 | path = applets/FIDO2Applet 36 | url = https://github.com/BryanJacobs/FIDO2Applet.git 37 | [submodule "applets/apex-spark"] 38 | path = applets/apex-spark 39 | url = https://github.com/Vivokey/apex-spark.git 40 | [submodule "applets/SatochipApplet"] 41 | path = applets/SatochipApplet 42 | url = https://github.com/Toporin/SatochipApplet.git 43 | [submodule "applets/Satodime-Applet"] 44 | path = applets/Satodime-Applet 45 | url = https://github.com/Toporin/Satodime-Applet.git 46 | [submodule "applets/Seedkeeper-Applet"] 47 | path = applets/Seedkeeper-Applet 48 | url = https://github.com/Toporin/Seedkeeper-Applet.git 49 | -------------------------------------------------------------------------------- /.vscode/.gitignore: -------------------------------------------------------------------------------- 1 | setup* 2 | assert_param 3 | cred* 4 | pubkey 5 | test_select.sh -------------------------------------------------------------------------------- /.vscode/jcardsim_fido2.1.cfg: -------------------------------------------------------------------------------- 1 | com.licel.jcardsim.card.applet.0.AID=A0000006472F0001 2 | com.licel.jcardsim.card.applet.0.Class=us.q3q.fido2.FIDO2Applet 3 | com.licel.jcardsim.card.ATR=3BF91800FF8131FE4550565F4A334130343040 4 | com.licel.jcardsim.vsmartcard.host=localhost 5 | com.licel.jcardsim.vsmartcard.port=35963 -------------------------------------------------------------------------------- /.vscode/jcardsim_fido2.cfg: -------------------------------------------------------------------------------- 1 | com.licel.jcardsim.card.applet.0.AID=A0000006472F0001 2 | com.licel.jcardsim.card.applet.0.Class=com.vivokey.fido2.Dispatcher 3 | com.licel.jcardsim.card.ATR=3BF91800FF8131FE4550565F4A334130343040 4 | com.licel.jcardsim.vsmartcard.host=localhost 5 | com.licel.jcardsim.vsmartcard.port=35963 -------------------------------------------------------------------------------- /.vscode/jcardsim_ndef.cfg: -------------------------------------------------------------------------------- 1 | com.licel.jcardsim.card.applet.0.AID=D2760000850101 2 | com.licel.jcardsim.card.applet.0.Class=com.vivokey.ndef.NDEF 3 | com.licel.jcardsim.card.ATR=3BF91800FF8131FE4550565F4A334130343040 4 | com.licel.jcardsim.vsmartcard.host=localhost 5 | com.licel.jcardsim.vsmartcard.port=35963 -------------------------------------------------------------------------------- /.vscode/jcardsim_spark.cfg: -------------------------------------------------------------------------------- 1 | com.licel.jcardsim.card.applet.0.AID=A000000846737061726B3201 2 | com.licel.jcardsim.card.applet.0.Class=com.vivokey.spark.Spark2 3 | com.licel.jcardsim.card.ATR=3BF91800FF8131FE4550565F4A334130343040 4 | com.licel.jcardsim.vsmartcard.host=localhost 5 | com.licel.jcardsim.vsmartcard.port=35963 -------------------------------------------------------------------------------- /.vscode/jcardsim_tesla.cfg: -------------------------------------------------------------------------------- 1 | com.licel.jcardsim.card.applet.0.AID=7465736C614C6F67696330303201 2 | com.licel.jcardsim.card.applet.0.Class=com.vivokey.teslaIdent.TeslaIdent 3 | com.licel.jcardsim.card.ATR=3BF91800FF8131FE4550565F4A334130343040 4 | com.licel.jcardsim.vsmartcard.host=localhost 5 | com.licel.jcardsim.vsmartcard.port=35963 -------------------------------------------------------------------------------- /.vscode/jcardsim_totp.cfg: -------------------------------------------------------------------------------- 1 | com.licel.jcardsim.card.applet.0.AID=A0000005272101014150455801 2 | com.licel.jcardsim.card.applet.0.Class=com.vivokey.otp.YkneoOath 3 | com.licel.jcardsim.card.ATR=3B8D80010031C173C8400052A51000900070 4 | com.licel.jcardsim.vsmartcard.host=localhost 5 | com.licel.jcardsim.vsmartcard.port=35963 -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "java", 9 | "name": "Jcardsim FIDO2", 10 | "request": "launch", 11 | "mainClass": "com.licel.jcardsim.remote.VSmartCard", 12 | "projectName": "fido2", 13 | "args": [ 14 | "${workspaceFolder}/.vscode/jcardsim_fido2.cfg", 15 | // "<", "${workspaceFolder}/cpipe" 16 | ], 17 | "classPaths": [ 18 | "${workspaceFolder}/smartcard-ci/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar", 19 | "${workspaceFolder}/applets/apex-fido2/target" 20 | ], 21 | "console": "integratedTerminal", 22 | "preLaunchTask": "Compile FIDO2" 23 | }, 24 | { 25 | "type": "java", 26 | "name": "Jcardsim FIDO2.1", 27 | "request": "launch", 28 | "mainClass": "com.licel.jcardsim.remote.VSmartCard", 29 | "projectName": "fido2applet", 30 | "args": [ 31 | "${workspaceFolder}/.vscode/jcardsim_fido2.1.cfg", 32 | // "<", "${workspaceFolder}/cpipe" 33 | ], 34 | "classPaths": [ 35 | "${workspaceFolder}/smartcard-ci/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar", 36 | "${workspaceFolder}/applets/FIDO2Applet/build/classes/java/main" 37 | ], 38 | "console": "integratedTerminal", 39 | "preLaunchTask": "Compile FIDO2.1" 40 | }, 41 | { 42 | "type": "java", 43 | "name": "Jcardsim Tesla", 44 | "request": "launch", 45 | "mainClass": "com.licel.jcardsim.remote.VSmartCard", 46 | "args": [ 47 | "${workspaceFolder}/.vscode/jcardsim_tesla.cfg" 48 | ], 49 | "classPaths": [ 50 | "${workspaceFolder}/smartcard-ci/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar", 51 | "${workspaceFolder}/applets/apex-tesla/target" 52 | ], 53 | "console": "integratedTerminal", 54 | "preLaunchTask": "Compile Tesla" 55 | }, 56 | { 57 | "type": "java", 58 | "name": "Jcardsim NDEF", 59 | "request": "launch", 60 | "mainClass": "com.licel.jcardsim.remote.VSmartCard", 61 | "projectName": "ndef", 62 | "args": [ 63 | "${workspaceFolder}/.vscode/jcardsim_ndef.cfg" 64 | ], 65 | "classPaths": [ 66 | "${workspaceFolder}/smartcard-ci/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar", 67 | "${workspaceFolder}/applets/apex-ndef/target" 68 | ], 69 | "console": "integratedTerminal", 70 | "preLaunchTask": "Compile NDEF" 71 | }, 72 | { 73 | "type": "java", 74 | "name": "Jcardsim Spark", 75 | "request": "launch", 76 | "mainClass": "com.licel.jcardsim.remote.VSmartCard", 77 | "projectName": "spark", 78 | "args": [ 79 | "${workspaceFolder}/.vscode/jcardsim_spark.cfg" 80 | ], 81 | "classPaths": [ 82 | "${workspaceFolder}/smartcard-ci/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar", 83 | "${workspaceFolder}/applets/apex-spark/target" 84 | ], 85 | "console": "integratedTerminal", 86 | "preLaunchTask": "Compile Spark" 87 | }, 88 | { 89 | "type": "java", 90 | "name": "Jcardsim TOTP", 91 | "request": "launch", 92 | "mainClass": "com.licel.jcardsim.remote.VSmartCard", 93 | "projectName": "totp", 94 | "args": [ 95 | "${workspaceFolder}/.vscode/jcardsim_totp.cfg" 96 | ], 97 | "classPaths": [ 98 | "${workspaceFolder}/smartcard-ci/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar", 99 | "${workspaceFolder}/applets/apex-totp/target" 100 | ], 101 | "console": "integratedTerminal", 102 | "preLaunchTask": "Compile TOTP", 103 | "stepFilters": { 104 | "classNameFilters": [ 105 | "java.*", 106 | "javax.*", 107 | "com.sun.*", 108 | "sun.*", 109 | "sunw.*", 110 | "org.omg.*", 111 | "com.licel.jcardsim.*", 112 | "com.licel.jcardsim.base.*" 113 | ], 114 | "skipSynthetics": false, 115 | "skipStaticInitializers": false, 116 | "skipConstructors": false 117 | } 118 | } 119 | ] 120 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.autoRepositoryDetection": "openEditors", 3 | "git.detectSubmodules": false, 4 | "java.project.referencedLibraries": [ 5 | "${workspaceRoot}/applets/apex-fido2/sdks/js305u3_kit/lib/*.jar" 6 | ], 7 | "java.import.exclusions": [ 8 | "**", 9 | "!**/applets/apex-fido2", 10 | "!**/applets/apex-fido2/**", 11 | "!**/applets/FIDO2Applet", 12 | "!**/applets/FIDO2Applet/**", 13 | "!**/applets/apex-ndef", 14 | "!**/applets/apex-ndef/**", 15 | "!**/applets/apex-spark", 16 | "!**/applets/apex-spark/**", 17 | "!**/applets/apex-totp", 18 | "!**/applets/apex-totp/**", 19 | "!**/smartcard-ci/jcardsim", 20 | "!**/smartcard-ci/jcardsim/**" 21 | ], 22 | "java.debug.settings.exceptionBreakpoint.skipClasses": [ 23 | "$JDK", 24 | "$Libraries", 25 | "com.licel.jcardsim.*", 26 | "com.licel.jcardsim.base.*" 27 | ], 28 | "java.debug.settings.stepping.skipClasses": [ 29 | "$JDK", 30 | "$Libraries", 31 | "com.licel.jcardsim.*", 32 | "com.licel.jcardsim.base.*" 33 | ], 34 | "java.debug.settings.onBuildFailureProceed": true, 35 | "java.format.settings.url": "eclipse-formatter.xml", 36 | "java.debug.settings.showHex": true, 37 | "java.configuration.updateBuildConfiguration": "interactive" 38 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Compile FIDO2", 8 | "type": "shell", 9 | "command": "JAVA_HOME=$JAVA_HOME_JDK8 ant", 10 | "options": { 11 | "cwd": "${workspaceFolder}/applets/apex-fido2", 12 | "env": { 13 | "JC_HOME": "${workspaceFolder}/applets/apex-fido2/sdks/jc305u3_kit" 14 | } 15 | }, 16 | "group": { 17 | "kind": "build", 18 | "isDefault": false 19 | }, 20 | "problemMatcher": [] 21 | }, 22 | { 23 | "label": "Compile FIDO2.1", 24 | "type": "shell", 25 | "command": "JAVA_HOME=$JAVA_HOME_JDK8 ./gradlew buildJavaCard classes", 26 | "options": { 27 | "cwd": "${workspaceFolder}/applets/FIDO2Applet", 28 | "env": { 29 | "JC_HOME": "${workspaceFolder}/applets/apex-fido2/sdks/jc304_kit" 30 | } 31 | }, 32 | "group": { 33 | "kind": "build", 34 | "isDefault": false 35 | }, 36 | "problemMatcher": [] 37 | }, 38 | { 39 | "label": "Compile Tesla", 40 | "type": "shell", 41 | "command": "JAVA_HOME=$JAVA_HOME_JDK8 ant", 42 | "options": { 43 | "cwd": "${workspaceFolder}/applets/apex-tesla", 44 | "env": { 45 | "JC_HOME": "${workspaceFolder}/applets/apex-tesla/sdks/jc304_kit" 46 | } 47 | }, 48 | "group": { 49 | "kind": "build", 50 | "isDefault": false 51 | }, 52 | "problemMatcher": [] 53 | }, 54 | { 55 | "label": "Compile NDEF", 56 | "type": "shell", 57 | "command": "JAVA_HOME=$JAVA_HOME_JDK8 ant", 58 | "options": { 59 | "cwd": "${workspaceFolder}/applets/apex-ndef", 60 | "env": { 61 | "JC_HOME": "${workspaceFolder}/applets/apex-ndef/sdks/jc305u3_kit" 62 | } 63 | }, 64 | "group": { 65 | "kind": "build", 66 | "isDefault": false 67 | }, 68 | "problemMatcher": [] 69 | }, 70 | { 71 | "label": "Compile Spark", 72 | "type": "shell", 73 | "command": "JAVA_HOME=$JAVA_HOME_JDK8 ant", 74 | "options": { 75 | "cwd": "${workspaceFolder}/applets/apex-spark", 76 | "env": { 77 | "JC_HOME": "${workspaceFolder}/applets/apex-spark/sdks/jc305u3_kit" 78 | } 79 | }, 80 | "group": { 81 | "kind": "build", 82 | "isDefault": true 83 | }, 84 | "problemMatcher": [] 85 | }, 86 | { 87 | "label": "Compile TOTP", 88 | "type": "shell", 89 | "command": "JAVA_HOME=$JAVA_HOME_JDK8 ant", 90 | "options": { 91 | "cwd": "${workspaceFolder}/applets/apex-totp", 92 | "env": { 93 | "JC_HOME": "${workspaceFolder}/applets/apex-totp/oracle_javacard_sdks/jc304_kit" 94 | } 95 | }, 96 | "group": { 97 | "kind": "build", 98 | "isDefault": false 99 | }, 100 | "problemMatcher": [] 101 | }, 102 | { 103 | "label": "Clean FIDO2", 104 | "type": "shell", 105 | "command": "rm -rf ${workspaceFolder}/applets/apex-fido2/target", 106 | "problemMatcher": [] 107 | }, 108 | { 109 | "label": "Clean FIDO2.1", 110 | "type": "shell", 111 | "command": "cd ${workspaceFolder}/applets/FIDO2Applet && rm -rf build .gradle bin", 112 | "problemMatcher": [] 113 | }, 114 | { 115 | "label": "Document FIDO2", 116 | "type": "shell", 117 | "command": "doxygen", 118 | "options": { 119 | "cwd": "${workspaceFolder}/applets/apex-fido2" 120 | }, 121 | "problemMatcher": [], 122 | "group": { 123 | "kind": "test", 124 | "isDefault": false 125 | } 126 | }, 127 | { 128 | "label": "Clean Tesla", 129 | "type": "shell", 130 | "command": "rm -rf ${workspaceFolder}/applets/apex-tesla/target", 131 | "problemMatcher": [] 132 | }, 133 | { 134 | "label": "Clean NDEF", 135 | "type": "shell", 136 | "command": "rm -rf ${workspaceFolder}/applets/apex-ndef/target", 137 | "problemMatcher": [] 138 | }, 139 | { 140 | "label": "Clean Spark", 141 | "type": "shell", 142 | "command": "rm -rf ${workspaceFolder}/applets/apex-spark/target", 143 | "problemMatcher": [] 144 | }, 145 | { 146 | "label": "Clean TOTP", 147 | "type": "shell", 148 | "command": "rm -rf ${workspaceFolder}/applets/apex-totp/target", 149 | "problemMatcher": [] 150 | }, 151 | { 152 | "label": "Document NDEF", 153 | "type": "shell", 154 | "command": "doxygen", 155 | "options": { 156 | "cwd": "${workspaceFolder}/applets/apex-ndef" 157 | }, 158 | "problemMatcher": [], 159 | "group": { 160 | "kind": "test", 161 | "isDefault": true 162 | } 163 | }, 164 | { 165 | "label": "Compile JCardSim", 166 | "type": "shell", 167 | "command": "JAVA_HOME=$JAVA_HOME_JDK8 mvn install", 168 | "options": { 169 | "cwd": "${workspaceFolder}/smartcard-ci/jcardsim", 170 | "env": { 171 | "JC_CLASSIC_HOME": "${workspaceFolder}/applets/apex-fido2/sdks/jc305u3_kit" 172 | } 173 | }, 174 | "group": { 175 | "kind": "build", 176 | "isDefault": false 177 | }, 178 | "problemMatcher": [] 179 | }, 180 | { 181 | "label": "Clean JCardSim", 182 | "type": "shell", 183 | "command": "rm -rf ${workspaceFolder}/smartcard-ci/jcardsim/target", 184 | "problemMatcher": [] 185 | }, 186 | { 187 | "label": "Reset JCardSim", 188 | "type": "shell", 189 | "command": "echo 'r' > ${workspaceFolder}/cpipe", 190 | "problemMatcher": [] 191 | }, 192 | { 193 | "label": "Emulate FIDO2", 194 | "type": "shell", 195 | "command": "JAVA_HOME=$JAVA_HOME_JDK8 java -cp ${workspaceFolder}/smartcard-ci/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:${workspaceFolder}/applets/apex-fido2/target com.licel.jcardsim.remote.VSmartCard ${workspaceFolder}/smartcard-ci/jcardsim/jcardsim_fido2.cfg 2>&1", 196 | "problemMatcher": [], 197 | }, 198 | { 199 | "label": "Setup FIDO2", 200 | "type": "shell", 201 | "command": "${workspaceFolder}/.vscode/setup_fido2.sh", 202 | "problemMatcher": [], 203 | }, 204 | { 205 | "label": "Setup FIDO2.1", 206 | "type": "shell", 207 | "command": "${workspaceFolder}/.vscode/setup_fido2.1.sh", 208 | "problemMatcher": [], 209 | }, 210 | { 211 | "label": "Setup Tesla", 212 | "type": "shell", 213 | "command": "${workspaceFolder}/.vscode/setup_tesla.sh", 214 | "problemMatcher": [], 215 | }, 216 | { 217 | "label": "Setup NDEF", 218 | "type": "shell", 219 | "command": "${workspaceFolder}/.vscode/setup_ndef.sh", 220 | "problemMatcher": [], 221 | }, 222 | { 223 | "label": "Setup TOTP", 224 | "type": "shell", 225 | "command": "${workspaceFolder}/.vscode/setup_totp.sh", 226 | "problemMatcher": [], 227 | }, 228 | { 229 | "label": "Setup Spark", 230 | "type": "shell", 231 | "command": "${workspaceFolder}/.vscode/setup_spark.sh", 232 | "problemMatcher": [], 233 | }, 234 | ] 235 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Christoph Honal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://drone-github.infrastructure.vivokey.com/api/badges/DangerousThings/flexsecure-applets/status.svg)](https://drone-github.infrastructure.vivokey.com/DangerousThings/flexsecure-applets) 2 | 3 | # flexsecure-applets 4 | 5 | Collection of JavaCard applets for the DangerousThings FlexSecure and VivoKey Apex, as well as build and testing scripts. 6 | 7 | For documentation, see `docs/` . Or read the forums at https://forum.dangerousthings.com/c/support/flexsecure-support/24 . 8 | 9 | Some submodules contain private / proprietary applets and require access permissions. 10 | 11 | ## Download 12 | 13 | Public compiled binaries are available from the GitHub releases page: https://github.com/DangerousThings/flexsecure-applets/releases . 14 | 15 | ## Development Usage 16 | 17 | Install Docker. Use the `docker-*.sh` scripts in `scripts/` to compile and test the applets. Binaries will be placed in `bin/`. This repository also runs on a Drone CI server. 18 | 19 | ## Version Command 20 | 21 | The build system in this repository adds an extra version APDU command to each applet. See `scripts/compile/res/version.py`. Use this build system if you want to generate release equivalent binaries. 22 | -------------------------------------------------------------------------------- /docs/1-technology.md: -------------------------------------------------------------------------------- 1 | # Introduction to the JavaCard Ecosystem 2 | 3 | **JavaCards** are a subset of the devices known as **Smartcards**, i.e. small plastic cards or tokens which contains a microprocessor and a communication interface. 4 | 5 | Even if you don't know it, chances are good you used a JavaCard today. Most SIM cards run on JavaCard, the chips inside modern credit cards and debit cards do as well, and there are even chips embedded in some passports which run JavaCard. Ever wondered where that ominous "3 billion devices run Java" tagline comes from? Well, now you know :^). 6 | 7 | Compared to other microprocessors, JavaCards are actually pretty complex. They usually come with an operating system, a set of software libraries and even a security and permissions control system. However, most chips are rather limited in terms of storage and memory - think kilobytes instead of gigabytes. 8 | 9 | Some chips come with a wireless NFC interface, some come with gold contacts (like on a SIM card), and some have both. 10 | 11 | ![](img/javacards.jpeg) 12 | 13 | ## JavaCard (JC) 14 | 15 | **"JavaCard"** is a set of standards and specifications to run software on embedded systems. If you are used to the Java ecosystem, many things will be familiar: the software is packaged into applets, which are then run in a Virtual Machine. This allows for portability of an applet across many cards. 16 | 17 | The programming language used is a true subset of Java, however the available APIs are different, and special care has to be taken when managing memory. For example, special atomic data transfer functions are available to ensure data integrity. 18 | 19 | JavaCard and the development SDKs are nowadays managed by Oracle Inc. 20 | 21 | ## GlobalPlatform (GP) 22 | 23 | The **GlobalPlatform** specifications are another set of industry standards, which primarily define interactions with the JavaCard - specifically the management and installation of applets. 24 | 25 | ### Keys and Authentication 26 | 27 | GP enforces authentication and code signatures (DAP Verification) during the applet installation. The card applet storage can only be modified if the correct card administration key is provided, or if the applets are properly signed. The flexSecure ships with the default GP development administration key `404142434445464748494a4b4c4d4e4f`. You can change this key if you want to - but do not forget it, there is no way to recover the card once it is locked. 28 | 29 | This key is additionally used to open a secure communication channel to the card, via which the applet data is transferred. 30 | 31 | Although unusual, it is possible to internally communicate between applets on a card. It is also possible to segment the card memory and storage into multiple independent security domains, and then use e.g. a "high-security" one for payment applets. These partitions can use different keys, and/or use derived keys from a master key or certificate. This is how Fidesmo runs payment functionality next to signed third-party applets on the same card, while ensuring the integrity of the payment applet. 32 | 33 | The whole signature and key derivation process is complex, and out of scope for this introduction. 34 | 35 | Many vendors implement their own proprietary extensions on top of GP, e.g. for EMV payment applets or legacy emulation. 36 | 37 | ### GlobalPlatformPro (GPP) 38 | 39 | A good and open-source GP interfacing software is GlobalPlatformPro (GPP). Download the latest stable version of GPP from https://github.com/martinpaljak/GlobalPlatformPro/releases . On Windows, you have the option to use the exe file, the jar file works on all operating systems. 40 | 41 | If you use the jar version, download and install the latest version of the Java runtime from your package manager or e.g. the Oracle website. 42 | 43 | The best user guide for GPP can be found in its repository readme file. 44 | 45 | ## Java Card OpenPlatform (JCOP) 46 | 47 | JCOP is an embedded operating system for secure elements, which implements the JavaCard and GlobalPlatform specifications. It is mainly developed by NXP, and used on their chips. 48 | 49 | On some chips, JCOP might provide additional proprietary functionality. The version running on the flexSecure is JCOP4, which implements GP 2.2.1 and 2.3, and is compatible to the JC API 3.0.4 Classic and 3.0.5 Classic. 50 | 51 | ## ISO 7816 and Personal Computer / Smart Card (PC/SC) 52 | 53 | The ISO/IEC 7816 standard defines smart cards in general. Among things like physical characteristics or electrical connections, the most relevant section is part 4, which defines the data exchange protocol using **APDUs** (Application Defined Data Units). 54 | 55 | The PC/SC industry standard defines a set of mechanisms and APIs for the usage of smart cards on host operating systems, like Linux and Windows. An open-source implementation for Linux is provided by pcsc-lite, Windows and OSX ship their own implementations. All these APIs implement the WinSCard interface. 56 | 57 | ### Answer To Reset (ATR) 58 | 59 | When a smartcard is reset / connected, it responds with a characteristic message, the ATR. This message contains information about data coding conventions, supported communication speeds, and much more. It can be used to identify cards of the same type and/or manufacturer. For example, pcsc-lite ships with a list of known ATRs, and displays a human-readable name for the one it recognizes. 60 | 61 | ### Application Protocol Data Units (APDUs) 62 | 63 | The communication with a smartcard is performed by sending command data buffers to the card, and receiving response buffers. These APDU buffers have to follow the ISO 7816 standard. 64 | 65 | Each APDU response contains a response code, The most important one is `0x90 0x00`, which signals a successful command. 66 | 67 | ## Packages and Applets 68 | 69 | JC applications are distributed in `.cap` (converted applet) files. These files contain (usually) one **package**. A package can be loaded onto a card using GP, where it will be placed into the embedded filesystem. 70 | 71 | ### Application Identifiers (AIDs) 72 | 73 | An application identifier (AID) is a hexadecimal string of numbers, which globally uniquely identifies an applet. Companies have to apply to get their AIDs registered, and in theory no one else should use these AIDs for anything else. This of it like a domain name in the internet, a list of known AIDs is linked below. 74 | 75 | ### Applet Instances 76 | 77 | After a package has been deployed, the next step is to create an applet **instance** from it. A package can contain multiple applets, and an applet can be instantiated more than once if needed. The package ID, applet ID and AID can be dynamically specified at the time of instantiation, or be read from preset values in the package metadata. 78 | 79 | Usually, loading the package and instantiating the applet is done in one step. Some applets may require some additional installation configuration parameters, which can be passed as well. 80 | 81 | Before any communication with an applet can happen, it has to be selected by using its AID. An applet can be marked as **default**, in which case it is always automatically selected after a card reset. 82 | 83 | Instances are retained across card resets and power cycles, and so is their non-volatile data (e.g. private keys). 84 | 85 | ## Sources and Further Reading 86 | 87 | - https://en.wikipedia.org/wiki/Java_Card 88 | - https://en.wikipedia.org/wiki/Java_Card_OpenPlatform 89 | - https://www.oracle.com/java/technologies/java-card-tech.html 90 | - https://www.oracle.com/java/technologies/java-card/javacard1.html 91 | - https://globalplatform.org/ 92 | - https://github.com/martinpaljak/GlobalPlatformPro 93 | - https://javacardos.com/javacardforum/ 94 | - https://en.wikipedia.org/wiki/ISO/IEC_7816 95 | - http://cardwerk.com/iso-7816-part-4 96 | - https://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit 97 | - https://en.wikipedia.org/wiki/PC/SC 98 | - https://docs.microsoft.com/en-us/windows/win32/api/winscard/ 99 | - https://pcsclite.apdu.fr/ 100 | - https://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit 101 | - https://www.javacardos.com/tools/apdu-parser 102 | - https://www.eftlab.com/knowledge-base/complete-list-of-apdu-responses/ 103 | - https://www.eftlab.com/knowledge-base/171-atr-list-full/ 104 | - https://smartcard-atr.apdu.fr/ 105 | - https://www.eftlab.com/knowledge-base/211-emv-aid-rid-pix/ 106 | 107 | Improve this document: https://github.com/dangerousthings/flexSecure-applets/tree/master/docs 108 | -------------------------------------------------------------------------------- /docs/2-hardware.md: -------------------------------------------------------------------------------- 1 | # flexSecure vs. Apex Flex 2 | 3 | Please read the [*Introduction to the JavaCard Ecosystem*](https://github.com/DangerousThings/flexSecure-applets/blob/master/docs/1-technology.md) first, to understand the technical differences. 4 | 5 | ## Target Audience 6 | 7 | If you want an easy-to-use implant with an existing ecosystem, a mobile app-store and the potential payment functionality in the future, then the [Apex Flex](https://dngr.us/apex-flex) is for you. 8 | 9 | If you want full offline control over your hardware and keys, the maximum possible storage and memory, and are not afraid of using the console and reading into the technical documentation, then the [flexSecure](https://dngr.us/flexsecure) is for you. 10 | 11 | ## The NXP P71 Chip 12 | 13 | The specification of the chip used in the flexSecure and Apex Flex (with a differing configuration, see below) is as follows: 14 | 15 | - Manufacturer: NXP Semiconductors 16 | - Series: SmartMX3 Secure and Flexible Microcontroller 17 | - Model: `P71D321` 18 | - Operating system: `JCOP4` 19 | - Software interface: `SCP02` GlobalPlatform `2.2.1` and `2.3` / Java Card `3.0.4` Classic and `3.0.5` Classic 20 | - Variant: J3R200 (`200KB` EEPROM) 21 | - Package: MOB10 ultra-thin (chip: `5 mm * 5 mm`, total: `5 mm * 8 mm`, thickness: `0.1 mm`) punched from `35 mm` tape reels 22 | - Hardware interface: Contactless (NFC `13.56 MHz`, ISO/IEC 14443 Type A) only 23 | - Capacitance: `56 pF` 24 | - Configuration: "MIFARE Plus EV1 in classic mode 4K applet" removed, leaves `>= 164K` EEPROM, `>= 4KB` RAM usable (for details, see below) 25 | - GlobalPlatform key: `404142434445464748494a4b4c4d4e4f` (default test key) 26 | - Supported algorithms: RSA 4096bits, AES, SHA1/SHA224/SHA256/SHA384/SHA512, 3DES(ECB,CBC), KOREAN SEED, ECC FP 160 bits to 521 bits 27 | 28 | ## Storage and Memory 29 | 30 | The P71 has a few hundreds kilobytes of ROM (read-only) memory. The contents of the ROM, as well as its layout is specified by the **ROM mask**. This ROM mask is applied by the card factory, according to the customers order. This process requires **fabrication keys** by NXP (or even a custom silicon die), which are highly protected and usually only provided to contracted partners and factories. 31 | 32 | The P71 J3R200 has about `200 KB` of EEPROM (re-writeable) nonvolatile flash memory. According to our manufacturer, the flexSecure has at least `164 KB` of EEPROM available. The Mifare classic emulation applet was removed from the ROM mask, otherwise only about `99 KB` flash would have been available. 33 | 34 | Measurements show an available persistent (EEPROM) storage of at least `167736` bytes for the flexSecure. 35 | 36 | The ROM is typically used for storing pre-deployed packages which will never change. The EEPROM then stores only the applet instances, as well as configuration data like e.g. secret keys. In our case, all packages are loaded during runtime into the EEPROM, and the ROM is pretty much unused expect for some cryptographic algorithms and the operating system. 37 | 38 | The P71 J3R200 has about `8 KB` of volatile RAM available. Some of that is used by the operating system and cryptographic algorithms. According to our manufacturer, at least `4 KB` of RAM is available for applets on the flexSecure. 39 | 40 | Measurements show a transient (RAM) storage size of at least `4115` / `4112` (reset / deselect) bytes for the flexSecure. 41 | 42 | The Apex Flex uses either the `J3R200` or the `J3R180` chip, which one is unclear at the time of writing. They have the same base specs (besides the `J3R180` having a `20 KB` smaller EEPROM), and use a different ROM mask specified by Fidesmo. The ROM mask should contain the pre-loaded payment package, and the EEPROM additionally contains the instance of this payment applet. This takes quite a chunk of memory (allegedly about `100 KB`). Information on these Fidesmo-deployed chips is scarce, maybe the payment package is stored in the EEPROM as well. In any case, the remaining amount of storage and memory is significantly smaller than on the flexSecure. 43 | 44 | Measurements show an available persistent (EEPROM) storage of at least `84336` bytes, and a transient (RAM) storage size of at least `4054` / `4160` (reset / deselect) bytes for the Apex Flex. 45 | 46 | ## Important Note concerning Lockout 47 | 48 | The P71 includes a hardware functionality which physically bricks the chip after too many authentication failures, when using the wrong GlobalPlatform key. There is no way to recover the chip after that, it permanently turns into dead silicon. If you change your GlobalPlatformKey, be sure to made a backup of the key. Also make extra sure to always specify the correct key when using GlobalPlatformPro. By default (if no key is specified), the default test key (see above) is used. Also, do not remove the management applet package (`A0000001515350`), or security controller (`A000000151000000`). They are part of the operating system. 49 | 50 | It is important to note, if you have an Apex Flex then you do not have the master key and you cannot change it. You can brick your Apex Flex by attempting to use GlobalPlatformPro to access it without the key. Do not attempt to access your Apex Flex using GPP or you will end up bricking it. 51 | 52 | ## Apex Flex & Fidesmo AB 53 | 54 | The Apex Flex uses a chip personalized by Fidesmo AB, a swedish company providing a set of services and APIs for managing, deploying, and communicating with smartcard applets across many devices. They provide a mobile app-store, which can be used to load new applets onto your smartcard. They also provide payment functionality on their cards, as well as backend connections to service providers. 55 | 56 | ### Ecosystem Constraints 57 | 58 | Loading a third-party applet onto a Fidesmo-deployed smartcard requires the applet to be signed by Fidesmo, as they keep the administrative keys to the cards private. This signing process requires a developer account and an internet connection to the Fidesmo signing servers. The signature ensures that third-party applets are only allowed to be deployed into the "low-security" domain, i.e. not the one where the payment code runs. 59 | 60 | Fidesmo retains the right to refuse to sign any applet they do not want running on their card. In addition, they only allow AIDs starting with their registered AID, joined with your developer ID. This ensures that your AIDs don't collide with any others. In special cases, you might be able to reach an agreement with them to use a different AID. 61 | 62 | The Fidesmo `fdsm` tool handles the signing process, and is able to interface GP to load and manage applets onto a card. GPP can only be used in a very limited amount, as the administrative key is kept by Fidesmo. On an empty card with administrative access, signatures are not enforced - unless you specifically configure a security domain and sign the applets using your own certificates. 63 | 64 | ### Applet Availability 65 | 66 | It should be said that Fidesmo provides a very valuable service, and that their partnership with VivoKey on the Apex Flex is a big win for everyone. For example, Fidesmo provides the mentioned mobile app store, which provides an easy way to discover and install applets onto the Apex Flex. 67 | 68 | Typically companies will deploy their applets to a smart card and lock he chip down, creating a single application card (like payment cards, access badges, Tesla key cards, etc). Fidesmo brokers on-chip security in a way that makes it possible for 3rd parties to feel comfortable enough to allow their applets to be deployed and operate on-chip with other applets. More specifically, Fidesmo's management of the master key, review of applets before publication, and deployment of applets into separate security domains on-chip, does not allow end users the means to access or attempt to subvert or maliciously attack the applet code or data stored in memory. Without this arrangement, it would not be possible to deploy trusted applications from 3rd parties (like payment applets) in a multi-application environment. 69 | 70 | The flexSecure uses an empty chip with administrative keys available, which has not been personalized by Fidesmo. Consequently, it can not interact with the Fidesmo services and app store. You have to source the packages you want to install by yourself somewhere on the internet, or to compile them from source. You also have to load them onto the card manually, everything has to be managed using GP / GPP, but any AID you want can be deployed in order to impersonate other tokens or cards. 71 | 72 | ## Payments 73 | 74 | It is unclear if and when the payment functionality of the Apex Flex will ever be active. Mastercard / Visa have some ideological issues supporting implants, so although the Fidesmo payment applet works great, it is unable to be tokenized (configured with payment account data) on the Apex Flex. The payment applet will be loaded on the chip, but won't be possible to use. The applet will lie dormant until Visa / Mastercard sort out their issues. 75 | 76 | The flexSecure comes without a payment applet. Although there are payment applet implementations by Fidesmo and e.g. Mastercard available, the legal paperwork and security requirements (sectioned chips, private administrative keys) mean that the flexSecure cannot and will not be able to make payments. 77 | 78 | ## Sources and Further Reading 79 | 80 | - https://www.nxp.com/products/security-and-authentication/security-controllers/smartmx3-p71d321-secure-and-flexible-microcontroller:SMARTMX3-P71D321 81 | - https://www.javacardos.com/store/products/11020 82 | - https://fidesmo.com/ 83 | - https://github.com/fidesmo/fdsm 84 | - https://github.com/DangerousThings/javacard-memory 85 | 86 | Improve this document: https://github.com/DangerousThings/flexSecure-applets/tree/master/docs 87 | -------------------------------------------------------------------------------- /docs/3-dev-setup.md: -------------------------------------------------------------------------------- 1 | # JavaCard Development Setup 2 | 3 | If you want to compile applets from source, you need to install a few requirements. These instructions are for Linux, but it should work on Windows as well (using Docker or maybe WSL, see below). 4 | 5 | ## Local Development 6 | 7 | You need to install a few software packages. 8 | 9 | - JavaCard Development Kit 3.0.4 from [Oracle](https://www.oracle.com/java/technologies/javacard-downloads.html), or from the [GitHub mirror](https://github.com/martinpaljak/oracle_javacard_sdks). 10 | - Apache Ant from the [website](https://ant.apache.org/) or your package manager. 11 | - Java Development Kit 8 from [Oracle](https://www.oracle.com/de/java/technologies/javase/javase8u211-later-archive-downloads.html), or even better from [OpenJDK](https://openjdk.org/), available via your package manager. 12 | 13 | For Ubuntu, the packages are called `ant` and `openjdk-8-jdk`. You might have to switch to the JDK using `update-alternatives --set java /usr/lib/jvm/java-8-openjdk-*/jre/bin/java`. 14 | 15 | I also recommend installing a few tools to interact with PCSC readers, e.g. `opensc`, `pcscd`, `pcsc-tools`, and `python3-pyscard` if you use Python. 16 | 17 | ### JavaCard SDKs as Submodule 18 | 19 | Some repositories include the JavaCard SDKs as a submodule. You can use either these submodules or your own download. Make sure to clone the repositories using `git clone --recursive` to clone the submodules as well, or make sure to initialize the submodule after cloning. 20 | 21 | ## Testing and Emulation 22 | 23 | You can emulate and debug your applet locally by simulating a PCSC reader and running your applet in a virtual environment. This requires you to use Linux. 24 | 25 | ### Virtual Reader 26 | 27 | Install `pcscd`, `pcsc-tools`, `opensc` and `vsmartcard-vpcd` from your package manager. 28 | 29 | Make sure the virtual reader shows up when running `pcsc_scan -r` or `opensc-tool -lr`: 30 | 31 | ``` 32 | pcsc_scan -r 33 | 34 | 0: Virtual PCD 00 00 35 | 1: Virtual PCD 00 01 36 | ``` 37 | 38 | ``` 39 | opensc-tool -l 40 | 41 | # Detected readers (pcsc) 42 | Nr. Card Features Name 43 | 0 Yes Virtual PCD 00 00 44 | 1 No Virtual PCD 00 01 45 | ``` 46 | 47 | ### Applet Emulation 48 | 49 | Clone `jcardsim` from https://github.com/DangerousThings/jcardsim using git. To emulate the compiled applet, run: 50 | 51 | ``` 52 | java -cp jcardsim-3.0.5-SNAPSHOT.jar:TARGET com.licel.jcardsim.remote.VSmartCard CONFIG.cfg 53 | ``` 54 | 55 | Replace `TARGET` with the relative path to the directory containing the compiled class files of your applet, e.g. `./target`. Replace `CONFIG.cfg` with the path to your jcardsim configuration file. This file looks like this: 56 | 57 | ``` 58 | com.licel.jcardsim.card.applet.0.AID=YOURAID 59 | com.licel.jcardsim.card.applet.0.Class=your.main.ClassName 60 | com.licel.jcardsim.card.ATR=YOURATR 61 | com.licel.jcardsim.vsmartcard.host=localhost 62 | com.licel.jcardsim.vsmartcard.port=35963 63 | ``` 64 | 65 | Replace `YOURAID` with the AID you want the applet to have, e.g. `A0000005272001`. Replace `your.main.ClassName` with the class name of the main class, e.g. `com.vivokey.ykhmac.YkHMACApplet`. Replace `ATR` with the answer to reset to emulate, e.g. `3B8D80018073C021C057597562694B6579F9`; look at the pcsc-tools list or some online sources (see below) to find an appropriate ATR. 66 | 67 | ### Initializing the Applet 68 | 69 | Next, send the initial boot APDU to create the applet, using `opensc-tool` to send raw APDUs: 70 | 71 | ``` 72 | opensc-tool -r 'Virtual PCD 00 00' -s '80 b8 00 00 KK PP QQ QQ QQ ... 00 [RR SS SS SS ...] FF' 73 | ``` 74 | 75 | Replace `KK` with the amount of bytes after `KK`. Replace `PP` with the amount of `QQ` bytes. Replace `QQ QQ QQ ...` with the AID of the applet. If you want to pass initialization parameters, replace `RR` with the amount of `SS` bytes, and `SS SS SS ...` with the initialization data. Do not actually write the `[ ]` brackets, these just mean that the initialization section is optional. Example: `80 b8 00 00 0A 07 a0 00 00 05 27 20 01 00 FF`. 76 | 77 | Make sure the command was successful by watching for `Received (SW1=0x90, SW2=0x00)`. 78 | 79 | ### Using the Emulated Applet 80 | 81 | From here on, the applet should behave like a hardware card running the applet. You have to specify the correct reader (`Virtual PCD 00 00`) to access it. 82 | 83 | Jcardsim will print a log of all APDUs, which is very helpful for debugging. You can also attach an interactive debugger to the emulator, although exceptions from your applet code will be printed by Jcardsim by default. 84 | 85 | To "eject" the card, just stop the Jcardsim process. 86 | 87 | ## Docker Container 88 | 89 | If you do not want to clutter your system, or don't have a compatible Linux system, you can use a pre-made Docker container for compilation. Install Docker, and use the image at https://hub.docker.com/r/vivokey/smartcard-ci . You can find the source Dockerfile at https://github.com/DangerousThings/smartcard-ci . This image is also used to compile the applets distributed via https://github.com/DangerousThings/flexSecure-applets/releases . 90 | 91 | To run a command inside the Docker container: 92 | 93 | ``` 94 | docker run -it --rm -v SOURCES:/app/src:rw vivokey/smartcard-ci "command" 95 | ``` 96 | 97 | Replace `SOURCES` with the absolute path to your source code directory, and `"command"` with the command you want to run. 98 | 99 | You can look at the compilation scripts in https://github.com/DangerousThings/flexSecure-applets for reference. 100 | 101 | The container also contains the virtual smartcard emulator, as well as the Bats test runner. You can use that to run tests against emulated applets. Refer to the test scripts in the repository. 102 | 103 | ## Sideloading 104 | 105 | Use the GlobalPlatformPro tools (GPP) from https://github.com/martinpaljak/GlobalPlatformPro/releases to load the compiled applets onto a card. Refer to the GPP documentation for details. 106 | 107 | For Fidesmo-deployed cards, use the `fdsm` tool from https://github.com/fidesmo/fdsm/releases to sign and sideload your applet. Refer to the Fidesmo developer documentation for details. 108 | 109 | Do not remove the management applet package (`A0000001515350`), or security controller (`A000000151000000`). They are part of the operating system. 110 | 111 | ## Sources and Further Reading 112 | 113 | - https://www.docker.com/ 114 | - https://github.com/DangerousThings/smartcard-ci/blob/master/Dockerfile 115 | - https://github.com/DangerousThings/flexSecure-applets/tree/master/scripts 116 | - https://frankmorgner.github.io/vsmartcard/ 117 | - https://pcsclite.apdu.fr/ 118 | - https://github.com/DangerousThings/jcardsim 119 | - https://www.eftlab.com/knowledge-base/171-atr-list-full/ 120 | - https://github.com/LudovicRousseau/pcsc-tools/blob/master/smartcard_list.txt 121 | - https://github.com/bats-core/bats-core 122 | - https://github.com/martinpaljak/GlobalPlatformPro 123 | - https://github.com/fidesmo/fdsm 124 | - https://fidesmo.com/technology/java-card/ 125 | 126 | Improve this document: https://github.com/DangerousThings/flexSecure-applets/tree/master/docs 127 | -------------------------------------------------------------------------------- /docs/4-android.md: -------------------------------------------------------------------------------- 1 | # Android Problems and Solutions 2 | 3 | Android has some particularities concerning NFC. 4 | 5 | ## FIDO requires Security Manager 6 | 7 | FIDO keys are handled by a Google Services component, which is absent on FOSS (e.g. Lineage) Android builds. Use MicroG instead, which implements a security manager and FIDO adapter since version `v0.2.25.223616` . I contributed a few patches to ensure smooth operation, make sure to use at least version `v0.2.26.223616`. 8 | 9 | ## Maximum NFC Transceive Length 10 | 11 | On some Android ROMS, the NFC driver is configured improperly, which limits the size of data packets that can be exchanged. FIDO2 requires very large packets if no chained fragmentation is used (~1KB). 12 | 13 | To change the configuration, add the line 14 | 15 | ``` 16 | ISO_DEP_MAX_TRANSCEIVE=0xFEFF 17 | ``` 18 | 19 | to each of the files `/vendor/etc/libnfc-nci.conf` and `/vendor/etc/libnfc-brcm.conf` (and any other files you find like e.g. `libnfc-nxp.conf`). 20 | 21 | This requires root access. 22 | 23 | ## Google Services 24 | 25 | The proprietary Google Services security manager does not implement support for FIDO2, only U2F (time of writing: October 2022). The FIDO2 applet is backwards-compatible to U2F. 26 | 27 | ## Sources and Further Reading 28 | 29 | - https://github.com/microg/GmsCore 30 | - https://microg.org/ 31 | - https://android.stackexchange.com/questions/110927/how-to-mount-system-rewritable-or-read-only-rw-ro 32 | - https://github.com/microg/GmsCore/pulls/StarGate01 33 | - https://github.com/NXPNFCLinux/linux_libnfc-nci/issues/116 34 | - https://groups.google.com/a/fidoalliance.org/g/fido-dev/c/H_32sr1STAg 35 | 36 | Improve this document: https://github.com/DangerousThings/flexSecure-applets/tree/master/docs 37 | -------------------------------------------------------------------------------- /docs/5-otp-naming.md: -------------------------------------------------------------------------------- 1 | # OTP / OATH Applet Naming 2 | 3 | Due to some historical decisions and industry conventions, the naming of the two-factor authentication applets is a bit confusing. 4 | 5 | ## 1. Rolling One-Time Passwords 6 | 7 | This applet stores a list of user accounts and generates rolling 6-digit codes for each one. 8 | 9 | The version distributed via the VivoKey Fidesmo store should also be compatible with the Yubico Authenticator programs. 10 | 11 | - Supported protocols: `OATH-TOTP` (RFC 6238) and `OATH-HOTP` (RFC 4226) 12 | - Yubico calls this `OATH` (see https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html) 13 | - Repository: https://github.com/VivoKey/apex-totp 14 | - Documentation: https://github.com/DangerousThings/flexsecure-applets/blob/master/docs/applets/2-totp-hotp.md 15 | - Applet name: `vivokey-otp.cap`, AID: `A0:00:00:05:27:21:01:01` 16 | 17 | ## 2. Static Challenge-Response 18 | 19 | This applet provides two key slots, which can be programmed with a static secret key. 20 | 21 | Even though this applet implements the Yubico-compatible `HMAC-SHA1` challenge-response protocol, it does not support other slot configurations such as static `HOTP`, `NDEF`, or `YubiOTP`. For `HOTP`, use the other applet. 22 | 23 | - Supported protocols: `HMAC-SHA1` (RFC 2104) 24 | - Yubico calls this `OTP` (see https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html, specifically `chalresp`) 25 | - Repository: https://github.com/DangerousThings/flexsecure-ykhmac 26 | - Documentation: https://github.com/DangerousThings/flexsecure-applets/blob/master/docs/applets/3-hmac-sha1.md 27 | - Applet name: `YkHMACApplet.cap`, AID: `A0:00:00:05:27:20:01:01` 28 | 29 | ## Sources and Further Reading 30 | 31 | - https://docs.yubico.com/software/yubikey/tools/ykman/intro.html 32 | 33 | Improve this document: https://github.com/DangerousThings/flexsecure-applets/tree/master/docs 34 | -------------------------------------------------------------------------------- /docs/6-algorithms.md: -------------------------------------------------------------------------------- 1 | # Required JavaCard Algorithms 2 | 3 | The applets distributed by VivoKey and contained in this repository require hardware support for a range of cryptographic algorithms. 4 | 5 | Not all of these algorithms are hard requirements, some applets might provide fallbacks (e.g. for `ALG_HMAC_SHA*`) or limit certain functionality instead (e.g. PGP for generating large key sizes). 6 | 7 | The `scripts/algscan.sh` script was used to generate this report. 8 | 9 | ## Overview 10 | 11 | AES: 12 | - AES sizes 128, 256 13 | - AES modes CBC, ECB 14 | - AES paddings ISO9797-M2, None 15 | 16 | RSA: 17 | - RSA sizes 2048, 3072, 4096 18 | - RSA paddings PKCS#1, None 19 | - RSA signatures SHA 256 20 | - RSA signature paddings PKCS1, PKCS1-PSS 21 | 22 | SHA: 23 | - SHA sizes 224, 256, 512 24 | - SHA signatures ECDSA, RSA 25 | - SHA paddings PKCS1, PKCS1-PSS, None 26 | 27 | EC: 28 | - EC sizes 256, 384, 521 29 | 30 | ECDH: 31 | - ECDH types Default, Plain, Plain XY 32 | 33 | HMAC: 34 | - HMAC types SHA1, SHA1 (64 block), SHA256 35 | 36 | CMAC: 37 | - CMAC types AES (CMAC 128) 38 | - CMAC paddings ISO9797-M2, None 39 | 40 | MAC: 41 | - MAC types AES 128 42 | - MAC paddings None 43 | 44 | ECDSA: 45 | - ECDSA SHA sizes 224, 256, 384, 512 46 | 47 | RNG: 48 | - RNG types Pseudo, True, Secure 49 | 50 | ## Combined list 51 | 52 | ``` 53 | Cipher.ALG_AES_BLOCK_128_CBC_NOPAD 54 | Cipher.ALG_AES_BLOCK_128_ECB_NOPAD 55 | Cipher.ALG_AES_CBC_ISO9797_M2 56 | Cipher.ALG_RSA_PKCS1 57 | Cipher.CIPHER_AES_CBC, Cipher.PAD_NOPAD 58 | KeyAgreement.ALG_EC_SVDP_DH 59 | KeyAgreement.ALG_EC_SVDP_DH_PLAIN 60 | KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY 61 | KeyBuilder.ALG_TYPE_AES, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_128 62 | KeyBuilder.ALG_TYPE_EC_FP_PARAMETERS, JCSystem.MEMORY_TYPE_PERSISTENT, KeyBuilder.LENGTH_EC_FP_256 63 | KeyBuilder.ALG_TYPE_EC_FP_PRIVATE, JCSystem.MEMORY_TYPE_PERSISTENT 64 | KeyBuilder.ALG_TYPE_EC_FP_PRIVATE, JCSystem.MEMORY_TYPE_PERSISTENT, KeyBuilder.LENGTH_EC_FP_256 65 | KeyBuilder.ALG_TYPE_EC_FP_PRIVATE, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT 66 | KeyBuilder.ALG_TYPE_EC_FP_PRIVATE, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_EC_FP_256 67 | KeyBuilder.ALG_TYPE_EC_FP_PUBLIC, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT 68 | KeyBuilder.ALG_TYPE_EC_FP_PUBLIC, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_EC_FP_256 69 | KeyBuilder.ALG_TYPE_RSA_PRIVATE, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_RSA_2048 70 | KeyBuilder.ALG_TYPE_RSA_PUBLIC, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_RSA_2048 71 | KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256 72 | KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, 73 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128 74 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256 75 | KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_EC_FP_256 76 | KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256 77 | KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256 78 | KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_384 79 | KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_521 80 | KeyBuilder.TYPE_EC_FP_PRIVATE, LENGTH_EC_FP_256 81 | KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256 82 | KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_384 83 | KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_521 84 | KeyBuilder.TYPE_EC_FP_PUBLIC, LENGTH_EC_FP_256 85 | KeyBuilder.TYPE_HMAC_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256 86 | KeyBuilder.TYPE_HMAC_TRANSIENT_RESET, KeyBuilder.LENGTH_HMAC_SHA_1_BLOCK_64 87 | KeyBuilder.TYPE_RSA_CRT_PRIVATE, KeyBuilder.LENGTH_RSA_2048 88 | KeyBuilder.TYPE_RSA_CRT_PRIVATE, KeyBuilder.LENGTH_RSA_3072 89 | KeyBuilder.TYPE_RSA_CRT_PRIVATE, KeyBuilder.LENGTH_RSA_4096 90 | KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_2048 91 | KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_3072 92 | KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_4096 93 | KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048 94 | KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_3072 95 | KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_4096 96 | KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256 97 | MessageDigest.ALG_NULL, Signature.SIG_CIPHER_AES_CMAC128, Cipher.PAD_ISO9797_M2 98 | MessageDigest.ALG_SHA 99 | MessageDigest.ALG_SHA_224 100 | MessageDigest.ALG_SHA_256 101 | MessageDigest.ALG_SHA_256, Signature.SIG_CIPHER_ECDSA, Cipher.PAD_NULL 102 | MessageDigest.ALG_SHA_256, Signature.SIG_CIPHER_RSA, Cipher.PAD_PKCS1 103 | MessageDigest.ALG_SHA_256, Signature.SIG_CIPHER_RSA, Cipher.PAD_PKCS1_PSS 104 | MessageDigest.ALG_SHA_512 105 | RandomData.ALG_PSEUDO_RANDOM 106 | RandomData.ALG_SECURE_RANDOM 107 | RandomData.ALG_TRNG 108 | Signature.ALG_AES_CMAC_128 109 | Signature.ALG_AES_MAC_128_NOPAD 110 | Signature.ALG_ECDSA_SHA 111 | Signature.ALG_ECDSA_SHA_224 112 | Signature.ALG_ECDSA_SHA_256 113 | Signature.ALG_ECDSA_SHA_384 114 | Signature.ALG_ECDSA_SHA_512 115 | Signature.ALG_HMAC_SHA_512 116 | Signature.ALG_HMAC_SHA1 117 | Signature.ALG_RSA_SHA_256_PKCS1 118 | Signature.ALG_RSA_SHA_256_PKCS1_PSS 119 | ``` 120 | 121 | ## Individual applets 122 | 123 | ### apex-tesla 124 | 125 | ``` 126 | Cipher.ALG_AES_BLOCK_128_ECB_NOPAD 127 | KeyAgreement.ALG_EC_SVDP_DH 128 | KeyBuilder.ALG_TYPE_AES, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_128 129 | KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256 130 | ``` 131 | 132 | ### apex-totp 133 | 134 | ``` 135 | MessageDigest.ALG_SHA 136 | MessageDigest.ALG_SHA_224 137 | MessageDigest.ALG_SHA_256 138 | RandomData.ALG_PSEUDO_RANDOM 139 | ``` 140 | 141 | ### status-keycard 142 | 143 | ``` 144 | Cipher.ALG_AES_CBC_ISO9797_M2 145 | KeyAgreement.ALG_EC_SVDP_DH_PLAIN 146 | KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY 147 | KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256 148 | KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256 149 | KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256 150 | KeyBuilder.TYPE_HMAC_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256 151 | KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256 152 | MessageDigest.ALG_SHA_256 153 | MessageDigest.ALG_SHA_512 154 | RandomData.ALG_SECURE_RANDOM 155 | Signature.ALG_AES_MAC_128_NOPAD 156 | Signature.ALG_ECDSA_SHA_256 157 | Signature.ALG_HMAC_SHA_512 158 | ``` 159 | 160 | ### apex-spark 161 | 162 | ``` 163 | Cipher.ALG_AES_BLOCK_128_CBC_NOPAD 164 | Cipher.CIPHER_AES_CBC, Cipher.PAD_NOPAD 165 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128 166 | RandomData.ALG_SECURE_RANDOM 167 | RandomData.ALG_TRNG 168 | ``` 169 | 170 | ### u2f-javacard 171 | 172 | ``` 173 | Cipher.ALG_AES_BLOCK_128_CBC_NOPAD 174 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256 175 | KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_EC_FP_256 176 | KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256 177 | KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256 178 | KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256 179 | RandomData.ALG_SECURE_RANDOM 180 | Signature.ALG_ECDSA_SHA_256 181 | ``` 182 | 183 | ### apex-fido2 184 | 185 | ``` 186 | Cipher.ALG_AES_BLOCK_128_CBC_NOPAD 187 | Cipher.CIPHER_AES_CBC, Cipher.PAD_NOPAD 188 | KeyAgreement.ALG_EC_SVDP_DH_PLAIN 189 | KeyBuilder.ALG_TYPE_EC_FP_PARAMETERS, JCSystem.MEMORY_TYPE_PERSISTENT, KeyBuilder.LENGTH_EC_FP_256 190 | KeyBuilder.ALG_TYPE_EC_FP_PRIVATE, JCSystem.MEMORY_TYPE_PERSISTENT 191 | KeyBuilder.ALG_TYPE_EC_FP_PRIVATE, JCSystem.MEMORY_TYPE_PERSISTENT, KeyBuilder.LENGTH_EC_FP_256 192 | KeyBuilder.ALG_TYPE_EC_FP_PRIVATE, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT 193 | KeyBuilder.ALG_TYPE_EC_FP_PRIVATE, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_EC_FP_256 194 | KeyBuilder.ALG_TYPE_EC_FP_PUBLIC, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT 195 | KeyBuilder.ALG_TYPE_EC_FP_PUBLIC, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_EC_FP_256 196 | KeyBuilder.ALG_TYPE_RSA_PRIVATE, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_RSA_2048 197 | KeyBuilder.ALG_TYPE_RSA_PUBLIC, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_RSA_2048 198 | KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, 199 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256 200 | KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256 201 | KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256 202 | KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_2048 203 | KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048 204 | MessageDigest.ALG_SHA_256 205 | MessageDigest.ALG_SHA_256, Signature.SIG_CIPHER_ECDSA, Cipher.PAD_NULL 206 | MessageDigest.ALG_SHA_256, Signature.SIG_CIPHER_RSA, Cipher.PAD_PKCS1 207 | MessageDigest.ALG_SHA_256, Signature.SIG_CIPHER_RSA, Cipher.PAD_PKCS1_PSS 208 | RandomData.ALG_SECURE_RANDOM 209 | RandomData.ALG_TRNG 210 | Signature.ALG_ECDSA_SHA_256 211 | Signature.ALG_RSA_SHA_256_PKCS1 212 | Signature.ALG_RSA_SHA_256_PKCS1_PSS 213 | ``` 214 | 215 | ### SatochipApplet 216 | 217 | ``` 218 | Cipher.ALG_AES_BLOCK_128_CBC_NOPAD 219 | Cipher.ALG_AES_BLOCK_128_ECB_NOPAD 220 | KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY 221 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128 222 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256 223 | KeyBuilder.TYPE_EC_FP_PRIVATE, LENGTH_EC_FP_256 224 | KeyBuilder.TYPE_EC_FP_PUBLIC, LENGTH_EC_FP_256 225 | MessageDigest.ALG_SHA 226 | MessageDigest.ALG_SHA_256 227 | MessageDigest.ALG_SHA_512 228 | RandomData.ALG_SECURE_RANDOM 229 | ``` 230 | 231 | ### FIDO2Applet 232 | 233 | ``` 234 | Cipher.ALG_AES_BLOCK_128_CBC_NOPAD 235 | KeyAgreement.ALG_EC_SVDP_DH_PLAIN 236 | KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256 237 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256 238 | KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_EC_FP_256 239 | KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256 240 | KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256 241 | KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256 242 | MessageDigest.ALG_SHA_256 243 | RandomData.ALG_SECURE_RANDOM 244 | Signature.ALG_ECDSA_SHA_256 245 | ``` 246 | 247 | ### apex-ndef 248 | 249 | ``` 250 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128 251 | MessageDigest.ALG_NULL, Signature.SIG_CIPHER_AES_CMAC128, Cipher.PAD_ISO9797_M2 252 | Signature.ALG_AES_CMAC_128 253 | ``` 254 | 255 | ### SmartPGP 256 | 257 | ``` 258 | Cipher.ALG_AES_BLOCK_128_CBC_NOPAD 259 | Cipher.ALG_RSA_PKCS1 260 | KeyAgreement.ALG_EC_SVDP_DH_PLAIN 261 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128 262 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256 263 | KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256 264 | KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_384 265 | KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_521 266 | KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256 267 | KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_384 268 | KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_521 269 | KeyBuilder.TYPE_RSA_CRT_PRIVATE, KeyBuilder.LENGTH_RSA_2048 270 | KeyBuilder.TYPE_RSA_CRT_PRIVATE, KeyBuilder.LENGTH_RSA_3072 271 | KeyBuilder.TYPE_RSA_CRT_PRIVATE, KeyBuilder.LENGTH_RSA_4096 272 | KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_2048 273 | KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_3072 274 | KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_4096 275 | KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048 276 | KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_3072 277 | KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_4096 278 | RandomData.ALG_SECURE_RANDOM 279 | Signature.ALG_ECDSA_SHA 280 | Signature.ALG_ECDSA_SHA_224 281 | Signature.ALG_ECDSA_SHA_256 282 | Signature.ALG_ECDSA_SHA_384 283 | Signature.ALG_ECDSA_SHA_512 284 | ``` 285 | 286 | ### flexsecure-ykhmac 287 | 288 | ``` 289 | KeyBuilder.TYPE_HMAC_TRANSIENT_RESET, KeyBuilder.LENGTH_HMAC_SHA_1_BLOCK_64 290 | MessageDigest.ALG_SHA 291 | RandomData.ALG_SECURE_RANDOM 292 | Signature.ALG_HMAC_SHA1 293 | ``` 294 | 295 | ### Satodime-Applet 296 | 297 | ``` 298 | Cipher.ALG_AES_BLOCK_128_CBC_NOPAD 299 | Cipher.ALG_AES_BLOCK_128_ECB_NOPAD 300 | KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY 301 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128 302 | KeyBuilder.TYPE_EC_FP_PRIVATE, LENGTH_EC_FP_256 303 | KeyBuilder.TYPE_EC_FP_PUBLIC, LENGTH_EC_FP_256 304 | MessageDigest.ALG_SHA 305 | MessageDigest.ALG_SHA_256 306 | RandomData.ALG_SECURE_RANDOM 307 | ``` 308 | 309 | ### Seedkeeper-Applet 310 | 311 | ``` 312 | Cipher.ALG_AES_BLOCK_128_CBC_NOPAD 313 | Cipher.ALG_AES_BLOCK_128_ECB_NOPAD 314 | KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY 315 | KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128 316 | KeyBuilder.TYPE_EC_FP_PRIVATE, LENGTH_EC_FP_256 317 | KeyBuilder.TYPE_EC_FP_PUBLIC, LENGTH_EC_FP_256 318 | MessageDigest.ALG_SHA 319 | MessageDigest.ALG_SHA_256 320 | MessageDigest.ALG_SHA_512 321 | RandomData.ALG_SECURE_RANDOM 322 | ``` 323 | 324 | ## Sources and Further Reading 325 | 326 | - https://docs.oracle.com/javase/7/docs/api/javax/crypto/package-summary.html 327 | 328 | Improve this document: https://github.com/DangerousThings/flexsecure-applets/tree/master/docs 329 | -------------------------------------------------------------------------------- /docs/7-aid-list.md: -------------------------------------------------------------------------------- 1 | # List of applets and their IDs 2 | 3 | When compiling the applets using the build scripts in this repository, the following IDs are used. 4 | 5 | | Lifecycle | Vivokey Branding | Suggested Name | Source Code | License | Vivokey Fidesmo App ID | CAP Package ID | Industry Standard AID(s) | CAP Encoded AID(s) | Fidesmo Deployed AID(s) | Notes on the AID(s) | 6 | | ------------- | -------------------- | ---------------------------- | -------------------------------------------------------------------------------------- | ----------- | ---------------------- | -------------------------- | ---------------------------------- | ---------------------------------- | ---------------------------------- | ------------------- | 7 | | ✅ Active | HMAC-SHA1 Generator | HMAC-SHA1 Challenge-Response | [flexsecure-ykhmac](https://github.com/DangerousThings/flexsecure-ykhmac) | MPL v2 | `2f2e363b` | `A00000052720` | `A000000527200101` | `A000000527200101` | `A000000527200101` | None | 8 | | ✅ Active | SmartPGP | OpenPGP Card 3.4 | [SmartPGP](https://github.com/ANSSI-FR/SmartPGP) | GPL v2 | `30c2ea30` | `D27600012401` | `D27600012401XXXXYYYYZZZZZZZZ0000` | `D276000124010304000A000000000000` | `D276000124010304000A000000000000` | Vivokey uses the `000A` OpenPGP card vendor identifier. | 9 | | ✅ Active | BIP32 Wallet | Keycard.tech BIP32 Wallet | [status-keycard](https://github.com/status-im/status-keycard) | Apache v2 | `38ea914a` | `A0000008040001` | `A0000008040001[01,02,03]` | `A0000008040001[01,02,03]` | `A0000008040001[01,03]01` | Only the Keycard and Cash applet are deployed, the NDEF integration is skipped. Trailing `01` due to legacy configuration. | 10 | | ⚠️ Phase-Out | NFC Share (current) | NDEF Storage | [openjavacard-ndef](https://github.com/OpenJavaCard/openjavacard-ndef) | GPL v3 | `61b4b03d` | `D276000085` | `D2760000850101` | `D2760000850101` | `D2760000850101` | None | 11 | | ⏰️ Planned | NFC Share (future) | Signed NDEF Storage | [apex-ndef](https://github.com/VivoKey/apex-ndef) | Proprietary | `61b4b03d` | `D27600008501` | `D2760000850101` | `D2760000850101` | TBD | TBD | 12 | | ✅ Active | OTP Authenticator | TOTP/HOTP Authenticator | [apex-totp](https://github.com/VivoKey/apex-totp) | GPL v3 | `61fc54d5` | `A00000052721010141504558` | `A0000005272101` | `A0000005272101014150455801` | `A0000005272101014150455801` | Trailing `014150455801` is used to detect Vivokey deployments. | 13 | | ✅ Active | Free Memory | Memory Usage Reporting | [javacard-memory](https://github.com/DangerousThings/javacard-memory) | MIT | `99848a60` | `A0000008466D656D6F7279` | N/A | `A0000008466D656D6F727901` | `A0000008466D656D6F727901` | Vivokey-owned Fidesmo AID | 14 | | ⚠️ Deprecated | FIDO Security | U2F Authenticator | [u2f-javacard](https://github.com/darconeous/u2f-javacard) | Apache v2 | `cc68e88c` | `A0000006472F0001` | `A0000006472F0001` | `A0000006472F000101` | `A0000006472F000101` | Trailing `01` to differentiate from CAP ID. | 15 | | ✅ Active | FIDO Security (beta) | FIDO2/U2F Authenticator | [apex-fido2](https://github.com/VivoKey/apex-fido2) | Proprietary | `cc68e88c` | `A0000006472F0001` | `A0000006472F0001` | `A0000006472F000101` | `A0000006472F000102` | Trailing `02` to differentiate from CAP ID, `02` is used to differentiate from U2F (deprecated detection mechanism) | 16 | | ✅ Active | Tesla Keycard | Tesla Keycard | [apex-tesla](https://github.com/VivoKey/apex-tesla) | Proprietary | `e819c674` | `7465736C614C6F676963` | `7465736C614C6F67696330303201` | `7465736C614C6F67696330303201` | `F465736C614C6F67696330303201` | Unknown why the encoded AID is different from the actually used one. | 17 | | ❌ Obsolete | N/A | Ledger Unplugged | [apex-ledger-unplugged](https://github.com/VivoKey/apex-ledger-unplugged) | AGPL v3 | N/A | `FF4C4547522E57414C543031` | `FF4C4547522E57414C5430312E493031` | `FF4C4547522E57414C5430312E493031` | N/A | N/A | 18 | | ❌ Obsolete | N/A | Ledger Unplugged Eligibility | [ledger-javacard-eligibility](https://github.com/LedgerHQ/ledger-javacard-eligibility) | AGPL v3 | N/A | `FF4C4547522E454C49473031` | `FF4C4547522E454C494730312E493031` | `FF4C4547522E454C494730312E493031` | N/A | N/A | 19 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # flexSecure Primers 2 | 3 | This repository contains documentation and instructions on how to use the upcoming flexSecure chips by Dangerous Things. 4 | 5 | ## Disclaimer 6 | 7 | I am not a crypto expert, and I also won't be responsible for bricked chips, please do your own research if you are unsure. 8 | -------------------------------------------------------------------------------- /docs/applets/1-pgp.md: -------------------------------------------------------------------------------- 1 | # Encryption and Signatures using PGP 2 | 3 | PGP (Pretty Good Privacy), and its popular implementation GnuPG (GNU Privacy Guard) are used to securely sign, encrypt and decrypt data. 4 | 5 | Explaining the theory of public-key cryptography is out of scope, please refer to the sources below for more info. 6 | 7 | ## Applet Information 8 | 9 | - Repository: https://github.com/ANSSI-FR/SmartPGP (javacard-3.0.4-without-secure-messaging branch) 10 | - Binary name: `SmartPGPApplet-default.cap` and `SmartPGPApplet-large.cap` 11 | - Download: https://github.com/DangerousThings/flexsecure-applets/releases 12 | - AID: `d2:76:00:01:24:01:03:04:00:0A:00:00:00:00:00:00` (has to be adjusted, see below), Package: `d2:76:00:01:24:01` 13 | - Storage requirements: 14 | - Persistent: `24776` bytes (`28148` with one RSA 2048 key) 15 | - Transient reset: `2118` bytes 16 | - Transient deselect: `16` bytes 17 | 18 | ## Compiling the Applet Yourself 19 | 20 | Setup your environment as described in *JavaCard Development Setup* . 21 | 22 | Use git to clone the sources, and change into the directory. To compile, run `JC_HOME=//jc304_kit ant`, replacing `` with the path to your JavaCard SDKs. 23 | 24 | ## Using Large Keys 25 | 26 | If you want to use RSA keys larger than 2048 bits, you have to change the constant `INTERNAL_BUFFER_MAX_LENGTH` (default configuration: `0x500`) in `src/fr/anssi/smartpgp/Constants.java`: 27 | 28 | - for RSA 2048 bits at least `0x3b0` 29 | - for RSA 3072 bits at least `0x570` 30 | - for RSA 4096 bits at least `0x730` (large configuration) 31 | 32 | Otherwise, gpg might fail with a message like `gpg: KEYTOCARD failed: Hardware problem`. 33 | 34 | You might also want to use my Docker image and build environment, which contains all necessary packages for compilation and testing: https://github.com/DangerousThings/flexsecure-applets . This environment automatically builds both the default and large configuration. 35 | 36 | For more options, see the SmartPGP README file. 37 | 38 | ## Installing the Applet 39 | 40 | To install the applet to your card, you have to first construct a valid AID (refer to section 4.2.1 of the OpenPGP card specification, linked below). Every AID starts with `D2 76 00 01 24 01`, which is the unique identifier of the FSFE, joined with the application identifier `01`. Next comes the OpenPGP version, which is `03 04` (3.4) for this applet. The next two bytes are a manufacturer id, which should be registered with the FSF Europe e.V. , however you can just put whatever you like - Vivokey uses `00 0A`. The next four bytes specify the card serial number (e.g. `00 00 00 01`), and the last two bytes are reserved for future use and are always zero. 41 | 42 | The complete AID should look like this: `D2 76 00 01 24 01 03 04 C0 FE 00 00 00 01 00 00`. 43 | 44 | Use GlobalPlatformPro (GPP) from https://github.com/martinpaljak/GlobalPlatformPro/releases to install the applet: 45 | 46 | ``` 47 | gp -install SmartPGPApplet.cap -create D276000124010304C0FE000000010000 48 | ``` 49 | 50 | Listing the applets using `gp --list` should print something like this: 51 | 52 | ``` 53 | APP: D276000124010304C0FE000000010000 (SELECTABLE) 54 | Parent: A000000151000000 55 | From: D27600012401 56 | 57 | PKG: D27600012401 (LOADED) 58 | Parent: A000000151000000 59 | Version: 1.0 60 | Applet: D276000124010304AFAF000000000000 61 | ``` 62 | 63 | For more options, see the SmartPGP README file. 64 | 65 | ## Using the Applet 66 | 67 | For usage, refer to the manuals for GnuPGP, GPG4Win, OpenKeychain, Thunderbird, or whatever you use PGP with. The card should behave like a YubiKey or OpenPGP card, so you can use instructions for these tokens as well. 68 | 69 | ### Importing Keys 70 | 71 | Due to an implementation detail of the SmartPGP applet (https://github.com/ANSSI-FR/SmartPGP/issues/15), the card has to be configured for a specific algorithm before an existing key can be imported. This can be done using the `smartpgp-cli` tool in `SmartPGP/bin/`. For example, to configure the card for NIST P-512, run `./smartpgp-cli switch-p521`. You might have to install various Python 3 modules like `pyscard` and `pyasn1` using your system or Python package manager. 72 | 73 | Generating keys on the card itself can be done for any algorithm without having to pre-configure the algorithm. 74 | 75 | ## Sources and Further Reading 76 | 77 | - https://en.wikipedia.org/wiki/Public-key_cryptography 78 | - https://en.wikipedia.org/wiki/Pretty_Good_Privacy 79 | - https://www.thunderbird.net/ 80 | - https://gnupg.org/ 81 | - https://en.wikipedia.org/wiki/OpenPGP_card 82 | - https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.pdf 83 | - https://www.gpg4win.org/ 84 | 85 | Improve this document: https://github.com/DangerousThings/flexsecure-applets/tree/master/docs -------------------------------------------------------------------------------- /docs/applets/2-totp-hotp.md: -------------------------------------------------------------------------------- 1 | # One-Time Passwords using OATH-TOTP/HOTP 2 | 3 | Time-based (TOTP) and counter-based (HOTP) one-time passwords are used to generate rolling codes for two-factor authentication. 4 | 5 | These codes are preferred over e.g. SMS codes, because the process requires no codes to be received from a server; instead all rolling codes are generated locally and cannot be intercepted. 6 | 7 | ## Applet Information 8 | 9 | - Repository: https://github.com/VivoKey/apex-totp 10 | - Binary name: `vivokey-otp.cap` 11 | - Download: https://github.com/DangerousThings/flexsecure-applets/releases 12 | - AID: `A0:00:00:05:27:21:01:01:41:50:45:58:01`, Package: `A0:00:00:05:27:21:01:01:41:50:45:58` 13 | - Storage requirements: 14 | - Persistent: `5128` bytes (`6020` with three TOTP accounts) 15 | - Transient reset: `2296` bytes (`2392`) 16 | - Transient deselect: `64` bytes 17 | 18 | ## Compiling the Applet Yourself 19 | 20 | Setup your environment as described in *JavaCard Development Setup* . 21 | 22 | Use git to clone the sources recursively, and change into the directory. Make sure the submodule in `/oracle_javacard_sdks` is checked out. To compile, run `ant dist`. 23 | 24 | ## Installing the Applet 25 | 26 | Use GlobalPlatformPro (GPP) from https://github.com/martinpaljak/GlobalPlatformPro/releases to install the applet: 27 | 28 | ``` 29 | gp -install vivokey-otp.cap 30 | ``` 31 | 32 | Listing the applets using `gp --list` should print something like this: 33 | 34 | ``` 35 | APP: A0000005272101014150455801 (SELECTABLE) 36 | Parent: A000000151000000 37 | From: A00000052721010141504558 38 | 39 | PKG: A00000052721010141504558 (LOADED) 40 | Parent: A000000151000000 41 | Version: 1.1 42 | Applet: A0000005272101014150455801 43 | ``` 44 | 45 | ## Using the Applet 46 | 47 | Use the VivoKey Apex Manager App to interface this applet. 48 | 49 | The Yubikey Authenticator tool is able to interface this applet on both Desktop and Mobile as well, but it requires you to also have the HMAC-SHA1 applet installed (it does not necessarily have to be initialized with keys). On Desktop, you have to specify your PCSC reader in **Settings -> Advanced -> Custom Reader**. 50 | 51 | You can also use the yubikey-manager CLI tool (`ykman`) to interface with the applet. You have to specify your reader using the `-r` flag (use `ykman list -r` to get a list of readers). Replace `SECRET` with a 32 character Base-32 encoded secret: 52 | 53 | ``` 54 | ykman -r 'READER' oath accounts uri "otpauth://totp/Test?secret=SECRET" 55 | 56 | ykman -r 'READER' oath accounts code Test 57 | ``` 58 | 59 | This URI string is the same as is encoded in the usual QR codes. 60 | 61 | ## Sources and Further Reading 62 | 63 | - https://www.yubico.com/products/yubico-authenticator/ 64 | - https://en.wikipedia.org/wiki/Time-based_one-time_password 65 | - https://www.yubico.com/resources/glossary/oath-totp/ 66 | - https://www.yubico.com/resources/glossary/oath-hotp/ 67 | - https://stefansundin.github.io/2fa-qr/ 68 | - https://developers.yubico.com/yubikey-manager/ 69 | 70 | Improve this document: https://github.com/DangerousThings/flexsecure-applets/tree/master/docs -------------------------------------------------------------------------------- /docs/applets/3-hmac-sha1.md: -------------------------------------------------------------------------------- 1 | # Challenge-Response using HMAC-SHA1 2 | 3 | HMAC-SHA1 challenge-response provides a mechanism for two systems to ensure bilateral knowledge of a secret, without disclosing or transmitting the secret. 4 | 5 | This applet is compatible to the Yubikey-style protocol, supported by e.g. KeePassXC. 6 | 7 | ## Applet Information 8 | 9 | - Repository: https://github.com/DangerousThings/flexsecure-ykhmac (which is a fork of https://github.com/arekinath/YkOtpApplet. The fork fixes some bugs.). 10 | - Binary name: `YkHMACApplet.cap` 11 | - Download: https://github.com/DangerousThings/flexsecure-applets/releases 12 | - AID: `A0:00:00:05:27:20:01:01`, Package: `A0:00:00:05:27:20` 13 | - Storage requirements: 14 | - Persistent: `3204` bytes 15 | - Transient reset: `240` bytes 16 | - Transient deselect: `128` bytes 17 | 18 | ## Compiling the Applet Yourself 19 | 20 | Setup your environment as described in *JavaCard Development Setup* . 21 | 22 | Use git to clone the sources recursively, and change into the directory. Make sure the submodule in `/sdks` is checked out. To compile, run `ant dist`. 23 | 24 | ## Installing the Applet 25 | 26 | Use GlobalPlatformPro (GPP) from https://github.com/martinpaljak/GlobalPlatformPro/releases to install the applet: 27 | 28 | ``` 29 | gp -install YkHMACApplet.cap 30 | ``` 31 | 32 | Listing the applets using `gp --list` should print something like this: 33 | 34 | ``` 35 | APP: A000000527200101 (SELECTABLE) 36 | Parent: A000000151000000 37 | From: A00000052720 38 | 39 | PKG: A00000052720 (LOADED) 40 | Parent: A000000151000000 41 | Version: 1.0 42 | Applet: A000000527200101 43 | ``` 44 | 45 | ## Using the Applet 46 | 47 | This applet behaves the same way as the challenge-response functionality on a Yubikey. However, it cannot be initialized using the Yubikey Personalization GUI tools, because these require a USB connection. Instead, various other tools can be used. 48 | 49 | First of all, make sure no YubiKeys are connected to your PC, or it might be overwritten if you are not careful. 50 | 51 | Second, make sure to keep a backup of your secret key somewhere. 52 | 53 | You can use the yubikey-manager CLI tool (`ykman`) to interface with the applet. You have to specify your reader using the `-r` flag (use `ykman list -r` to get a list of readers). Replace `SECRET` with a 40 character (20 byte) hexadecimal secret: 54 | 55 | ``` 56 | ykman -r 'READER' otp chalresp -f 1 SECRET 57 | ``` 58 | 59 | Use the `-f` flag to specify the slot (1 or 2). 60 | 61 | You can also use the `yktool.jar` utility (Download from https://github.com/arekinath/yktool/releases). Take care of the string encoding on your operating system, this command is for Linux: 62 | 63 | ``` 64 | echo SECRET | java -jar yktool.jar program hmac 1 -x -X 65 | ``` 66 | 67 | Again, the `1` specifies the key slot number. 68 | 69 | ### Manual Challenge-Response 70 | 71 | For testing, you can issue a challenge and get a response. Replace `CHALLENGE` with a 64 character (32 byte) hexadecimal challenge: 72 | 73 | ``` 74 | ykman -r 'READER' otp calculate 1 CHALLENGE 75 | ``` 76 | 77 | You can also use `yktool.jar`: 78 | 79 | ``` 80 | printf CHALLENGE | java -jar yktool.jar hmac 1 -x -X 81 | ``` 82 | 83 | If everything is encoded correctly, the commands should give the same response. 84 | 85 | ### Usage with KeePassXC 86 | 87 | Thanks to a PR by me (https://github.com/keepassxreboot/keepassxc/pull/6895, https://github.com/keepassxreboot/keepassxc/pull/6766) KeePassXC is able to interface with this applet and Yubikeys via NFC using any compatible reader. This work on Windows, Linux and Mac. 88 | 89 | To add a Yubikey as protection to your Database, refer to the KeePassXC documentation (or just look at the UI). 90 | 91 | ### Usage with ykdroid 92 | 93 | The `ykdroid` Android library implements this protocol, and provides it to apps like KeePass2Android. In these apps, make sure to select *Password + Challenge-Response for KeePass XC* as decryption method (if you use KeePassXC with the same Database). 94 | 95 | ## Sources and Further Reading 96 | 97 | - https://keepassxc.org/ 98 | - https://en.wikipedia.org/wiki/HMAC 99 | - https://chrz.de/2021/12/22/nfc-hacking-part-1-authentication-systems-security/ 100 | - https://github.com/DangerousThings/flexsecure-ykhmac 101 | - https://github.com/arekinath/yktool 102 | - http://www.average.org/chal-resp-auth/ 103 | - https://crypto.stackexchange.com/questions/26510/why-is-hmac-sha1-still-considered-secure 104 | - https://www.rfc-editor.org/rfc/rfc4226#appendix-B.2 105 | - https://developers.yubico.com/yubikey-manager/ 106 | - https://github.com/arekinath/yktool 107 | - https://github.com/PhilippC/keepass2android 108 | - https://github.com/pp3345/ykDroid 109 | - https://play.google.com/store/apps/details?id=keepass2android.keepass2android_nonet 110 | - https://play.google.com/store/apps/details?id=net.pp3345.ykdroid 111 | 112 | Improve this document: https://github.com/DangerousThings/flexsecure-applets/tree/master/docs 113 | -------------------------------------------------------------------------------- /docs/applets/4-ndef.md: -------------------------------------------------------------------------------- 1 | # Storing Data using NDEF 2 | 3 | NDEF (NFC Data Exchange Format) is a data format used to store structured data. 4 | 5 | ## Applet Information 6 | 7 | - Repository: https://github.com/OpenJavaCard/openjavacard-ndef 8 | - Binary name: `openjavacard-ndef-full.cap` and `openjavacard-ndef-tiny.cap` 9 | - Download: https://github.com/DangerousThings/flexsecure-applets/releases 10 | - AID: `D2:76:00:00:85:01:01`, Package: `D2:76:00:00:85` 11 | - Storage requirements: 12 | - Persistent: `4372` bytes 13 | - Transient reset: `16` bytes 14 | - Transient deselect: `0` bytes 15 | 16 | ## Compiling the Applet Yourself 17 | 18 | Setup your environment as described in *JavaCard Development Setup* . 19 | 20 | Use git to clone the sources, and change into the directory. To compile, run `ant -DJAVACARD_HOME=/jc222_kit build`, replacing `` with the path to your JavaCard SDKs. 21 | 22 | The build definition produces various versions of the applet, the most interesting ones are `full`, which is a read-write enabled version, and `tiny`, which is a read-only version with static data. 23 | 24 | ## Installing the Applet 25 | 26 | To install the applet to your card, you have to pass along some configuration data. 27 | 28 | Use GlobalPlatformPro (GPP) from https://github.com/martinpaljak/GlobalPlatformPro/releases to install the applet: 29 | 30 | To install the `full` variant with 2KB re-writeable storage: 31 | 32 | ``` 33 | gp -install openjavacard-ndef-full.cap -create D2760000850101 -params 8102000082020800 34 | ``` 35 | 36 | The TLV configuration format has a few options, for the specification see the openjavacard-ndef documentation at https://github.com/OpenJavaCard/openjavacard-ndef/blob/master/doc/install.md . 37 | 38 | To install the `tiny` variant with the static URL "https://chrz.de": 39 | 40 | ``` 41 | gp -install openjavacard-ndef-tiny.cap -create D2760000850101 -params d90108015531046368727a2e6465 42 | ``` 43 | 44 | You can generate the parameter data for the `tiny` variant using a few lines of Python 3 and the `ndeflib` Pip module: 45 | 46 | ```python 47 | import ndef 48 | record = ndef.Record('urn:nfc:wkt:U', '1', b'\x04chrz.de') 49 | print((b''.join((ndef.message_encoder([ record ])))).hex()) 50 | ``` 51 | 52 | Check the documentation at https://ndeflib.readthedocs.io/en/latest/ndef.html#record-class . Make sure your data has a maximum size of about 200 bytes. 53 | 54 | Listing the applets using `gp --list` should print something like this: 55 | 56 | ``` 57 | APP: D2760000850101 (SELECTABLE) 58 | Parent: A000000151000000 59 | From: D276000177100211030001 60 | 61 | PKG: D276000177100211030001 (LOADED) 62 | Parent: A000000151000000 63 | Version: 0.0 64 | Applet: D27600017710021103000101 65 | ``` 66 | 67 | For more options, see the openjavacard-ndef documentation. 68 | 69 | ## Using the Applet 70 | 71 | NDEF is widely supported by most smartphones. To write data to a re-writeable tag, I recommend using NFC Tools Pro an Android, but most apps should be compatible. 72 | 73 | On PC, you can use the `pcsc_ndef.py` tool from https://github.com/Giraut/pcsc-ndef, you have to specify your reader using the `-r` flag. Substitute `PAYLOAD` for the data you want to write: 74 | 75 | ``` 76 | echo PAYLOAD | python3 pcsc_ndef.py -r "READER" -t 4 write 77 | 78 | python3 pcsc_ndef.py -r "READER" -t 4 read 79 | ``` 80 | 81 | ## Sources and Further Reading 82 | 83 | - https://learn.adafruit.com/adafruit-pn532-rfid-nfc/ndef 84 | - https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.0.0/nrf/include/nfc/ndef/nfc.html 85 | - http://sweet.ua.pt/andre.zuquete/Aulas/IRFID/11-12/docs/NFC%20Data%20Exchange%20Format%20(NDEF).pdf 86 | - https://www.netes.com.tr/netes/dosyalar/dosya/B6159F60458582512B16EF1263ADE707.pdf 87 | - https://github.com/OpenJavaCard/openjavacard-ndef/tree/master/doc 88 | - https://github.com/Giraut/pcsc-ndef 89 | - https://github.com/nfcpy/ndeflib 90 | - https://ndeflib.readthedocs.io/en/latest 91 | - https://play.google.com/store/apps/details?id=com.wakdev.nfctools.pro 92 | 93 | Improve this document: https://github.com/DangerousThings/flexsecure-applets/tree/master/docs -------------------------------------------------------------------------------- /docs/applets/5-u2f.md: -------------------------------------------------------------------------------- 1 | # Universal Two-Factor Authentication using U2F 2 | 3 | **FIDO** (Fast IDentity Online) **U2F** (Universal 2nd Factor) is a standard for two-factor authentication. It is extended and superseded by FIDO2, but still widely used. 4 | 5 | The applet requires an attestation certificate. This certificate can be a default one, or generated by you, or an official one signed by a company like Vivokey or Yubico. You don't want to generate a unique certificate for each token, because that would make the tokens uniquely identifiable, leading to privacy concerns. 6 | 7 | The attestation certificate is used to sign certificates for transport when you register with a service. The token manufacturer (e.g. Vivokey) can also use this certificate (which they sign using their certificate authority) to validate the authenticity and model of the token and applet. 8 | 9 | Supported features (if installed via Fidesmo): 10 | - Normal and extended APDU support 11 | - Server credentials 12 | - Credential types: 13 | - ECDSA P-256 + SHA-256 (ES2569) 14 | - Basic attestation using a fleet certificate 15 | - Signed by the VivoKey certificate authority 16 | - User presence (assuming the chip is implanted) 17 | - FIDO MDS entry 18 | 19 | ## Applet Information 20 | 21 | ### FIDO U2F 22 | 23 | - Repository: https://github.com/darconeous/u2f-javacard 24 | - Binary name: `U2FApplet.cap` 25 | - Download: https://github.com/DangerousThings/flexsecure-applets/releases 26 | - AID: `a0:00:00:06:47:2F:00:01:01`, Package: `a0:00:00:06:47:2F:00:01` 27 | - Storage requirements: 28 | - Persistent: `8020` bytes 29 | - Transient reset: `865` bytes 30 | - Transient deselect: `0` bytes 31 | 32 | ## Compiling the Applet Yourself 33 | 34 | Setup your environment as described in *JavaCard Development Setup* . 35 | 36 | Use git to clone the sources recursively, and change into the directory. To compile, run `JC_HOME=/jc304_kit ant`, replacing `` with the path to your JavaCard SDKs. 37 | 38 | ## Installing the Applet 39 | 40 | You can not use the U2F applet at the same time as the FIDO2 one because they use the same AID. 41 | 42 | ### Generate Attestation Certificate 43 | 44 | You can generate your own attestation certificate. This makes your token unique, which is maybe not something you want. 45 | 46 | In the future, Vivokey plans offer signed certificates using their own certificate authority in some way. It is unclear if or how these would be coming to the FlexSecure, as they require the more protected environment of the Apex Flex in order to not leak. 47 | 48 | Creating certificates used to be quite the involved task requiring advanced knowledge of `openssl` commands, but I have written a small tool to simplify the process. Install Python3, and the `cryptography`, `asn1`, and `pyscard` modules (e.g. using Pip). Then, clone or download https://github.com/DangerousThings/fido-attestation-loader . 49 | 50 | If you specify no flags, the script will use the default file names `attestation.der`, `attestation_key.p8`, `ca.der`, `ca_key.p8`, and `settings.ini`. If you want to, you can edit the metadata in `settings.ini`, also refer to the Readme file. 51 | 52 | First, generate a certificate authority, the script will ask you for a passphrase to secure the private key. 53 | 54 | ``` 55 | ./attestation.py ca create 56 | ``` 57 | 58 | Next, generate an attestation certificate and sign it using the CA. You have to create another passphrase to protect the private key of the attestation certificate. 59 | 60 | ``` 61 | ./attestation.py cert create 62 | ``` 63 | 64 | Then, you can derive the applet installation parameter by running, for FIDO U2F: 65 | 66 | ``` 67 | ./attestation.py cert show -m u2f 68 | ``` 69 | 70 | The attestation script has a lot more flags to control which files to use, and to provide passphrases via the arguments instead of interactively typing them. It also provides functionality to validate a certificate gainst an certificate authority. See the `-h` help command for more details, or refer to the Readme file of https://github.com/DangerousThings/fido-attestation-loader . 71 | 72 | Use GlobalPlatformPro (GPP) from https://github.com/martinpaljak/GlobalPlatformPro/releases to install the applet, for Fido U2F: 73 | 74 | ``` 75 | gp -install U2FApplet.cap --params INSTALLPARAM 76 | ``` 77 | 78 | The parameter data (`INSTALLPARAM`) is `00`, joined to the length in bytes of the public attestation certificate (16 bit integer = 2 bytes), and joined to the private key (32 bytes). See https://github.com/darconeous/u2f-javacard/blob/master/README.md for more info. You can copy it from the last line of the output of `./attestation.py cert show`. 79 | 80 | Listing the applets using `gp --list` should print something like this: 81 | 82 | ``` 83 | APP: A0000006472F0001 (SELECTABLE) 84 | Parent: A000000151000000 85 | From: A000000617004F97A2E95001 86 | 87 | PKG: A000000617004F97A2E95001 (LOADED) 88 | Parent: A000000151000000 89 | Version: 1.1 90 | Applet: A000000617004F97A2E94901 91 | ``` 92 | 93 | Next, you have to load the public attestation certificate by sending a few chained APDUs. The DER encoded public certificate has to be chopped into `128` byte chunks, which are sent attached to a small header. The header is `80 01 HHLL KK`, with `HHLL` being a 16 bit integer offset of that chunk, and `KK` being the chunk length (hex `80`, usually smaller for the last chunk). Before sending the certificate, selecting the applet is required. 94 | 95 | The FIDO2 applet requires a few more bytes to specify the AAGUID. 96 | 97 | This task is covered by the attestation script as well, for FIDO U2F: 98 | 99 | ``` 100 | ./attestation.py cert upload -m u2f 101 | ``` 102 | 103 | You might have to specify your PCSC reader index using `-r`, use `-l` to list all readers. Note that you have to run the loader as Administator on Windows, because low-level access to FIDO applets is blocked by default. 104 | 105 | See also https://gist.github.com/darconeous/adb1b2c4b15d3d8fbc72a5097270cdaf for more info on these APDUs for U2F. 106 | 107 | ## Using the Applet 108 | 109 | Using the applet in the web requires a modern browser with support for FIDO. NFC tokens don't work on Linux (yet, see https://twitter.com/FIDOAlliance/status/1278331283874156544). 110 | 111 | You can use the *Yubikey WebAuthn test page* at https://demo.yubico.com/webauthn-technical/registration to test your token. 112 | 113 | On Android, you can use the *FIDO / Webauthn Example* App at https://play.google.com/store/apps/details?id=de.cotech.hw.fido.example for testing (Use the U2F tab), or use any Browser which supports the Security Manager (for details, see *Android Problems and Solutions*) and use the Yubico page. 114 | 115 | ## Sources and Further Reading 116 | 117 | - https://en.wikipedia.org/wiki/Universal_2nd_Factor 118 | - https://www.yubico.com/authentication-standards/fido-u2f/ 119 | - https://fidoalliance.org/fido-technotes-the-truth-about-attestation/ 120 | - https://gist.github.com/darconeous/adb1b2c4b15d3d8fbc72a5097270cdaf 121 | - https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#examples 122 | - https://demo.yubico.com/webauthn-technical/registration 123 | - https://research.kudelskisecurity.com/2020/02/12/fido2-deep-dive-attestations-trust-model-and-security/ 124 | - https://play.google.com/store/apps/details?id=de.cotech.hw.fido.example 125 | - https://developers.yubico.com/U2F/Attestation_and_Metadata/ 126 | - https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-authenticator-transports-extension-v1.2-ps-20170411.html#fido-u2f-certificate-extensions 127 | - https://github.com/DangerousThings/fido-attestation-loader 128 | 129 | Improve this document: https://github.com/DangerousThings/flexsecure-applets/tree/master/docs 130 | -------------------------------------------------------------------------------- /docs/applets/6-fido2.md: -------------------------------------------------------------------------------- 1 | # Universal Two-Factor Authentication using FIDO2 2 | 3 | **FIDO2 CTAP2** (Client to Authenticator Protocol) is an extension and improvement over FIDO U2F. 4 | 5 | The FIDO2 applet is still in development, and not completely finished. For example, Windows Hello is not supported yet. Stay tuned. It is also not officially certified. 6 | 7 | You can however already test the FIDO2 applet via the Vivokey Apex on Fidesmo. 8 | 9 | Supported features (if installed via Fidesmo): 10 | - Normal, chained and extended APDU support 11 | - Server and resident credentials 12 | - Credential types: 13 | - ECDSA P-256 + SHA-256 (ES2569) 14 | - RSASSA-PKCS1-v1_5 2048 + SHA-256 (RS256) 15 | - RSASSA-PSS 2048 + SHA-256 (PS256) 16 | - HMAC secret extension 17 | - Basic direct attestation using a fleet certificate 18 | - Signed by the VivoKey certificate authority 19 | - User verification types: 20 | - Client PIN protocol version 1 21 | - User presence (assuming the chip is implanted) 22 | - Multiple accounts per relying party 23 | - FIDO MDS entry 24 | 25 | The FIDO2 applet source code is not publicly available (anymore). Binaries are only distributed via Fidesmo (as of now. Options on how to bring it to the FlexSecure are in development). If you want an open-source authenticator, use the U2F one. 26 | 27 | ## Applet Information 28 | 29 | ### FIDO2 CTAP2 30 | 31 | - Repository: Private 32 | - Binary name: Not published on GitHub 33 | - Download: N/A 34 | - AID: `a0:00:00:06:47:2F:00:01:01`, Package: `a0:00:00:06:47:2F:00:01` 35 | - Storage requirements: 36 | - Persistent: `19336` bytes 37 | - Transient reset: `2273` bytes 38 | - Transient deselect: `32` bytes 39 | 40 | ## Using the Applet 41 | 42 | Using the applet in the web requires a modern browser with support for FIDO. NFC tokens don't work on Linux browsers (yet, see https://twitter.com/FIDOAlliance/status/1278331283874156544), however you can use my CTAP-Bridge (https://github.com/StarGate01/CTAP-bridge) to proxy NFC tokens as virtual USB tokens in Linux. 43 | 44 | You can use the *Yubikey WebAuthn test page* at https://demo.yubico.com/webauthn-technical/registration or the Webauthn Debugger (https://webauthn.me/debugger) to test your token. 45 | 46 | On Android, you can use the *FIDO / Webauthn Example* App at https://play.google.com/store/apps/details?id=de.cotech.hw.fido.example for testing, or use any Browser which supports the Security Manager (for details, see *Android Problems and Solutions*) and use the Yubico page. 47 | 48 | ### Attestation 49 | 50 | Similar to the U2F applet, the FIDO2 applet contains an embedded attestation certificate and key of the manufacturer. This certificate is used to sign responses of the authenticator, such that the relying party can verify the manufacturer and model of the authenticator. 51 | 52 | ### User Presence and User Verification 53 | 54 | User presence is always ensured by default, because the mode of data transportation is via NFC, which requires physical proximity. However, only one operation may be performed per touch, after which the token must be re-presented. This is to defend against automated attacks. 55 | 56 | User verification has to be requested by the relying party and is provided via the client PIN protocol. 57 | 58 | ### Server and Resident Credentials 59 | 60 | By default, the authenticator creates server credentials, which are not stored on the authenticator, but instead encoded and encrypted into the credential ID and stored with the relying party. If requested by the relying party, the authenticator will instead create a resident credential, which stores the key material on the authenticator until it runs out of storage space. 61 | 62 | ## Sources and Further Reading 63 | 64 | - https://fidoalliance.org/fido-technotes-the-truth-about-attestation/ 65 | - https://demo.yubico.com/webauthn-technical/registration 66 | - https://en.wikipedia.org/wiki/FIDO2_Project 67 | - https://www.1kosmos.com/authentication/fido2-authentication/ 68 | - https://research.kudelskisecurity.com/2020/02/12/fido2-deep-dive-attestations-trust-model-and-security/ 69 | - https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html 70 | - https://play.google.com/store/apps/details?id=de.cotech.hw.fido.example 71 | 72 | Improve this document: https://github.com/DangerousThings/flexsecure-applets/tree/master/docs -------------------------------------------------------------------------------- /docs/applets/8-bip32.md: -------------------------------------------------------------------------------- 1 | # BIP32 Cryptocurrency Wallet using KeyCard 2 | 3 | The BIP32 Wallet is a distribution of the Status.im KeyCard applet. Read more at https://status.im/secure-wallet/ and https://keycard.tech/ . 4 | 5 | ## Applet Information 6 | 7 | - Repository: https://github.com/status-im/status-keycard 8 | - Binary name: `keycard.cap` 9 | - Download: https://github.com/DangerousThings/flexsecure-applets/releases 10 | - AID: `A0:00:00:08:04:00:01:01:01` (core) and `A0:00:00:08:04:00:01:03:01` (cash), Package: `A0:00:00:08:04:00:01` 11 | - Storage requirements: 12 | - Persistent: `16424` bytes 13 | - Transient reset: `1366` bytes 14 | - Transient deselect: `400` bytes 15 | 16 | ## Compiling the Applet Yourself 17 | 18 | Setup your environment as described in *JavaCard Development Setup* . 19 | 20 | Use git to clone the sources recursively, and change into the directory. To compile, run `./gradlew convertJavacard`. 21 | 22 | ## Installing the Applet 23 | 24 | The cabinet file contains three distinct applets, of which the NDEF one is not needed. The other two (core and cash) need to be installed. 25 | 26 | Use GlobalPlatformPro (GPP) from https://github.com/martinpaljak/GlobalPlatformPro/releases to install the applets: 27 | 28 | ``` 29 | gp -load keycard.cap 30 | 31 | gp -package A0000008040001 -applet A000000804000101 -create A00000080400010101 32 | 33 | gp -package A0000008040001 -applet A000000804000103 -create A00000080400010301 34 | ``` 35 | 36 | Listing the applets using `gp --list` should print something like this: 37 | 38 | ``` 39 | APP: A00000080400010101 (SELECTABLE) 40 | Parent: A000000151000000 41 | From: A0000008040001 42 | Privs: 43 | 44 | APP: A00000080400010301 (SELECTABLE) 45 | Parent: A000000151000000 46 | From: A0000008040001 47 | Privs: 48 | 49 | PKG: A0000008040001 (LOADED) 50 | Parent: A000000151000000 51 | Version: 3.1 52 | Applet: A000000804000101 53 | Applet: A000000804000102 54 | Applet: A000000804000103 55 | ``` 56 | 57 | ## Using the Applet 58 | 59 | Install the Status.im app on your phone and follow the setup instructions. For more information, refer to the app documentation. 60 | 61 | ## Sources and Further Reading 62 | 63 | - https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki 64 | - https://keycard.tech/ 65 | - https://status.im/ 66 | - https://gist.github.com/rbnpercy/adae04c4fddeee4d324d6028ab4b4d47 67 | - https://play.google.com/store/apps/details?id=im.status.ethereum 68 | 69 | Improve this document: https://github.com/DangerousThings/flexsecure-applets/tree/master/docs -------------------------------------------------------------------------------- /docs/img/javacards.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DangerousThings/flexsecure-applets/096ce2ab1ce0279b868d964fd053a6e647feba4a/docs/img/javacards.jpeg -------------------------------------------------------------------------------- /docs/notes/command_surface.md: -------------------------------------------------------------------------------- 1 | This document lists all the `INS` instruction bytes accepted by the applets linked in this repository. 2 | 3 | The `CLA` class byte is usually `00`, `80`, `B0`, or any of these `| 10` . 4 | 5 | ## All applets 6 | 7 | Standard ISO commands: 8 | 9 | - `C0`: GET RESPONSE 10 | - `A4`: SELECT 11 | 12 | Vivokey extension: 13 | 14 | - `F4`: GET VERSION 15 | 16 | ## apex-fido2, FIDO2Applet, and u2f-javacard 17 | 18 | NFCCTAP 2.0 commands, apex-fido2 and FIDO2Applet only: 19 | 20 | - `10`: MESSAGE 21 | - `11`: GET RESPONSE 22 | - `12`: CONTROL 23 | 24 | U2F commands: 25 | 26 | - `01`: REGISTER 27 | - `02`: AUTHENTICATE 28 | - `03`: VERSION 29 | 30 | ## apex-ndef, openjavacard-ndef, and status-keycard/NDEFApplet 31 | 32 | T4TOP 2.0 commands: 33 | 34 | - `B0`: READ BINARY 35 | - `D6`: UPDATE BINARY 36 | 37 | apex-ndef only: 38 | 39 | - `E1`: DISABLE WRITE 40 | 41 | ## apex-spark 42 | 43 | NTAGDNA commands: 44 | 45 | - `71`: AUTH FIRST 46 | - `AF`: AUTH FIRST P2 47 | 48 | ## apex-tesla 49 | 50 | Tesla commands: 51 | 52 | - `04`: GET PUBKEY 53 | - `06`: GET CERT 54 | - `07`: GET VERSIONS 55 | - `11`: GET CHALLENGE 56 | - `14`: GET FACTOR 57 | - `1B`: SET INFO 58 | - `00`, `01`, `02`, `03`, `04`, `05`, `08`, `12`, `13`, `14`, `15`: UNKNOWN 59 | 60 | ## apex-totp 61 | 62 | Yubico OTP commands: 63 | 64 | - `01`: PUT 65 | - `02`: DELETE 66 | - `03`: SET CODE 67 | - `04`: RESET 68 | - `05`: RENAME 69 | - `A1`: LIST 70 | - `A2`: CALCULATE 71 | - `A3`: VALIDATE 72 | - `A4`: CALCULATE ALL 73 | - `A5`: SEND REMAINING 74 | 75 | ## flexsecure-ykhmac 76 | 77 | Yubico HMAC commands 78 | 79 | - `01`: API REQ 80 | - `02`: OTP (unused) 81 | - `03`: STATUS 82 | - `04`: NDEF (unused) 83 | 84 | ## javacard-memory 85 | 86 | No commands beyond applet selection 87 | 88 | ## SatochipApplet, Satodime-Applet, and Seedkeeper-Applet 89 | 90 | Common commands: 91 | 92 | - `2A`: SETUP 93 | - `3C`: GET STATUS 94 | - `3D`: CARD LABEL 95 | - `81`: INIT SECURE CHANNEL 96 | - `82`: PROCESS SECURE CHANNEL 97 | - `AD`: EXPORT AUTHENTIKEY 98 | - `92`: IMPORT PKI CERTIFICATE 99 | - `93`: EXPORT PKI CERTIFICATE 100 | - `94`: SIGN PKI CSR 101 | - `98`: EXPORT PKI PUBKEY 102 | - `99`: LOCK PKI 103 | - `9A`: CHALLENGE RESPONSE PKI 104 | 105 | Satochip and Seedkeeper: 106 | 107 | - `40`: CREATE PIN 108 | - `42`: VERIFY PIN 109 | - `44`: CHANGE PIN 110 | - `46`: UNBLOCK PIN 111 | - `60`: LOGOUT ALL 112 | - `48`: LIST PINS 113 | - `73`: BIP32 GET AUTHENTIKEY 114 | - `FF`: RESET TO FACTORY 115 | 116 | Satochip-only commands: 117 | 118 | - `32`: IMPORT KEY 119 | - `33`: RESET KEY 120 | - `35`: GET PUBLIC FROM PRIVATE 121 | - `6C`: BIP32 IMPORT SEED 122 | - `77`: BIP32 RESET SEED 123 | - `75`: BIP32 SET AUTHENTIKEY PUBKEY 124 | - `6D`: BIP32 GET EXTENDED KEY 125 | - `74`: BIP32 SET EXTENDED PUBKEY 126 | - `6E`: SIGN MESSAGE 127 | - `72`: SIGN SHORT MESSAGE 128 | - `6F`: SIGN TRANSACTION 129 | - `71`: PARSE TRANSACTION 130 | - `76`: CRYPT TRANSACTION 2FA 131 | - `79`: SET 2FA KEY 132 | - `78`: RESET 2FA KEY 133 | - `7A`: SIGN TRANSACTION HASH 134 | - `AC`: IMPORT ENCRYPTED SECRET 135 | - `AA`: IMPORT TRUSTED PUBKEY 136 | - `AB`: EXPORT TRUSTED PUBKEY 137 | 138 | Seedkeeper-only commands: 139 | 140 | - `A0`: GENERATE MASTERSEED 141 | - `AE`: GENERATE 2FA SECRET 142 | - `A1`: IMPORT SECRET 143 | - `A2`: EXPORT SECRET 144 | - `A5`: RESET SECRET 145 | - `A6`: LIST SECRET HEADERS 146 | - `A9`: PRINT LOGS 147 | 148 | Satodime-only commands: 149 | 150 | - `50`: GET SATODIME STATUS 151 | - `51`: GET SATODIME KEYSLOT STATUS 152 | - `52`: SET SATODIME KEYSLOT STATUS 153 | - `53`: GET SATODIME UNLOCK CODE (unused) 154 | - `55`: GET SATODIME PUBKEY 155 | - `56`: GET SATODIME PRIVKEY 156 | - `57`: SEAL SATODIME KEY 157 | - `58`: UNSEAL SATODIME KEY 158 | - `59`: RESET SATODIME KEY 159 | - `5A`: INITIATE SATODIME TRANSFER 160 | 161 | ## SmartPGP 162 | 163 | OpenPGP Card commands: 164 | 165 | - `A5`: SELECT DATA 166 | - `CA`: GET DATA 167 | - `CC`: GET NEXT DATA 168 | - `20`: VERIFY 169 | - `24`: CHANGE REFERENCE DATA 170 | - `2C`: RESET RETRY COUNTER 171 | - `DA`: PUT DATA DA 172 | - `DB`: PUT DATA DB 173 | - `47`: GENERATE ASYMMETRIC KEY PAIR 174 | - `2A`: PERFORM SECURITY OPERATION 175 | - `88`: INTERNAL AUTHENTICATE 176 | - `84`: GET CHALLENGE 177 | - `E6`: TERMINATE DF 178 | - `44`: ACTIVATE FILE 179 | 180 | ## status-keycard 181 | 182 | Keycard commands: 183 | 184 | - `F2`: GET STATUS 185 | - `FE`: INIT 186 | - `FD`: FACTORY RESET 187 | - `20`: VERIFY PIN 188 | - `21`: CHANGE PIN 189 | - `22`: UNBLOCK PIN 190 | - `D0`: LOAD KEY 191 | - `D1`: DERIVE KEY 192 | - `D2`: GENERATE MNEMONIC 193 | - `D3`: REMOVE KEY 194 | - `D4`: GENERATE KEY 195 | - `C0`: SIGN 196 | - `C1`: SET PINLESS PATH 197 | - `C2`: EXPORT KEY 198 | - `CA`: GET DATA 199 | - `E2`: STORE DATA 200 | -------------------------------------------------------------------------------- /eclipse-formatter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1741513245, 6 | "narHash": "sha256-7rTAMNTY1xoBwz0h7ZMtEcd8LELk9R5TzBPoHuhNSCk=", 7 | "owner": "nixos", 8 | "repo": "nixpkgs", 9 | "rev": "e3e32b642a31e6714ec1b712de8c91a3352ce7e1", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "nixos", 14 | "ref": "nixos-unstable", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; 4 | }; 5 | 6 | outputs = { self, nixpkgs }: 7 | let 8 | pkgs = import nixpkgs { 9 | system = "x86_64-linux"; 10 | }; 11 | in 12 | { 13 | devShell.x86_64-linux = 14 | pkgs.mkShell { 15 | shellHook = '' 16 | export JAVA_HOME="${pkgs.jdk}" 17 | export JAVA_HOME_JDK8="${pkgs.jdk8}" 18 | ''; 19 | 20 | buildInputs = with pkgs; [ 21 | jdk 22 | jdk8 23 | ant 24 | maven 25 | doxygen 26 | graphviz 27 | libfido2 28 | (python3.withPackages (ps: with ps; [ 29 | pyscard 30 | cryptography 31 | fido2 32 | JPype1 33 | parameterized 34 | pyasn1 35 | requests 36 | pyjwt 37 | (buildPythonPackage rec { 38 | pname = "uhid"; 39 | version = "0.0.1"; 40 | src = fetchPypi { 41 | inherit pname version; 42 | sha256 = "sha256-PHgkiYkNvzNiH7LDDRrIH7wbPvGRGufUxzkHzcD1mqs="; 43 | }; 44 | format = "pyproject"; 45 | doCheck = false; 46 | propagatedBuildInputs = [ 47 | setuptools 48 | ]; 49 | }) 50 | ])) 51 | ]; 52 | }; 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /scripts/algscan.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | grep -Er '\b(Cipher|Signature|MessageDigest|RandomData|KeyBuilder|KeyAgreement|Checksum|KeyPair|AEADCipher|OwnerPINBuilder|InitializedMessageDigest)\.[A-Z]' --include='*.java' applets/ \ 4 | | grep -vE '/(test|sdks)/' \ 5 | | grep -v '\.MODE_' \ 6 | | sed -E 's|^applets/([^/]+)/[^:]*:(.*)|\1: \2|' -------------------------------------------------------------------------------- /scripts/clean-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "${0%/*}" 4 | 5 | for i in clean/*.sh; do 6 | [ -f "$i" ] || break 7 | echo "Cleaning $i" 8 | $i 9 | done 10 | 11 | echo "Cleaning binaries" 12 | cd /app/src/bin && rm -f *.cap *.jar 13 | -------------------------------------------------------------------------------- /scripts/clean/FIDO2Applet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/FIDO2Applet 4 | rm -rf build .gradle bin 5 | -------------------------------------------------------------------------------- /scripts/clean/SatochipApplet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/SatochipApplet 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/Satodime-Applet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/Satodime-Applet 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/Seedkeeper-Applet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/Seedkeeper-Applet 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/SmartPGP.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/SmartPGP 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/apex-fido2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/apex-fido2 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/apex-ndef.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/apex-ndef 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/apex-spark.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/apex-spark 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/apex-tesla.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/apex-tesla 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/apex-totp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/apex-totp 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/flexsecure-ykhmac.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/flexsecure-ykhmac 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/javacard-memory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/javacard-memory 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/clean/openjavacard-ndef.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/openjavacard-ndef 4 | rm -rf build 5 | -------------------------------------------------------------------------------- /scripts/clean/status-keycard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/status-keycard 4 | rm -rf build .gradle 5 | -------------------------------------------------------------------------------- /scripts/clean/u2f-javacard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/applets/u2f-javacard 4 | rm -rf target 5 | -------------------------------------------------------------------------------- /scripts/compile-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "${0%/*}" 4 | 5 | FAIL=0 6 | 7 | for i in compile/*.sh; do 8 | [ -f "$i" ] || break 9 | if [[ "$i" != *"apex-fido2"* && "$i" != *"apex-tesla"* && "$i" != *"apex-ndef"* && "$i" != *"apex-spark"* ]] || [[ "$1" == "private" ]]; then 10 | echo "Compiling $i" 11 | $i 12 | else 13 | echo "Skipping $i" 14 | fi 15 | if [ "$?" != 0 ]; then 16 | echo "Failed to compile $i" 17 | FAIL=1 18 | fi 19 | done 20 | 21 | if [ "$FAIL" == 0 ]; then 22 | echo "All binaries compiled successfully." 23 | exit 0 24 | else 25 | echo "One or more binaries failed to compile." 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /scripts/compile/FIDO2Applet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build FIDO2Applet 6 | patch_version $BUILD/src/main/java/us/q3q/fido2/FIDO2Applet.java 7 | cd $BUILD 8 | JC_HOME=/app/sdks/jc304_kit ./gradlew -PPackageID=A0000006472F0001 -PApplicationID=A0000006472F000101 buildJavaCard classes 9 | cp $BUILD/build/javacard/*.cap /app/src/bin/ 10 | -------------------------------------------------------------------------------- /scripts/compile/SatochipApplet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build SatochipApplet 6 | cp -f /app/src/scripts/compile/res/SatochipApplet.build.xml $BUILD/build.xml 7 | patch_version $BUILD/src/org/satochip/applet/CardEdge.java 8 | JC_HOME=/app/sdks/jc304_kit build_default -------------------------------------------------------------------------------- /scripts/compile/Satodime-Applet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build Satodime-Applet 6 | cp /app/src/scripts/compile/res/Satodime-Applet.build.xml $BUILD/build.xml 7 | patch_version $BUILD/src/org/satodime/applet/Satodime.java 8 | JC_HOME=/app/sdks/jc304_kit build_default -------------------------------------------------------------------------------- /scripts/compile/Seedkeeper-Applet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build Seedkeeper-Applet 6 | cp /app/src/scripts/compile/res/Seedkeeper-Applet.build.xml $BUILD/build.xml 7 | patch_version $BUILD/src/org/seedkeeper/applet/SeedKeeper.java 8 | JC_HOME=/app/sdks/jc304_kit build_default -------------------------------------------------------------------------------- /scripts/compile/SmartPGP.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build SmartPGP 6 | cp /app/src/scripts/compile/res/SmartPGP.build.xml $BUILD/build.xml 7 | patch_version $BUILD/src/fr/anssi/smartpgp/SmartPGPApplet.java 8 | JC_HOME=/app/sdks/jc304_kit build_default -------------------------------------------------------------------------------- /scripts/compile/apex-fido2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build apex-fido2 6 | patch_version $BUILD/src/main/java/com/vivokey/fido2/Dispatcher.java 7 | JC_HOME=/app/sdks/jc305u3_kit build_default -------------------------------------------------------------------------------- /scripts/compile/apex-ndef.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build apex-ndef 6 | patch_version $BUILD/src/main/java/com/vivokey/ndef/NDEF.java 7 | JC_HOME=/app/sdks/jc305u3_kit build_default -------------------------------------------------------------------------------- /scripts/compile/apex-spark.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build apex-spark 6 | patch_version $BUILD/src/com/vivokey/spark/Spark2.java 7 | JC_HOME=/app/sdks/jc305u3_kit build_default -------------------------------------------------------------------------------- /scripts/compile/apex-tesla.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build apex-tesla 6 | patch_version $BUILD/src/com/vivokey/teslaIdent/TeslaIdent.java 7 | build_default -------------------------------------------------------------------------------- /scripts/compile/apex-totp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build apex-totp 6 | patch_version $BUILD/src/com/vivokey/otp/YkneoOath.java 7 | JC_HOME=/app/sdks/jc304_kit build_default dist 8 | -------------------------------------------------------------------------------- /scripts/compile/flexsecure-ykhmac.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build flexsecure-ykhmac 6 | patch_version $BUILD/src/main/java/com/vivokey/ykhmac/YkHMACApplet.java 7 | build_default dist 8 | -------------------------------------------------------------------------------- /scripts/compile/javacard-memory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build javacard-memory dist 6 | patch_version $BUILD/src/de/chrz/jcmemory/JCMemoryApplet.java 7 | JC_HOME=/app/sdks/jc304_kit build_default 8 | -------------------------------------------------------------------------------- /scripts/compile/openjavacard-ndef.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build openjavacard-ndef 6 | cd $BUILD 7 | cp -f /app/src/scripts/compile/res/openjavacard-ndef.build.xml build.xml 8 | patch_version $BUILD/applet-advanced/src/main/java/org/openjavacard/ndef/advanced/NdefApplet.java 9 | patch_version $BUILD/applet-full/src/main/java/org/openjavacard/ndef/full/NdefApplet.java 10 | patch_version $BUILD/applet-stub/src/main/java/org/openjavacard/ndef/stub/NdefApplet.java 11 | patch_version $BUILD/applet-tiny/src/main/java/org/openjavacard/ndef/tiny/NdefApplet.java 12 | ant -DJAVACARD_HOME=/app/sdks/jc222_kit build 13 | cd build/javacard 14 | cp *full.cap *tiny.cap /app/src/bin/ -------------------------------------------------------------------------------- /scripts/compile/res/SatochipApplet.build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /scripts/compile/res/Satodime-Applet.build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /scripts/compile/res/Seedkeeper-Applet.build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /scripts/compile/res/SmartPGP.build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ant build for SmartPGP applet 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /scripts/compile/res/compile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | prepare_build() { 4 | export BUILD=/tmp/builds/$1 5 | echo "Setting up build for $1 in $BUILD" 6 | mkdir -p /app/src/bin 7 | rm -rf $BUILD 8 | mkdir -p /tmp/builds 9 | cp -r /app/src/applets/$1 $BUILD 10 | } 11 | 12 | patch_version() { 13 | SRC="$BUILD/build.xml" 14 | if [ ! -f $SRC ]; then 15 | SRC="$BUILD/build.gradle" 16 | fi 17 | /app/src/scripts/compile/res/version.py -s $SRC -p $1 -v $DRONE_TAG 18 | } 19 | 20 | build_default() { 21 | cd $BUILD 22 | mkdir -p $BUILD/target 23 | ant $@ 24 | cp $BUILD/target/*.cap /app/src/bin/ 25 | } 26 | -------------------------------------------------------------------------------- /scripts/compile/res/openjavacard-ndef.build.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | JavaCard implementation of an NDEF Type 4 tag 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 61 | 63 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 77 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 91 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 105 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /scripts/compile/res/u2f-javacard.build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /scripts/compile/res/version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse, os, re 4 | 5 | if __name__ == '__main__': 6 | # Parse CLI arguments 7 | parser = argparse.ArgumentParser(description = 'FlexSecure-Applets version patching tool') 8 | parser.add_argument('-s', '--source', nargs='?', dest='source', type=str, 9 | const='', default='', help='File to read the applet version from') 10 | parser.add_argument('-p', '--patch', nargs='?', dest='patch', type=str, 11 | const='', default='', help='File to patch') 12 | parser.add_argument('-v', '--version', nargs='?', dest='version', type=str, 13 | const='255.255.255', default='255.255.255', help='Build version to encode') 14 | args = parser.parse_args() 15 | version = args.version.strip('v') 16 | print('info: Patching file: ' + args.patch) 17 | print('info: Applet version from: ' + args.source) 18 | print('info: Additional build version: ' + version) 19 | 20 | # Parse version source file 21 | _, ext = os.path.splitext(args.source) 22 | if(not os.path.isfile(args.source)): 23 | print('error: source file ' + args.source + 'does not exist') 24 | exit(1) 25 | with open(args.source, 'r') as f: 26 | config = f.read() 27 | if(ext == '.xml'): 28 | # Ant XML file 29 | matches = re.search("cap.*version[\s='\"]*([^\s'\"]*)", config, flags=re.DOTALL) 30 | elif(ext == '.gradle'): 31 | # Gradle config 32 | matches = re.search("javacard {.*version[\s=']*([^\s']*)", config, flags=re.DOTALL) 33 | else: 34 | print('error: Unknown source file format: ' + ext) 35 | if(matches == None): 36 | print("error: Cannot find version in config file") 37 | exit(1) 38 | appversion = matches.group(1) 39 | print("info: Found applet version: " + appversion) 40 | 41 | # Generate patch 42 | appversion = appversion.split('.') 43 | version = version.split('.') 44 | patch = ''' 45 | byte[] ver_buf = apdu.getBuffer(); 46 | if(ver_buf[ISO7816.OFFSET_INS] == (byte) 0xF4 && ver_buf[ISO7816.OFFSET_P1] == (byte) 0x99 && ver_buf[ISO7816.OFFSET_P2] == (byte) 0x99) {{ 47 | short ver_le = apdu.setOutgoing(); 48 | short ver_len = (short) 5; 49 | ver_len = ver_le > (short) 0 ? (ver_le > ver_len ? ver_len : ver_le) : ver_len; 50 | ver_buf[0] = (byte) {}; 51 | ver_buf[1] = (byte) {}; 52 | ver_buf[2] = (byte) {}; 53 | ver_buf[3] = (byte) {}; 54 | ver_buf[4] = (byte) {}; 55 | apdu.setOutgoingLength(ver_len); 56 | apdu.sendBytes((short) 0, ver_len); 57 | ver_buf = null; 58 | return; 59 | }} else {{ 60 | ver_buf = null; 61 | }} 62 | '''.format(appversion[0], appversion[1], version[0], version[1], version[2]) 63 | 64 | # Find patch location and apply patch 65 | if(not os.path.isfile(args.patch)): 66 | print('error: patch file ' + args.patch + 'does not exist') 67 | exit(1) 68 | with open(args.patch, 'r') as f: 69 | patchtarget = f.read() 70 | match = re.search("void\s*process\s*\((?:final)?\s*APDU apdu\)\s*(?:throws ISOException)?\s*{", patchtarget, flags=re.DOTALL) 71 | if(match == None): 72 | print("error: Cannot find process method in patch file") 73 | exit(1) 74 | offset = match.end() 75 | patchtarget = patchtarget[:offset] + patch + patchtarget[offset:] 76 | with open(args.patch, 'w') as f: 77 | f.write(patchtarget) 78 | 79 | print("info: Done patching") 80 | -------------------------------------------------------------------------------- /scripts/compile/status-keycard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build status-keycard 6 | patch_version $BUILD/src/main/java/im/status/keycard/CashApplet.java 7 | patch_version $BUILD/src/main/java/im/status/keycard/IdentApplet.java 8 | patch_version $BUILD/src/main/java/im/status/keycard/KeycardApplet.java 9 | patch_version $BUILD/src/main/java/im/status/keycard/NDEFApplet.java 10 | cd $BUILD 11 | JC_HOME=/app/sdks/jc304_kit ./gradlew convertJavacard 12 | cp $BUILD/build/javacard/im/status/keycard/javacard/*.cap /app/src/bin/ 13 | -------------------------------------------------------------------------------- /scripts/compile/u2f-javacard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "${0%/*}/res/compile.sh" 4 | 5 | prepare_build u2f-javacard 6 | cp /app/src/scripts/compile/res/u2f-javacard.build.xml $BUILD/build.xml 7 | patch_version $BUILD/src/main/java/com/ledger/u2f/U2FApplet.java 8 | JC_HOME=/app/sdks/jc304_kit build_default 9 | -------------------------------------------------------------------------------- /scripts/docker-build-image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "${0%/*}/../smartcard-ci" 4 | 5 | docker build -t vivokey/smartcard-ci:latest . -------------------------------------------------------------------------------- /scripts/docker-run-image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "${0%/*}/../smartcard-ci" 4 | 5 | docker run -it --rm -v `pwd`/..:/app/src:rw -v /tmp/smartcard-ci:/tmp:rw vivokey/smartcard-ci:latest "$@" 6 | -------------------------------------------------------------------------------- /scripts/jcardsim.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /app/src/jcardsim 4 | JC_CLASSIC_HOME=/app/sdks/jc305u3_kit/ mvn initialize 5 | JC_CLASSIC_HOME=/app/sdks/jc305u3_kit/ mvn clean install -------------------------------------------------------------------------------- /scripts/test-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "${0%/*}" 4 | 5 | FAIL=0 6 | 7 | for i in test/*.bats; do 8 | [ -f "$i" ] || break 9 | if [[ "$i" != *"apex-fido2"* && "$i" != *"apex-tesla"* && "$i" != *"apex-ndef"* && "$i" != *"apex-spark"* ]] || [[ "$1" == "private" ]]; then 10 | echo "Testing $i" 11 | $i 12 | else 13 | echo "Skipping $i" 14 | fi 15 | if [ "$?" != 0 ]; then 16 | echo "Failed to test $i" 17 | FAIL=1 18 | fi 19 | done 20 | 21 | if [ "$FAIL" == 0 ]; then 22 | echo "All tests passed." 23 | exit 0 24 | else 25 | echo "One or more tests failed." 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /scripts/test/FIDO2Applet.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load res/common.sh 4 | load res/FIDO.common.sh 5 | 6 | setup_file() { 7 | _setup_file 8 | } 9 | 10 | teardown_file() { 11 | _teardown_file 12 | } 13 | 14 | setup() { 15 | cd /tmp/builds/FIDO2Applet 16 | java -cp /app/tools/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:./build/classes/java/main com.licel.jcardsim.remote.VSmartCard /app/src/scripts/test/res/FIDO2Applet.jcardsim.cfg > /dev/null & 17 | JCSIM_PID="$!" 18 | sleep 2 19 | cd /app/tools/fido-attestation-loader 20 | ./attestation.py ca create -cap 123456 21 | ./attestation.py cert create -p 1234 -cap 123456 -m fido21 22 | PARAM=`./attestation.py cert show -p 1234 -f parameter -m fido21` 23 | PLEN=$((${#PARAM} / 2)) 24 | ALEN=$(($PLEN + 11)) 25 | PLEN=$(printf "%x\n" $PLEN) 26 | ALEN=$(printf "%x\n" $ALEN) 27 | opensc-tool -r 'Virtual PCD 00 00' -s "80 b8 00 00 $ALEN 08 A0 00 00 06 47 2F 00 01 00 $PLEN $PARAM FF" 28 | ./attestation.py cert upload -m fido21 29 | } 30 | 31 | teardown() { 32 | cd /app/tools/fido-attestation-loader 33 | rm -f *.der *.p8 assert_param cred* pubkey 34 | _teardown 35 | } 36 | 37 | 38 | @test "FIDO2 Register and Authenticate CTAP2-CTAP2 ES256" { 39 | fido_make_cred es256 hmac fido2 40 | fido_assert_cred es256 hmac fido2 41 | } 42 | 43 | @test "FIDO2 Register and Authenticate CTAP2-CTAP1" { 44 | fido_make_cred es256 nohmac fido2 45 | fido_assert_cred es256 nohmac u2f 46 | } 47 | 48 | @test "FIDO2 Register and Authenticate CTAP1-CTAP2" { 49 | fido_make_cred es256 nohmac u2f 50 | fido_assert_cred es256 nohmac fido2 51 | } 52 | 53 | @test "FIDO2 Register and Authenticate CTAP1-CTAP1" { 54 | fido_make_cred es256 nohmac u2f 55 | fido_assert_cred es256 nohmac u2f 56 | } 57 | 58 | #@test "FIDO2 Register and Authenticate https://demo.yubico.com/" { 59 | # RES=`fido2-webauthn-client "pcsc://slot0" 2>&1 | sed -n -e '/http_response_json: https:\/\/demo\.yubico\.com\/api\/v1\/simple\/webauthn\/authenticate-finish/,$p' | sed 1d` 60 | # STATUS=`echo $RES | jq -r '.status'` 61 | # [ "$STATUS" == "success" ] 62 | #} 63 | -------------------------------------------------------------------------------- /scripts/test/SmartPGP.default.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load res/common.sh 4 | load res/SmartPGP.common.sh 5 | 6 | setup_file() { 7 | _setup_file 8 | } 9 | 10 | teardown_file() { 11 | _teardown_file 12 | } 13 | 14 | setup() { 15 | pgp_setup default 16 | } 17 | 18 | teardown() { 19 | rm -rf /app/tmp 20 | rm -rf ~/.gnupg 21 | _teardown 22 | } 23 | 24 | 25 | @test "GPG generate RSA 2048 key and sign" { 26 | generate_sign RSA 2048 27 | [ "$?" == 0 ] 28 | } 29 | 30 | @test "GPG generate ECC NIST P-256 key and sign" { 31 | generate_sign ECC 3 32 | [ "$?" == 0 ] 33 | } 34 | 35 | @test "GPG generate ECC NIST P-384 key and sign" { 36 | generate_sign ECC 4 37 | [ "$?" == 0 ] 38 | } 39 | 40 | @test "GPG generate ECC NIST P-521 key and sign" { 41 | generate_sign ECC 5 42 | [ "$?" == 0 ] 43 | } 44 | 45 | @test "GPG import RSA 2048 key and sign" { 46 | algo_switch rsa2048 47 | write_rsa_keygen 2048 48 | import_sign 49 | [ "$?" == 0 ] 50 | } 51 | 52 | @test "GPG import ECC NIST P-256 key and sign" { 53 | algo_switch p256 54 | write_ecc_keygen nistp256 55 | import_sign 56 | [ "$?" == 0 ] 57 | } 58 | 59 | @test "GPG import ECC NIST P-384 key and sign" { 60 | algo_switch p384 61 | write_ecc_keygen nistp384 62 | import_sign 63 | [ "$?" == 0 ] 64 | } 65 | 66 | @test "GPG import ECC NIST P-521 key and sign" { 67 | algo_switch p521 68 | write_ecc_keygen nistp521 69 | import_sign 70 | [ "$?" == 0 ] 71 | } 72 | -------------------------------------------------------------------------------- /scripts/test/SmartPGP.large.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load res/common.sh 4 | load res/SmartPGP.common.sh 5 | 6 | setup_file() { 7 | _setup_file 8 | } 9 | 10 | teardown_file() { 11 | _teardown_file 12 | } 13 | 14 | setup() { 15 | pgp_setup large 16 | } 17 | 18 | teardown() { 19 | rm -rf /app/tmp 20 | rm -rf ~/.gnupg 21 | _teardown 22 | } 23 | 24 | 25 | @test "GPG generate RSA 3072 key and sign" { 26 | generate_sign RSA 3072 27 | [ "$?" == 0 ] 28 | } 29 | 30 | @test "GPG generate RSA 4096 key and sign" { 31 | generate_sign RSA 4096 32 | [ "$?" == 0 ] 33 | } 34 | 35 | @test "GPG import RSA 3072 key and sign" { 36 | algo_switch rsa3072 37 | write_rsa_keygen 3072 38 | import_sign 39 | [ "$?" == 0 ] 40 | } 41 | 42 | @test "GPG import RSA 4096 key and sign" { 43 | algo_switch rsa4096 44 | write_rsa_keygen 4096 45 | import_sign 46 | [ "$?" == 0 ] 47 | } 48 | -------------------------------------------------------------------------------- /scripts/test/apex-fido2.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load res/common.sh 4 | load res/FIDO.common.sh 5 | 6 | setup_file() { 7 | _setup_file 8 | } 9 | 10 | teardown_file() { 11 | _teardown_file 12 | } 13 | 14 | setup() { 15 | cd /tmp/builds/apex-fido2 16 | java -cp /app/tools/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:./target com.licel.jcardsim.remote.VSmartCard /app/src/scripts/test/res/apex-fido2.jcardsim.cfg > /dev/null & 17 | JCSIM_PID="$!" 18 | sleep 2 19 | cd /app/tools/fido-attestation-loader 20 | ./attestation.py ca create -cap 123456 21 | ./attestation.py cert create -p 1234 -cap 123456 22 | PARAM=`./attestation.py cert show -p 1234 -f parameter -m fido2ci` 23 | PLEN=$((${#PARAM} / 2)) 24 | ALEN=$(($PLEN + 11)) 25 | PLEN=$(printf "%x\n" $PLEN) 26 | ALEN=$(printf "%x\n" $ALEN) 27 | opensc-tool -r 'Virtual PCD 00 00' -s "80 b8 00 00 $ALEN 08 A0 00 00 06 47 2F 00 01 00 $PLEN $PARAM FF" 28 | ./attestation.py cert upload -m fido2 29 | } 30 | 31 | teardown() { 32 | cd /app/tools/fido-attestation-loader 33 | rm -f *.der *.p8 assert_param cred* pubkey 34 | _teardown 35 | } 36 | 37 | 38 | @test "FIDO2 Register and Authenticate CTAP2-CTAP2 ES256" { 39 | fido_make_cred es256 hmac fido2 40 | fido_assert_cred es256 hmac fido2 41 | } 42 | 43 | @test "FIDO2 Register and Authenticate CTAP2-CTAP2 RS256" { 44 | fido_make_cred rs256 hmac fido2 45 | fido_assert_cred rs256 hmac fido2 46 | } 47 | 48 | @test "FIDO2 Register and Authenticate CTAP2-CTAP1" { 49 | fido_make_cred es256 nohmac fido2 50 | fido_assert_cred es256 nohmac u2f 51 | } 52 | 53 | @test "FIDO2 Register and Authenticate CTAP1-CTAP2" { 54 | fido_make_cred es256 nohmac u2f 55 | fido_assert_cred es256 nohmac fido2 56 | } 57 | 58 | @test "FIDO2 Register and Authenticate CTAP1-CTAP1" { 59 | fido_make_cred es256 nohmac u2f 60 | fido_assert_cred es256 nohmac u2f 61 | } 62 | 63 | #@test "FIDO2 Register and Authenticate https://demo.yubico.com/" { 64 | # RES=`fido2-webauthn-client "pcsc://slot0" 2>&1 | sed -n -e '/http_response_json: https:\/\/demo\.yubico\.com\/api\/v1\/simple\/webauthn\/authenticate-finish/,$p' | sed 1d` 65 | # STATUS=`echo $RES | jq -r '.status'` 66 | # [ "$STATUS" == "success" ] 67 | #} 68 | -------------------------------------------------------------------------------- /scripts/test/apex-ndef.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load res/common.sh 4 | load res/NDEF.common.sh 5 | 6 | setup_file() { 7 | _setup_file 8 | } 9 | 10 | teardown_file() { 11 | _teardown_file 12 | } 13 | 14 | setup() { 15 | cd /tmp/builds/apex-ndef 16 | java -cp /app/tools/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:./target com.licel.jcardsim.remote.VSmartCard /app/src/scripts/test/res/apex-ndef.jcardsim.cfg > /dev/null & 17 | JCSIM_PID="$!" 18 | sleep 2 19 | CUID='fff860203a257128' 20 | KEY='4173f37fbec4f93f3c66bb9fbf7284bf' 21 | SALT='ead73d4e5aeb64b0ddb26b470bb85856' 22 | opensc-tool -r 'Virtual PCD 00 00' -s "80 b8 00 00 34 07 D2760000850101 00 2A 0800 $CUID $KEY $SALT FF" 23 | } 24 | 25 | teardown() { 26 | _teardown 27 | } 28 | 29 | 30 | 31 | cmac_setup() { 32 | cd /tmp/builds/apex-ndef/test 33 | ./cmac.py randomurl | python3 ./pcsc-ndef/pcsc_ndef.py -r "Virtual PCD 00 00" -t4 write 34 | } 35 | 36 | cmac_verify() { 37 | ./cmac.py verifyurl -k $1 -i $CUID -a $SALT -u $(python3 ./pcsc-ndef/pcsc_ndef.py -r "Virtual PCD 00 00" -t4 read 2>/dev/null) 38 | res=$? 39 | return $res 40 | } 41 | 42 | 43 | @test "NDEF check size" { 44 | ndef_check_size 45 | } 46 | 47 | @test "NDEF read write" { 48 | ndef_read_write 49 | } 50 | 51 | @test "NDEF CMAC positive" { 52 | cmac_setup 53 | cmac_verify $KEY 54 | cmac_verify $KEY 55 | cmac_verify $KEY 56 | } 57 | 58 | @test "NDEF CMAC negative" { 59 | cmac_setup 60 | run cmac_verify '1eedb2ff62cfe26dd58c8368d5169bdb' 61 | [ "$status" -eq 1 ] 62 | } 63 | -------------------------------------------------------------------------------- /scripts/test/apex-spark.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load res/common.sh 4 | 5 | setup_file() { 6 | _setup_file 7 | } 8 | 9 | teardown_file() { 10 | _teardown_file 11 | } 12 | 13 | setup() { 14 | cd /tmp/builds/apex-spark 15 | java -cp /app/tools/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:./target com.licel.jcardsim.remote.VSmartCard /app/src/scripts/test/res/apex-spark.jcardsim.cfg > /dev/null & 16 | JCSIM_PID="$!" 17 | sleep 2 18 | CUID='fff860203a257128' 19 | KEY='20f780716ba49ae163bd638486c71723' 20 | opensc-tool -r 'Virtual PCD 00 00' -s "80 b8 00 00 27 0C A000000846737061726B3201 00 18 $CUID $KEY FF" 21 | } 22 | 23 | teardown() { 24 | _teardown 25 | } 26 | 27 | 28 | @test "Authentication positive" { 29 | cd /tmp/builds/apex-spark/test 30 | ./authenticate.py -k $KEY 31 | } 32 | 33 | @test "Authentication negative" { 34 | cd /tmp/builds/apex-spark/test 35 | run ./authenticate.py -k "ec96ca0a9bb855fac4bde8c2781f3f3d" 36 | [ "$status" -eq 1 ] 37 | } 38 | -------------------------------------------------------------------------------- /scripts/test/apex-totp.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load res/common.sh 4 | 5 | setup_file() { 6 | _setup_file 7 | } 8 | 9 | teardown_file() { 10 | _teardown_file 11 | } 12 | 13 | setup() { 14 | cd /tmp/builds/apex-totp 15 | java -cp /app/tools/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:./target com.licel.jcardsim.remote.VSmartCard /app/src/scripts/test/res/apex-totp.jcardsim.cfg > /dev/null & 16 | JCSIM_PID="$!" 17 | sleep 2 18 | opensc-tool -r 'Virtual PCD 00 00' -s '80 b8 00 00 10 0D A0 00 00 05 27 21 01 01 41 50 45 58 01 00 FF' 19 | SECRETB32='IVCEGRTIOQ3UGSLNI5KDMT2RKF4FGUCO' 20 | } 21 | 22 | teardown() { 23 | _teardown 24 | } 25 | 26 | 27 | @test "ykman program TOTP and oathtool validate" { 28 | cd /app/tools/yubikey-manager 29 | poetry run ykman -r 'Virtual PCD 00 00' oath accounts uri "otpauth://totp/Test?secret=$SECRETB32" 30 | YKRES=`poetry run ykman -r 'Virtual PCD 00 00' oath accounts code Test` 31 | YKRES=${YKRES#"Test "} 32 | REF=`oathtool -b --totp "$SECRETB32"` 33 | [ "$YKRES" == "$REF" ] 34 | } 35 | 36 | @test "ykman program HOTP and oathtool validate" { 37 | cd /app/tools/yubikey-manager 38 | poetry run ykman -r 'Virtual PCD 00 00' oath accounts uri "otpauth://hotp/Test?secret=$SECRETB32&counter=42" 39 | YKRES=`poetry run ykman -r 'Virtual PCD 00 00' oath accounts code Test` 40 | YKRES=${YKRES#"Test "} 41 | REF=`oathtool -c 42 -b --hotp "$SECRETB32"` 42 | [ "$YKRES" == "$REF" ] 43 | } 44 | -------------------------------------------------------------------------------- /scripts/test/flexsecure-ykhmac.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load res/common.sh 4 | 5 | setup_file() { 6 | _setup_file 7 | } 8 | 9 | teardown_file() { 10 | _teardown_file 11 | } 12 | 13 | setup() { 14 | cd /tmp/builds/flexsecure-ykhmac 15 | java -cp /app/tools/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:./target com.licel.jcardsim.remote.VSmartCard /app/src/scripts/test/res/flexsecure-ykhmac.jcardsim.cfg > /dev/null & 16 | JCSIM_PID="$!" 17 | sleep 2 18 | opensc-tool -r 'Virtual PCD 00 00' -s '80 b8 00 00 0A 08 a0 00 00 05 27 20 01 01 00 FF' 19 | SECRET='59fc9f75041ce4848614738a1c39bb565090ad9f' 20 | CHALLENGE='4e7cbb8fedc4ae11b7546f3c9986fdffeba2d9d7d1cc00799a7e5bcfb267e1bf' 21 | RESPONSE='4ff8aa748188a4be57f4d7eff27eccda639b289f' 22 | } 23 | 24 | teardown() { 25 | _teardown 26 | } 27 | 28 | 29 | @test "ykman program and respond" { 30 | cd /app/tools/yubikey-manager 31 | poetry run ykman -r 'Virtual PCD 00 00' otp chalresp -f 1 $SECRET 32 | YKMANRES=`poetry run ykman -r 'Virtual PCD 00 00' otp calculate 1 $CHALLENGE` 33 | [ "$YKMANRES" == "$RESPONSE" ] 34 | } 35 | 36 | @test "ykhmac program and respond" { 37 | echo $SECRET | java -jar /usr/bin/yktool.jar program hmac 1 -x -X 38 | YKRES=`printf $CHALLENGE | java -jar /usr/bin/yktool.jar hmac 1 -x -X` 39 | YKRES=${YKRES//:/} 40 | YKRES=${YKRES,,} 41 | [ "$YKRES" == "$RESPONSE" ] 42 | } 43 | 44 | @test "KeePassXC decrypt and read " { 45 | echo $SECRET | java -jar /usr/bin/yktool.jar program hmac 1 -x -X 46 | SERIAL=`java -jar /usr/bin/yktool.jar list | sed -r 's/.*#([0-9]*)\s.*/\1/'` 47 | SECRET=`echo '12345678' | keepassxc-cli show -s -a Password -y "1:$SERIAL" /app/src/scripts/test/res/flexsecure-ykhmac.testdb.kdbx Test` 48 | [ "$SECRET" == "RMGG4lkT4Kd3k8FYsQ3b" ] 49 | } 50 | -------------------------------------------------------------------------------- /scripts/test/openjavacard-ndef.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load res/common.sh 4 | load res/NDEF.common.sh 5 | 6 | setup_file() { 7 | _setup_file 8 | } 9 | 10 | teardown_file() { 11 | _teardown_file 12 | } 13 | 14 | setup() { 15 | cd /tmp/builds/openjavacard-ndef 16 | java -cp /app/tools/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:./build/classes/full com.licel.jcardsim.remote.VSmartCard /app/src/scripts/test/res/openjavacard-ndef.jcardsim.cfg > /dev/null & 17 | JCSIM_PID="$!" 18 | sleep 2 19 | opensc-tool -r 'Virtual PCD 00 00' -s '80 b8 00 00 13 07 D2 76 00 00 85 01 01 00 08 81 02 00 00 82 02 08 00 ff' 20 | } 21 | 22 | teardown() { 23 | _teardown 24 | } 25 | 26 | 27 | @test "NDEF check size" { 28 | ndef_check_size 29 | } 30 | 31 | @test "NDEF read write" { 32 | ndef_read_write 33 | } 34 | -------------------------------------------------------------------------------- /scripts/test/res/FIDO.common.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | FIDO_RP="longrelyingpartyid.yeetcool.boi.domain.verylonglong64.example.de" 4 | FIDO_USRID="averylongaswell64k@longrelyingpartyid.averylongstring.example.de" 5 | 6 | fido_make_cred() { 7 | dd if=/dev/urandom bs=1 count=16 2>/dev/null | openssl sha256 -binary | base64 > cred_param 8 | echo $FIDO_RP >> cred_param 9 | echo $FIDO_USRID >> cred_param 10 | MKOPT="" 11 | VALOPT="" 12 | if [ "$2" == "hmac" ]; then 13 | MKOPT="-h" 14 | VALOPT="-h" 15 | fi 16 | if [ "$3" == "u2f" ]; then 17 | MKOPT="$MKOPT -u" 18 | fi 19 | dd if=/dev/urandom bs=1 count=32 2>/dev/null | base64 >> cred_param 20 | fido2-cred -M $MKOPT -i cred_param "pcsc://slot0" $1 | fido2-cred -V $VALOPT -o cred $1 21 | } 22 | 23 | fido_assert_cred() { 24 | dd if=/dev/urandom bs=1 count=16 2>/dev/null | openssl sha256 -binary | base64 > assert_param 25 | echo $FIDO_RP >> assert_param 26 | head -1 cred >> assert_param 27 | MKOPT="" 28 | VALOPT="" 29 | if [ "$2" == "hmac" ]; then 30 | MKOPT="-h" 31 | VALOPT="-h" 32 | dd if=/dev/urandom bs=1 count=32 2>/dev/null | base64 >> assert_param 33 | fi 34 | if [ "$3" == "u2f" ]; then 35 | MKOPT="$MKOPT -u" 36 | fi 37 | tail -n +2 cred > pubkey 38 | fido2-assert -G $MKOPT -i assert_param "pcsc://slot0" $1 | fido2-assert -V $VALOPT pubkey -d $1 39 | } 40 | -------------------------------------------------------------------------------- /scripts/test/res/FIDO2Applet.jcardsim.cfg: -------------------------------------------------------------------------------- 1 | com.licel.jcardsim.card.applet.0.AID=A0000006472F0001 2 | com.licel.jcardsim.card.applet.0.Class=us.q3q.fido2.FIDO2Applet 3 | com.licel.jcardsim.card.ATR=3BF91800FF8131FE4550565F4A334130343040 4 | com.licel.jcardsim.vsmartcard.host=localhost 5 | com.licel.jcardsim.vsmartcard.port=35963 -------------------------------------------------------------------------------- /scripts/test/res/NDEF.common.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ndef_check_size() { 4 | cd /app/tools/pcsc-ndef 5 | RESP=`python3 pcsc_ndef.py -r "Virtual PCD 00 00" -t4 getmax` 6 | [ "$RESP" == "2046" ] 7 | } 8 | 9 | ndef_read_write() { 10 | cd /app/tools/pcsc-ndef 11 | PAYLOAD='fHwG61CGBRM3L6ZrpGpq' 12 | echo $PAYLOAD | python3 pcsc_ndef.py -r "Virtual PCD 00 00" -t 4 write 13 | RESP=`python3 pcsc_ndef.py -r "Virtual PCD 00 00" -t 4 read` 14 | [ "$RESP" == "$PAYLOAD" ] 15 | } 16 | -------------------------------------------------------------------------------- /scripts/test/res/SmartPGP.common.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pgp_setup() { 4 | mkdir -p /app/tmp 5 | cd /tmp/builds/SmartPGP 6 | java -cp /app/tools/jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:./target/$1 com.licel.jcardsim.remote.VSmartCard /app/src/scripts/test/res/SmartPGP.jcardsim.cfg > /dev/null & 7 | JCSIM_PID="$!" 8 | sleep 2 9 | opensc-tool -r 'Virtual PCD 00 00' -s '80 b8 00 00 13 10 d2 76 00 01 24 01 03 04 C0 FE 00 00 00 01 00 00 00 FF' 10 | } 11 | 12 | algo_switch() { 13 | cd /tmp/builds/SmartPGP/bin 14 | ./smartpgp-cli switch-$1 15 | } 16 | 17 | sign_verify() { 18 | echo "Test" > /app/tmp/secret.txt 19 | echo '123456' | gpg --output /app/tmp/secret.txt.sig --passphrase-fd=0 --pinentry-mode loopback --detach-sig /app/tmp/secret.txt 20 | RES=`gpg --verify /app/tmp/secret.txt.sig /app/tmp/secret.txt 2>&1` 21 | if [[ $RES == *"Good signature from \"CI Test (CI Testing Key) \""* ]]; then return 0; else return 1; fi 22 | } 23 | 24 | generate_sign() { 25 | /app/src/scripts/test/res/SmartPGP.generate.$1.expect $2 26 | KUID=`gpg --list-keys --with-colons | awk -F: '$1=="uid" {print $10; exit}'` 27 | sign_verify 28 | return "$?" 29 | } 30 | 31 | import_sign() { 32 | gpg --batch --generate-key /app/tmp/gen-key 33 | /app/src/scripts/test/res/SmartPGP.import.expect 34 | KUID=`gpg --list-keys --with-colons | awk -F: '$1=="uid" {print $10; exit}'` 35 | sign_verify 36 | return "$?" 37 | } 38 | 39 | write_rsa_keygen() { 40 | cat >/app/tmp/gen-key </app/tmp/gen-key < /dev/null & 17 | JCSIM_PID="$!" 18 | sleep 2 19 | cd /app/tools/fido-attestation-loader 20 | ./attestation.py ca create -cap 123456 21 | ./attestation.py cert create -p 1234 -cap 123456 22 | PARAM=`./attestation.py cert show -p 1234 -f parameter -m u2fci` 23 | opensc-tool -r 'Virtual PCD 00 00' -s "80 b8 00 00 2F 08 A0 00 00 06 47 2F 00 01 00 23 $PARAM FF" 24 | ./attestation.py cert upload -m u2fci 25 | } 26 | 27 | teardown() { 28 | cd /app/tools/fido-attestation-loader 29 | rm -f *.der *.p8 assert_param cred* pubkey 30 | _teardown 31 | } 32 | 33 | 34 | @test "U2F Register and Authenticate CTAP1-CTAP1" { 35 | fido_make_cred es256 nohmac u2f 36 | fido_assert_cred es256 nohmac u2f 37 | } 38 | 39 | #@test "U2F Register and Authenticate https://demo.yubico.com/" { 40 | # RES=`fido2-webauthn-client "pcsc://slot0" 2>&1 | sed -n -e '/http_response_json: https:\/\/demo\.yubico\.com\/api\/v1\/simple\/webauthn\/authenticate-finish/,$p' | sed 1d` 41 | # STATUS=`echo $RES | jq -r '.status'` 42 | # [ "$STATUS" == "success" ] 43 | #} 44 | --------------------------------------------------------------------------------