├── .gitignore ├── .gitmodules ├── AUTHORS ├── ChangeLog ├── ChangeLog-1_0 ├── FSIJ-s.png ├── GNUK_SERIAL_NUMBER ├── GNUK_USB_DEVICE_ID ├── NEWS ├── README ├── THANKS ├── VERSION ├── doc ├── Makefile ├── __update_web ├── conf.py ├── development.rst ├── generating-key.rst ├── gnuk-keytocard-noremoval.rst ├── gnuk-keytocard.rst ├── gnuk-passphrase-setting.rst ├── gnuk-personalization.rst ├── gnuk-token-initial-configuration.rst ├── gpg-settings.rst ├── images │ └── gnuk-sticker.png ├── index.rst ├── intro.rst ├── note │ ├── HACKING │ ├── NOTES │ ├── firmware-update │ ├── firmware-update-2 │ └── settings-for-DnDpinentry ├── stop-scdaemon.rst ├── udev-rules.rst └── using-gnuk-token-with-another-computer.rst ├── docker ├── Dockerfile.check ├── Dockerfile.debug ├── Dockerfile.release └── Makefile ├── gnuk-sticker.svg ├── gnuk-stickers.svg ├── gnuk.png ├── gnuk.svg ├── misc ├── debug-bn.c ├── t-eddsa.c └── t-mont.c ├── polarssl ├── ChangeLog ├── LICENSE ├── README ├── include │ └── polarssl │ │ ├── aes.h │ │ ├── bignum.h │ │ ├── bn_mul.h │ │ ├── config.h │ │ └── rsa.h └── library │ ├── aes.c │ ├── bignum.c │ └── rsa.c ├── regnual ├── Makefile ├── regnual.c ├── regnual.ld ├── reset.c └── types.h ├── src ├── .gdbinit ├── COPYING ├── Makefile ├── ac.c ├── affine.h ├── binary-edit.sh ├── bn.c ├── bn.h ├── call-ec.c ├── call-ec_p256k1.c ├── call-ec_p256r1.c ├── call-rsa.c ├── config.h.in ├── configure ├── crypt.mk ├── debug.c ├── debug.h ├── ec_p256k1.c ├── ec_p256k1.h ├── ec_p256r1.c ├── ec_p256r1.h ├── ecc-edwards.c ├── ecc-mont.c ├── ecc.c ├── field-group-select.h ├── flash.c ├── gnuk-malloc.h ├── gnuk.h ├── gnuk.ld.in ├── jpc-ac_p256k1.h ├── jpc-ac_p256r1.h ├── jpc.c ├── jpc_p256k1.c ├── jpc_p256r1.c ├── main.c ├── mcu-stm32f103.c ├── mod.c ├── mod.h ├── mod25638.c ├── mod25638.h ├── modp256k1.c ├── modp256k1.h ├── modp256r1.c ├── modp256r1.h ├── muladd_256.h ├── neug.c ├── neug.h ├── openpgp-do.c ├── openpgp.c ├── pin-cir.c ├── pin-dnd.c ├── random.c ├── random.h ├── sha256.c ├── sha256.h ├── sha512.c ├── sha512.h ├── stack-def.h ├── status-code.h ├── stdaln-sys.ld.in ├── usb-ccid.c ├── usb-cdc.h ├── usb-msc.c ├── usb-msc.h ├── usb_conf.h ├── usb_ctrl.c └── usb_desc.c ├── test ├── README ├── ecc_nistp256_keys.py ├── features │ ├── 000_empty_check.feature │ ├── 001_empty_check_passphrase.feature │ ├── 002_get_data_static.feature │ ├── 003_keyattr_change.feature │ ├── 010_setup_passphrase.feature │ ├── 020_personalization_write.feature │ ├── 021_personalization_read.feature │ ├── 030_key_registration.feature │ ├── 040_passphrase_change.feature │ ├── 100_compute_signature.feature │ ├── 101_decryption.feature │ ├── 200_key_removal.feature │ ├── 201_keygen.feature │ ├── 202_setup_passphrase.feature │ ├── 203_passphrase_change.feature │ ├── 210_compute_signature.feature │ ├── 211_decryption.feature │ ├── 370_key_removal.feature │ ├── 380_personalization_reset.feature │ ├── 390_reset_passphrase.feature │ ├── 400_empty_check.feature │ ├── 401_empty_check_passphrase.feature │ ├── 402_get_data_static.feature │ ├── 410_setup_passphrase.feature │ ├── 420_personalization_write.feature │ ├── 421_personalization_read.feature │ ├── 430_key_registration.feature │ ├── 440_passphrase_change.feature │ ├── 500_compute_signature.feature │ ├── 501_decryption.feature │ ├── 600_key_removal.feature │ ├── 601_keygen.feature │ ├── 602_setup_passphrase.feature │ ├── 603_passphrase_change.feature │ ├── 610_compute_signature.feature │ ├── 611_decryption.feature │ ├── 770_key_removal.feature │ ├── 780_personalization_reset.feature │ ├── 790_reset_passphrase.feature │ ├── 800_empty_check.feature │ ├── 801_empty_check_passphrase.feature │ ├── 802_get_data_static.feature │ ├── 810_setup_passphrase.feature │ ├── 820_personalization_write.feature │ ├── 821_personalization_read.feature │ ├── 830_key_registration.feature │ ├── 850_compute_signature.feature │ ├── 851_decryption.feature │ ├── 860_key_removal.feature │ ├── 862_keygen.feature │ ├── 870_compute_signature.feature │ ├── 871_decryption.feature │ ├── 970_key_removal.feature │ ├── 980_personalization_reset.feature │ ├── 990_reset_passphrase.feature │ ├── 991_version_string.feature │ └── steps.py ├── generate_keys.py ├── gnuk_token.py ├── rsa-aut.key ├── rsa-dec.key ├── rsa-sig.key └── rsa_keys.py ├── tests ├── README ├── card_const.py ├── card_reader.py ├── card_test_kdf_full.py ├── card_test_kdf_single.py ├── card_test_keygen.py ├── card_test_personalize_admin_less.py ├── card_test_personalize_card.py ├── card_test_personalize_reset.py ├── card_test_remove_keys.py ├── card_test_reset_pw3.py ├── conftest.py ├── constants_for_test.py ├── kdf_calc.py ├── openpgp_card.py ├── rsa-aut.key ├── rsa-dec.key ├── rsa-sig.key ├── rsa_keys.py ├── skip_gnuk_only_tests.py ├── test_000_empty_card.py ├── test_001_personalize_card.py ├── test_002_personalize_reset.py ├── test_003_remove_keys.py ├── test_004_reset_pw3.py ├── test_005_personalize_admin_less.py ├── test_009_keygen.py ├── test_011_kdf_full.py ├── test_016_kdf_single.py ├── test_021_personalize_admin_less.py ├── test_025_kdf_none.py └── util.py └── tool ├── add_openpgp_authkey_from_gpgssh.py ├── asm-thumb ├── README ├── blank_check.S ├── flash_write.S └── opt_bytes_write.S ├── calc_precompute_table_ecc.py ├── dfuse.py ├── dump_mem.py ├── get_raw_public_key.py ├── gnuk-emulation-setup ├── gnuk_get_random.py ├── gnuk_put_binary_libusb.py ├── gnuk_remove_keys_libusb.py ├── gnuk_token.py ├── gnuk_upgrade.py ├── gpg_agent.py ├── hub_ctrl.py ├── intel_hex.py ├── kdf_calc.py ├── openocd-script ├── lock.tcl ├── options_read.tcl ├── unlock.tcl └── write.tcl ├── pageant_proxy_to_gpg.py ├── pinpadtest.py ├── rsa.py ├── rsa_example.key ├── sexp.py ├── stlinkv2.py ├── upgrade_by_passwd.py └── usb_strings.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.lst 2 | *.o 3 | *.pyc 4 | regnual/regnual-no-vidpid.elf 5 | src/.dep 6 | src/config.mk 7 | src/config.h 8 | src/gnuk.ld 9 | src/stdaln-sys.ld 10 | src/board.h 11 | src/build/* 12 | src/*.inc 13 | src/put-vid-pid-ver.sh 14 | regnual/regnual.bin 15 | regnual/regnual.hex 16 | regnual/regnual.elf 17 | doc/_build 18 | tests/.cache 19 | tests/__pycache__ 20 | tests/.pytest_cache 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "chopstx"] 2 | path = chopstx 3 | url = https://github.com/TheStaticTurtle/chopstx 4 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Aurelien Jarno: 2 | Modified: 3 | src/Makefile 4 | src/configure 5 | src/main.c 6 | src/stack-def.h 7 | 8 | Anthony Romano: 9 | Modified: 10 | src/call-rsa.c 11 | src/main.c 12 | src/mod.c 13 | 14 | Jeremy Drake: 15 | Modified: 16 | regnual/regnual.c 17 | 18 | Kaz Kojima: 19 | Added STM32 Primer2 support. 20 | 21 | NIIBE Yutaka: 22 | Founder of the project. 23 | Wrote tools for STLink/V2: 24 | tool/stlinkv2.py 25 | Wrote tools for DfuSe: 26 | tool/dfuse.py 27 | tool/dump_mem.py 28 | tool/intel_hex.py 29 | Wrote a tool for Gnuk: 30 | tool/gnuk_put_binary.py 31 | tool/gnuk_put_binary_libusb.py 32 | tool/gnuk_remove_keys.py 33 | tool/gnuk_upgrade.py 34 | Wrote a tool for USB Hub: 35 | tool/hub_ctrl.py 36 | Wrote a tool for testing card reader with pinpad: 37 | tool/pinpadtest.py 38 | Wrote reGNUal implementation: 39 | regnual/regnual.c 40 | regnual/sys.c 41 | Wrote Gnuk implementation: 42 | gnuk.svg 43 | src/configure 44 | src/ac.c 45 | src/call-rsa.c 46 | src/debug.c 47 | src/flash.c 48 | src/gnuk.h 49 | src/main.c 50 | src/neug.c 51 | src/openpgp-do.c 52 | src/openpgp.c 53 | src/openpgp.h 54 | src/pin-cir.c 55 | src/pin-dial.c 56 | src/pin-dnd.c 57 | src/random.c 58 | src/sys.c 59 | src/usb-icc.c 60 | src/usb-msc.c 61 | src/usb-msc.h 62 | src/usb_ctrl.c 63 | src/usb_desc.c 64 | src/usb_lld.c 65 | src/usb_lld.h 66 | * 67 | and others. 68 | 69 | Peter Lebbing: 70 | Modified: 71 | src/config.h.in 72 | src/configure 73 | src/main.c 74 | src/Makefile 75 | Wrote: 76 | src/stdaln-sys.ld.in 77 | -------------------------------------------------------------------------------- /FSIJ-s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheStaticTurtle/gnuk/710fabc347fbc4723dcd3b0d91908be7e1053534/FSIJ-s.png -------------------------------------------------------------------------------- /GNUK_SERIAL_NUMBER: -------------------------------------------------------------------------------- 1 | # Email # 6-byte serial number, separated by ':' 2 | samuel@thestaticturtle.fr 51:10:00:00:00:01 -------------------------------------------------------------------------------- /GNUK_USB_DEVICE_ID: -------------------------------------------------------------------------------- 1 | # VID:PID bcdDev Product_STRING Vendor_STRING 2 | 0000:0000 0200 Gnuk Emulation Free Software Initiative of Japan 3 | 234b:0000 0200 Gnuk Token Free Software Initiative of Japan 4 | 20a0:4211 0200 Nitrokey Start Nitrokey 5 | 1209:2440 0200 Gnuk Token GnuPG e.V. 6 | ########## ## ########## ################# 7 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | -*- coding: utf-8 -*- 2 | 3 | We would like to express our gratitudes to Werner Koch for GnuPG, and 4 | Giovanni Di Sirio for ChibiOS/RT. 5 | 6 | Gnuk was originally written by NIIBE Yutaka. People contributed by 7 | encouraging the development, testing the implementation, suggesting 8 | improvements, or fixing bugs. Here is a list of those people. 9 | 10 | Aurelien Jarno aurelien@aurel32.net 11 | Achim Pietig achim@pietig.com 12 | Aidan Thornton 13 | Anibal Monsalve Salazar anibal@debian.org 14 | Andre Zepezauer andre.zepezauer@student.uni-halle.de 15 | Anthony Romano anthony.romano@coreos.com 16 | Bertrand Jacquin bertrand@jacquin.bzh 17 | Clint Adams clint@softwarefreedom.org 18 | Daniel Kahn Gillmor dkg@fifthhorseman.net 19 | Elliott Mitchell 20 | Fabio Utzig utzig@apache.org 21 | Hironobu SUZUKI hironobu@h2np.net 22 | Jan Suhr jan@suhr.info 23 | Jeremy Drake jeremydrake+gnuk@eacceleration.com 24 | Jonathan McDowell noodles@earth.li 25 | Kaz Kojima kkojima@rr.iij4u.or.jp 26 | Kenji Rikitake 27 | Ludovic Rousseau ludovic.rousseau@free.fr 28 | Luis Felipe R. Murillo luisfelipe@ucla.edu 29 | Mateusz Zalega mateusz@nitrokey.com 30 | MATSUU Takuto matsuu@gentoo.org 31 | Micah Anderson micah@debian.org 32 | NAGAMI Takeshi nagami-takeshi@aist.go.jp 33 | Nguyễn Hồng Quân quannguyen@mbm.vn 34 | Nico Rikken nico@nicorikken.eu 35 | NOKUBI Takatsugu knok@daionet.gr.jp 36 | Paul Fertser 37 | Paul Bakker polarssl_maintainer@polarssl.org 38 | Peter Lebbing peter@digitalbrains.com 39 | Santiago Ruano Rincón santiago@debian.org 40 | Shane Coughlan scoughlan@openinventionnetwork.com 41 | Stanislas Bach sbach@0g.re 42 | Szczepan Zalega szczepan@nitrokey.com 43 | Vasily Evseenko 44 | Werner Koch wk@gnupg.org 45 | Yuji Imai ug@xcast.jp 46 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | release/1.2.15 2 | -------------------------------------------------------------------------------- /doc/__update_web: -------------------------------------------------------------------------------- 1 | cd _build 2 | rsync -rntpv html/ atom.fsij.org:/home/fsij/gnuk-doc-html/ 3 | rsync -rtpv html/ atom.fsij.org:/home/fsij/gnuk-doc-html/ 4 | -------------------------------------------------------------------------------- /doc/development.rst: -------------------------------------------------------------------------------- 1 | Development Environment 2 | ======================= 3 | 4 | 5 | Hardware 6 | -------- 7 | 8 | For development, it is highly recommended to have JTAG/SWD debugger. 9 | 10 | For boards with DFU (Device Firmware Upgrade) feature (such as DfuSe), 11 | it is possible to develop with that. But it should be considered 12 | *experimental* environment, and it should not be used for usual 13 | purpose. That's because it is basically impossible for DfuSe 14 | implementations to disable reading-out from flash ROM. It means 15 | that your secrets will be readily extracted by DfuSe. 16 | 17 | For JTAG debugger, Olimex JTAG-Tiny is good and supported well. For 18 | SWD debugger, ST-Link/V2 would be good, and it is supported by 19 | tool/stlinkv2.py. 20 | 21 | 22 | OpenOCD 23 | ------- 24 | 25 | For JTAG/SWD debugger, we can use OpenOCD. 26 | 27 | 28 | GNU Toolchain 29 | ------------- 30 | 31 | You need GNU toolchain and newlib for 'arm-none-eabi' target. 32 | In Debian, we can just apt-get packages of: gcc-arm-none-eabi, binutils-arm-none-eabi, gdb-arm-none-eabi and libnewlib-arm-none-eabi. 33 | 34 | For other distributiions, there is "gcc-arm-embedded" project. See: 35 | https://launchpad.net/gcc-arm-embedded/ 36 | 37 | We are using "-O3 -Os" for compiler option. 38 | 39 | 40 | Building Gnuk 41 | ------------- 42 | 43 | Change directory to ``src``: :: 44 | 45 | $ cd gnuk-VERSION/src 46 | 47 | Then, run ``configure``: :: 48 | 49 | $ ./configure --vidpid= 50 | 51 | Here, you need to specify USB vendor ID and product ID. For FSIJ's, 52 | it's: --vidpid=234b:0000 . Please read the section 'USB vendor ID and 53 | product ID' in README. 54 | 55 | Type: :: 56 | 57 | $ make 58 | 59 | Then, we will have "gnuk.elf" under src/build directory. 60 | 61 | If you are not the authorized vendor, please never distribute this 62 | file of "gnuk.elf", which includes VID:PID in the image. If you would 63 | like to distribute the image (for example, to check if it's 64 | reproducible or not), the file "gnuk-no-vidpid.elf" is the one with no 65 | VID:PID. 66 | -------------------------------------------------------------------------------- /doc/gnuk-keytocard-noremoval.rst: -------------------------------------------------------------------------------- 1 | ============================================= 2 | Key import from PC to Gnuk Token (no removal) 3 | ============================================= 4 | 5 | This document describes how I put my **keys on PC** to the Token 6 | without removing keys from PC. 7 | 8 | The difference is only the last step. 9 | I don't save changes on PC after keytocard. 10 | 11 | For the steps before the last step, please see `keytocard with removing keys on PC`_. 12 | 13 | .. _keytocard with removing keys on PC: gnuk-keytocard 14 | 15 | Here is the session log of the last step. 16 | 17 | Lastly, I quit GnuPG. Note that I **don't** save changes. :: 18 | 19 | gpg> quit 20 | Save changes? (y/N) n 21 | Quit without saving? (y/N) y 22 | $ 23 | 24 | All keys are imported to Gnuk Token now. 25 | Still, secret keys are available on PC, too. 26 | -------------------------------------------------------------------------------- /doc/gnuk-personalization.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Personalization of Gnuk Token 3 | ============================= 4 | 5 | 6 | Personalize your Gnuk Token 7 | =========================== 8 | 9 | Invoke GnuPG with the option ``--card-edit``. :: 10 | 11 | $ gpg --card-edit 12 | 13 | Reader ...........: 234B:0000:FSIJ-1.2.0-87193059:0 14 | Application ID ...: D276000124010200FFFE871930590000 15 | Version ..........: 2.0 16 | Manufacturer .....: unmanaged S/N range 17 | Serial number ....: 87193059 18 | Name of cardholder: [not set] 19 | Language prefs ...: [not set] 20 | Sex ..............: unspecified 21 | URL of public key : [not set] 22 | Login data .......: [not set] 23 | Signature PIN ....: forced 24 | Key attributes ...: rsa2048 rsa2048 rsa2048 25 | Max. PIN lengths .: 127 127 127 26 | PIN retry counter : 3 3 3 27 | Signature counter : 0 28 | Signature key ....: [none] 29 | Encryption key....: [none] 30 | Authentication key: [none] 31 | General key info..: [none] 32 | 33 | gpg/card> 34 | 35 | It shows the status of the card (as same as the output of ``gpg --card-status``). 36 | 37 | Then, GnuPG enters its own command interaction mode. The prompt is ``gpg/card>``. 38 | 39 | First, enabling admin command, I put name of mine. 40 | Note that I input admin PIN of factory setting (12345678) here. :: 41 | 42 | gpg/card> admin 43 | Admin commands are allowed 44 | 45 | gpg/card> name 46 | Cardholder's surname: Niibe 47 | Cardholder's given name: Yutaka 48 | gpg: 3 Admin PIN attempts remaining before card is permanently locked 49 | 50 | Please enter the Admin PIN 51 | Enter Admin PIN: 12345678 52 | 53 | Secondly, I put some other informations, such as language, sex, 54 | login, and URL. URL specifies the place where I put my public keys. :: 55 | 56 | gpg/card> lang 57 | Language preferences: ja 58 | 59 | gpg/card> sex 60 | Sex ((M)ale, (F)emale or space): m 61 | 62 | gpg/card> url 63 | URL to retrieve public key: http://www.gniibe.org/gniibe-20150813.asc 64 | 65 | gpg/card> login 66 | Login data (account name): gniibe 67 | 68 | Since I don't force PIN input everytime, 69 | toggle it to non-force-pin-for-signature. :: 70 | 71 | gpg/card> forcesig 72 | 73 | Then, I quit. :: 74 | 75 | gpg/card> quit 76 | 77 | That's all in this step. 78 | -------------------------------------------------------------------------------- /doc/gnuk-token-initial-configuration.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Initial Configuration of Gnuk Token 3 | =================================== 4 | 5 | This is optional step. 6 | 7 | You don't need to setup the serial number of Gnuk Token, 8 | as it comes with its default serial number based on MCU's chip ID. 9 | 10 | You can setup the serial number of Gnuk Token only once. 11 | 12 | 13 | Conditions 14 | ========== 15 | 16 | I assume you are using GNU/Linux. 17 | 18 | 19 | Preparation 20 | =========== 21 | 22 | Make sure there is no ``scdaemon`` for configuring Gnuk Token. You can kill ``scdaemon`` by: :: 23 | 24 | $ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye 25 | 26 | 27 | Serial Number (optional) 28 | ======================== 29 | 30 | Note that this is completely optional step. I don't know anyone other than me, do this. Even for me, I only do that for a single device among multiple devices I use. I do that to test the feature. 31 | 32 | In the file ``GNUK_SERIAL_NUMBER``, each line has email and 6-byte serial number. The first two bytes are organization number (F5:17 is for FSIJ). Last four bytes are number for tokens. 33 | 34 | The tool ``../tool/gnuk_put_binary_libusb.py`` examines environment variable of ``EMAIL``, and writes corresponding serial number to Gnuk Token. :: 35 | 36 | $ ../tool/gnuk_put_binary_libusb.py -s ../GNUK_SERIAL_NUMBER 37 | Writing serial number 38 | Device: 39 | Configuration: 1 40 | Interface: 0 41 | d2 76 00 01 24 01 02 00 f5 17 00 00 00 01 00 00 42 | -------------------------------------------------------------------------------- /doc/gpg-settings.rst: -------------------------------------------------------------------------------- 1 | .. -*- coding: utf-8 -*- 2 | 3 | ============== 4 | GnuPG settings 5 | ============== 6 | 7 | Here is my GnuPG settings. 8 | 9 | .gnupg/gpg.conf 10 | =============== 11 | 12 | I create ``.gnupg/gpg.conf`` file with the following content. :: 13 | 14 | use-agent 15 | default-key 0xE267B052364F028D 16 | 17 | In addition to the ``use-agent`` option, I specify my default key. 18 | 19 | The ``use-agent`` option is for GnuPG 1.4.x and it means using gpg-agent if available. 20 | If no option, GnuPG 1.4.x directly connects to Gnuk Token by itself, instead of through scdaemon. When GnuPG 1.4.x tries to access Gnuk Token and scdaemon is running, there are conflicts. 21 | 22 | We recommend to specify the ``use-agent`` option for GnuPG 1.4.x to access Gnuk Token through gpg-agent and scdaemon. 23 | 24 | For GnuPG 2.0 and 2.1, gpg-agent is always used, so, there is no need to specify the ``use-agent`` option, but having this option is no harm, anyway. 25 | 26 | 27 | Let gpg-agent manage SSH key 28 | ============================ 29 | 30 | I create ``.gnupg/gpg-agent.conf`` file with the following content. :: 31 | 32 | enable-ssh-support 33 | 34 | I edit the file /etc/X11/Xsession.options and comment out use-ssh-agent line, 35 | so that Xsession doesn't invoke original ssh-agent. We use gpg-agent as ssh-agent. 36 | 37 | In the files /etc/xdg/autostart/gnome-keyring-ssh.desktop, 38 | I have a line something like: :: 39 | 40 | OnlyShowIn=GNOME;Unity;MATE; 41 | 42 | I edit this line to: :: 43 | 44 | OnlyShowIn= 45 | 46 | So that no desktop environment enables gnome-keyring for ssh. 47 | 48 | References 49 | ========== 50 | 51 | * `Creating a new GPG key`_ 52 | * `Use OpenPGP Keys for OpenSSH, how to use gpg with ssh`_ 53 | 54 | .. _Creating a new GPG key: http://keyring.debian.org/creating-key.html 55 | .. _Use OpenPGP Keys for OpenSSH, how to use gpg with ssh: http://www.programmierecke.net/howto/gpg-ssh.html 56 | -------------------------------------------------------------------------------- /doc/images/gnuk-sticker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheStaticTurtle/gnuk/710fabc347fbc4723dcd3b0d91908be7e1053534/doc/images/gnuk-sticker.png -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | .. Gnuk Documentation documentation master file, created by 2 | sphinx-quickstart on Wed Jul 4 15:29:05 2012. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | Copyright (C) 2012, 2013, 2016 NIIBE Yutaka 6 | Copyright (C) 2012, 2013, 2016 Free Software Initiative of Japan 7 | This document is licensed under a CC-BY-SA 3.0 Unported License 8 | 9 | Gnuk Documentation 10 | ================== 11 | 12 | Contents: 13 | 14 | .. toctree:: 15 | :maxdepth: 2 16 | 17 | intro.rst 18 | gpg-settings.rst 19 | stop-scdaemon.rst 20 | udev-rules.rst 21 | gnuk-token-initial-configuration.rst 22 | gnuk-personalization.rst 23 | generating-key.rst 24 | gnuk-keytocard.rst 25 | gnuk-keytocard-noremoval.rst 26 | gnuk-passphrase-setting.rst 27 | using-gnuk-token-with-another-computer.rst 28 | development.rst 29 | 30 | 31 | Indices and tables 32 | ================== 33 | 34 | * :ref:`genindex` 35 | * :ref:`modindex` 36 | * :ref:`search` 37 | 38 | -------------------------------------------------------------------------------- /doc/intro.rst: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | 5 | What's Gnuk? 6 | ------------ 7 | 8 | Gnuk is an implementation of USB cryptographic token for GNU Privacy 9 | Guard. Gnuk supports OpenPGP card protocol version 2, and it runs on 10 | STM32F103 processor. 11 | 12 | This document explains about Gnuk 1.2, which comes with ECC algorithm. 13 | 14 | 15 | Cryptographic token and feature of Gnuk 16 | --------------------------------------- 17 | 18 | Cryptographic token is a store of private keys and it computes cryptographic 19 | functions on the device. 20 | 21 | The idea is to separate important secrets to independent device, 22 | from where nobody can extract them. 23 | 24 | 25 | Development Environment 26 | ----------------------- 27 | 28 | See :doc:`development` for development environment for Gnuk. 29 | Gnuk is developed on the environment where there are only Free Software. 30 | 31 | 32 | Target boards for running Gnuk 33 | ------------------------------ 34 | 35 | Hardware requirement for Gnuk is the micro controller STM32F103. 36 | In version 1.2, Gnuk supports following boards. 37 | 38 | * FST-01 (Flying Stone Tiny ZERO-ONE) 39 | 40 | * Olimex STM32-H103 41 | 42 | * ST Nucleo F103 43 | 44 | * Nitrokey Start 45 | 46 | 47 | Host prerequisites for using Gnuk Token 48 | --------------------------------------- 49 | 50 | * GNU Privacy Guard (GnuPG) 51 | 52 | * libusb 53 | 54 | * [Optional] SSH: openssh 55 | 56 | * [experimental] Web: scute, firefox 57 | 58 | 59 | Usages 60 | ------ 61 | 62 | * Sign with GnuPG 63 | * Decrypt with GnuPG 64 | * Use with OpenSSH through gpg-agent (as ssh-agent) 65 | * [experimental] Use with Firefox through Scute for X.509 client certificate authentication 66 | -------------------------------------------------------------------------------- /doc/note/HACKING: -------------------------------------------------------------------------------- 1 | * [DONE] Random Number Generator 2 | 3 | RNG is needed for Data Encryption Key to encrypt private key (P and Q). 4 | It is important to collect enough entropy. Perhaps, it would 5 | be possible to get entropy from USB traffic (of other devices). 6 | 7 | 8 | * [Mostly DONE] RSA 9 | 10 | It would be good not to use malloc. 11 | 12 | 13 | * Flash ROM recover from unexpected shutdown during write 14 | 15 | 16 | * [DONE] configure support 17 | 18 | configure script would be good to select a board and to generate 19 | random serial number. 20 | 21 | 22 | * [DONE] Random number update 23 | 24 | Implemented using SECECT_FILE and UPDATE_BINARY command, which is not 25 | in the OpenPGP card specification. 26 | 27 | Old description: Currently, Gnuk doesn't have random number generator, 28 | but use random bytes calculated by hosts. After Gnuk uses random 29 | number, the entry in Flash ROM will be cleared. Some scheme to update 30 | random number bytes is needed. Possibly, private Data Objects, or by 31 | another SELECT FILE. 32 | 33 | 34 | * [DONE] Manufacture ID 35 | 36 | Get it from FSFE. 37 | 38 | 39 | * [DONE] Serial number 40 | 41 | The AID of the card contains serial number. It should be unique. USB 42 | serial number should be unique to identify different tokens, too. 43 | 44 | 45 | * [DONE] Flash ROM garbage collection 46 | 47 | 48 | * [DONE] Flash ROM protection 49 | 50 | Flash ROM can be protected with OpenOCD. DfuSe users should know that 51 | the content can be accessible by DfuSe, even if we enable read 52 | protection of flash ROM. For proper protection, don't use DfuSe but 53 | use OpenOCD to write and protect. 54 | -------------------------------------------------------------------------------- /doc/note/NOTES: -------------------------------------------------------------------------------- 1 | USB communication (current) 2 | =========================== 3 | 4 | * Get response, command chaining, short APDU only. 5 | 6 | 7 | If it were only for token and no smartcard: 8 | 9 | * Get response, command chaining and short APDU would be considered 10 | useless. 11 | 12 | * It would be wise to use extended APDU and CCID/ICCD block chaining. 13 | 14 | The question would be: When lower layer (CCID/ICCD layer) support 15 | enough mechanism of block assembly, why not use one in the application 16 | layer (ISO 7816)? 17 | 18 | For token implementation, CCID/ICCD would be lower layer and ISO 7816 19 | would be higher layer, but it's different in fact. The figure of 20 | communication is like:: 21 | 22 | host <-----------> reader <---------> smartcard 23 | CCID/ICCD ISO 7816 24 | 25 | host <--> token 26 | 27 | Given the situation host side (GnuPG) already has the features of 28 | handling get response, command chaining, and short APDU only, it is 29 | rather better to do that on token side too. 30 | 31 | Besides, supporting extended APDU on host side, it would be needed to 32 | prepare 64KB buffer (that's the maximum size), as there is no explicit 33 | limitation for buffer size. 64KB would be large, and this could be 34 | avoided when we use short APDU only. 35 | 36 | 37 | USB communication (second attempt) 38 | ================================== 39 | 40 | * No get response, no command chaining, but extended APDU and extended 41 | Lc and Le. I think that this keep the code simple. 42 | 43 | * The value of dwMaxCCIDMessageLength is 320, that's the size 44 | of header of ICC block plus size of maximum APDU (by 64 45 | granularity). Still, some ccid implementation (ccid 1.3.11, for 46 | example) sends ICC block using chaining unfortunately, so we keep 47 | the code of ICC block chaining. 48 | 49 | 50 | USB communication (initial attempt) 51 | =================================== 52 | 53 | * Once in the past (version <= 0.4), the value of 54 | dwMaxCCIDMessageLength was 64 and we supported CCID/ICCD block chaining, 55 | so that we could not handle multple Bulk transactions. 56 | 57 | 58 | OpenPGP card protocol implementation 59 | ==================================== 60 | 61 | I try to follow "no clear password(s)" policy, even if it is on 62 | protected flash memory. Further, keystrings for user and reset code 63 | are removed after key imports. Because of this, replacing keys are 64 | not possible without password information. (Thus, replacing existing 65 | keys are not supported.) 66 | 67 | Therefore, there is "no clear password" and "no keystrings" on flash 68 | ROM when Gnuk is used by admin-less mode. When it is used with admin, 69 | the keystring of admin is on flash ROM. 70 | 71 | 72 | How a private key is stored 73 | =========================== 74 | 75 | KEYPTR 76 | ----> [ P ][ Q ][ N ] 77 | <---encrypted----><--- plain ----> 78 | 79 | initial_vector (random) 16-byte 80 | checksum_encrypted 16-byte 81 | dek_encrypted_by_keystring_pw1 16-byte 82 | dek_encrypted_by_keystring_rc 16-byte 83 | dek_encrypted_by_keystring_pw3 16-byte 84 | 85 | ... decrypted to 86 | 87 | [ P ][ Q ] 88 | checksum 16-byte 89 | -------------------------------------------------------------------------------- /doc/note/firmware-update: -------------------------------------------------------------------------------- 1 | Firmware update feature 2 | ======================= 3 | 4 | The firmware update feature of Gnuk is experimental. Please be 5 | careful using that. 6 | 7 | Note that updating firmware, all data objects and keys will be 8 | removed. There is _no way_ to preserve those data. 9 | 10 | 11 | Preparation 12 | =========== 13 | 14 | In addition to settings of Gnuk, I create a file 15 | /etc/udev/rules.d/92-gnuk.rules:: 16 | 17 | # For updating firmware, permission settings are needed. 18 | 19 | SUBSYSTEMS=="usb", ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \ 20 | ENV{ID_USB_INTERFACES}=="*:ff0000:*", GROUP="pcscd" 21 | 22 | 23 | While I am a member of group "pcscd" in /etc/group. 24 | 25 | This is needed for reGNUal, the firmware update program. 26 | 27 | 28 | Registering a public key for firmware update 29 | ============================================ 30 | 31 | You need to register a public key to update the firmware. It should 32 | be RSA 2048-bit. 33 | 34 | One way to extract public key data is by using "gpg-connect-agent" 35 | command connecting gpg-agent. 36 | 37 | We can examine key information of gpg-agent by "KEYINFO" command. 38 | Here is my example:: 39 | 40 | $ gpg-connect-agent "KEYINFO --list" /bye 41 | S KEYINFO 65F67E742101C7FE6D5B33FCEFCF4F65EAF0688C T D276000124010200F517000000010000 OPENPGP.2 - - - 42 | S KEYINFO 101DE7B639FE29F4636BDEECF442A9273AFA6565 T D276000124010200F517000000010000 OPENPGP.1 - - - 43 | S KEYINFO 5D6C89682D07CCFC034AF508420BF2276D8018ED T D276000124010200F517000000010000 OPENPGP.3 - - - 44 | OK 45 | 46 | I have three keys in my token. 47 | 48 | With the script below, I extract public key of the keygrip 49 | 5D6C89682D07CCFC034AF508420BF2276D8018ED into the file: 5D6C8968.bin:: 50 | 51 | $ ./get_raw_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED 52 | 53 | (The script is available in the directory gnuk/tool. Please note that 54 | it was written in the early stage of the development. The quality of 55 | the code is somewhat questionable.) 56 | 57 | 58 | Then, we can put the data of public key into token by:: 59 | 60 | $ tool/gnuk_put_binary_libusb.py -k 0 5D6C8968.bin 61 | 62 | 63 | Invoking firmware update 64 | ======================== 65 | 66 | We specify reGNUal binary and Gnuk binary. 67 | 68 | $ ../tool/gnuk_upgrade.py ../regnual/regnual.bin gnuk.bin 69 | 70 | 71 | Two or more tokens 72 | ================== 73 | 74 | Currently, GnuPG doesn't support multiple devices connected to the 75 | host. 76 | 77 | In order to update the firmware of a TARGET token, we use GnuPG to 78 | authenticate with public key. It is assumed that you have another 79 | AUTH token for this. This situation is somewhat complicated. 80 | 81 | What I do is: 82 | (1) Don't run PC/SC daemon:: 83 | 84 | # /etc/init.d/pcscd stop 85 | 86 | (2) To make sure, kill scdaemon:: 87 | 88 | $ killall -9 scdaemon 89 | 90 | (3) Insert the AUTH token to USB, and use it:: 91 | 92 | $ gpg --card-status 93 | 94 | (4) Insert the TARGET token to USB (after scdaemon communicates AUTH 95 | token), and invoke gnuk_upgrade.py. 96 | In this situation, gnuk_upgrade.py tries to connect one of tokens, 97 | but a connection to the AUTH token will fail because scdaemon is 98 | connecting to that device, and will be expected to connect to the 99 | TARGET token succesufully, instead. 100 | -- 101 | -------------------------------------------------------------------------------- /doc/note/settings-for-DnDpinentry: -------------------------------------------------------------------------------- 1 | On GNU/Linux Desktop, I use udisks-glue so that DnDpinentry folder can 2 | be mounted with sync and noatime options. 3 | 4 | After installing udisks-glue, I invoke gnome-session-properties to 5 | add udisks-glue to "Startup Program". 6 | 7 | Then, I have two files to configure udisks (disable udisks for 8 | DnDpinentry) and udisks-glue (enable and specify options for DnDpinentry). 9 | 10 | /etc/udev/rules.d/88-udisks.rules 11 | --------------- 12 | ENV{ID_VENDOR}=="FSIJ", ENV{DEVTYPE}=="disk", ENV{ID_FS_LABEL}=="DnDpinentry", ENV{UDISKS_PRESENTATION_NOPOLICY}="1" 13 | --------------- 14 | 15 | ~/.udisks-glue.conf 16 | --------------- 17 | filter gone { 18 | label = "DnDpinentry" 19 | optical = false 20 | } 21 | 22 | match gone { 23 | automount = true 24 | automount_options = { sync, noatime } 25 | } 26 | --------------- 27 | 28 | We need following setting for pinentry. Or else, you can't do 29 | anything when pinentry grabs mouse focus. 30 | 31 | ~/.gnupg/gpg-agent.conf 32 | --------------- 33 | no-grab 34 | --------------- 35 | -------------------------------------------------------------------------------- /doc/stop-scdaemon.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Stopping/Resetting SCDAEMON 3 | =========================== 4 | 5 | There is a daemon named ``scdaemon`` behind gpg-agent, which handles 6 | communication to smartcard/token. 7 | 8 | Ideally, we don't need to care about ``scdaemon``, and it should 9 | handle everything automatically. But, there are some cases (because 10 | of bugs), where we need to talk to the daemon directly, in practice. 11 | 12 | 13 | How to communicate SCDAEMON 14 | =========================== 15 | 16 | We have a utility to communicate with a running gpg-agent, that's 17 | gpg-connect-agent. We can use it to communicate with scdaemon, 18 | as it supports sub-command "SCD", exactly for this purpose. 19 | 20 | 21 | Stopping SCDAEMON 22 | ================= 23 | 24 | To stop SCDAEMON and let it exit, type:: 25 | 26 | $ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye 27 | 28 | Then, you can confirm that there is no SCDAEMON any more by ``ps`` 29 | command. 30 | 31 | Or, you can use ``gpgconf`` command. Type:: 32 | 33 | $ gpgconf --reload scdaemon 34 | 35 | will do the same thing. 36 | 37 | 38 | Let GPG-AGENT/SCDAEMON learn 39 | ============================ 40 | 41 | To let gpg-agent/scdaemon "learn" from Gnuk Token, type:: 42 | 43 | $ gpg-connect-agent learn /bye 44 | -------------------------------------------------------------------------------- /doc/udev-rules.rst: -------------------------------------------------------------------------------- 1 | =============================================== 2 | Device Configuration for Gnuk Token with libusb 3 | =============================================== 4 | 5 | In order to use Gnuk Token with libusb, configuration of device is 6 | needed for permissions. Note that this is not needed for the case of 7 | PC/SC Lite, as it has its own device configuration. 8 | 9 | 10 | udev rules for Gnuk Token 11 | ========================= 12 | 13 | In case of Debian, there is a file /lib/udev/rules.d/60-gnupg.rules 14 | (or /lib/udev/rules.d/60-scdamon.rules for newer version), 15 | when you install "gnupg" package (or "scdaemon" package). 16 | This is the place we need to 17 | change, if your installation is older than jessie. Newer "gnupg" 18 | package (1.4.15-1 or later) or "scdaemon" package has already 19 | supported Gnuk Token. 20 | 21 | If needed, please add lines for Gnuk Token to give a desktop user the 22 | permission to use the device. We specify USB ID of Gnuk Token (by 23 | FSIJ):: 24 | 25 | --- /lib/udev/rules.d/60-gnupg.rules.orig 2012-06-24 21:51:26.000000000 +0900 26 | +++ /lib/udev/rules.d/60-gnupg.rules 2012-07-13 17:18:55.149587687 +0900 27 | @@ -10,4 +10,7 @@ 28 | ATTR{idVendor}=="04e6", ATTR{idProduct}=="5115", ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg" 29 | ATTR{idVendor}=="20a0", ATTR{idProduct}=="4107", ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg" 30 | 31 | +# Gnuk 32 | +ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg" 33 | + 34 | LABEL="gnupg_rules_end" 35 | 36 | When we only install "gnupg2" package for 2.0 (with no "gnupg" package), 37 | there will be no udev rules (there is a bug report #543217 for this issue). 38 | In this case, we need something like this in /etc/udev/rules.d/60-gnuk.rules:: 39 | 40 | SUBSYSTEMS=="usb", ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \ 41 | ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg" 42 | 43 | Usually, udev daemon automatically handles for the changes of configuration 44 | files. If not, please let the daemon reload rules:: 45 | 46 | # udevadm control --reload-rules 47 | 48 | 49 | 50 | 51 | udev rules for ST-Link/V2 52 | ========================= 53 | 54 | For development of Gnuk, we use ST-Link/V2 as JTAG/SWD debugger. 55 | We need to have a udev rule for ST-Link/V2. It's like:: 56 | 57 | ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="3748", GROUP="tape", MODE="664", SYMLINK+="stlink" 58 | 59 | I have this in the file /etc/udev/rules.d/10-stlink.rules. 60 | -------------------------------------------------------------------------------- /docker/Dockerfile.check: -------------------------------------------------------------------------------- 1 | FROM gnuk:latest 2 | 3 | LABEL Description="Image for checking gnuK" 4 | 5 | RUN apt install -y shellcheck 6 | RUN apt install -y clang libfindbin-libs-perl 7 | RUN apt clean 8 | -------------------------------------------------------------------------------- /docker/Dockerfile.debug: -------------------------------------------------------------------------------- 1 | FROM gnuk:latest 2 | LABEL Description="Image for building gnuK with debugging" 3 | 4 | RUN apt install -y gdb-arm-none-eabi && apt clean 5 | -------------------------------------------------------------------------------- /docker/Dockerfile.release: -------------------------------------------------------------------------------- 1 | FROM debian:latest 2 | LABEL Description="Image for building gnuK" 3 | 4 | RUN apt update -y && apt install -y make gcc-arm-none-eabi && apt clean 5 | 6 | CMD ["/bin/sh", "-c", "cd /gnuk/src && make clean && ./configure $GNUK_CONFIG && make"] 7 | -------------------------------------------------------------------------------- /docker/Makefile: -------------------------------------------------------------------------------- 1 | ifndef GNUK_CONFIG 2 | $(warning configuration flags not set in GNUK_CONFIG) 3 | endif 4 | 5 | all: ../chopstx docker-build-release 6 | docker run --user=`id -u` --env GNUK_CONFIG --rm -v `pwd`/..:/gnuk/ -t gnuk:latest 7 | 8 | clean: docker-build-release 9 | docker run --user=`id -u` --env GNUK_CONFIG --rm -v `pwd`/..:/gnuk/ -w /gnuk/src -t gnuk:latest make clean 10 | 11 | gdb: docker-build-debug 12 | docker run --net host --rm -i -v `pwd`/..:/gnuk/ -t gnuk:latest-debug arm-none-eabi-gdb /gnuk/src/build/gnuk.elf 13 | 14 | shellcheck: docker-build-check 15 | docker run --rm -v `pwd`/..:/gnuk/ -t gnuk:latest-check shellcheck /gnuk/src/configure 16 | 17 | CHECKERS=security optin nullability core deadcode alpha.core alpha.security 18 | scan-build: clean docker-build-check 19 | docker run --user=`id -u` --rm -v `pwd`/..:/gnuk/ -w /gnuk/src -t gnuk:latest-check scan-build -o scan-build \ 20 | -analyze-headers -stats $(addprefix -enable-checker ,$(CHECKERS)) -k \ 21 | --use-cc=arm-none-eabi-gcc \ 22 | make 23 | ../chopstx: 24 | git submodule update --init 25 | 26 | docker-build-release: 27 | docker build -t gnuk:latest -f `pwd`/Dockerfile.release .. 28 | 29 | docker-build-debug: docker-build-release 30 | docker build -t gnuk:latest-debug -f `pwd`/Dockerfile.debug .. 31 | 32 | docker-build-check: docker-build-release 33 | docker build -t gnuk:latest-check -f `pwd`/Dockerfile.check .. 34 | 35 | .PHONY: all clean gdb shellcheck scan-build \ 36 | docker-build-release docker-build-debug docker-build-check 37 | -------------------------------------------------------------------------------- /gnuk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheStaticTurtle/gnuk/710fabc347fbc4723dcd3b0d91908be7e1053534/gnuk.png -------------------------------------------------------------------------------- /misc/t-mont.c: -------------------------------------------------------------------------------- 1 | /* 2 | * t-eddsa.c - testing EdDSA 3 | * Copyright (C) 2014 Free Software Initiative of Japan 4 | * Author: NIIBE Yutaka 5 | * 6 | * Run following commands. The file t-ed25519.inp is available in GNU 7 | * libgcrypt source code under 'tests' directory. 8 | 9 | gcc -Wall -c -DBN256_C_IMPLEMENTATION ecc-mont.c 10 | gcc -Wall -c -DBN256_NO_RANDOM -DBN256_C_IMPLEMENTATION bn.c 11 | gcc -Wall -c mod.c 12 | gcc -Wall -c -DBN256_C_IMPLEMENTATION mod25638.c 13 | gcc -Wall -c t-mont.c 14 | gcc -Wall -c debug-bn.c 15 | gcc -o t-mont t-mont.o ecc-mont.o bn.o mod.o mod25638.o debug-bn.o 16 | 17 | 18 | * 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "bn.h" 28 | 29 | const uint8_t k[32] = { 30 | 0x30, 0x01, 0x33, 0xE7, 0xDC, 0x52, 0xAD, 0x9F, 31 | 0x89, 0xFE, 0xC0, 0x59, 0x4A, 0x6D, 0x65, 0xE5, 32 | 0xF8, 0x7A, 0xD6, 0xA9, 0xA4, 0x89, 0x00, 0xB1, 33 | 0x93, 0x7E, 0xD3, 0x6F, 0x09, 0x1E, 0xB7, 0x76, 34 | }; 35 | 36 | int 37 | main (int argc, char *argv[]) 38 | { 39 | int all_good = 1; 40 | int r; 41 | bn256 *pk; 42 | bn256 a[1]; 43 | uint8_t out[32]; 44 | 45 | extern void ecdh_decrypt_curve25519 (const uint8_t *input, 46 | uint8_t *output, 47 | const bn256 *k); 48 | extern uint8_t *ecdh_compute_public_25519 (const uint8_t*k); 49 | extern void print_le_bn256 (const bn256 *X); 50 | 51 | while (1) 52 | { 53 | #if 0 54 | hash[0] &= 248; 55 | hash[31] &= 127; 56 | hash[31] |= 64; 57 | memcpy (a, hash, sizeof (bn256)); /* Lower half of hash */ 58 | #endif 59 | 60 | pk = ecdh_compute_public_25519 (k); 61 | print_le_bn256 (pk); 62 | return 0; 63 | 64 | #if 0 65 | if (memcmp (pk, pk_calculated, sizeof (bn256)) != 0) 66 | { 67 | printf ("ERR PK: %d\n", test_no); 68 | print_be_bn256 (sk); 69 | print_be_bn256 (pk); 70 | print_be_bn256 (pk_calculated); 71 | all_good = 0; 72 | continue; 73 | } 74 | 75 | ecdh_decrypt_25519 (msg, out, a); 76 | if (memcmp (sig, R, sizeof (bn256)) != 0 77 | || memcmp (((const uint8_t *)sig)+32, S, sizeof (bn256)) != 0) 78 | { 79 | printf ("ERR SIG: %d\n", test_no); 80 | print_le_bn256 (R); 81 | print_le_bn256 (S); 82 | print_le_bn256 ((const bn256 *)sig); 83 | print_le_bn256 ((const bn256 *)(((const uint8_t *)sig)+32)); 84 | all_good = 0; 85 | continue; 86 | } 87 | 88 | printf ("%d\n", test_no); 89 | #endif 90 | } 91 | return all_good == 1?0:1; 92 | } 93 | -------------------------------------------------------------------------------- /polarssl/README: -------------------------------------------------------------------------------- 1 | README for PolarSSL 2 | 3 | -- COMPILING 4 | There are currently three active build systems within the PolarSSL releases: 5 | - Make 6 | - CMake 7 | - Microsoft Visual Studio 8 | 9 | The main system used for development is CMake. That system is always the most up-to-date. The others should reflect all changes present in the CMake build system, but some features are not ported there by default. 10 | 11 | --- Make 12 | In order to build the source using Make, just enter at the command line: 13 | make 14 | 15 | In order to run the tests, enter: 16 | make check 17 | 18 | --- CMake 19 | In order to build the source using CMake, just enter at the command line: 20 | cmake . 21 | make 22 | 23 | There are 3 different active build modes specified within the CMake buildsystem: 24 | - Release 25 | This generates the default code without any unnecessary information in the binary files. 26 | - Debug 27 | This generates debug information and disables optimization of the code. 28 | - Coverage 29 | This generates code coverage information in addition to debug information. 30 | 31 | Switching build modes in CMake is simple. For debug mode, enter at the command line: 32 | cmake -D CMAKE_BUILD_TYPE:String="Debug" . 33 | 34 | In order to run the tests, enter: 35 | make test 36 | 37 | --- Microsoft Visual Studio 38 | The build files for Microsoft Visual Studio are generated for Visual Studio 6.0 all future Visual Studio's should be able to open and use this older version of the build files. 39 | 40 | The workspace 'polarssl.dsw' contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need a perl environment as well. 41 | -------------------------------------------------------------------------------- /regnual/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for reGNUal 2 | 3 | PROJECT = regnual-no-vidpid 4 | 5 | OBJS = regnual.o usb-stm32f103.o reset.o 6 | 7 | include ../src/config.mk 8 | 9 | LDSCRIPT= regnual.ld 10 | 11 | ################################### 12 | MCU = cortex-m3 13 | 14 | TRGT = arm-none-eabi- 15 | CC = $(TRGT)gcc 16 | LD = $(TRGT)ld 17 | OBJCOPY = $(TRGT)objcopy 18 | OBJDUMP = $(TRGT)objdump 19 | 20 | # THUMB-specific options here 21 | TOPT = -mthumb -DTHUMB -mno-thumb-interwork 22 | # Define C warning options here 23 | CWARN = -Wall -Wextra -Wstrict-prototypes 24 | MCFLAGS= -mcpu=$(MCU) 25 | DEFS += -DFREE_STANDING 26 | 27 | CFLAGS = -O2 -g 28 | CFLAGS += -Wa,-alms=$(notdir $(<:.c=.lst)) -fpie 29 | CFLAGS += $(CWARN) -I . -I ../chopstx -fno-common $(MCFLAGS) $(TOPT) $(DEFS) 30 | 31 | LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT) 32 | 33 | 34 | #################### 35 | 36 | all: regnual.hex 37 | 38 | regnual.o: regnual.c ../chopstx/sys.h ../chopstx/usb_lld.h 39 | 40 | regnual.hex: regnual.elf 41 | $(OBJCOPY) -Obinary regnual.elf regnual.bin 42 | $(OBJCOPY) -Oihex regnual.elf regnual.hex 43 | 44 | regnual.elf: regnual-no-vidpid.elf 45 | cp -p regnual-no-vidpid.elf regnual.elf 46 | env FILE="regnual.elf" PATH="../src:$$PATH" bash put-vid-pid-ver.sh 47 | 48 | usb-stm32f103.o: ../chopstx/mcu/usb-stm32f103.c 49 | $(CC) $(CFLAGS) -c -o usb-stm32f103.o ../chopstx/mcu/usb-stm32f103.c 50 | 51 | regnual-no-vidpid.elf: $(OBJS) $(LDSCRIPT) 52 | $(CC) $(LDFLAGS) -o regnual-no-vidpid.elf $(OBJS) 53 | 54 | clean: 55 | -rm -f $(OBJS) regnual-no-vidpid.elf regnual.elf regnual.hex regnual.bin \ 56 | *.lst 57 | 58 | distclean: clean 59 | -------------------------------------------------------------------------------- /regnual/regnual.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * ST32F103 memory setup. 3 | */ 4 | __main_stack_size__ = 0x0400; 5 | __process_stack_size__ = 0x0200; 6 | __stacks_total_size__ = __main_stack_size__ + __process_stack_size__; 7 | 8 | MEMORY 9 | { 10 | ram0 : org = 0x20000000, len = 0x1400 11 | ram1 : org = 0x20001400, len = 20k - 0x1400 12 | } 13 | 14 | vector = 0x08000000; 15 | 16 | __ram_start__ = ORIGIN(ram0); 17 | __ram_size__ = 20k; 18 | __ram_end__ = __ram_start__ + __ram_size__; 19 | 20 | SECTIONS 21 | { 22 | . = 0; 23 | 24 | .text : ALIGN(16) SUBALIGN(16) 25 | { 26 | _text = .; 27 | KEEP(*(.vectors)) 28 | *(.text.entry) 29 | *(.text) 30 | *(.text.*) 31 | *(.rodata) 32 | *(.rodata.*) 33 | *(.glue_7t) 34 | *(.glue_7) 35 | *(.gcc*) 36 | } > ram1 37 | 38 | .got : 39 | { 40 | *(.got) 41 | *(.got.*) 42 | } > ram1 43 | 44 | .ctors : 45 | { 46 | PROVIDE(_ctors_start_ = .); 47 | KEEP(*(SORT(.ctors.*))) 48 | KEEP(*(.ctors)) 49 | PROVIDE(_ctors_end_ = .); 50 | } > ram1 51 | 52 | .dtors : 53 | { 54 | PROVIDE(_dtors_start_ = .); 55 | KEEP(*(SORT(.dtors.*))) 56 | KEEP(*(.dtors)) 57 | PROVIDE(_dtors_end_ = .); 58 | } > ram1 59 | 60 | .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} 61 | 62 | __exidx_start = .; 63 | .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > ram1 64 | __exidx_end = .; 65 | 66 | .eh_frame_hdr : {*(.eh_frame_hdr)} 67 | 68 | .eh_frame : ONLY_IF_RO {*(.eh_frame)} 69 | 70 | . = ALIGN(4); 71 | _etext = .; 72 | _textdata = _etext; 73 | 74 | .data : 75 | { 76 | _data = .; 77 | *(.data) 78 | . = ALIGN(4); 79 | *(.data.*) 80 | . = ALIGN(4); 81 | *(.ramtext) 82 | . = ALIGN(4); 83 | _edata = .; 84 | } > ram1 85 | 86 | .bss : 87 | { 88 | _bss_start = .; 89 | *(.bss) 90 | . = ALIGN(4); 91 | *(.bss.*) 92 | . = ALIGN(4); 93 | *(COMMON) 94 | . = ALIGN(4); 95 | _bss_end = .; 96 | } > ram1 97 | 98 | PROVIDE(end = .); 99 | _end = .; 100 | } 101 | 102 | __heap_base__ = _end; 103 | __heap_end__ = __ram_end__ - __stacks_total_size__; 104 | -------------------------------------------------------------------------------- /regnual/reset.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | 3 | static void fatal (void) 4 | { 5 | for (;;); 6 | } 7 | 8 | static void none (void) 9 | { 10 | } 11 | 12 | /* 13 | * Note: the address of this routine 'entry' will be in the vectors as 14 | * RESET, but this will be called from application. It's not RESET 15 | * state, then. 16 | * 17 | * This routine doesn't change PSP and MSP. Application should 18 | * prepare those stack pointers. 19 | */ 20 | static __attribute__ ((naked,section(".text.entry"))) 21 | void entry (void) 22 | { 23 | asm volatile ("mov r0, pc\n\t" 24 | "bic r0, r0, #255\n\t" /* R0 := vector_table address */ 25 | "mov r1, #0x90\n\t" /* R1 := numbers of entries * 4 */ 26 | "ldr r3, .L01\n" /* R3 := -0x20001400 fixed addr */ 27 | "0:\n\t" 28 | "ldr r2, [r0, r1]\n\t" 29 | "add r2, r0\n\t" /* Relocate: R0 - 0x20001400 */ 30 | "add r2, r3\n\t" 31 | "str r2, [r0, r1]\n\t" 32 | "subs r1, r1, #4\n\t" 33 | "bne 0b\n\t" 34 | /* Relocation done. */ 35 | "add r0, r3\n\t" 36 | "ldr r3, .L00\n" 37 | ".LPIC00:\n\t" 38 | "add r3, pc\n\t" /* R3 := @_GLOBAL_OFFSET_TABLE_ */ 39 | /* Compute the address of BSS. */ 40 | "ldr r4, .L00+4\n\t" 41 | "ldr r1, [r3, r4]\n\t" 42 | "add r1, r0\n\t" /* relocate bss_start */ 43 | "ldr r4, .L00+8\n\t" 44 | "ldr r2, [r3, r4]\n" 45 | "add r2, r0\n\t" /* relocate bss_end */ 46 | /* Clear BSS. */ 47 | "mov r0, #0\n\t" 48 | "0:\n\t" 49 | "str r0, [r1], #4\n\t" 50 | "cmp r2, r1\n\t" 51 | "bhi 0b\n\t" 52 | "cpsie i\n\t" /* Enable interrupts */ 53 | "mov r0, #0\n\t" 54 | "mov r1, r0\n\t" 55 | "bl main\n" 56 | "1:\n\t" 57 | "b 1b\n\t" 58 | ".align 2\n" 59 | ".L01:\n\t" 60 | ".word -0x20001400\n" 61 | ".L00:\n\t" 62 | ".word _GLOBAL_OFFSET_TABLE_-(.LPIC00+4)\n\t" 63 | ".word _bss_start(GOT)\n\t" 64 | ".word _bss_end(GOT)" 65 | : /* no output */ : /* no input */ : "memory"); 66 | } 67 | 68 | typedef void (*handler)(void); 69 | extern uint8_t __ram_end__; 70 | extern void usb_interrupt_handler (void); 71 | 72 | handler vector_table[] __attribute__ ((section(".vectors"))) = { 73 | (handler)&__ram_end__, 74 | entry, 75 | fatal, /* nmi */ 76 | fatal, /* hard fault */ 77 | /* 10 */ 78 | fatal, /* mem manage */ 79 | fatal, /* bus fault */ 80 | fatal, /* usage fault */ 81 | none, 82 | /* 20 */ 83 | none, none, none, none, none, none, none, none, 84 | /* 40 */ 85 | none, none, none, none, none, none, none, none, 86 | /* 60 */ 87 | none, none, none, none, none, none, none, none, 88 | /* 80 */ 89 | none, none, none, none, 90 | /* 90 */ 91 | usb_interrupt_handler, 92 | }; 93 | -------------------------------------------------------------------------------- /regnual/types.h: -------------------------------------------------------------------------------- 1 | typedef unsigned long size_t; 2 | 3 | typedef unsigned char uint8_t; 4 | typedef unsigned short uint16_t; 5 | typedef unsigned int uint32_t; 6 | typedef unsigned int uintptr_t; 7 | 8 | #define TRUE 1 9 | #define FALSE 0 10 | 11 | #define NULL 0 12 | -------------------------------------------------------------------------------- /src/.gdbinit: -------------------------------------------------------------------------------- 1 | set arm force-mode thumb 2 | set arm fallback-mode thumb 3 | target remote localhost:3333 4 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Gnuk 2 | 3 | # Define project name here 4 | PROJECT = gnuk 5 | 6 | CHOPSTX = ../chopstx 7 | 8 | CSRC = main.c call-rsa.c \ 9 | usb_desc.c usb_ctrl.c \ 10 | usb-ccid.c openpgp.c ac.c openpgp-do.c flash.c \ 11 | bn.c mod.c \ 12 | modp256r1.c jpc_p256r1.c ec_p256r1.c call-ec_p256r1.c \ 13 | modp256k1.c jpc_p256k1.c ec_p256k1.c call-ec_p256k1.c \ 14 | mod25638.c ecc-edwards.c ecc-mont.c sha512.c \ 15 | random.c neug.c sha256.c 16 | 17 | INCDIR = 18 | 19 | CRYPTDIR = ../polarssl 20 | CRYPTSRCDIR = $(CRYPTDIR)/library 21 | CRYPTINCDIR = $(CRYPTDIR)/include 22 | CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/aes.c 23 | 24 | CSRC += $(CRYPTSRC) 25 | INCDIR += $(CRYPTINCDIR) 26 | 27 | include config.mk 28 | 29 | USE_SYS = yes 30 | USE_USB = yes 31 | USE_ADC = yes 32 | USE_EVENTFLAG = yes 33 | 34 | ifeq ($(EMULATION),) 35 | DEFS += -DFLASH_UPGRADE_SUPPORT 36 | else 37 | DEFS += -DBN256_C_IMPLEMENTATION 38 | endif 39 | 40 | ifneq ($(ENABLE_DEBUG),) 41 | CSRC += debug.c 42 | endif 43 | 44 | ifneq ($(ENABLE_PINPAD),) 45 | CSRC += pin-$(ENABLE_PINPAD).c 46 | endif 47 | 48 | ifeq ($(ENABLE_PINPAD),dnd) 49 | CSRC += usb-msc.c 50 | endif 51 | 52 | ifeq ($(CHIP),stm32f103) 53 | CSRC += mcu-stm32f103.c 54 | endif 55 | 56 | ifneq ($(USE_DFU),) 57 | OBJS_ADD += build/stdaln-sys-bin.o 58 | endif 59 | 60 | ################################### 61 | CC = $(CROSS)gcc 62 | LD = $(CROSS)gcc 63 | OBJCOPY = $(CROSS)objcopy 64 | 65 | CWARN = -Wall -Wextra -Wstrict-prototypes 66 | OPT = -O3 -Os -g 67 | 68 | ####################### 69 | include $(CHOPSTX)/rules.mk 70 | 71 | board.h: 72 | @echo Please run configure to have a symbolic link \'board.h\' 73 | @exit 1 74 | 75 | sys.c: board.h 76 | 77 | build/bignum.o: OPT = -O3 -g 78 | 79 | build/stdaln-sys.elf: build/sys-$(CHIP).o stdaln-sys.ld 80 | @echo 81 | $(LD) -v $< $(MCFLAGS) -nostartfiles -Tstdaln-sys.ld -Wl,--no-warn-mismatch,--gc-sections $(LLIBDIR) -o $@ 82 | 83 | build/stdaln-sys-bin.o: build/stdaln-sys.elf 84 | @echo 85 | $(OBJCOPY) -O binary -j .sys $< build/stdaln-sys.bin 86 | $(OBJCOPY) -I binary -O default --rename-section .data=.rodata \ 87 | build/stdaln-sys.bin $@ 88 | 89 | distclean: clean 90 | -rm -f gnuk.ld stdaln-sys.ld config.h board.h config.mk \ 91 | usb-strings.c.inc put-vid-pid-ver.sh 92 | 93 | ifeq ($(EMULATION),) 94 | build/gnuk.elf: build/gnuk-no-vidpid.elf binary-edit.sh put-vid-pid-ver.sh 95 | cp -p build/gnuk-no-vidpid.elf build/gnuk.elf 96 | env FILE="build/gnuk.elf" bash put-vid-pid-ver.sh 97 | $(OBJCOPY) -O ihex build/gnuk.elf build/gnuk.hex 98 | $(OBJCOPY) -O binary build/gnuk.elf build/gnuk.bin 99 | else 100 | # By specifying DESTDIR on invocation of "make", you can install 101 | # program to different ROOT. 102 | 103 | # The variables prefix, exec_prefix, libexecdir are defined in 104 | # config.mk. 105 | 106 | install: build/gnuk 107 | test -d "$(DESTDIR)$(libexecdir)" || mkdir -p "$(DESTDIR)$(libexecdir)" 108 | install -c build/gnuk "$(DESTDIR)$(libexecdir)" 109 | 110 | endif 111 | -------------------------------------------------------------------------------- /src/affine.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Affine coordinates 3 | */ 4 | typedef struct 5 | { 6 | bn256 x[1]; 7 | bn256 y[1]; 8 | } ac; 9 | -------------------------------------------------------------------------------- /src/binary-edit.sh: -------------------------------------------------------------------------------- 1 | # This is a Bash script to be included. 2 | 3 | # Idx Name Size VMA LMA File off Algn 4 | # ================= 5 | # 2 .text 00004a40 080010f0 080010f0 000110f0 2**4 6 | # 08006550 l O .text 00000012 device_desc 7 | # ================= 8 | # VMA =0x080010f0 9 | # FOFF=0x000110f0 10 | # ADDR=0x08005ad0 11 | # file_off_ADDR = ADDR - VMA + FOFF 12 | # = 0x08005ad0 - 0x080010f0 + 0x000110f0 = 0x00015ad0 13 | 14 | function calc_addr () { 15 | local line_sym="" VMA FOFF ADDR 16 | 17 | arm-none-eabi-objdump -h -t -j .text $FILE | \ 18 | egrep -e '(^ +[0-9] +\.text +|device_desc)' | \ 19 | while read -r F0 F1 F2 F3 F4 F5 F6; do 20 | if [ -z "$line_sym" ]; then 21 | VMA=$F3 22 | FOFF=$F5 23 | line_sym="next is a line for the symbol" 24 | else 25 | ADDR=$F0 26 | echo "$((0x$ADDR - 0x$VMA + 0x$FOFF))" 27 | fi 28 | done 29 | } 30 | 31 | declare -a OFFSETS 32 | OFFSETS=($(calc_addr)) 33 | file_off_ADDR=${OFFSETS[0]} 34 | file_off_fraucheky_ADDR=${OFFSETS[1]} 35 | 36 | echo "Offset is $file_off_ADDR" 37 | if [ -n "$file_off_fraucheky_ADDR" ]; then 38 | echo "Offset is $file_off_fraucheky_ADDR" 39 | fi 40 | 41 | function replace_file_byte_at () { 42 | printf "\x$1" | dd of=$FILE bs=1 seek=$2 conv=notrunc >& /dev/null 43 | } 44 | 45 | # 46 | # vid_lsb: 8 47 | # vid_msb: 9 48 | # pid_lsb: 10 49 | # pid_msb: 11 50 | # bcd_device_lsb: 12 51 | # bcd_device_msb: 13 52 | # 53 | 54 | function replace_vid_lsb () { 55 | replace_file_byte_at $1 $((addr + 8)) 56 | } 57 | 58 | function replace_vid_msb () { 59 | replace_file_byte_at $1 $((addr + 9)) 60 | } 61 | 62 | function replace_pid_lsb () { 63 | replace_file_byte_at $1 $((addr + 10)) 64 | } 65 | 66 | function replace_pid_msb () { 67 | replace_file_byte_at $1 $((addr + 11)) 68 | } 69 | 70 | function replace_bcd_device_lsb () { 71 | replace_file_byte_at $1 $((addr + 12)) 72 | } 73 | 74 | function replace_bcd_device_msb () { 75 | replace_file_byte_at $1 $((addr + 13)) 76 | } 77 | -------------------------------------------------------------------------------- /src/bn.h: -------------------------------------------------------------------------------- 1 | #define BN256_WORDS 8 2 | typedef struct bn256 { 3 | uint32_t word[ BN256_WORDS ]; /* Little endian */ 4 | } bn256; 5 | 6 | #define BN512_WORDS 16 7 | typedef struct bn512 { 8 | uint32_t word[ BN512_WORDS ]; /* Little endian */ 9 | } bn512; 10 | 11 | uint32_t bn256_add (bn256 *X, const bn256 *A, const bn256 *B); 12 | uint32_t bn256_sub (bn256 *X, const bn256 *A, const bn256 *B); 13 | uint32_t bn256_add_uint (bn256 *X, const bn256 *A, uint32_t w); 14 | uint32_t bn256_sub_uint (bn256 *X, const bn256 *A, uint32_t w); 15 | 16 | void bn256_mul (bn512 *X, const bn256 *A, const bn256 *B); 17 | void bn256_sqr (bn512 *X, const bn256 *A); 18 | uint32_t bn256_shift (bn256 *X, const bn256 *A, int shift); 19 | int bn256_is_zero (const bn256 *X); 20 | int bn256_is_even (const bn256 *X); 21 | int bn256_is_ge (const bn256 *A, const bn256 *B); 22 | int bn256_cmp (const bn256 *A, const bn256 *B); 23 | void bn256_random (bn256 *X); 24 | -------------------------------------------------------------------------------- /src/call-ec_p256k1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * call-ec_p256k1.c - interface between Gnuk and Elliptic curve over 3 | * GF(p256k1) 4 | * 5 | * Copyright (C) 2014, 2017 Free Software Initiative of Japan 6 | * Author: NIIBE Yutaka 7 | * 8 | * This file is a part of Gnuk, a GnuPG USB Token implementation. 9 | * 10 | * Gnuk is free software: you can redistribute it and/or modify it 11 | * under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Gnuk is distributed in the hope that it will be useful, but WITHOUT 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 18 | * License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | #include 26 | #include 27 | #include "bn.h" 28 | #include "affine.h" 29 | #include "jpc-ac_p256k1.h" 30 | #include "ec_p256k1.h" 31 | 32 | #define FIELD p256k1 33 | 34 | #include "call-ec.c" 35 | -------------------------------------------------------------------------------- /src/call-ec_p256r1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * call-ec_p256r1.c - interface between Gnuk and Elliptic curve over 3 | * GF(p256r1) 4 | * 5 | * Copyright (C) 2014, 2017 Free Software Initiative of Japan 6 | * Author: NIIBE Yutaka 7 | * 8 | * This file is a part of Gnuk, a GnuPG USB Token implementation. 9 | * 10 | * Gnuk is free software: you can redistribute it and/or modify it 11 | * under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Gnuk is distributed in the hope that it will be useful, but WITHOUT 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 18 | * License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | #include 26 | #include 27 | #include "bn.h" 28 | #include "affine.h" 29 | #include "jpc-ac_p256r1.h" 30 | #include "ec_p256r1.h" 31 | 32 | #define FIELD p256r1 33 | 34 | #include "call-ec.c" 35 | -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | @DEBUG_DEFINE@ 2 | #ifdef DEBUG 3 | #define ENABLE_VIRTUAL_COM_PORT 1 4 | #endif 5 | @DFU_DEFINE@ 6 | @ORIGIN_DEFINE@ 7 | @ORIGIN_REAL_DEFINE@ 8 | @PINPAD_DEFINE@ 9 | @PINPAD_MORE_DEFINE@ 10 | @CERTDO_DEFINE@ 11 | @HID_CARD_CHANGE_DEFINE@ 12 | @LIFE_CYCLE_MANAGEMENT_DEFINE@ 13 | @ACKBTN_DEFINE@ 14 | @SERIALNO_STR_LEN_DEFINE@ 15 | @CONFIRM_BUTTON_DEFINE@ 16 | @LED_BLINK_STATUS_DEFINE@ -------------------------------------------------------------------------------- /src/crypt.mk: -------------------------------------------------------------------------------- 1 | CRYPTDIR = ../polarssl 2 | CRYPTSRCDIR = $(CRYPTDIR)/library 3 | CRYPTINCDIR = $(CRYPTDIR)/include 4 | CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c \ 5 | $(CRYPTSRCDIR)/aes.c \ 6 | sha256.c call-rsa.c 7 | -------------------------------------------------------------------------------- /src/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * debug.c -- Debuging with virtual COM port 3 | * 4 | * Copyright (C) 2010 Free Software Initiative of Japan 5 | * Author: NIIBE Yutaka 6 | * 7 | * This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | * 9 | * Gnuk is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | * License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | extern void _write (const char *s, int len); 28 | 29 | static void 30 | put_hex (uint8_t nibble) 31 | { 32 | uint8_t c; 33 | 34 | if (nibble < 0x0a) 35 | c = '0' + nibble; 36 | else 37 | c = 'a' + nibble - 0x0a; 38 | 39 | _write ((const char *)&c, 1); 40 | } 41 | 42 | void 43 | put_byte (uint8_t b) 44 | { 45 | put_hex (b >> 4); 46 | put_hex (b &0x0f); 47 | _write ("\r\n", 2); 48 | } 49 | 50 | void 51 | put_byte_with_no_nl (uint8_t b) 52 | { 53 | _write (" ", 1); 54 | put_hex (b >> 4); 55 | put_hex (b &0x0f); 56 | } 57 | 58 | void 59 | put_short (uint16_t x) 60 | { 61 | put_hex (x >> 12); 62 | put_hex ((x >> 8)&0x0f); 63 | put_hex ((x >> 4)&0x0f); 64 | put_hex (x & 0x0f); 65 | _write ("\r\n", 2); 66 | } 67 | 68 | void 69 | put_word (uint32_t x) 70 | { 71 | put_hex (x >> 28); 72 | put_hex ((x >> 24)&0x0f); 73 | put_hex ((x >> 20)&0x0f); 74 | put_hex ((x >> 16)&0x0f); 75 | put_hex ((x >> 12)&0x0f); 76 | put_hex ((x >> 8)&0x0f); 77 | put_hex ((x >> 4)&0x0f); 78 | put_hex (x & 0x0f); 79 | _write ("\r\n", 2); 80 | } 81 | 82 | void 83 | put_int (uint32_t x) 84 | { 85 | char s[10]; 86 | int i; 87 | 88 | for (i = 0; i < 10; i++) 89 | { 90 | s[i] = '0' + (x % 10); 91 | x /= 10; 92 | if (x == 0) 93 | break; 94 | } 95 | 96 | while (i) 97 | { 98 | _write (s+i, 1); 99 | i--; 100 | } 101 | 102 | _write (s, 1); 103 | _write ("\r\n", 2); 104 | } 105 | 106 | void 107 | put_binary (const char *s, int len) 108 | { 109 | int i; 110 | 111 | for (i = 0; i < len; i++) 112 | { 113 | put_byte_with_no_nl (s[i]); 114 | if ((i & 0x0f) == 0x0f) 115 | _write ("\r\n", 2); 116 | } 117 | _write ("\r\n", 2); 118 | } 119 | 120 | void 121 | put_string (const char *s) 122 | { 123 | _write (s, strlen (s)); 124 | } 125 | 126 | 127 | -------------------------------------------------------------------------------- /src/debug.h: -------------------------------------------------------------------------------- 1 | struct stdout { 2 | chopstx_mutex_t m; 3 | /**/ 4 | chopstx_mutex_t m_dev; 5 | chopstx_cond_t cond_dev; 6 | uint8_t connected; 7 | }; 8 | 9 | extern struct stdout stdout; 10 | -------------------------------------------------------------------------------- /src/ec_p256k1.h: -------------------------------------------------------------------------------- 1 | int compute_kP_p256k1 (ac *X, const bn256 *K, const ac *P); 2 | int compute_kG_p256k1 (ac *X, const bn256 *K); 3 | void ecdsa_p256k1 (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d); 4 | int check_secret_p256k1 (const bn256 *q, bn256 *d1); 5 | -------------------------------------------------------------------------------- /src/ec_p256r1.h: -------------------------------------------------------------------------------- 1 | int compute_kP_p256r1 (ac *X, const bn256 *K, const ac *P); 2 | int compute_kG_p256r1 (ac *X, const bn256 *K); 3 | void ecdsa_p256r1 (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d); 4 | int check_secret_p256r1 (const bn256 *q, bn256 *d1); 5 | -------------------------------------------------------------------------------- /src/field-group-select.h: -------------------------------------------------------------------------------- 1 | #define CONCAT0(a,b) a##b 2 | #define CONCAT1(a,b) CONCAT0(a,b) 3 | #define CONCAT2(a,b,c) CONCAT1(a,b##c) 4 | #define CONCAT3(a,b,c) CONCAT2(a,b,c) 5 | 6 | #define FUNC(func) CONCAT1(func##_,FIELD) 7 | #define MFNC(func) CONCAT3(mod,FIELD,_##func) 8 | -------------------------------------------------------------------------------- /src/gnuk-malloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Gnuk uses its own malloc functions. 3 | * 4 | * The intention is no-dependency to C library. But, we provide 5 | * malloc and free here, since RSA routines uses malloc/free 6 | * internally. 7 | * 8 | */ 9 | 10 | #include /* NULL and size_t */ 11 | 12 | #define malloc(size) gnuk_malloc (size) 13 | #define free(p) gnuk_free (p) 14 | 15 | void *gnuk_malloc (size_t); 16 | void gnuk_free (void *); 17 | -------------------------------------------------------------------------------- /src/gnuk.ld.in: -------------------------------------------------------------------------------- 1 | /* 2 | * ST32F103 memory setup. 3 | */ 4 | MEMORY 5 | { 6 | flash0 : org = @ORIGIN@, len = 4k 7 | flash : org = @ORIGIN@+0x1000, len = @FLASH_SIZE@k - 4k 8 | ram : org = 0x20000000, len = @MEMORY_SIZE@k 9 | } 10 | 11 | __ram_start__ = ORIGIN(ram); 12 | __ram_size__ = LENGTH(ram); 13 | __ram_end__ = __ram_start__ + __ram_size__; 14 | 15 | SECTIONS 16 | { 17 | . = 0; 18 | 19 | .sys : ALIGN(4) SUBALIGN(4) 20 | { 21 | _sys = .; 22 | KEEP(*(.vectors)) 23 | . = ALIGN(16); 24 | KEEP(*(.sys.version)) 25 | KEEP(*(.sys.board_id)) 26 | KEEP(*(.sys.board_name)) 27 | build/sys-*.o(.text) 28 | build/sys-*.o(.text.*) 29 | build/sys-*.o(.rodata) 30 | build/sys-*.o(.rodata.*) 31 | . = ALIGN(1024); 32 | *(.sys.0) 33 | *(.sys.1) 34 | *(.sys.2) 35 | } > flash0 36 | 37 | _text = .; 38 | 39 | .startup : ALIGN(128) SUBALIGN(128) 40 | { 41 | KEEP(*(.startup.vectors)) 42 | . = ALIGN (16); 43 | } > flash =0xffffffff 44 | 45 | .text : ALIGN(16) SUBALIGN(16) 46 | { 47 | *(.text.startup.*) 48 | *(.text) 49 | *(.text.*) 50 | *(.rodata) 51 | *(.rodata.*) 52 | *(.glue_7t) 53 | *(.glue_7) 54 | *(.gcc*) 55 | . = ALIGN(8); 56 | } > flash 57 | 58 | .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} > flash 59 | 60 | .ARM.exidx : { 61 | PROVIDE(__exidx_start = .); 62 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 63 | PROVIDE(__exidx_end = .); 64 | } > flash 65 | 66 | .eh_frame_hdr : {*(.eh_frame_hdr)} > flash 67 | 68 | .eh_frame : ONLY_IF_RO {*(.eh_frame)} > flash 69 | 70 | .textalign : ONLY_IF_RO { . = ALIGN(8); } > flash 71 | 72 | _etext = .; 73 | _textdata = _etext; 74 | 75 | .stacks (NOLOAD) : 76 | { 77 | . = ALIGN(8); 78 | *(.main_stack) 79 | *(.process_stack.0) 80 | *(.process_stack.1) 81 | *(.process_stack.2) 82 | *(.process_stack.3) 83 | *(.process_stack.4) 84 | *(.process_stack.5) 85 | *(.process_stack.6) 86 | *(.process_stack.7) 87 | . = ALIGN(8); 88 | } > ram 89 | 90 | .data : 91 | { 92 | . = ALIGN(4); 93 | PROVIDE(_data = .); 94 | *(.data) 95 | . = ALIGN(4); 96 | *(.data.*) 97 | . = ALIGN(4); 98 | *(.ramtext) 99 | . = ALIGN(4); 100 | PROVIDE(_edata = .); 101 | } > ram AT > flash 102 | 103 | .bss : 104 | { 105 | . = ALIGN(4); 106 | PROVIDE(_bss_start = .); 107 | *(.bss) 108 | . = ALIGN(4); 109 | *(.bss.*) 110 | . = ALIGN(4); 111 | *(COMMON) 112 | . = ALIGN(4); 113 | PROVIDE(_bss_end = .); 114 | } > ram 115 | 116 | . = ALIGN(16); 117 | PROVIDE(end = .); 118 | _end = .; 119 | . = ALIGN(512); 120 | 121 | _regnual_start = .; 122 | 123 | @CERTDO_SUPPORT_START@ 124 | .gnuk_ch_certificate : 125 | { 126 | . = ALIGN (@FLASH_PAGE_SIZE@); 127 | ch_certificate_start = .; 128 | LONG(0xffffffff); 129 | . += 1920; 130 | . = ALIGN (@FLASH_PAGE_SIZE@); 131 | } > flash =0xffffffff 132 | @CERTDO_SUPPORT_END@ 133 | 134 | .gnuk_flash : 135 | { 136 | . = ALIGN (@FLASH_PAGE_SIZE@); 137 | _keystore_pool = .; 138 | . += 1024; 139 | . = ALIGN(@FLASH_PAGE_SIZE@); 140 | . += 1024; 141 | . = ALIGN(@FLASH_PAGE_SIZE@); 142 | . += 1024; 143 | . = ALIGN(@FLASH_PAGE_SIZE@); 144 | _updatekey_store = .; 145 | . += 1024; 146 | . = ALIGN(@FLASH_PAGE_SIZE@); 147 | _data_pool = .; 148 | KEEP(*(.gnuk_data)) 149 | . = ALIGN(@FLASH_PAGE_SIZE@); 150 | . += @FLASH_PAGE_SIZE@; 151 | } > flash =0xffffffff 152 | } 153 | 154 | __heap_base__ = _end; 155 | __heap_end__ = __ram_end__; 156 | -------------------------------------------------------------------------------- /src/jpc-ac_p256k1.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Jacobian projective coordinates 3 | */ 4 | typedef struct 5 | { 6 | bn256 x[1]; 7 | bn256 y[1]; 8 | bn256 z[1]; 9 | } jpc; 10 | 11 | void jpc_double_p256k1 (jpc *X, const jpc *A); 12 | void jpc_add_ac_p256k1 (jpc *X, const jpc *A, const ac *B); 13 | void jpc_add_ac_signed_p256k1 (jpc *X, const jpc *A, const ac *B, int minus); 14 | int jpc_to_ac_p256k1 (ac *X, const jpc *A); 15 | -------------------------------------------------------------------------------- /src/jpc-ac_p256r1.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Jacobian projective coordinates 3 | */ 4 | typedef struct 5 | { 6 | bn256 x[1]; 7 | bn256 y[1]; 8 | bn256 z[1]; 9 | } jpc; 10 | 11 | void jpc_double_p256r1 (jpc *X, const jpc *A); 12 | void jpc_add_ac_p256r1 (jpc *X, const jpc *A, const ac *B); 13 | void jpc_add_ac_signed_p256r1 (jpc *X, const jpc *A, const ac *B, int minus); 14 | int jpc_to_ac_p256r1 (ac *X, const jpc *A); 15 | -------------------------------------------------------------------------------- /src/jpc_p256k1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jpc_p256k1.c -- arithmetic on Jacobian projective coordinates for p256k1. 3 | * 4 | * Copyright (C) 2014 Free Software Initiative of Japan 5 | * Author: NIIBE Yutaka 6 | * 7 | * This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | * 9 | * Gnuk is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | * License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | #include 25 | #include 26 | #include "bn.h" 27 | #include "mod.h" 28 | #include "modp256k1.h" 29 | #include "affine.h" 30 | #include "jpc-ac_p256k1.h" 31 | 32 | #define FIELD p256k1 33 | #define CONST_P256 P256K1 34 | #define COEFFICIENT_A_IS_ZERO 1 35 | 36 | #include "jpc.c" 37 | -------------------------------------------------------------------------------- /src/jpc_p256r1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jpc_p256r1.c -- arithmetic on Jacobian projective coordinates for p256r1. 3 | * 4 | * Copyright (C) 2014 Free Software Initiative of Japan 5 | * Author: NIIBE Yutaka 6 | * 7 | * This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | * 9 | * Gnuk is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | * License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | #include 25 | #include 26 | #include "bn.h" 27 | #include "mod.h" 28 | #include "modp256r1.h" 29 | #include "affine.h" 30 | #include "jpc-ac_p256r1.h" 31 | 32 | #define FIELD p256r1 33 | #define CONST_P256 P256R1 34 | #define COEFFICIENT_A_IS_MINUS_3 1 35 | 36 | #include "jpc.c" 37 | -------------------------------------------------------------------------------- /src/mcu-stm32f103.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mcu-stm32f103.c - STM32F103 specific routines 3 | * 4 | * Copyright (C) 2017 5 | * Free Software Initiative of Japan 6 | * Author: NIIBE Yutaka 7 | * 8 | * This file is a part of Gnuk, a GnuPG USB Token implementation. 9 | * 10 | * Gnuk is free software: you can redistribute it and/or modify it 11 | * under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Gnuk is distributed in the hope that it will be useful, but WITHOUT 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 18 | * License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | #include 26 | #include "mcu/stm32f103.h" 27 | 28 | uint8_t * 29 | sram_address (uint32_t offset) 30 | { 31 | return ((uint8_t *)0x20000000) + offset; 32 | } 33 | -------------------------------------------------------------------------------- /src/mod.h: -------------------------------------------------------------------------------- 1 | void mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, 2 | const bn256 *MU_lower); 3 | void mod_inv (bn256 *X, const bn256 *A, const bn256 *N); 4 | -------------------------------------------------------------------------------- /src/mod25638.h: -------------------------------------------------------------------------------- 1 | extern const bn256 p25519[1]; 2 | 3 | void mod25638_add (bn256 *X, const bn256 *A, const bn256 *B); 4 | void mod25638_sub (bn256 *X, const bn256 *A, const bn256 *B); 5 | void mod25638_mul (bn256 *X, const bn256 *A, const bn256 *B); 6 | void mod25638_sqr (bn256 *X, const bn256 *A); 7 | void mod25519_reduce (bn256 *X); 8 | -------------------------------------------------------------------------------- /src/modp256k1.h: -------------------------------------------------------------------------------- 1 | extern const bn256 p256k1; 2 | #define P256K1 (&p256k1) 3 | 4 | void modp256k1_add (bn256 *X, const bn256 *A, const bn256 *B); 5 | void modp256k1_sub (bn256 *X, const bn256 *A, const bn256 *B); 6 | void modp256k1_reduce (bn256 *X, const bn512 *A); 7 | void modp256k1_mul (bn256 *X, const bn256 *A, const bn256 *B); 8 | void modp256k1_sqr (bn256 *X, const bn256 *A); 9 | void modp256k1_shift (bn256 *X, const bn256 *A, int shift); 10 | -------------------------------------------------------------------------------- /src/modp256r1.h: -------------------------------------------------------------------------------- 1 | extern const bn256 p256r1; 2 | #define P256R1 (&p256r1) 3 | 4 | void modp256r1_add (bn256 *X, const bn256 *A, const bn256 *B); 5 | void modp256r1_sub (bn256 *X, const bn256 *A, const bn256 *B); 6 | void modp256r1_reduce (bn256 *X, const bn512 *A); 7 | void modp256r1_mul (bn256 *X, const bn256 *A, const bn256 *B); 8 | void modp256r1_sqr (bn256 *X, const bn256 *A); 9 | void modp256r1_shift (bn256 *X, const bn256 *A, int shift); 10 | -------------------------------------------------------------------------------- /src/muladd_256.h: -------------------------------------------------------------------------------- 1 | #define MULADD_256_ASM(s_,d_,w_,c_) \ 2 | asm ( "ldmia %[s]!, { r8, r9, r10 } \n\t" \ 3 | "ldmia %[d], { r5, r6, r7 } \n\t" \ 4 | "umull r4, r8, %[w], r8 \n\t" \ 5 | "adds r5, r5, r4 \n\t" \ 6 | "adcs r6, r6, r8 \n\t" \ 7 | "umull r4, r8, %[w], r9 \n\t" \ 8 | "adc %[c], r8, #0 \n\t" \ 9 | "adds r6, r6, r4 \n\t" \ 10 | "adcs r7, r7, %[c] \n\t" \ 11 | "umull r4, r8, %[w], r10 \n\t" \ 12 | "adc %[c], r8, #0 \n\t" \ 13 | "adds r7, r7, r4 \n\t" \ 14 | "stmia %[d]!, { r5, r6, r7 } \n\t" \ 15 | "ldmia %[s]!, { r8, r9, r10 } \n\t" \ 16 | "ldmia %[d], { r5, r6, r7 } \n\t" \ 17 | "adcs r5, r5, %[c] \n\t" \ 18 | "umull r4, r8, %[w], r8 \n\t" \ 19 | "adc %[c], r8, #0 \n\t" \ 20 | "adds r5, r5, r4 \n\t" \ 21 | "adcs r6, r6, %[c] \n\t" \ 22 | "umull r4, r8, %[w], r9 \n\t" \ 23 | "adc %[c], r8, #0 \n\t" \ 24 | "adds r6, r6, r4 \n\t" \ 25 | "adcs r7, r7, %[c] \n\t" \ 26 | "umull r4, r8, %[w], r10 \n\t" \ 27 | "adc %[c], r8, #0 \n\t" \ 28 | "adds r7, r7, r4 \n\t" \ 29 | "stmia %[d]!, { r5, r6, r7 } \n\t" \ 30 | "ldmia %[s]!, { r8, r9 } \n\t" \ 31 | "ldmia %[d], { r5, r6 } \n\t" \ 32 | "adcs r5, r5, %[c] \n\t" \ 33 | "umull r4, r8, %[w], r8 \n\t" \ 34 | "adc %[c], r8, #0 \n\t" \ 35 | "adds r5, r5, r4 \n\t" \ 36 | "adcs r6, r6, %[c] \n\t" \ 37 | "umull r4, r8, %[w], r9 \n\t" \ 38 | "adc %[c], r8, #0 \n\t" \ 39 | "adds r6, r6, r4 \n\t" \ 40 | "adc %[c], %[c], #0 \n\t" \ 41 | "stmia %[d]!, { r5, r6 }" \ 42 | : [s] "=&r" (s_), [d] "=&r" (d_), [c] "=&r" (c_) \ 43 | : "[s]" (s_), "[d]" (d_), [w] "r" (w_) \ 44 | : "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 45 | "memory", "cc" ) 46 | 47 | #define MULADD_256(s__,d__,w__,c__) do { \ 48 | MULADD_256_ASM(s__,d__,w__,c__); \ 49 | *d__ = c__; \ 50 | } while (0) 51 | -------------------------------------------------------------------------------- /src/neug.h: -------------------------------------------------------------------------------- 1 | #define NEUG_NO_KICK 0 2 | #define NEUG_KICK_FILLING 1 3 | 4 | #define NEUG_PRE_LOOP 32 5 | 6 | #define NEUG_MODE_CONDITIONED 0 /* Conditioned data. */ 7 | #define NEUG_MODE_RAW 1 /* CRC-32 filtered sample data. */ 8 | #define NEUG_MODE_RAW_DATA 2 /* Sample data directly. */ 9 | 10 | extern uint8_t neug_mode; 11 | extern uint16_t neug_err_cnt; 12 | extern uint16_t neug_err_cnt_rc; 13 | extern uint16_t neug_err_cnt_p64; 14 | extern uint16_t neug_err_cnt_p4k; 15 | extern uint16_t neug_rc_max; 16 | extern uint16_t neug_p64_max; 17 | extern uint16_t neug_p4k_max; 18 | 19 | void neug_init (uint32_t *buf, uint8_t size); 20 | uint32_t neug_get (int kick); 21 | int neug_get_nonblock (uint32_t *p); 22 | void neug_kick_filling (void); 23 | void neug_flush (void); 24 | void neug_wait_full (void); 25 | void neug_fini (void); 26 | void neug_mode_select (uint8_t mode); 27 | 28 | int neug_consume_random (void (*proc) (uint32_t, int)); 29 | 30 | void crc32_rv_reset (void); 31 | void crc32_rv_step (uint32_t v); 32 | uint32_t crc32_rv_get (void); 33 | uint32_t rbit (uint32_t v); 34 | -------------------------------------------------------------------------------- /src/random.c: -------------------------------------------------------------------------------- 1 | /* 2 | * random.c -- get random bytes 3 | * 4 | * Copyright (C) 2010, 2011, 2012, 2013, 2015 5 | * Free Software Initiative of Japan 6 | * Author: NIIBE Yutaka 7 | * 8 | * This file is a part of Gnuk, a GnuPG USB Token implementation. 9 | * 10 | * Gnuk is free software: you can redistribute it and/or modify it 11 | * under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Gnuk is distributed in the hope that it will be useful, but WITHOUT 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 18 | * License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #include "gnuk.h" 29 | #include "neug.h" 30 | 31 | #define RANDOM_BYTES_LENGTH 32 32 | static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)]; 33 | 34 | void 35 | random_init (void) 36 | { 37 | int i; 38 | 39 | neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t)); 40 | 41 | for (i = 0; i < NEUG_PRE_LOOP; i++) 42 | (void)neug_get (NEUG_KICK_FILLING); 43 | } 44 | 45 | void 46 | random_fini (void) 47 | { 48 | neug_fini (); 49 | } 50 | 51 | /* 52 | * Return pointer to random 32-byte 53 | */ 54 | const uint8_t * 55 | random_bytes_get (void) 56 | { 57 | neug_wait_full (); 58 | return (const uint8_t *)random_word; 59 | } 60 | 61 | /* 62 | * Free pointer to random 32-byte 63 | */ 64 | void 65 | random_bytes_free (const uint8_t *p) 66 | { 67 | (void)p; 68 | memset (random_word, 0, RANDOM_BYTES_LENGTH); 69 | neug_flush (); 70 | } 71 | 72 | /* 73 | * Return 4-byte salt 74 | */ 75 | void 76 | random_get_salt (uint8_t *p) 77 | { 78 | uint32_t rnd; 79 | 80 | rnd = neug_get (NEUG_KICK_FILLING); 81 | memcpy (p, &rnd, sizeof (uint32_t)); 82 | rnd = neug_get (NEUG_KICK_FILLING); 83 | memcpy (p + sizeof (uint32_t), &rnd, sizeof (uint32_t)); 84 | } 85 | 86 | 87 | /* 88 | * Random byte iterator 89 | */ 90 | int 91 | random_gen (void *arg, unsigned char *out, size_t out_len) 92 | { 93 | uint8_t *index_p = (uint8_t *)arg; 94 | uint8_t index = *index_p; 95 | size_t n; 96 | 97 | while (out_len) 98 | { 99 | neug_wait_full (); 100 | 101 | n = RANDOM_BYTES_LENGTH - index; 102 | if (n > out_len) 103 | n = out_len; 104 | 105 | memcpy (out, ((unsigned char *)random_word) + index, n); 106 | out += n; 107 | out_len -= n; 108 | index += n; 109 | 110 | if (index >= RANDOM_BYTES_LENGTH) 111 | { 112 | index = 0; 113 | neug_flush (); 114 | } 115 | } 116 | 117 | *index_p = index; 118 | 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /src/random.h: -------------------------------------------------------------------------------- 1 | void random_init (void); 2 | void random_fini (void); 3 | 4 | /* 32-byte random bytes */ 5 | const uint8_t *random_bytes_get (void); 6 | void random_bytes_free (const uint8_t *p); 7 | 8 | /* 8-byte salt */ 9 | void random_get_salt (uint8_t *p); 10 | 11 | /* iterator returning a byta at a time */ 12 | int random_gen (void *arg, unsigned char *output, size_t output_len); 13 | -------------------------------------------------------------------------------- /src/sha256.h: -------------------------------------------------------------------------------- 1 | #define SHA256_DIGEST_SIZE 32 2 | #define SHA256_BLOCK_SIZE 64 3 | 4 | typedef struct 5 | { 6 | uint32_t total[2]; 7 | uint32_t state[8]; 8 | uint32_t wbuf[16]; 9 | } sha256_context; 10 | 11 | void sha256 (const unsigned char *input, unsigned int ilen, 12 | unsigned char output[32]); 13 | void sha256_start (sha256_context *ctx); 14 | void sha256_finish (sha256_context *ctx, unsigned char output[32]); 15 | void sha256_update (sha256_context *ctx, const unsigned char *input, 16 | unsigned int ilen); 17 | void sha256_process (sha256_context *ctx); 18 | -------------------------------------------------------------------------------- /src/sha512.h: -------------------------------------------------------------------------------- 1 | #define SHA512_DIGEST_SIZE 64 2 | #define SHA512_BLOCK_SIZE 128 3 | 4 | typedef struct 5 | { 6 | uint64_t total[2]; 7 | uint64_t state[8]; 8 | uint64_t wbuf[16]; 9 | } sha512_context; 10 | 11 | void sha512 (const unsigned char *input, unsigned int ilen, 12 | unsigned char output[64]); 13 | void sha512_start (sha512_context *ctx); 14 | void sha512_finish (sha512_context *ctx, unsigned char output[64]); 15 | void sha512_update (sha512_context *ctx, const unsigned char *input, 16 | unsigned int ilen); 17 | void sha512_process (sha512_context *ctx); 18 | -------------------------------------------------------------------------------- /src/stack-def.h: -------------------------------------------------------------------------------- 1 | #ifdef GNU_LINUX_EMULATION 2 | #define SIZE_1 4096 3 | #define SIZE_2 4096 4 | #define SIZE_3 (5 * 4096) 5 | #else 6 | #define SIZE_0 0x0160 /* Main */ 7 | #define SIZE_1 0x01a0 /* CCID */ 8 | #define SIZE_2 0x0180 /* RNG */ 9 | #if MEMORY_SIZE >= 32 10 | #define SIZE_3 0x4640 /* openpgp-card */ 11 | #elif MEMORY_SIZE >= 24 12 | #define SIZE_3 0x2640 /* openpgp-card */ 13 | #else 14 | #define SIZE_3 0x1640 /* openpgp-card */ 15 | #endif 16 | #define SIZE_4 0x0000 /* --- */ 17 | #define SIZE_5 0x0200 /* msc */ 18 | #define SIZE_6 0x00c0 /* timer (cir) */ 19 | #define SIZE_7 0x00c0 /* ext (cir) */ 20 | #endif 21 | 22 | #if defined(STACK_MAIN) && !defined(GNU_LINUX_EMULATION) 23 | /* Idle+Exception handlers */ 24 | char __main_stack_end__[0] __attribute__ ((section(".main_stack"))); 25 | char main_base[0x0080] __attribute__ ((section(".main_stack"))); 26 | 27 | /* Main program */ 28 | char __process0_stack_end__[0] __attribute__ ((section(".process_stack.0"))); 29 | char process0_base[SIZE_0] __attribute__ ((section(".process_stack.0"))); 30 | #endif 31 | 32 | /* First thread program */ 33 | #if defined(STACK_PROCESS_1) 34 | char process1_base[SIZE_1] __attribute__ ((section(".process_stack.1"))); 35 | #endif 36 | 37 | /* Second thread program */ 38 | #if defined(STACK_PROCESS_2) 39 | char process2_base[SIZE_2] __attribute__ ((section(".process_stack.2"))); 40 | #endif 41 | 42 | /* Third thread program */ 43 | #if defined(STACK_PROCESS_3) 44 | char process3_base[SIZE_3] __attribute__ ((section(".process_stack.3"))); 45 | #endif 46 | 47 | /* Fourth thread program */ 48 | #if defined(STACK_PROCESS_4) 49 | char process4_base[SIZE_4] __attribute__ ((section(".process_stack.4"))); 50 | #endif 51 | 52 | /* Fifth thread program */ 53 | #if defined(STACK_PROCESS_5) 54 | char process5_base[SIZE_5] __attribute__ ((section(".process_stack.5"))); 55 | #endif 56 | 57 | /* Sixth thread program */ 58 | #if defined(STACK_PROCESS_6) 59 | char process6_base[SIZE_6] __attribute__ ((section(".process_stack.6"))); 60 | #endif 61 | 62 | /* Seventh thread program */ 63 | #if defined(STACK_PROCESS_7) 64 | char process7_base[SIZE_7] __attribute__ ((section(".process_stack.7"))); 65 | #endif 66 | -------------------------------------------------------------------------------- /src/status-code.h: -------------------------------------------------------------------------------- 1 | #define GPG_APPLICATION_TERMINATED() set_res_sw (0x62, 0x85) 2 | #define GPG_MEMORY_FAILURE() set_res_sw (0x65, 0x81) 3 | #define GPG_WRONG_LENGTH() set_res_sw (0x67, 0x00) 4 | #define GPG_SECURITY_FAILURE() set_res_sw (0x69, 0x82) 5 | #define GPG_SECURITY_AUTH_BLOCKED() set_res_sw (0x69, 0x83) 6 | #define GPG_CONDITION_NOT_SATISFIED() set_res_sw (0x69, 0x85) 7 | #define GPG_COMMAND_NOT_ALLOWED() set_res_sw (0x69, 0x86) 8 | #define GPG_FUNCTION_NOT_SUPPORTED() set_res_sw (0x6a, 0x81) 9 | #define GPG_NO_FILE() set_res_sw (0x6a, 0x82) 10 | #define GPG_NO_RECORD() set_res_sw (0x6a, 0x88) 11 | #define GPG_BAD_P1_P2() set_res_sw (0x6b, 0x00) 12 | #define GPG_NO_INS() set_res_sw (0x6d, 0x00) 13 | #define GPG_ERROR() set_res_sw (0x6f, 0x00) 14 | #define GPG_SUCCESS() set_res_sw (0x90, 0x00) 15 | -------------------------------------------------------------------------------- /src/stdaln-sys.ld.in: -------------------------------------------------------------------------------- 1 | /* 2 | * ST32F103 memory setup. 3 | */ 4 | MEMORY 5 | { 6 | flash0 : org = @ORIGIN_REAL@, len = 4k 7 | ram : org = 0x20000000, len = @MEMORY_SIZE@k 8 | } 9 | 10 | __ram_start__ = ORIGIN(ram); 11 | __ram_size__ = LENGTH(ram); 12 | __ram_end__ = __ram_start__ + __ram_size__; 13 | 14 | SECTIONS 15 | { 16 | . = 0; 17 | 18 | .sys : ALIGN(4) SUBALIGN(4) 19 | { 20 | _sys = .; 21 | KEEP(*(.vectors)) 22 | . = ALIGN(16); 23 | KEEP(*(.sys.version)) 24 | KEEP(*(.sys.board_id)) 25 | KEEP(*(.sys.board_name)) 26 | build/sys-*.o(.text) 27 | build/sys-*.o(.text.*) 28 | build/sys-*.o(.rodata) 29 | build/sys-*.o(.rodata.*) 30 | . = ALIGN(1024); 31 | } > flash0 32 | 33 | .aesft : ALIGN(4) SUBALIGN(4) 34 | { 35 | *(.sys.0) 36 | *(.sys.1) 37 | *(.sys.2) 38 | } > flash0 39 | } 40 | -------------------------------------------------------------------------------- /src/usb-cdc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Class specific control requests for CDC 3 | */ 4 | #define USB_CDC_REQ_SET_LINE_CODING 0x20 5 | #define USB_CDC_REQ_GET_LINE_CODING 0x21 6 | #define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 7 | #define USB_CDC_REQ_SEND_BREAK 0x23 8 | 9 | #define VIRTUAL_COM_PORT_DATA_SIZE 16 10 | #define VIRTUAL_COM_PORT_INT_SIZE 8 11 | -------------------------------------------------------------------------------- /src/usb-msc.h: -------------------------------------------------------------------------------- 1 | #define MSC_CBW_SIGNATURE 0x43425355 2 | #define MSC_CSW_SIGNATURE 0x53425355 3 | 4 | #define MSC_GET_MAX_LUN_COMMAND 0xFE 5 | #define MSC_MASS_STORAGE_RESET_COMMAND 0xFF 6 | 7 | #define MSC_CSW_STATUS_PASSED 0 8 | #define MSC_CSW_STATUS_FAILED 1 9 | 10 | #define SCSI_INQUIRY 0x12 11 | #define SCSI_MODE_SENSE6 0x1A 12 | #define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E 13 | #define SCSI_READ10 0x28 14 | #define SCSI_READ_CAPACITY10 0x25 15 | #define SCSI_REQUEST_SENSE 0x03 16 | #define SCSI_START_STOP_UNIT 0x1B 17 | #define SCSI_TEST_UNIT_READY 0x00 18 | #define SCSI_WRITE10 0x2A 19 | #define SCSI_VERIFY10 0x2F 20 | #define SCSI_READ_FORMAT_CAPACITIES 0x23 21 | #define SCSI_SYNCHRONIZE_CACHE 0x35 22 | #define SCSI_REPORT_LUN 0xA0 23 | 24 | #define MSC_IDLE 0 25 | #define MSC_DATA_OUT 1 26 | #define MSC_DATA_IN 2 27 | #define MSC_SENDING_CSW 3 28 | #define MSC_ERROR 4 29 | 30 | struct CBW { 31 | uint32_t dCBWSignature; 32 | uint32_t dCBWTag; 33 | uint32_t dCBWDataTransferLength; 34 | uint8_t bmCBWFlags; 35 | uint8_t bCBWLUN; 36 | uint8_t bCBWCBLength; 37 | uint8_t CBWCB[16]; 38 | } __attribute__((packed)); 39 | 40 | struct CSW { 41 | uint32_t dCSWSignature; 42 | uint32_t dCSWTag; 43 | uint32_t dCSWDataResidue; 44 | uint8_t bCSWStatus; 45 | } __attribute__((packed)); 46 | 47 | #define SCSI_ERROR_NOT_READY 2 48 | #define SCSI_ERROR_ILLEAGAL_REQUEST 5 49 | #define SCSI_ERROR_UNIT_ATTENTION 6 50 | #define SCSI_ERROR_DATA_PROTECT 7 51 | 52 | extern uint8_t media_available; 53 | extern chopstx_mutex_t *pinpad_mutex; 54 | extern chopstx_cond_t *pinpad_cond; 55 | -------------------------------------------------------------------------------- /src/usb_conf.h: -------------------------------------------------------------------------------- 1 | /* USB buffer memory definition and number of string descriptors */ 2 | 3 | #ifndef __USB_CONF_H 4 | #define __USB_CONF_H 5 | 6 | #define CCID_NUM_INTERFACES 1 7 | #define CCID_INTERFACE 0 8 | #ifdef HID_CARD_CHANGE_SUPPORT 9 | #define HID_NUM_INTERFACES 1 10 | #define HID_INTERFACE 1 11 | #else 12 | #define HID_NUM_INTERFACES 0 13 | #endif 14 | #ifdef ENABLE_VIRTUAL_COM_PORT 15 | #define VCOM_NUM_INTERFACES 2 16 | #define VCOM_INTERFACE_0 (CCID_NUM_INTERFACES + HID_NUM_INTERFACES) 17 | #define VCOM_INTERFACE_1 (CCID_NUM_INTERFACES + HID_NUM_INTERFACES + 1) 18 | #else 19 | #define VCOM_NUM_INTERFACES 0 20 | #endif 21 | #ifdef PINPAD_DND_SUPPORT 22 | #define MSC_NUM_INTERFACES 1 23 | #define MSC_INTERFACE (CCID_NUM_INTERFACES + HID_NUM_INTERFACES + VCOM_NUM_INTERFACES) 24 | #else 25 | #define MSC_NUM_INTERFACES 0 26 | #endif 27 | #define NUM_INTERFACES (CCID_NUM_INTERFACES + HID_NUM_INTERFACES \ 28 | + VCOM_NUM_INTERFACES + MSC_NUM_INTERFACES) 29 | 30 | #if defined(USB_SELF_POWERED) 31 | #define USB_INITIAL_FEATURE 0xC0 /* bmAttributes: self powered */ 32 | #else 33 | #define USB_INITIAL_FEATURE 0x80 /* bmAttributes: bus powered */ 34 | #endif 35 | 36 | /* Control pipe */ 37 | /* EP0: 64-byte, 64-byte */ 38 | #define ENDP0_RXADDR (0x40) 39 | #define ENDP0_TXADDR (0x80) 40 | 41 | /* CCID/ICCD BULK_IN, BULK_OUT */ 42 | /* EP1: 64-byte, 64-byte */ 43 | #define ENDP1_TXADDR (0xc0) 44 | #define ENDP1_RXADDR (0x100) 45 | /* EP2: INTR_IN: 4-byte */ 46 | #define ENDP2_TXADDR (0x140) 47 | 48 | /* CDC BULK_IN, INTR_IN, BULK_OUT */ 49 | /* EP3: 16-byte */ 50 | #define ENDP3_TXADDR (0x144) 51 | /* EP4: 8-byte */ 52 | #define ENDP4_TXADDR (0x154) 53 | /* EP5: 16-byte */ 54 | #define ENDP5_RXADDR (0x15c) 55 | 56 | /* 0x16c - 0x17e : 18-byte */ 57 | 58 | /* HID INTR_IN */ 59 | /* EP7: 2-byte */ 60 | #define ENDP7_TXADDR (0x17e) 61 | 62 | /* MSC BULK_IN, BULK_OUT */ 63 | /* EP6: 64-byte, 64-byte */ 64 | #define ENDP6_TXADDR (0x180) 65 | #define ENDP6_RXADDR (0x1c0) 66 | 67 | #endif /* __USB_CONF_H */ 68 | -------------------------------------------------------------------------------- /test/README: -------------------------------------------------------------------------------- 1 | This is a functionality test suite for Gnuk. 2 | 3 | You need python-nose, python-freshen as well as python-usb. 4 | 5 | Besides, python-crypto is needed when you use generate_keys.py to 6 | update contents of *.key. 7 | 8 | 9 | Type: 10 | 11 | $ nosetests --with-freshen 12 | 13 | or 14 | 15 | $ nosetests -v --with-freshen 16 | 17 | to run the test suite. 18 | 19 | To skip tests for key generation, add an option "--tag ~keygen". To 20 | stop running tests after the first error or failure, add "--stop" option. 21 | -------------------------------------------------------------------------------- /test/ecc_nistp256_keys.py: -------------------------------------------------------------------------------- 1 | # Data taken from: 2 | # A. Jivsov, Sample Keys and Messages: 3 | # https://sites.google.com/site/brainhub/pgpecckeys 4 | 5 | # uid ec_dsa_dh_256 6 | # sign key: 7 | # nistp256/BAA59D9C 2010-09-17 8 | # keygrip: 8E06A180EFFE4C65B812150CAF19BF30C0689A4C 9 | # 10 | # q=(x, y) and d 11 | key[0] = (0x0bc7a7baebd5f08c74c77b71ee44e7bb0b5a18317b996da5393e33acc52932c6, 12 | 0xd2f60f4d1efe35a0b9fb8d3787ed4bee97ca012d07b8f5835be7093545d532e6, 13 | 0xd8f28c530c99821faa5ee2ff4dd8d1df01995d4e98fb45f8768cb65abd4adaa9) 14 | 15 | # decryption key: 16 | # sub nistp256/4089AB73 2010-09-17 nistp256 17 | # keygrip: E4403F3FD7A443FAC29FEF288FA0D20AC212851E 18 | # 19 | # q=(x, y) and d 20 | key[1] = (0x7f70c0a8184cdcaea5db20ba8fed17e47bdefb744d575ec449130af37edade65, 21 | 0x8ae7ee35d20e8897911c9f564be33d9a94bc1e5c927b1aa07ff750d2d11c2971, 22 | 0xa05cd14749bea3f3d14c92dc438e45e351efe860360c431705b7d42410581843) 23 | 24 | # auth key from: uid ec_dsa_dh_256_no_pass 25 | # 26 | # q=(x, y) and d 27 | key[2] = (0x81fbbc20eea9e8d1c3ceabb0a8185925b113d1ac42cd5c78403bd83da19235c6, 28 | 0x5ed6db13d91db34507d0129bf88981878d29adbf8fcd1720afdb767bb3fcaaff, 29 | 0xa355916f8665eb99c1af48d9560b5c6889e5287bc75aa693aaae9bdb15e8b3fd) 30 | 31 | # This file is here to extend the test suite for ECC. 32 | -------------------------------------------------------------------------------- /test/features/000_empty_check.feature: -------------------------------------------------------------------------------- 1 | Feature: confirm empty token 2 | In order to start tests 3 | A token should be empty (no data, no keys) 4 | 5 | Scenario: data object Login 6 | When requesting login data: 5e 7 | Then you should get NULL 8 | 9 | Scenario: data object Name 10 | When requesting name: 5b 11 | Then you should get NULL 12 | 13 | Scenario: data object Language preference 14 | When requesting anguage preference: 5f2d 15 | Then you should get NULL 16 | 17 | Scenario: data object Sex 18 | When requesting sex: 5f35 19 | Then you should get NULL 20 | 21 | Scenario: data object URL 22 | When requesting URL: 5f50 23 | Then you should get NULL 24 | 25 | Scenario: data object ds counter 26 | When requesting ds counter: 93 27 | Then you should get: \x00\x00\x00 28 | 29 | Scenario: data object pw1 status bytes 30 | When requesting pw1 status bytes: c4 31 | Then you should get: \x00\x7f\x7f\x7f\x03\x03\x03 32 | 33 | Scenario: data object finger print 0 34 | When requesting finger print: c5 35 | Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 36 | 37 | Scenario: data object finger print 1 38 | When requesting finger print: c7 39 | Then you should get NULL 40 | 41 | Scenario: data object finger print 2 42 | When requesting finger print: c8 43 | Then you should get NULL 44 | 45 | Scenario: data object finger print 3 46 | When requesting finger print: c9 47 | Then you should get NULL 48 | 49 | Scenario: data object CA finger print 0 50 | When requesting finger print: c6 51 | Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 52 | 53 | Scenario: data object CA finger print 1 54 | When requesting finger print: ca 55 | Then you should get NULL 56 | 57 | Scenario: data object CA finger print 2 58 | When requesting finger print: cb 59 | Then you should get NULL 60 | 61 | Scenario: data object CA finger print 3 62 | When requesting finger print: cc 63 | Then you should get NULL 64 | 65 | Scenario: data object date/time of key pair 0 66 | When requesting date/time of key pair: cd 67 | Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 68 | 69 | Scenario: data object date/time of key pair 1 70 | When requesting date/time of key pair: ce 71 | Then you should get NULL 72 | 73 | Scenario: data object date/time of key pair 2 74 | When requesting date/time of key pair: cf 75 | Then you should get NULL 76 | 77 | Scenario: data object date/time of key pair 3 78 | When requesting date/time of key pair: d0 79 | Then you should get NULL 80 | -------------------------------------------------------------------------------- /test/features/001_empty_check_passphrase.feature: -------------------------------------------------------------------------------- 1 | Feature: confirm empty token 2 | In order to start tests 3 | A token should be empty (no pass phrase) 4 | 5 | Scenario: verify PW1 factory setting (1) 6 | Given cmd_verify with 1 and "123456" 7 | Then it should get success 8 | 9 | Scenario: verify PW1 factory setting (2) 10 | Given cmd_verify with 2 and "123456" 11 | Then it should get success 12 | 13 | Scenario: verify PW3 factory setting 14 | Given cmd_verify with 3 and "12345678" 15 | Then it should get success 16 | -------------------------------------------------------------------------------- /test/features/002_get_data_static.feature: -------------------------------------------------------------------------------- 1 | Feature: command GET DATA 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support all mandatory features of the specification 4 | 5 | Scenario: data object historical bytes 6 | When requesting historical bytes: 5f52 7 | Then data should match: \x00\x31\x84\x73\x80\x01\x80[\x00\x05]\x90\x00 8 | 9 | Scenario: data object extended capabilities 10 | When requesting extended capabilities: c0 11 | Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00 12 | 13 | Scenario: data object algorithm attributes 1 14 | When requesting algorithm attributes 1: c1 15 | Then you should get: \x01\x08\x00\x00\x20\x00 16 | 17 | Scenario: data object algorithm attributes 2 18 | When requesting algorithm attributes 2: c2 19 | Then you should get: \x01\x08\x00\x00\x20\x00 20 | 21 | Scenario: data object algorithm attributes 3 22 | When requesting algorighm attributes 3: c3 23 | Then you should get: \x01\x08\x00\x00\x20\x00 24 | 25 | Scenario: data object AID 26 | When requesting AID: 4f 27 | Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00 28 | -------------------------------------------------------------------------------- /test/features/003_keyattr_change.feature: -------------------------------------------------------------------------------- 1 | @keyattr 2 | Feature: key attribute change 3 | In order to use a token with multiple different kind of key algorighm 4 | A token should support key attribute change 5 | 6 | Scenario: key attribute data object write: algorithm for signature (RSA-4K) 7 | Given cmd_put_data with c1 and "\x01\x10\x00\x00\x20\x00" 8 | Then it should get success 9 | 10 | Scenario: key attribute data object write: algorithm for signature (RSA-2K) 11 | Given cmd_put_data with c1 and "\x01\x08\x00\x00\x20\x00" 12 | Then it should get success 13 | 14 | Scenario: key attribute data object write: algorithm for decryption (RSA-4K) 15 | Given cmd_put_data with c2 and "\x01\x10\x00\x00\x20\x00" 16 | Then it should get success 17 | 18 | Scenario: key attribute data object write: algorithm for decryption (RSA-2K) 19 | Given cmd_put_data with c2 and "\x01\x08\x00\x00\x20\x00" 20 | Then it should get success 21 | 22 | Scenario: key attribute data object write: algorithm for authentication (RSA-4K) 23 | Given cmd_put_data with c3 and "\x01\x10\x00\x00\x20\x00" 24 | Then it should get success 25 | 26 | Scenario: key attribute data object write: algorithm for authentication (RSA-2K) 27 | Given cmd_put_data with c3 and "\x01\x08\x00\x00\x20\x00" 28 | Then it should get success 29 | -------------------------------------------------------------------------------- /test/features/010_setup_passphrase.feature: -------------------------------------------------------------------------------- 1 | Feature: setup pass phrase 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support pass phrase: PW1, PW3 and reset code 4 | 5 | Scenario: setup PW3 (admin-full mode) 6 | Given cmd_change_reference_data with 3 and "12345678admin pass phrase" 7 | Then it should get success 8 | 9 | Scenario: verify PW3 (admin-full mode) 10 | Given cmd_verify with 3 and "admin pass phrase" 11 | Then it should get success 12 | -------------------------------------------------------------------------------- /test/features/020_personalization_write.feature: -------------------------------------------------------------------------------- 1 | Feature: personalize token write 2 | In order to use a token 3 | A token should be personalized with name, sex, url, etc. 4 | 5 | Scenario: data object Login 6 | Given cmd_put_data with 5e and "gpg_user" 7 | Then it should get success 8 | 9 | Scenario: data object Name 10 | Given cmd_put_data with 5b and "GnuPG User" 11 | Then it should get success 12 | 13 | Scenario: data object Language preference 14 | Given cmd_put_data with 5f2d and "ja" 15 | Then it should get success 16 | 17 | Scenario: data object Sex 18 | Given cmd_put_data with 5f35 and "1" 19 | Then it should get success 20 | 21 | Scenario: data object URL 22 | Given cmd_put_data with 5f50 and "http://www.fsij.org/gnuk/" 23 | Then it should get success 24 | 25 | Scenario: data object pw1 status bytes 26 | Given cmd_put_data with c4 and "\x01" 27 | Then it should get success 28 | -------------------------------------------------------------------------------- /test/features/021_personalization_read.feature: -------------------------------------------------------------------------------- 1 | Feature: personalize token read 2 | In order to use a token 3 | A token should be personalized with name, sex, url, etc. 4 | 5 | Scenario: data object Login 6 | When requesting login data: 5e 7 | Then you should get: gpg_user 8 | 9 | Scenario: data object Name 10 | When requesting name: 5b 11 | Then you should get: GnuPG User 12 | 13 | Scenario: data object Language preference 14 | When requesting anguage preference: 5f2d 15 | Then you should get: ja 16 | 17 | Scenario: data object Sex 18 | When requesting sex: 5f35 19 | Then you should get: 1 20 | 21 | Scenario: data object URL 22 | When requesting URL: 5f50 23 | Then you should get: http://www.fsij.org/gnuk/ 24 | 25 | Scenario: data object pw1 status bytes 26 | When requesting pw1 status bytes: c4 27 | Then you should get: \x01\x7f\x7f\x7f\x03\x03\x03 28 | -------------------------------------------------------------------------------- /test/features/030_key_registration.feature: -------------------------------------------------------------------------------- 1 | Feature: import keys to token 2 | In order to use a token 3 | A token should have keys 4 | 5 | Scenario: importing OPENPGP.1 key (sign) 6 | Given a RSA key pair 0 7 | And importing it to the token as OPENPGP.1 8 | Then it should get success 9 | 10 | Scenario: importing OPENPGP.2 key (decrypt) 11 | Given a RSA key pair 1 12 | And importing it to the token as OPENPGP.2 13 | Then it should get success 14 | 15 | Scenario: importing OPENPGP.3 key (authentication) 16 | Given a RSA key pair 2 17 | And importing it to the token as OPENPGP.3 18 | Then it should get success 19 | 20 | Scenario: setup data object Finger print sig 21 | Given a fingerprint of OPENPGP.1 key 22 | And put the data to c7 23 | Then it should get success 24 | 25 | Scenario: setup data object Finger print dec 26 | Given a fingerprint of OPENPGP.2 key 27 | And put the data to c8 28 | Then it should get success 29 | 30 | Scenario: setup data object Finger print aut 31 | Given a fingerprint of OPENPGP.3 key 32 | And put the data to c9 33 | Then it should get success 34 | 35 | Scenario: setup data object keygeneration data/time sig 36 | Given a timestamp of OPENPGP.1 key 37 | And put the data to ce 38 | Then it should get success 39 | 40 | Scenario: setup data object keygeneration data/time dec 41 | Given a timestamp of OPENPGP.2 key 42 | And put the data to cf 43 | Then it should get success 44 | 45 | Scenario: setup data object keygeneration data/time aut 46 | Given a timestamp of OPENPGP.3 key 47 | And put the data to d0 48 | Then it should get success 49 | 50 | Scenario: setup PW1 (admin-full mode) 51 | Given cmd_change_reference_data with 1 and "123456another user pass phrase" 52 | Then it should get success 53 | 54 | Scenario: verify PW1 (1) again 55 | Given cmd_verify with 1 and "another user pass phrase" 56 | Then it should get success 57 | 58 | Scenario: verify PW1 (2) again 59 | Given cmd_verify with 2 and "another user pass phrase" 60 | Then it should get success 61 | -------------------------------------------------------------------------------- /test/features/040_passphrase_change.feature: -------------------------------------------------------------------------------- 1 | Feature: change pass phrase 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support pass phrase: PW1, PW3 and reset code 4 | 5 | Scenario: change PW1 6 | Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG" 7 | Then it should get success 8 | 9 | Scenario: verify PW1 (1) again 10 | Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG" 11 | Then it should get success 12 | 13 | Scenario: verify PW1 (2) again 14 | Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG" 15 | Then it should get success 16 | 17 | Scenario: setup reset code (in admin-full mode) 18 | Given cmd_put_data with d3 and "example reset code 000" 19 | Then it should get success 20 | 21 | Scenario: reset pass phrase by reset code (in admin-full mode) 22 | Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase" 23 | Then it should get success 24 | 25 | Scenario: verify PW1 (1) again 26 | Given cmd_verify with 1 and "new user pass phrase" 27 | Then it should get success 28 | 29 | Scenario: verify PW1 (2) again 30 | Given cmd_verify with 2 and "new user pass phrase" 31 | Then it should get success 32 | 33 | Scenario: change PW3 (admin-full mode) 34 | Given cmd_change_reference_data with 3 and "admin pass phraseanother admin pass phrase" 35 | Then it should get success 36 | 37 | Scenario: verify PW3 (admin-full mode) 38 | Given cmd_verify with 3 and "another admin pass phrase" 39 | Then it should get success 40 | 41 | Scenario: reset pass phrase by admin (in admin-full mode) 42 | Given cmd_reset_retry_counter with 2 and "new user pass phrase" 43 | Then it should get success 44 | 45 | Scenario: verify PW1 (1) again 46 | Given cmd_verify with 1 and "new user pass phrase" 47 | Then it should get success 48 | 49 | Scenario: verify PW1 (2) again 50 | Given cmd_verify with 2 and "new user pass phrase" 51 | Then it should get success 52 | 53 | Scenario: change PW1 54 | Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase" 55 | Then it should get success 56 | 57 | Scenario: verify PW1 (1) again 58 | Given cmd_verify with 1 and "another user pass phrase" 59 | Then it should get success 60 | 61 | Scenario: verify PW1 (2) again 62 | Given cmd_verify with 2 and "another user pass phrase" 63 | Then it should get success 64 | 65 | Scenario: change PW3 (admin-full mode) 66 | Given cmd_change_reference_data with 3 and "another admin pass phraseadmin pass phrase" 67 | Then it should get success 68 | 69 | Scenario: verify PW3 (admin-full mode) 70 | Given cmd_verify with 3 and "admin pass phrase" 71 | Then it should get success 72 | -------------------------------------------------------------------------------- /test/features/100_compute_signature.feature: -------------------------------------------------------------------------------- 1 | Feature: compute digital signature 2 | In order to use a token 3 | A token should compute digital signature properly 4 | 5 | Scenario: compute digital signature by OPENPGP.1 key (1) 6 | Given a message "This is a test message." 7 | And let a token compute digital signature 8 | And compute digital signature on host with RSA key pair 0 9 | Then results should be same 10 | 11 | Scenario: compute digital signature by OPENPGP.1 key (2) 12 | Given a message "This is another test message.\nMultiple lines.\n" 13 | And let a token compute digital signature 14 | And compute digital signature on host with RSA key pair 0 15 | Then results should be same 16 | 17 | Scenario: compute digital signature by OPENPGP.3 key (1) 18 | Given a message "This is a test message." 19 | And let a token authenticate 20 | And compute digital signature on host with RSA key pair 2 21 | Then results should be same 22 | 23 | Scenario: compute digital signature by OPENPGP.3 key (2) 24 | Given a message "This is another test message.\nMultiple lines.\n" 25 | And let a token authenticate 26 | And compute digital signature on host with RSA key pair 2 27 | Then results should be same 28 | 29 | Scenario: data object ds counter 30 | When requesting ds counter: 93 31 | Then you should get: \x00\x00\x02 32 | -------------------------------------------------------------------------------- /test/features/101_decryption.feature: -------------------------------------------------------------------------------- 1 | Feature: decryption 2 | In order to use a token 3 | A token should decrypt encrypted data 4 | 5 | Scenario: decrypt by OPENPGP.2 key (1) 6 | Given a plain text "This is a test message." 7 | And encrypt it on host with RSA key pair 1 8 | And let a token decrypt encrypted data 9 | Then decrypted data should be same as a plain text 10 | 11 | Scenario: decrypt by OPENPGP.2 key (2) 12 | Given a plain text "RSA decryption is as easy as pie." 13 | And encrypt it on host with RSA key pair 1 14 | And let a token decrypt encrypted data 15 | Then decrypted data should be same as a plain text 16 | 17 | -------------------------------------------------------------------------------- /test/features/200_key_removal.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: key removal 3 | In order to use a token 4 | A token should have keys 5 | 6 | Scenario: remove OPENPGP.1 key (sign) 7 | When removing a key OPENPGP.1 8 | Then it should get success 9 | 10 | Scenario: remove OPENPGP.2 key (decrypt) 11 | When removing a key OPENPGP.2 12 | Then it should get success 13 | 14 | Scenario: remove OPENPGP.3 key (authentication) 15 | When removing a key OPENPGP.3 16 | Then it should get success 17 | 18 | Scenario: remove data object Finger print sig 19 | Given cmd_put_data with c7 and "" 20 | Then it should get success 21 | 22 | Scenario: remove data object Finger print dec 23 | Given cmd_put_data with c8 and "" 24 | Then it should get success 25 | 26 | Scenario: remove data object Finger print aut 27 | Given cmd_put_data with c9 and "" 28 | Then it should get success 29 | 30 | Scenario: remove data object keygeneration data/time sig 31 | Given cmd_put_data with ce and "" 32 | Then it should get success 33 | 34 | Scenario: remove data object keygeneration data/time dec 35 | Given cmd_put_data with cf and "" 36 | Then it should get success 37 | 38 | Scenario: remove data object keygeneration data/time aut 39 | Given cmd_put_data with d0 and "" 40 | Then it should get success 41 | -------------------------------------------------------------------------------- /test/features/201_keygen.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: key generation 3 | In order to use a token 4 | A token should have keys 5 | 6 | Scenario: generate OPENPGP.1 key (sign) 7 | When generating a key of OPENPGP.1 8 | And put the first data to c7 9 | And put the second data to ce 10 | Then it should get success 11 | 12 | Scenario: generate OPENPGP.2 key (decrypt) 13 | When generating a key of OPENPGP.2 14 | And put the first data to c8 15 | And put the second data to cf 16 | Then it should get success 17 | 18 | Scenario: generate OPENPGP.3 key (authentication) 19 | When generating a key of OPENPGP.3 20 | And put the first data to c9 21 | And put the second data to d0 22 | Then it should get success 23 | -------------------------------------------------------------------------------- /test/features/202_setup_passphrase.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: setup pass phrase 3 | In order to conform OpenPGP card 2.0 specification 4 | A token should support pass phrase: PW1, PW3 and reset code 5 | 6 | Scenario: setup PW1 (admin-full mode) 7 | Given cmd_change_reference_data with 1 and "123456user pass phrase" 8 | Then it should get success 9 | 10 | Scenario: verify PW1 (1) 11 | Given cmd_verify with 1 and "user pass phrase" 12 | Then it should get success 13 | 14 | Scenario: verify PW1 (2) 15 | Given cmd_verify with 2 and "user pass phrase" 16 | Then it should get success 17 | 18 | Scenario: setup reset code (in admin-full mode) 19 | Given cmd_put_data with d3 and "example reset code 000" 20 | Then it should get success 21 | 22 | Scenario: reset pass phrase by reset code (in admin-full mode) 23 | Given cmd_reset_retry_counter with 0 and "example reset code 000another user pass phrase" 24 | Then it should get success 25 | 26 | Scenario: verify PW1 (1) again 27 | Given cmd_verify with 1 and "another user pass phrase" 28 | Then it should get success 29 | 30 | Scenario: verify PW1 (2) again 31 | Given cmd_verify with 2 and "another user pass phrase" 32 | Then it should get success 33 | -------------------------------------------------------------------------------- /test/features/203_passphrase_change.feature: -------------------------------------------------------------------------------- 1 | Feature: change pass phrase 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support pass phrase: PW1, PW3 and reset code 4 | 5 | Scenario: change PW1 6 | Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG" 7 | Then it should get success 8 | 9 | Scenario: verify PW1 (1) again 10 | Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG" 11 | Then it should get success 12 | 13 | Scenario: verify PW1 (2) again 14 | Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG" 15 | Then it should get success 16 | 17 | Scenario: setup reset code again (in admin-full mode) 18 | Given cmd_put_data with d3 and "example reset code 111" 19 | Then it should get success 20 | 21 | Scenario: reset pass phrase by reset code (in admin-full mode) 22 | Given cmd_reset_retry_counter with 0 and "example reset code 111new user pass phrase" 23 | Then it should get success 24 | 25 | Scenario: verify PW1 (1) again 26 | Given cmd_verify with 1 and "new user pass phrase" 27 | Then it should get success 28 | 29 | Scenario: verify PW1 (2) again 30 | Given cmd_verify with 2 and "new user pass phrase" 31 | Then it should get success 32 | 33 | Scenario: change PW3 (admin-full mode) 34 | Given cmd_change_reference_data with 3 and "admin pass phraseanother admin pass phrase" 35 | Then it should get success 36 | 37 | Scenario: verify PW3 (admin-full mode) 38 | Given cmd_verify with 3 and "another admin pass phrase" 39 | Then it should get success 40 | 41 | Scenario: reset pass phrase by admin (in admin-full mode) 42 | Given cmd_reset_retry_counter with 2 and "new user pass phrase" 43 | Then it should get success 44 | 45 | Scenario: verify PW1 (1) again 46 | Given cmd_verify with 1 and "new user pass phrase" 47 | Then it should get success 48 | 49 | Scenario: verify PW1 (2) again 50 | Given cmd_verify with 2 and "new user pass phrase" 51 | Then it should get success 52 | 53 | Scenario: change PW1 54 | Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase" 55 | Then it should get success 56 | 57 | Scenario: verify PW1 (1) again 58 | Given cmd_verify with 1 and "another user pass phrase" 59 | Then it should get success 60 | 61 | Scenario: verify PW1 (2) again 62 | Given cmd_verify with 2 and "another user pass phrase" 63 | Then it should get success 64 | 65 | Scenario: change PW3 (admin-full mode) 66 | Given cmd_change_reference_data with 3 and "another admin pass phraseadmin pass phrase" 67 | Then it should get success 68 | 69 | Scenario: verify PW3 (admin-full mode) 70 | Given cmd_verify with 3 and "admin pass phrase" 71 | Then it should get success 72 | -------------------------------------------------------------------------------- /test/features/210_compute_signature.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: compute digital signature 3 | In order to use a token 4 | A token should compute digital signature properly 5 | 6 | Scenario: compute digital signature by OPENPGP.1 key (1) 7 | Given a message "This is a test message." 8 | And a public key from token for OPENPGP.1 9 | And let a token compute digital signature 10 | And verify signature 11 | Then it should get success 12 | 13 | Scenario: compute digital signature by OPENPGP.1 key (2) 14 | Given a message "This is another test message.\nMultiple lines.\n" 15 | And a public key from token for OPENPGP.1 16 | And let a token compute digital signature 17 | And verify signature 18 | Then it should get success 19 | 20 | Scenario: compute digital signature by OPENPGP.3 key (1) 21 | Given a message "This is a test message." 22 | And a public key from token for OPENPGP.3 23 | And let a token authenticate 24 | And verify signature 25 | Then it should get success 26 | 27 | Scenario: compute digital signature by OPENPGP.3 key (2) 28 | Given a message "This is another test message.\nMultiple lines.\n" 29 | And a public key from token for OPENPGP.3 30 | And let a token authenticate 31 | And verify signature 32 | Then it should get success 33 | 34 | Scenario: data object ds counter 35 | When requesting ds counter: 93 36 | Then data should match: \x00\x00(\x02|\x03) 37 | -------------------------------------------------------------------------------- /test/features/211_decryption.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: decryption 3 | In order to use a token 4 | A token should decrypt encrypted data 5 | 6 | Scenario: decrypt by OPENPGP.2 key (1) 7 | Given a plain text "This is a test message." 8 | And a public key from token for OPENPGP.2 9 | And encrypt it on host 10 | And let a token decrypt encrypted data 11 | Then decrypted data should be same as a plain text 12 | 13 | Scenario: decrypt by OPENPGP.2 key (2) 14 | Given a plain text "RSA decryption is as easy as pie." 15 | And a public key from token for OPENPGP.2 16 | And encrypt it on host 17 | And let a token decrypt encrypted data 18 | Then decrypted data should be same as a plain text 19 | 20 | -------------------------------------------------------------------------------- /test/features/370_key_removal.feature: -------------------------------------------------------------------------------- 1 | Feature: key removal 2 | In order to use a token 3 | A token should have keys 4 | 5 | Scenario: remove OPENPGP.1 key (sign) 6 | When removing a key OPENPGP.1 7 | Then it should get success 8 | 9 | Scenario: remove OPENPGP.2 key (decrypt) 10 | When removing a key OPENPGP.2 11 | Then it should get success 12 | 13 | Scenario: remove OPENPGP.3 key (authentication) 14 | When removing a key OPENPGP.3 15 | Then it should get success 16 | 17 | Scenario: remove data object Finger print sig 18 | Given cmd_put_data with c7 and "" 19 | Then it should get success 20 | 21 | Scenario: remove data object Finger print dec 22 | Given cmd_put_data with c8 and "" 23 | Then it should get success 24 | 25 | Scenario: remove data object Finger print aut 26 | Given cmd_put_data with c9 and "" 27 | Then it should get success 28 | 29 | Scenario: remove data object keygeneration data/time sig 30 | Given cmd_put_data with ce and "" 31 | Then it should get success 32 | 33 | Scenario: remove data object keygeneration data/time dec 34 | Given cmd_put_data with cf and "" 35 | Then it should get success 36 | 37 | Scenario: remove data object keygeneration data/time aut 38 | Given cmd_put_data with d0 and "" 39 | Then it should get success 40 | -------------------------------------------------------------------------------- /test/features/380_personalization_reset.feature: -------------------------------------------------------------------------------- 1 | Feature: removal of data objects 2 | In order to use a token 3 | A token should have personalized data 4 | 5 | Scenario: remove data object Login 6 | Given cmd_put_data with 5e and "" 7 | Then it should get success 8 | 9 | Scenario: remove data object Name 10 | Given cmd_put_data with 5b and "" 11 | Then it should get success 12 | 13 | Scenario: remove data object Language preference 14 | Given cmd_put_data with 5f2d and "" 15 | Then it should get success 16 | 17 | Scenario: remove data object Sex 18 | Given cmd_put_data with 5f35 and "" 19 | Then it should get success 20 | 21 | Scenario: remove data object URL 22 | Given cmd_put_data with 5f50 and "" 23 | Then it should get success 24 | 25 | Scenario: remove data object pw1 status bytes 26 | Given cmd_put_data with c4 and "\x00" 27 | Then it should get success 28 | -------------------------------------------------------------------------------- /test/features/390_reset_passphrase.feature: -------------------------------------------------------------------------------- 1 | Feature: reset pass phrase 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support pass phrase: PW1, PW3 and reset code 4 | 5 | Scenario: setup PW3 (admin-full mode) 6 | Given cmd_change_reference_data with 3 and "admin pass phrase" 7 | Then it should get success 8 | -------------------------------------------------------------------------------- /test/features/400_empty_check.feature: -------------------------------------------------------------------------------- 1 | Feature: confirm empty token 2 | In order to start tests 3 | A token should be empty (no data, no keys) 4 | 5 | Scenario: data object Login 6 | When requesting login data: 5e 7 | Then you should get NULL 8 | 9 | Scenario: data object Name 10 | When requesting name: 5b 11 | Then you should get NULL 12 | 13 | Scenario: data object Language preference 14 | When requesting anguage preference: 5f2d 15 | Then you should get NULL 16 | 17 | Scenario: data object Sex 18 | When requesting sex: 5f35 19 | Then you should get NULL 20 | 21 | Scenario: data object URL 22 | When requesting URL: 5f50 23 | Then you should get NULL 24 | 25 | Scenario: data object ds counter 26 | When requesting ds counter: 93 27 | Then you should get: \x00\x00\x00 28 | 29 | Scenario: data object pw1 status bytes 30 | When requesting pw1 status bytes: c4 31 | Then you should get: \x00\x7f\x7f\x7f\x03\x03\x03 32 | 33 | Scenario: data object finger print 0 34 | When requesting finger print: c5 35 | Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 36 | 37 | Scenario: data object finger print 1 38 | When requesting finger print: c7 39 | Then you should get NULL 40 | 41 | Scenario: data object finger print 2 42 | When requesting finger print: c8 43 | Then you should get NULL 44 | 45 | Scenario: data object finger print 3 46 | When requesting finger print: c9 47 | Then you should get NULL 48 | 49 | Scenario: data object CA finger print 0 50 | When requesting finger print: c6 51 | Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 52 | 53 | Scenario: data object CA finger print 1 54 | When requesting finger print: ca 55 | Then you should get NULL 56 | 57 | Scenario: data object CA finger print 2 58 | When requesting finger print: cb 59 | Then you should get NULL 60 | 61 | Scenario: data object CA finger print 3 62 | When requesting finger print: cc 63 | Then you should get NULL 64 | 65 | Scenario: data object date/time of key pair 0 66 | When requesting date/time of key pair: cd 67 | Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 68 | 69 | Scenario: data object date/time of key pair 1 70 | When requesting date/time of key pair: ce 71 | Then you should get NULL 72 | 73 | Scenario: data object date/time of key pair 2 74 | When requesting date/time of key pair: cf 75 | Then you should get NULL 76 | 77 | Scenario: data object date/time of key pair 3 78 | When requesting date/time of key pair: d0 79 | Then you should get NULL 80 | -------------------------------------------------------------------------------- /test/features/401_empty_check_passphrase.feature: -------------------------------------------------------------------------------- 1 | Feature: confirm empty token 2 | In order to start tests 3 | A token should be empty (no pass phrase) 4 | 5 | Scenario: verify PW1 factory setting (1) 6 | Given cmd_verify with 1 and "123456" 7 | Then it should get success 8 | 9 | Scenario: verify PW1 factory setting (2) 10 | Given cmd_verify with 2 and "123456" 11 | Then it should get success 12 | 13 | Scenario: verify PW3 factory setting 14 | Given cmd_verify with 3 and "12345678" 15 | Then it should get success 16 | -------------------------------------------------------------------------------- /test/features/402_get_data_static.feature: -------------------------------------------------------------------------------- 1 | Feature: command GET DATA 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support all mandatory features of the specification 4 | 5 | Scenario: data object historical bytes 6 | When requesting historical bytes: 5f52 7 | Then data should match: \x00\x31\x84\x73\x80\x01\x80[\x00\x05]\x90\x00 8 | 9 | Scenario: data object extended capabilities 10 | When requesting extended capabilities: c0 11 | Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00 12 | 13 | Scenario: data object algorithm attributes 1 14 | When requesting algorithm attributes 1: c1 15 | Then you should get: \x01\x08\x00\x00\x20\x00 16 | 17 | Scenario: data object algorithm attributes 2 18 | When requesting algorithm attributes 2: c2 19 | Then you should get: \x01\x08\x00\x00\x20\x00 20 | 21 | Scenario: data object algorithm attributes 3 22 | When requesting algorighm attributes 3: c3 23 | Then you should get: \x01\x08\x00\x00\x20\x00 24 | 25 | Scenario: data object AID 26 | When requesting AID: 4f 27 | Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00 28 | -------------------------------------------------------------------------------- /test/features/410_setup_passphrase.feature: -------------------------------------------------------------------------------- 1 | Feature: setup pass phrase 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support pass phrase: PW1, PW3 and reset code 4 | 5 | Scenario: verify PW3 (admin-less mode) 6 | Given cmd_verify with 3 and "12345678" 7 | Then it should get success 8 | -------------------------------------------------------------------------------- /test/features/420_personalization_write.feature: -------------------------------------------------------------------------------- 1 | Feature: personalize token write 2 | In order to use a token 3 | A token should be personalized with name, sex, url, etc. 4 | 5 | Scenario: data object Login 6 | Given cmd_put_data with 5e and "gpg_user" 7 | Then it should get success 8 | 9 | Scenario: data object Name 10 | Given cmd_put_data with 5b and "GnuPG User" 11 | Then it should get success 12 | 13 | Scenario: data object Language preference 14 | Given cmd_put_data with 5f2d and "ja" 15 | Then it should get success 16 | 17 | Scenario: data object Sex 18 | Given cmd_put_data with 5f35 and "1" 19 | Then it should get success 20 | 21 | Scenario: data object URL 22 | Given cmd_put_data with 5f50 and "http://www.fsij.org/gnuk/" 23 | Then it should get success 24 | 25 | Scenario: data object pw1 status bytes 26 | Given cmd_put_data with c4 and "\x01" 27 | Then it should get success 28 | -------------------------------------------------------------------------------- /test/features/421_personalization_read.feature: -------------------------------------------------------------------------------- 1 | Feature: personalize token read 2 | In order to use a token 3 | A token should be personalized with name, sex, url, etc. 4 | 5 | Scenario: data object Login 6 | When requesting login data: 5e 7 | Then you should get: gpg_user 8 | 9 | Scenario: data object Name 10 | When requesting name: 5b 11 | Then you should get: GnuPG User 12 | 13 | Scenario: data object Language preference 14 | When requesting anguage preference: 5f2d 15 | Then you should get: ja 16 | 17 | Scenario: data object Sex 18 | When requesting sex: 5f35 19 | Then you should get: 1 20 | 21 | Scenario: data object URL 22 | When requesting URL: 5f50 23 | Then you should get: http://www.fsij.org/gnuk/ 24 | 25 | Scenario: data object pw1 status bytes 26 | When requesting pw1 status bytes: c4 27 | Then you should get: \x01\x7f\x7f\x7f\x03\x03\x03 28 | -------------------------------------------------------------------------------- /test/features/430_key_registration.feature: -------------------------------------------------------------------------------- 1 | Feature: import keys to token 2 | In order to use a token 3 | A token should have keys 4 | 5 | Scenario: importing OPENPGP.1 key (sign) 6 | Given a RSA key pair 0 7 | And importing it to the token as OPENPGP.1 8 | Then it should get success 9 | 10 | Scenario: importing OPENPGP.2 key (decrypt) 11 | Given a RSA key pair 1 12 | And importing it to the token as OPENPGP.2 13 | Then it should get success 14 | 15 | Scenario: importing OPENPGP.3 key (authentication) 16 | Given a RSA key pair 2 17 | And importing it to the token as OPENPGP.3 18 | Then it should get success 19 | 20 | Scenario: setup data object Finger print sig 21 | Given a fingerprint of OPENPGP.1 key 22 | And put the data to c7 23 | Then it should get success 24 | 25 | Scenario: setup data object Finger print dec 26 | Given a fingerprint of OPENPGP.2 key 27 | And put the data to c8 28 | Then it should get success 29 | 30 | Scenario: setup data object Finger print aut 31 | Given a fingerprint of OPENPGP.3 key 32 | And put the data to c9 33 | Then it should get success 34 | 35 | Scenario: setup data object keygeneration data/time sig 36 | Given a timestamp of OPENPGP.1 key 37 | And put the data to ce 38 | Then it should get success 39 | 40 | Scenario: setup data object keygeneration data/time dec 41 | Given a timestamp of OPENPGP.2 key 42 | And put the data to cf 43 | Then it should get success 44 | 45 | Scenario: setup data object keygeneration data/time aut 46 | Given a timestamp of OPENPGP.3 key 47 | And put the data to d0 48 | Then it should get success 49 | 50 | Scenario: setup PW1 (admin-less mode) 51 | Given cmd_change_reference_data with 1 and "123456another user pass phrase" 52 | Then it should get success 53 | 54 | Scenario: verify PW1 (1) again 55 | Given cmd_verify with 1 and "another user pass phrase" 56 | Then it should get success 57 | 58 | Scenario: verify PW1 (2) again 59 | Given cmd_verify with 2 and "another user pass phrase" 60 | Then it should get success 61 | -------------------------------------------------------------------------------- /test/features/440_passphrase_change.feature: -------------------------------------------------------------------------------- 1 | Feature: change pass phrase 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support pass phrase: PW1, PW3 and reset code 4 | 5 | Scenario: change PW1 (in admin-less mode) 6 | Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG" 7 | Then it should get success 8 | 9 | Scenario: verify PW1 (1) again 10 | Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG" 11 | Then it should get success 12 | 13 | Scenario: verify PW1 (2) again 14 | Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG" 15 | Then it should get success 16 | 17 | Scenario: verify PW3 (admin-less mode) 18 | Given cmd_verify with 3 and "PASSPHRASE SHOULD BE LONG" 19 | Then it should get success 20 | 21 | Scenario: setup reset code again (in admin-less mode) 22 | Given cmd_put_data with d3 and "example reset code 000" 23 | Then it should get success 24 | 25 | Scenario: reset pass phrase by reset code (in admin-less mode) 26 | Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase" 27 | Then it should get success 28 | 29 | Scenario: verify PW1 (1) again 30 | Given cmd_verify with 1 and "new user pass phrase" 31 | Then it should get success 32 | 33 | Scenario: verify PW1 (2) again 34 | Given cmd_verify with 2 and "new user pass phrase" 35 | Then it should get success 36 | 37 | Scenario: change PW1 38 | Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase" 39 | Then it should get success 40 | 41 | Scenario: verify PW1 (1) again 42 | Given cmd_verify with 1 and "another user pass phrase" 43 | Then it should get success 44 | 45 | Scenario: verify PW1 (2) again 46 | Given cmd_verify with 2 and "another user pass phrase" 47 | Then it should get success 48 | 49 | Scenario: verify PW3 (admin-less mode) 50 | Given cmd_verify with 3 and "another user pass phrase" 51 | Then it should get success 52 | -------------------------------------------------------------------------------- /test/features/500_compute_signature.feature: -------------------------------------------------------------------------------- 1 | Feature: compute digital signature 2 | In order to use a token 3 | A token should compute digital signature properly 4 | 5 | Scenario: compute digital signature by OPENPGP.1 key (1) 6 | Given a message "This is a test message." 7 | And let a token compute digital signature 8 | And compute digital signature on host with RSA key pair 0 9 | Then results should be same 10 | 11 | Scenario: compute digital signature by OPENPGP.1 key (2) 12 | Given a message "This is another test message.\nMultiple lines.\n" 13 | And let a token compute digital signature 14 | And compute digital signature on host with RSA key pair 0 15 | Then results should be same 16 | 17 | Scenario: compute digital signature by OPENPGP.3 key (1) 18 | Given a message "This is a test message." 19 | And let a token authenticate 20 | And compute digital signature on host with RSA key pair 2 21 | Then results should be same 22 | 23 | Scenario: compute digital signature by OPENPGP.3 key (2) 24 | Given a message "This is another test message.\nMultiple lines.\n" 25 | And let a token authenticate 26 | And compute digital signature on host with RSA key pair 2 27 | Then results should be same 28 | 29 | Scenario: data object ds counter 30 | When requesting ds counter: 93 31 | Then you should get: \x00\x00\x02 32 | -------------------------------------------------------------------------------- /test/features/501_decryption.feature: -------------------------------------------------------------------------------- 1 | Feature: decryption 2 | In order to use a token 3 | A token should decrypt encrypted data 4 | 5 | Scenario: decrypt by OPENPGP.2 key (1) 6 | Given a plain text "This is a test message." 7 | And encrypt it on host with RSA key pair 1 8 | And let a token decrypt encrypted data 9 | Then decrypted data should be same as a plain text 10 | 11 | Scenario: decrypt by OPENPGP.2 key (2) 12 | Given a plain text "RSA decryption is as easy as pie." 13 | And encrypt it on host with RSA key pair 1 14 | And let a token decrypt encrypted data 15 | Then decrypted data should be same as a plain text 16 | 17 | -------------------------------------------------------------------------------- /test/features/600_key_removal.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: key removal 3 | In order to use a token 4 | A token should have keys 5 | 6 | Scenario: remove OPENPGP.1 key (sign) 7 | When removing a key OPENPGP.1 8 | Then it should get success 9 | 10 | Scenario: remove OPENPGP.2 key (decrypt) 11 | When removing a key OPENPGP.2 12 | Then it should get success 13 | 14 | Scenario: remove OPENPGP.3 key (authentication) 15 | When removing a key OPENPGP.3 16 | Then it should get success 17 | 18 | Scenario: verify PW3 (admin-less mode) 19 | Given cmd_verify with 3 and "12345678" 20 | Then it should get success 21 | 22 | Scenario: remove data object Finger print sig 23 | Given cmd_put_data with c7 and "" 24 | Then it should get success 25 | 26 | Scenario: remove data object Finger print dec 27 | Given cmd_put_data with c8 and "" 28 | Then it should get success 29 | 30 | Scenario: remove data object Finger print aut 31 | Given cmd_put_data with c9 and "" 32 | Then it should get success 33 | 34 | Scenario: remove data object keygeneration data/time sig 35 | Given cmd_put_data with ce and "" 36 | Then it should get success 37 | 38 | Scenario: remove data object keygeneration data/time dec 39 | Given cmd_put_data with cf and "" 40 | Then it should get success 41 | 42 | Scenario: remove data object keygeneration data/time aut 43 | Given cmd_put_data with d0 and "" 44 | Then it should get success 45 | -------------------------------------------------------------------------------- /test/features/601_keygen.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: key generation 3 | In order to use a token 4 | A token should have keys 5 | 6 | Scenario: generate OPENPGP.1 key (sign) 7 | When generating a key of OPENPGP.1 8 | And put the first data to c7 9 | And put the second data to ce 10 | Then it should get success 11 | 12 | Scenario: generate OPENPGP.2 key (decrypt) 13 | When generating a key of OPENPGP.2 14 | And put the first data to c8 15 | And put the second data to cf 16 | Then it should get success 17 | 18 | Scenario: generate OPENPGP.3 key (authentication) 19 | When generating a key of OPENPGP.3 20 | And put the first data to c9 21 | And put the second data to d0 22 | Then it should get success 23 | -------------------------------------------------------------------------------- /test/features/602_setup_passphrase.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: setup pass phrase 3 | In order to conform OpenPGP card 2.0 specification 4 | A token should support pass phrase: PW1, PW3 and reset code 5 | 6 | Scenario: setup PW1 (admin-less mode) 7 | Given cmd_change_reference_data with 1 and "123456user pass phrase" 8 | Then it should get success 9 | 10 | Scenario: verify PW1 (1) 11 | Given cmd_verify with 1 and "user pass phrase" 12 | Then it should get success 13 | 14 | Scenario: verify PW1 (2) 15 | Given cmd_verify with 2 and "user pass phrase" 16 | Then it should get success 17 | 18 | Scenario: verify PW3 (admin-less mode) 19 | Given cmd_verify with 3 and "user pass phrase" 20 | Then it should get success 21 | 22 | Scenario: setup reset code (in admin-less mode) 23 | Given cmd_put_data with d3 and "example reset code 000" 24 | Then it should get success 25 | 26 | Scenario: reset pass phrase by reset code (in admin-less mode) 27 | Given cmd_reset_retry_counter with 0 and "example reset code 000another user pass phrase" 28 | Then it should get success 29 | 30 | Scenario: verify PW1 (1) again 31 | Given cmd_verify with 1 and "another user pass phrase" 32 | Then it should get success 33 | 34 | Scenario: verify PW1 (2) again 35 | Given cmd_verify with 2 and "another user pass phrase" 36 | Then it should get success 37 | 38 | Scenario: verify PW3 (admin-less mode) again 39 | Given cmd_verify with 3 and "another user pass phrase" 40 | Then it should get success 41 | -------------------------------------------------------------------------------- /test/features/603_passphrase_change.feature: -------------------------------------------------------------------------------- 1 | Feature: change pass phrase 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support pass phrase: PW1, PW3 and reset code 4 | 5 | Scenario: change PW1 6 | Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG" 7 | Then it should get success 8 | 9 | Scenario: verify PW1 (1) again 10 | Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG" 11 | Then it should get success 12 | 13 | Scenario: verify PW1 (2) again 14 | Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG" 15 | Then it should get success 16 | 17 | Scenario: verify PW3 (admin-less mode) 18 | Given cmd_verify with 3 and "PASSPHRASE SHOULD BE LONG" 19 | Then it should get success 20 | 21 | Scenario: setup reset code again (in admin-less mode) 22 | Given cmd_put_data with d3 and "example reset code 111" 23 | Then it should get success 24 | 25 | Scenario: reset pass phrase by reset code (in admin-less mode) 26 | Given cmd_reset_retry_counter with 0 and "example reset code 111new user pass phrase" 27 | Then it should get success 28 | 29 | Scenario: verify PW1 (1) again 30 | Given cmd_verify with 1 and "new user pass phrase" 31 | Then it should get success 32 | 33 | Scenario: verify PW1 (2) again 34 | Given cmd_verify with 2 and "new user pass phrase" 35 | Then it should get success 36 | 37 | Scenario: verify PW3 (admin-less mode) 38 | Given cmd_verify with 3 and "new user pass phrase" 39 | Then it should get success 40 | 41 | Scenario: reset pass phrase by admin (in admin-less mode) 42 | Given cmd_reset_retry_counter with 2 and "new user pass phrase" 43 | Then it should get success 44 | 45 | Scenario: verify PW1 (1) again 46 | Given cmd_verify with 1 and "new user pass phrase" 47 | Then it should get success 48 | 49 | Scenario: verify PW1 (2) again 50 | Given cmd_verify with 2 and "new user pass phrase" 51 | Then it should get success 52 | 53 | Scenario: change PW1 54 | Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase" 55 | Then it should get success 56 | 57 | Scenario: verify PW1 (1) again 58 | Given cmd_verify with 1 and "another user pass phrase" 59 | Then it should get success 60 | 61 | Scenario: verify PW1 (2) again 62 | Given cmd_verify with 2 and "another user pass phrase" 63 | Then it should get success 64 | 65 | Scenario: verify PW3 (admin-less mode) 66 | Given cmd_verify with 3 and "another user pass phrase" 67 | Then it should get success 68 | -------------------------------------------------------------------------------- /test/features/610_compute_signature.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: compute digital signature 3 | In order to use a token 4 | A token should compute digital signature properly 5 | 6 | Scenario: compute digital signature by OPENPGP.1 key (1) 7 | Given a message "This is a test message." 8 | And a public key from token for OPENPGP.1 9 | And let a token compute digital signature 10 | And verify signature 11 | Then it should get success 12 | 13 | Scenario: compute digital signature by OPENPGP.1 key (2) 14 | Given a message "This is another test message.\nMultiple lines.\n" 15 | And a public key from token for OPENPGP.1 16 | And let a token compute digital signature 17 | And verify signature 18 | Then it should get success 19 | 20 | Scenario: compute digital signature by OPENPGP.3 key (1) 21 | Given a message "This is a test message." 22 | And a public key from token for OPENPGP.3 23 | And let a token authenticate 24 | And verify signature 25 | Then it should get success 26 | 27 | Scenario: compute digital signature by OPENPGP.3 key (2) 28 | Given a message "This is another test message.\nMultiple lines.\n" 29 | And a public key from token for OPENPGP.3 30 | And let a token authenticate 31 | And verify signature 32 | Then it should get success 33 | 34 | Scenario: data object ds counter 35 | When requesting ds counter: 93 36 | Then data should match: \x00\x00(\x02|\x03) 37 | -------------------------------------------------------------------------------- /test/features/611_decryption.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: decryption 3 | In order to use a token 4 | A token should decrypt encrypted data 5 | 6 | Scenario: decrypt by OPENPGP.2 key (1) 7 | Given a plain text "This is a test message." 8 | And a public key from token for OPENPGP.2 9 | And encrypt it on host 10 | And let a token decrypt encrypted data 11 | Then decrypted data should be same as a plain text 12 | 13 | Scenario: decrypt by OPENPGP.2 key (2) 14 | Given a plain text "RSA decryption is as easy as pie." 15 | And a public key from token for OPENPGP.2 16 | And encrypt it on host 17 | And let a token decrypt encrypted data 18 | Then decrypted data should be same as a plain text 19 | 20 | -------------------------------------------------------------------------------- /test/features/770_key_removal.feature: -------------------------------------------------------------------------------- 1 | Feature: key removal 2 | In order to use a token 3 | A token should have keys 4 | 5 | Scenario: remove OPENPGP.1 key (sign) 6 | When removing a key OPENPGP.1 7 | Then it should get success 8 | 9 | Scenario: remove OPENPGP.2 key (decrypt) 10 | When removing a key OPENPGP.2 11 | Then it should get success 12 | 13 | Scenario: remove OPENPGP.3 key (authentication) 14 | When removing a key OPENPGP.3 15 | Then it should get success 16 | 17 | Scenario: verify PW3 (admin-less mode) 18 | Given cmd_verify with 3 and "12345678" 19 | Then it should get success 20 | 21 | Scenario: remove data object Finger print sig 22 | Given cmd_put_data with c7 and "" 23 | Then it should get success 24 | 25 | Scenario: remove data object Finger print dec 26 | Given cmd_put_data with c8 and "" 27 | Then it should get success 28 | 29 | Scenario: remove data object Finger print aut 30 | Given cmd_put_data with c9 and "" 31 | Then it should get success 32 | 33 | Scenario: remove data object keygeneration data/time sig 34 | Given cmd_put_data with ce and "" 35 | Then it should get success 36 | 37 | Scenario: remove data object keygeneration data/time dec 38 | Given cmd_put_data with cf and "" 39 | Then it should get success 40 | 41 | Scenario: remove data object keygeneration data/time aut 42 | Given cmd_put_data with d0 and "" 43 | Then it should get success 44 | -------------------------------------------------------------------------------- /test/features/780_personalization_reset.feature: -------------------------------------------------------------------------------- 1 | Feature: removal of data objects 2 | In order to use a token 3 | A token should have personalized data 4 | 5 | Scenario: remove data object Login 6 | Given cmd_put_data with 5e and "" 7 | Then it should get success 8 | 9 | Scenario: remove data object Name 10 | Given cmd_put_data with 5b and "" 11 | Then it should get success 12 | 13 | Scenario: remove data object Language preference 14 | Given cmd_put_data with 5f2d and "" 15 | Then it should get success 16 | 17 | Scenario: remove data object Sex 18 | Given cmd_put_data with 5f35 and "" 19 | Then it should get success 20 | 21 | Scenario: remove data object URL 22 | Given cmd_put_data with 5f50 and "" 23 | Then it should get success 24 | 25 | Scenario: remove data object pw1 status bytes 26 | Given cmd_put_data with c4 and "\x00" 27 | Then it should get success 28 | -------------------------------------------------------------------------------- /test/features/790_reset_passphrase.feature: -------------------------------------------------------------------------------- 1 | Feature: confirm factory setting pass phrase 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support pass phrase: PW1, PW3 and reset code 4 | 5 | Scenario: verify PW3 (admin-less mode) 6 | Given cmd_verify with 3 and "12345678" 7 | Then it should get success 8 | -------------------------------------------------------------------------------- /test/features/800_empty_check.feature: -------------------------------------------------------------------------------- 1 | Feature: confirm empty token 2 | In order to start tests 3 | A token should be empty (no data, no keys) 4 | 5 | Scenario: data object Login 6 | When requesting login data: 5e 7 | Then you should get NULL 8 | 9 | Scenario: data object Name 10 | When requesting name: 5b 11 | Then you should get NULL 12 | 13 | Scenario: data object Language preference 14 | When requesting anguage preference: 5f2d 15 | Then you should get NULL 16 | 17 | Scenario: data object Sex 18 | When requesting sex: 5f35 19 | Then you should get NULL 20 | 21 | Scenario: data object URL 22 | When requesting URL: 5f50 23 | Then you should get NULL 24 | 25 | Scenario: data object ds counter 26 | When requesting ds counter: 93 27 | Then you should get: \x00\x00\x00 28 | 29 | Scenario: data object pw1 status bytes 30 | When requesting pw1 status bytes: c4 31 | Then you should get: \x00\x7f\x7f\x7f\x03\x03\x03 32 | 33 | Scenario: data object finger print 0 34 | When requesting finger print: c5 35 | Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 36 | 37 | Scenario: data object finger print 1 38 | When requesting finger print: c7 39 | Then you should get NULL 40 | 41 | Scenario: data object finger print 2 42 | When requesting finger print: c8 43 | Then you should get NULL 44 | 45 | Scenario: data object finger print 3 46 | When requesting finger print: c9 47 | Then you should get NULL 48 | 49 | Scenario: data object CA finger print 0 50 | When requesting finger print: c6 51 | Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 52 | 53 | Scenario: data object CA finger print 1 54 | When requesting finger print: ca 55 | Then you should get NULL 56 | 57 | Scenario: data object CA finger print 2 58 | When requesting finger print: cb 59 | Then you should get NULL 60 | 61 | Scenario: data object CA finger print 3 62 | When requesting finger print: cc 63 | Then you should get NULL 64 | 65 | Scenario: data object date/time of key pair 0 66 | When requesting date/time of key pair: cd 67 | Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 68 | 69 | Scenario: data object date/time of key pair 1 70 | When requesting date/time of key pair: ce 71 | Then you should get NULL 72 | 73 | Scenario: data object date/time of key pair 2 74 | When requesting date/time of key pair: cf 75 | Then you should get NULL 76 | 77 | Scenario: data object date/time of key pair 3 78 | When requesting date/time of key pair: d0 79 | Then you should get NULL 80 | -------------------------------------------------------------------------------- /test/features/801_empty_check_passphrase.feature: -------------------------------------------------------------------------------- 1 | Feature: confirm empty token 2 | In order to start tests 3 | A token should be empty (no pass phrase) 4 | 5 | Scenario: verify PW1 factory setting (1) 6 | Given cmd_verify with 1 and "123456" 7 | Then it should get success 8 | 9 | Scenario: verify PW1 factory setting (2) 10 | Given cmd_verify with 2 and "123456" 11 | Then it should get success 12 | 13 | Scenario: verify PW3 factory setting 14 | Given cmd_verify with 3 and "12345678" 15 | Then it should get success 16 | -------------------------------------------------------------------------------- /test/features/802_get_data_static.feature: -------------------------------------------------------------------------------- 1 | Feature: command GET DATA 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support all mandatory features of the specification 4 | 5 | Scenario: data object historical bytes 6 | When requesting historical bytes: 5f52 7 | Then data should match: \x00\x31\x84\x73\x80\x01\x80[\x00\x05]\x90\x00 8 | 9 | Scenario: data object extended capabilities 10 | When requesting extended capabilities: c0 11 | Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00 12 | 13 | Scenario: data object algorithm attributes 1 14 | When requesting algorithm attributes 1: c1 15 | Then you should get: \x01\x08\x00\x00\x20\x00 16 | 17 | Scenario: data object algorithm attributes 2 18 | When requesting algorithm attributes 2: c2 19 | Then you should get: \x01\x08\x00\x00\x20\x00 20 | 21 | Scenario: data object algorithm attributes 3 22 | When requesting algorighm attributes 3: c3 23 | Then you should get: \x01\x08\x00\x00\x20\x00 24 | 25 | Scenario: data object AID 26 | When requesting AID: 4f 27 | Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00 28 | -------------------------------------------------------------------------------- /test/features/810_setup_passphrase.feature: -------------------------------------------------------------------------------- 1 | Feature: check pass phrase 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support pass phrase: PW1, PW3 and reset code 4 | 5 | Scenario: verify PW1 (1) 6 | Given cmd_verify with 1 and "123456" 7 | Then it should get success 8 | 9 | Scenario: verify PW1 (2) 10 | Given cmd_verify with 2 and "123456" 11 | Then it should get success 12 | 13 | Scenario: verify PW3 14 | Given cmd_verify with 3 and "12345678" 15 | Then it should get success 16 | -------------------------------------------------------------------------------- /test/features/820_personalization_write.feature: -------------------------------------------------------------------------------- 1 | Feature: personalize token write 2 | In order to use a token 3 | A token should be personalized with name, sex, url, etc. 4 | 5 | Scenario: data object Login 6 | Given cmd_put_data with 5e and "gpg_user" 7 | Then it should get success 8 | 9 | Scenario: data object Name 10 | Given cmd_put_data with 5b and "GnuPG User" 11 | Then it should get success 12 | 13 | Scenario: data object Language preference 14 | Given cmd_put_data with 5f2d and "ja" 15 | Then it should get success 16 | 17 | Scenario: data object Sex 18 | Given cmd_put_data with 5f35 and "1" 19 | Then it should get success 20 | 21 | Scenario: data object URL 22 | Given cmd_put_data with 5f50 and "http://www.fsij.org/gnuk/" 23 | Then it should get success 24 | 25 | Scenario: data object pw1 status bytes 26 | Given cmd_put_data with c4 and "\x01" 27 | Then it should get success 28 | -------------------------------------------------------------------------------- /test/features/821_personalization_read.feature: -------------------------------------------------------------------------------- 1 | Feature: personalize token read 2 | In order to use a token 3 | A token should be personalized with name, sex, url, etc. 4 | 5 | Scenario: data object Login 6 | When requesting login data: 5e 7 | Then you should get: gpg_user 8 | 9 | Scenario: data object Name 10 | When requesting name: 5b 11 | Then you should get: GnuPG User 12 | 13 | Scenario: data object Language preference 14 | When requesting anguage preference: 5f2d 15 | Then you should get: ja 16 | 17 | Scenario: data object Sex 18 | When requesting sex: 5f35 19 | Then you should get: 1 20 | 21 | Scenario: data object URL 22 | When requesting URL: 5f50 23 | Then you should get: http://www.fsij.org/gnuk/ 24 | 25 | Scenario: data object pw1 status bytes 26 | When requesting pw1 status bytes: c4 27 | Then you should get: \x01\x7f\x7f\x7f\x03\x03\x03 28 | -------------------------------------------------------------------------------- /test/features/830_key_registration.feature: -------------------------------------------------------------------------------- 1 | Feature: import keys to token 2 | In order to use a token 3 | A token should have keys 4 | 5 | Scenario: importing OPENPGP.1 key (sign) 6 | Given a RSA key pair 0 7 | And importing it to the token as OPENPGP.1 8 | Then it should get success 9 | 10 | Scenario: importing OPENPGP.2 key (decrypt) 11 | Given a RSA key pair 1 12 | And importing it to the token as OPENPGP.2 13 | Then it should get success 14 | 15 | Scenario: importing OPENPGP.3 key (authentication) 16 | Given a RSA key pair 2 17 | And importing it to the token as OPENPGP.3 18 | Then it should get success 19 | 20 | Scenario: setup data object Finger print sig 21 | Given a fingerprint of OPENPGP.1 key 22 | And put the data to c7 23 | Then it should get success 24 | 25 | Scenario: setup data object Finger print dec 26 | Given a fingerprint of OPENPGP.2 key 27 | And put the data to c8 28 | Then it should get success 29 | 30 | Scenario: setup data object Finger print aut 31 | Given a fingerprint of OPENPGP.3 key 32 | And put the data to c9 33 | Then it should get success 34 | 35 | Scenario: setup data object keygeneration data/time sig 36 | Given a timestamp of OPENPGP.1 key 37 | And put the data to ce 38 | Then it should get success 39 | 40 | Scenario: setup data object keygeneration data/time dec 41 | Given a timestamp of OPENPGP.2 key 42 | And put the data to cf 43 | Then it should get success 44 | 45 | Scenario: setup data object keygeneration data/time aut 46 | Given a timestamp of OPENPGP.3 key 47 | And put the data to d0 48 | Then it should get success 49 | 50 | Scenario: verify PW1 (1) again 51 | Given cmd_verify with 1 and "123456" 52 | Then it should get success 53 | 54 | Scenario: verify PW1 (2) again 55 | Given cmd_verify with 2 and "123456" 56 | Then it should get success 57 | -------------------------------------------------------------------------------- /test/features/850_compute_signature.feature: -------------------------------------------------------------------------------- 1 | Feature: compute digital signature 2 | In order to use a token 3 | A token should compute digital signature properly 4 | 5 | Scenario: compute digital signature by OPENPGP.1 key (1) 6 | Given a message "This is a test message." 7 | And let a token compute digital signature 8 | And compute digital signature on host with RSA key pair 0 9 | Then results should be same 10 | 11 | Scenario: compute digital signature by OPENPGP.1 key (2) 12 | Given a message "This is another test message.\nMultiple lines.\n" 13 | And let a token compute digital signature 14 | And compute digital signature on host with RSA key pair 0 15 | Then results should be same 16 | 17 | Scenario: compute digital signature by OPENPGP.3 key (1) 18 | Given a message "This is a test message." 19 | And let a token authenticate 20 | And compute digital signature on host with RSA key pair 2 21 | Then results should be same 22 | 23 | Scenario: compute digital signature by OPENPGP.3 key (2) 24 | Given a message "This is another test message.\nMultiple lines.\n" 25 | And let a token authenticate 26 | And compute digital signature on host with RSA key pair 2 27 | Then results should be same 28 | 29 | Scenario: data object ds counter 30 | When requesting ds counter: 93 31 | Then you should get: \x00\x00\x02 32 | -------------------------------------------------------------------------------- /test/features/851_decryption.feature: -------------------------------------------------------------------------------- 1 | Feature: decryption 2 | In order to use a token 3 | A token should decrypt encrypted data 4 | 5 | Scenario: decrypt by OPENPGP.2 key (1) 6 | Given a plain text "This is a test message." 7 | And encrypt it on host with RSA key pair 1 8 | And let a token decrypt encrypted data 9 | Then decrypted data should be same as a plain text 10 | 11 | Scenario: decrypt by OPENPGP.2 key (2) 12 | Given a plain text "RSA decryption is as easy as pie." 13 | And encrypt it on host with RSA key pair 1 14 | And let a token decrypt encrypted data 15 | Then decrypted data should be same as a plain text 16 | 17 | -------------------------------------------------------------------------------- /test/features/860_key_removal.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: key removal 3 | In order to use a token 4 | A token should have keys 5 | 6 | Scenario: remove OPENPGP.1 key (sign) 7 | When removing a key OPENPGP.1 8 | Then it should get success 9 | 10 | Scenario: remove OPENPGP.2 key (decrypt) 11 | When removing a key OPENPGP.2 12 | Then it should get success 13 | 14 | Scenario: remove OPENPGP.3 key (authentication) 15 | When removing a key OPENPGP.3 16 | Then it should get success 17 | 18 | Scenario: remove data object Finger print sig 19 | Given cmd_put_data with c7 and "" 20 | Then it should get success 21 | 22 | Scenario: remove data object Finger print dec 23 | Given cmd_put_data with c8 and "" 24 | Then it should get success 25 | 26 | Scenario: remove data object Finger print aut 27 | Given cmd_put_data with c9 and "" 28 | Then it should get success 29 | 30 | Scenario: remove data object keygeneration data/time sig 31 | Given cmd_put_data with ce and "" 32 | Then it should get success 33 | 34 | Scenario: remove data object keygeneration data/time dec 35 | Given cmd_put_data with cf and "" 36 | Then it should get success 37 | 38 | Scenario: remove data object keygeneration data/time aut 39 | Given cmd_put_data with d0 and "" 40 | Then it should get success 41 | 42 | Scenario: verify PW1 43 | Given cmd_verify with 1 and "123456" 44 | Then it should get success 45 | 46 | Scenario: verify PW2 47 | Given cmd_verify with 2 and "123456" 48 | Then it should get success 49 | -------------------------------------------------------------------------------- /test/features/862_keygen.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: key generation 3 | In order to use a token 4 | A token should have keys 5 | 6 | Scenario: generate OPENPGP.1 key (sign) 7 | When generating a key of OPENPGP.1 8 | And put the first data to c7 9 | And put the second data to ce 10 | Then it should get success 11 | 12 | Scenario: generate OPENPGP.2 key (decrypt) 13 | When generating a key of OPENPGP.2 14 | And put the first data to c8 15 | And put the second data to cf 16 | Then it should get success 17 | 18 | Scenario: generate OPENPGP.3 key (authentication) 19 | When generating a key of OPENPGP.3 20 | And put the first data to c9 21 | And put the second data to d0 22 | Then it should get success 23 | 24 | Scenario: compute digital signature by OPENPGP.1 key 25 | Given a message "GnuPG assumes that PW1 keeps valid after keygen." 26 | And a public key from token for OPENPGP.1 27 | And let a token compute digital signature 28 | And verify signature 29 | Then it should get success 30 | 31 | Scenario: verify PW1 (1) after keygen 32 | Given cmd_verify with 1 and "123456" 33 | Then it should get success 34 | 35 | Scenario: verify PW1 (2) after keygen 36 | Given cmd_verify with 2 and "123456" 37 | Then it should get success 38 | -------------------------------------------------------------------------------- /test/features/870_compute_signature.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: compute digital signature 3 | In order to use a token 4 | A token should compute digital signature properly 5 | 6 | Scenario: compute digital signature by OPENPGP.1 key (1) 7 | Given a message "This is a test message." 8 | And a public key from token for OPENPGP.1 9 | And let a token compute digital signature 10 | And verify signature 11 | Then it should get success 12 | 13 | Scenario: compute digital signature by OPENPGP.1 key (2) 14 | Given a message "This is another test message.\nMultiple lines.\n" 15 | And a public key from token for OPENPGP.1 16 | And let a token compute digital signature 17 | And verify signature 18 | Then it should get success 19 | 20 | Scenario: compute digital signature by OPENPGP.3 key (1) 21 | Given a message "This is a test message." 22 | And a public key from token for OPENPGP.3 23 | And let a token authenticate 24 | And verify signature 25 | Then it should get success 26 | 27 | Scenario: compute digital signature by OPENPGP.3 key (2) 28 | Given a message "This is another test message.\nMultiple lines.\n" 29 | And a public key from token for OPENPGP.3 30 | And let a token authenticate 31 | And verify signature 32 | Then it should get success 33 | 34 | Scenario: data object ds counter 35 | When requesting ds counter: 93 36 | Then data should match: \x00\x00(\x02|\x03) 37 | -------------------------------------------------------------------------------- /test/features/871_decryption.feature: -------------------------------------------------------------------------------- 1 | @keygen 2 | Feature: decryption 3 | In order to use a token 4 | A token should decrypt encrypted data 5 | 6 | Scenario: decrypt by OPENPGP.2 key (1) 7 | Given a plain text "This is a test message." 8 | And a public key from token for OPENPGP.2 9 | And encrypt it on host 10 | And let a token decrypt encrypted data 11 | Then decrypted data should be same as a plain text 12 | 13 | Scenario: decrypt by OPENPGP.2 key (2) 14 | Given a plain text "RSA decryption is as easy as pie." 15 | And a public key from token for OPENPGP.2 16 | And encrypt it on host 17 | And let a token decrypt encrypted data 18 | Then decrypted data should be same as a plain text 19 | 20 | -------------------------------------------------------------------------------- /test/features/970_key_removal.feature: -------------------------------------------------------------------------------- 1 | Feature: key removal 2 | In order to use a token 3 | A token should have keys 4 | 5 | Scenario: remove OPENPGP.1 key (sign) 6 | When removing a key OPENPGP.1 7 | Then it should get success 8 | 9 | Scenario: remove OPENPGP.2 key (decrypt) 10 | When removing a key OPENPGP.2 11 | Then it should get success 12 | 13 | Scenario: remove OPENPGP.3 key (authentication) 14 | When removing a key OPENPGP.3 15 | Then it should get success 16 | 17 | Scenario: verify PW3 (admin-less mode) 18 | Given cmd_verify with 3 and "12345678" 19 | Then it should get success 20 | 21 | Scenario: remove data object Finger print sig 22 | Given cmd_put_data with c7 and "" 23 | Then it should get success 24 | 25 | Scenario: remove data object Finger print dec 26 | Given cmd_put_data with c8 and "" 27 | Then it should get success 28 | 29 | Scenario: remove data object Finger print aut 30 | Given cmd_put_data with c9 and "" 31 | Then it should get success 32 | 33 | Scenario: remove data object keygeneration data/time sig 34 | Given cmd_put_data with ce and "" 35 | Then it should get success 36 | 37 | Scenario: remove data object keygeneration data/time dec 38 | Given cmd_put_data with cf and "" 39 | Then it should get success 40 | 41 | Scenario: remove data object keygeneration data/time aut 42 | Given cmd_put_data with d0 and "" 43 | Then it should get success 44 | -------------------------------------------------------------------------------- /test/features/980_personalization_reset.feature: -------------------------------------------------------------------------------- 1 | Feature: removal of data objects 2 | In order to use a token 3 | A token should have personalized data 4 | 5 | Scenario: remove data object Login 6 | Given cmd_put_data with 5e and "" 7 | Then it should get success 8 | 9 | Scenario: remove data object Name 10 | Given cmd_put_data with 5b and "" 11 | Then it should get success 12 | 13 | Scenario: remove data object Language preference 14 | Given cmd_put_data with 5f2d and "" 15 | Then it should get success 16 | 17 | Scenario: remove data object Sex 18 | Given cmd_put_data with 5f35 and "" 19 | Then it should get success 20 | 21 | Scenario: remove data object URL 22 | Given cmd_put_data with 5f50 and "" 23 | Then it should get success 24 | 25 | Scenario: remove data object pw1 status bytes 26 | Given cmd_put_data with c4 and "\x00" 27 | Then it should get success 28 | -------------------------------------------------------------------------------- /test/features/990_reset_passphrase.feature: -------------------------------------------------------------------------------- 1 | Feature: confirm factory setting pass phrase 2 | In order to conform OpenPGP card 2.0 specification 3 | A token should support pass phrase: PW1, PW3 and reset code 4 | 5 | Scenario: verify PW3 (admin-less mode) 6 | Given cmd_verify with 3 and "12345678" 7 | Then it should get success 8 | -------------------------------------------------------------------------------- /test/features/991_version_string.feature: -------------------------------------------------------------------------------- 1 | @usb 2 | Feature: examine USB version string 3 | In order to work as Gnuk Token 4 | A token should support version string 5 | 6 | Scenario: USB version string 7 | Given USB version string of the token 8 | Then data should match: ([a-zA-Z0-9]*)-([.0-9]+)-[0-9A-F]+ 9 | -------------------------------------------------------------------------------- /test/generate_keys.py: -------------------------------------------------------------------------------- 1 | from Crypto import Random 2 | from Crypto.PublicKey import RSA 3 | from binascii import hexlify 4 | 5 | def print_key_in_hex(k): 6 | prv = k.exportKey(format='DER', pkcs=8) 7 | n = prv[38:38+256] 8 | e = prv[38+256+2:38+256+2+3] 9 | p = prv[38+256+2+3+4+257+4:38+256+2+3+4+257+4+128] 10 | q = prv[38+256+2+3+4+257+4+128+4:38+256+2+3+4+257+4+128+4+128] 11 | n_str = hexlify(n) 12 | e_str = hexlify(e) 13 | p_str = hexlify(p) 14 | q_str = hexlify(q) 15 | if int(p_str, 16)*int(q_str, 16) != int(n_str, 16): 16 | raise ValueError("wrong key", k) 17 | print(n_str) 18 | print(e_str) 19 | print(p_str) 20 | print(q_str) 21 | 22 | rng = Random.new().read 23 | key = RSA.generate(2048, rng) 24 | 25 | print_key_in_hex(key) 26 | -------------------------------------------------------------------------------- /test/gnuk_token.py: -------------------------------------------------------------------------------- 1 | ../tool/gnuk_token.py -------------------------------------------------------------------------------- /test/rsa-aut.key: -------------------------------------------------------------------------------- 1 | 9cf7192b51a574d1ad3ccb08ba09b87f228573893eee355529ff243e90fd4b86f79a82097cc7922c0485bed1616b1656a9b0b19ef78ea8ec34c384019adc5d5bf4db2d2a0a2d9cf14277bdcb7056f48b81214e3f7f7742231e29673966f9b1106862112cc798dba8d4a138bb5abfc6d4c12d53a5d39b2f783da916da20852ee139bbafda61d429caf2a4f30847ce7e7ae32ab4061e27dd9e4d00d60910249db8d8559dd85f7ca59659ef400c8f6318700f4e97f0c6f4165de80641490433c88da8682befe68eb311f54af2b07d97ac74edb5399cf054764211694fbb8d1d333f3269f235abe025067f811ff83a2224826219b309ea3e6c968f42b3e52f245dc9 2 | 010001 3 | b5ab7b159220b18e363258f61ebde08bae83d6ce2dbfe4adc143628c527887acde9de09bf9b49f438019004d71855f30c2d69b6c29bb9882ab641b3387409fe9199464a7faa4b5230c56d9e17cd9ed074bc00180ebed62bae3af28e6ff2ac2654ad968834c5d5c88f8d9d3cc5e167b10453b049d4e454a5761fb0ac717185907 4 | dd2fffa9814296156a6926cd17b65564187e424dcadce9b032246ad7e46448bb0f9e0ff3c64f987424b1a40bc694e2e9ac4fb1930d163582d7acf20653a1c44b97846c1c5fd8a7b19bb225fb39c30e25410483deaf8c2538d222b748c4d8103b11cec04f666a5c0dbcbf5d5f625f158f65746c3fafe6418145f7cffa5fadeeaf 5 | -------------------------------------------------------------------------------- /test/rsa-dec.key: -------------------------------------------------------------------------------- 1 | d392714c29738aac6372f2c8654a08c25a1299fed7004bd512cd2452b503ebad6301130816ac525ba528dc155be6347a5c70407fb4fbdaed751dfc0a7cd5e3910272ff236c4ed1ce5de6620b191a172e5b247347b8cab73a43d79221708755c959a2f83f486439da30917384554331532aabc8326db48866f8c91198834a86ab94679f6175db737bdf399e3f0b737dcb1f4208279d3e1cc694e78686785e4f363a377dec912b7c2f757b1422d866fb9fa85c96b83adfd6a223989a9a02988bdee81ad17eff6385e7b38cec8611fdf367ba4ac8e90d5f48ac7715c5f47aea06a4a37cdaa3029ce59d29bc66853bf6758ef4a7da5a5953f5e557a5a22f67c368c3 2 | 010001 3 | dae085952c5beee38f25f09bc37a4ca2434c31f78055469d0d5f0bf3337e3a70ba6c91734f195b742e211a5fe283befdf66820008e6ef2c8ca54a91922838fce07d9e33a331ce20dac36803e777d5ee2195ed28d6a4045e28623a6a60b0661e45f7c4f84ae2b1dfad0cf1ec30605158323382a819e730c09a33fad704dd67501 4 | f774be43ea198aa2f089274e4fffd7d0092ee7b35a1d2f854cdb166f698caab72fdeb099e690e78438b2e043e452d4d2f19d7f44ba6b286642f0ce5204966ff98ecd9e3b448877324631365dc860797429b9414a21a7e166d504cace156588b9a145657eeb1afb43b8ff65d8d6d93cea2ba4ef8aab047885c4de64ffef0b49c3 5 | -------------------------------------------------------------------------------- /test/rsa-sig.key: -------------------------------------------------------------------------------- 1 | c6c877dfd3b441f8fb1b8dc504093a51c2efe4883fe0a6379205acc6e673709905e4d767ddf46143c535cc6d7f10b616f520d8346320ef69ff4a2c4f4a148edc65f7ad24ed7d4fe23bb862a0ae71f4f7904abac0397abf3213df91326b1a25554b3b18cf54584d8bf220169fc92b2aa511e8313983e72b4c9110b3a1aea087aebef95873865608e8faea9ef10e7f7f3a66ca8def2d499c3149c127491e0e4339fd6abe10bfc6c13e43d522004f1485767328eabe35d6ffa8df4c15f0fbcd4eb1c07cc6d85e275139ac69e2962273ae987236926dd6c1144fce3e7ae567fa58ea60620dfafc52f95299fea601739fce27ee71eea978d0074f21e7086f60ba8331 2 | 010001 3 | cc365b5702714bf203e8c49b0b8afa8dad586e929cf5edca38ad07fa45efd5c2d89022d29f40283a57e50ca24c5f28c8e911a74faaf796f112e7e48195956f9a4df7668a5342523b27179cec958f363211ee11d0ec0e0e1b92ca007a61e8c9ac14e00229b9a7624850199e6667afa1a44db8f3c5de0a8eef0e6de050ac0ac633 4 | f931a3c12f0e3a5276f712b7706590ba02e14a97ff9b8ce3152af0fc4d9cdc690ea9bc4c82cb16c7d23136cbdab58fbec69880a88bca85c4214df01045082cbe9f4192e3e39c79896533c37dad9eb9e73c2643b9c0a704a4f93d81573537963d6b6e5140a24c702d9f26e06a2095de906daa8824172a6b39f563b7153907050b 5 | -------------------------------------------------------------------------------- /tests/README: -------------------------------------------------------------------------------- 1 | Here is a test suite for OpenPGP card. 2 | 3 | For now, only TPDU card reader is supported for OpenPGP card. 4 | Gnuk Token is supported as well. 5 | 6 | 7 | You need to install: 8 | 9 | $ sudo apt install python3-pytest python3-usb python3-cffi 10 | 11 | Please run test by typing: 12 | 13 | $ py.test-3 -x 14 | -------------------------------------------------------------------------------- /tests/card_const.py: -------------------------------------------------------------------------------- 1 | FACTORY_PASSPHRASE_PW1=b"123456" 2 | FACTORY_PASSPHRASE_PW3=b"12345678" 3 | KEY_ATTRIBUTES_RSA4K=b"\x01\x10\x00\x00\x20\x00" 4 | KEY_ATTRIBUTES_RSA2K=b"\x01\x08\x00\x00\x20\x00" 5 | -------------------------------------------------------------------------------- /tests/card_test_kdf_full.py: -------------------------------------------------------------------------------- 1 | """ 2 | card_test_kdf_full.py - test KDF data object 3 | 4 | Copyright (C) 2018, 2019 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from card_const import * 24 | from constants_for_test import * 25 | 26 | class Test_Card_KDF_full(object): 27 | 28 | def test_verify_pw3(self, card): 29 | v = card.verify(3, FACTORY_PASSPHRASE_PW3) 30 | assert v 31 | 32 | def test_kdf_put_full(self, card): 33 | r = card.cmd_put_data(0x00, 0xf9, KDF_FULL) 34 | if r: 35 | card.configure_with_kdf() 36 | assert r 37 | -------------------------------------------------------------------------------- /tests/card_test_kdf_single.py: -------------------------------------------------------------------------------- 1 | """ 2 | card_test_kdf_single.py - test KDF data object 3 | 4 | Copyright (C) 2018, 2019 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from card_const import * 24 | from constants_for_test import * 25 | 26 | class Test_Card_KDF_Single(object): 27 | def test_verify_pw3(self, card): 28 | v = card.verify(3, FACTORY_PASSPHRASE_PW3) 29 | assert v 30 | 31 | def test_kdf_put_single(self, card): 32 | r = card.cmd_put_data(0x00, 0xf9, KDF_SINGLE) 33 | if r: 34 | card.configure_with_kdf() 35 | assert r 36 | -------------------------------------------------------------------------------- /tests/card_test_keygen.py: -------------------------------------------------------------------------------- 1 | """ 2 | card_test_keygen.py - test key generation 3 | 4 | Copyright (C) 2018, 2019 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from binascii import hexlify 24 | import rsa_keys 25 | from card_const import * 26 | 27 | class Test_Card_Keygen(object): 28 | def test_keygen_1(self, card): 29 | pk = card.cmd_genkey(1) 30 | fpr_date = rsa_keys.calc_fpr(pk[0], pk[1]) 31 | r = card.cmd_put_data(0x00, 0xc7, fpr_date[0]) 32 | if r: 33 | r = card.cmd_put_data(0x00, 0xce, fpr_date[1]) 34 | assert r 35 | 36 | def test_keygen_2(self, card): 37 | pk = card.cmd_genkey(2) 38 | fpr_date = rsa_keys.calc_fpr(pk[0], pk[1]) 39 | r = card.cmd_put_data(0x00, 0xc8, fpr_date[0]) 40 | if r: 41 | r = card.cmd_put_data(0x00, 0xcf, fpr_date[1]) 42 | assert r 43 | 44 | def test_keygen_3(self, card): 45 | pk = card.cmd_genkey(3) 46 | fpr_date = rsa_keys.calc_fpr(pk[0], pk[1]) 47 | r = card.cmd_put_data(0x00, 0xc9, fpr_date[0]) 48 | if r: 49 | r = card.cmd_put_data(0x00, 0xd0, fpr_date[1]) 50 | assert r 51 | 52 | def test_verify_pw1(self, card): 53 | v = card.cmd_verify(1, FACTORY_PASSPHRASE_PW1) 54 | assert v 55 | 56 | def test_signature_sigkey(self, card): 57 | msg = b"Sign me please" 58 | pk = card.cmd_get_public_key(1) 59 | pk_info = (pk[9:9+256], pk[9+256+2:]) 60 | digest = rsa_keys.compute_digestinfo(msg) 61 | sig = int(hexlify(card.cmd_pso(0x9e, 0x9a, digest)),16) 62 | r = rsa_keys.verify_signature(pk_info, digest, sig) 63 | assert r 64 | 65 | def test_verify_pw1_2(self, card): 66 | v = card.cmd_verify(2, FACTORY_PASSPHRASE_PW1) 67 | assert v 68 | 69 | def test_decryption(self, card): 70 | msg = b"encrypt me please" 71 | pk = card.cmd_get_public_key(2) 72 | pk_info = (pk[9:9+256], pk[9+256+2:]) 73 | ciphertext = rsa_keys.encrypt_with_pubkey(pk_info, msg) 74 | r = card.cmd_pso(0x80, 0x86, ciphertext) 75 | assert r == msg 76 | 77 | def test_signature_authkey(self, card): 78 | msg = b"Sign me please to authenticate" 79 | pk = card.cmd_get_public_key(3) 80 | pk_info = (pk[9:9+256], pk[9+256+2:]) 81 | digest = rsa_keys.compute_digestinfo(msg) 82 | sig = int(hexlify(card.cmd_internal_authenticate(digest)),16) 83 | r = rsa_keys.verify_signature(pk_info, digest, sig) 84 | assert r 85 | -------------------------------------------------------------------------------- /tests/card_test_personalize_reset.py: -------------------------------------------------------------------------------- 1 | """ 2 | card_test_personalize_reset.py - test resetting personalization of card 3 | 4 | Copyright (C) 2016, 2018, 2019 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from struct import pack 24 | from re import match, DOTALL 25 | from util import * 26 | import rsa_keys 27 | from card_const import * 28 | from constants_for_test import * 29 | 30 | class Test_Personalize_Reset(object): 31 | def test_login_put(self, card): 32 | r = card.cmd_put_data(0x00, 0x5e, b"") 33 | assert r 34 | 35 | def test_name_put(self, card): 36 | r = card.cmd_put_data(0x00, 0x5b, b"") 37 | assert r 38 | 39 | def test_lang_put(self, card): 40 | r = card.cmd_put_data(0x5f, 0x2d, b"") 41 | assert r 42 | 43 | def test_sex_put(self, card): 44 | try: 45 | # Gnuk 46 | r = card.cmd_put_data(0x5f, 0x35, b"") 47 | except ValueError: 48 | # OpenPGP card which doesn't allow b"" 49 | r = card.cmd_put_data(0x5f, 0x35, b"9") 50 | assert r 51 | 52 | def test_url_put(self, card): 53 | r = card.cmd_put_data(0x5f, 0x50, b"") 54 | assert r 55 | 56 | def test_pw1_status_put(self, card): 57 | r = card.cmd_put_data(0x00, 0xc4, b"\x00") 58 | assert r 59 | 60 | def test_setup_pw3_0(self, card): 61 | r = card.change_passwd(3, PW3_TEST0, FACTORY_PASSPHRASE_PW3) 62 | assert r 63 | 64 | def test_verify_pw3_0(self, card): 65 | v = card.verify(3, FACTORY_PASSPHRASE_PW3) 66 | assert v 67 | 68 | def test_setup_pw1_0(self, card): 69 | r = card.change_passwd(1, PW1_TEST4, FACTORY_PASSPHRASE_PW1) 70 | assert r 71 | 72 | def test_verify_pw1_0(self, card): 73 | v = card.verify(1, FACTORY_PASSPHRASE_PW1) 74 | assert v 75 | 76 | def test_verify_pw1_0_2(self, card): 77 | v = card.verify(2, FACTORY_PASSPHRASE_PW1) 78 | assert v 79 | 80 | def test_delete_reset_code(self, card): 81 | r = card.cmd_put_data(0x00, 0xd3, b"") 82 | assert r 83 | -------------------------------------------------------------------------------- /tests/card_test_remove_keys.py: -------------------------------------------------------------------------------- 1 | """ 2 | card_test_remove_keys.py - test removing keys on card 3 | 4 | Copyright (C) 2016, 2018, 2019 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | # Remove a key material on card by changing algorithm attributes of the key 24 | 25 | from card_const import * 26 | 27 | class Test_Remove_Keys(object): 28 | 29 | def test_rsa_keyattr_change_1(self, card): 30 | r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA4K) 31 | if r: 32 | r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA2K) 33 | assert r 34 | 35 | def test_rsa_keyattr_change_2(self, card): 36 | r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA4K) 37 | if r: 38 | r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA2K) 39 | assert r 40 | 41 | def test_rsa_keyattr_change_3(self, card): 42 | r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA4K) 43 | if r: 44 | r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA2K) 45 | assert r 46 | -------------------------------------------------------------------------------- /tests/card_test_reset_pw3.py: -------------------------------------------------------------------------------- 1 | """ 2 | card_test_reset_pw3.py - test resetting pw3 3 | 4 | Copyright (C) 2018, 2019 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from card_const import * 24 | import pytest 25 | 26 | class Test_Reset_PW3(object): 27 | # Gnuk specific feature of clear PW3 28 | def test_setup_pw3_null(self, card): 29 | if card.is_gnuk: 30 | r = card.change_passwd(3, FACTORY_PASSPHRASE_PW3, None) 31 | assert r 32 | else: 33 | pytest.skip("Gnuk only feature of clearing PW3") 34 | 35 | def test_verify_pw3(self, card): 36 | v = card.verify(3, FACTORY_PASSPHRASE_PW3) 37 | assert v 38 | 39 | # Check PW1 again to see the possiblity of admin-less mode 40 | def test_verify_pw1(self, card): 41 | v = card.verify(1, FACTORY_PASSPHRASE_PW1) 42 | assert v 43 | 44 | def test_verify_pw1_2(self, card): 45 | v = card.verify(2, FACTORY_PASSPHRASE_PW1) 46 | assert v 47 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from card_reader import get_ccid_device 3 | from openpgp_card import OpenPGP_Card 4 | 5 | def pytest_addoption(parser): 6 | parser.addoption("--reader", dest="reader", type=str, action="store", 7 | default="gnuk", help="specify reader: gnuk or gemalto") 8 | 9 | @pytest.fixture(scope="session") 10 | def card(): 11 | print() 12 | print("Test start!") 13 | reader = get_ccid_device() 14 | print("Reader:", reader.get_string(1), reader.get_string(2)) 15 | card = OpenPGP_Card(reader) 16 | card.cmd_select_openpgp() 17 | yield card 18 | del card 19 | reader.ccid_power_off() 20 | -------------------------------------------------------------------------------- /tests/constants_for_test.py: -------------------------------------------------------------------------------- 1 | PW1_TEST0=b"another user pass phrase" 2 | PW1_TEST1=b"PASSPHRASE SHOULD BE LONG" 3 | PW1_TEST2=b"new user pass phrase" 4 | PW1_TEST3=b"next user pass phrase" 5 | PW1_TEST4=b"another user pass phrase" 6 | PW3_TEST0=b"admin pass phrase" 7 | PW3_TEST1=b"another admin pass phrase" 8 | 9 | RESETCODE_TEST=b"example reset code 000" 10 | 11 | PLAIN_TEXT0=b"This is a test message." 12 | PLAIN_TEXT1=b"RSA decryption is as easy as pie." 13 | PLAIN_TEXT2=b"This is another test message.\nMultiple lines.\n" 14 | 15 | KDF_FULL=b"\x81\x01\x03\x82\x01\x08\x83\x04\x00\xC8\x00\x00\x84\x08\xC5\x1F\xB7\xF9\xEE\xF3\xD3\xE8\x85\x08\x75\x1A\x2A\x70\xC0\x7C\xB1\x81\x86\x08\xE6\xB2\x4E\x0C\xEE\x92\xAB\x93\x87\x20\xA2\x08\x89\x16\x09\xD3\xE4\x3D\x48\xAC\x5B\xAA\xBD\xE9\xF1\xB8\xD2\xFC\xD8\x3C\x5F\x35\xCB\xEB\xDA\xFB\x75\x92\x88\xC6\x8B\x2D\x88\x20\xF1\x34\x00\xD2\x5F\x28\x57\xE6\x66\xAA\x9E\xBB\xE0\x7C\x57\x4B\x84\x8B\xD6\x52\x14\xE7\x31\x99\x1A\x3D\x2D\xAA\x3F\x8A\x7F\x03" 16 | KDF_FULL_HASH_PW1=b"\xA2\x08\x89\x16\x09\xD3\xE4\x3D\x48\xAC\x5B\xAA\xBD\xE9\xF1\xB8\xD2\xFC\xD8\x3C\x5F\x35\xCB\xEB\xDA\xFB\x75\x92\x88\xC6\x8B\x2D" 17 | KDF_FULL_HASH_PW3=b"\xF1\x34\x00\xD2\x5F\x28\x57\xE6\x66\xAA\x9E\xBB\xE0\x7C\x57\x4B\x84\x8B\xD6\x52\x14\xE7\x31\x99\x1A\x3D\x2D\xAA\x3F\x8A\x7F\x03" 18 | 19 | KDF_SINGLE=b"\x81\x01\x03\x82\x01\x08\x83\x04\x00\xC8\x00\x00\x84\x08\x69\x9E\xDA\xAD\x5A\x72\x5F\x4C\x87\x20\x12\xDB\x16\x9A\x9D\x1A\x56\xCA\x2B\x9E\x96\x7F\xC4\xDA\xB8\xAE\x70\x41\x51\x8E\x3C\xEF\x49\x7E\xC2\x56\x60\x32\x2F\x4C\x03\x07\x88\x20\x1C\x93\x99\xC3\x6D\x49\x92\x27\x54\x39\x76\x7E\xA7\xB4\xEE\xE5\x16\xDA\x92\xC0\x0E\xF4\x74\xBD\x01\x28\x0F\x0C\x30\x45\x4B\xBB" 20 | KDF_SINGLE_HASH_PW1=b"\x12\xDB\x16\x9A\x9D\x1A\x56\xCA\x2B\x9E\x96\x7F\xC4\xDA\xB8\xAE\x70\x41\x51\x8E\x3C\xEF\x49\x7E\xC2\x56\x60\x32\x2F\x4C\x03\x07" 21 | KDF_SINGLE_HASH_PW3=b"\x1C\x93\x99\xC3\x6D\x49\x92\x27\x54\x39\x76\x7E\xA7\xB4\xEE\xE5\x16\xDA\x92\xC0\x0E\xF4\x74\xBD\x01\x28\x0F\x0C\x30\x45\x4B\xBB" 22 | -------------------------------------------------------------------------------- /tests/kdf_calc.py: -------------------------------------------------------------------------------- 1 | ../tool/kdf_calc.py -------------------------------------------------------------------------------- /tests/rsa-aut.key: -------------------------------------------------------------------------------- 1 | 9cf7192b51a574d1ad3ccb08ba09b87f228573893eee355529ff243e90fd4b86f79a82097cc7922c0485bed1616b1656a9b0b19ef78ea8ec34c384019adc5d5bf4db2d2a0a2d9cf14277bdcb7056f48b81214e3f7f7742231e29673966f9b1106862112cc798dba8d4a138bb5abfc6d4c12d53a5d39b2f783da916da20852ee139bbafda61d429caf2a4f30847ce7e7ae32ab4061e27dd9e4d00d60910249db8d8559dd85f7ca59659ef400c8f6318700f4e97f0c6f4165de80641490433c88da8682befe68eb311f54af2b07d97ac74edb5399cf054764211694fbb8d1d333f3269f235abe025067f811ff83a2224826219b309ea3e6c968f42b3e52f245dc9 2 | 010001 3 | b5ab7b159220b18e363258f61ebde08bae83d6ce2dbfe4adc143628c527887acde9de09bf9b49f438019004d71855f30c2d69b6c29bb9882ab641b3387409fe9199464a7faa4b5230c56d9e17cd9ed074bc00180ebed62bae3af28e6ff2ac2654ad968834c5d5c88f8d9d3cc5e167b10453b049d4e454a5761fb0ac717185907 4 | dd2fffa9814296156a6926cd17b65564187e424dcadce9b032246ad7e46448bb0f9e0ff3c64f987424b1a40bc694e2e9ac4fb1930d163582d7acf20653a1c44b97846c1c5fd8a7b19bb225fb39c30e25410483deaf8c2538d222b748c4d8103b11cec04f666a5c0dbcbf5d5f625f158f65746c3fafe6418145f7cffa5fadeeaf 5 | -------------------------------------------------------------------------------- /tests/rsa-dec.key: -------------------------------------------------------------------------------- 1 | d392714c29738aac6372f2c8654a08c25a1299fed7004bd512cd2452b503ebad6301130816ac525ba528dc155be6347a5c70407fb4fbdaed751dfc0a7cd5e3910272ff236c4ed1ce5de6620b191a172e5b247347b8cab73a43d79221708755c959a2f83f486439da30917384554331532aabc8326db48866f8c91198834a86ab94679f6175db737bdf399e3f0b737dcb1f4208279d3e1cc694e78686785e4f363a377dec912b7c2f757b1422d866fb9fa85c96b83adfd6a223989a9a02988bdee81ad17eff6385e7b38cec8611fdf367ba4ac8e90d5f48ac7715c5f47aea06a4a37cdaa3029ce59d29bc66853bf6758ef4a7da5a5953f5e557a5a22f67c368c3 2 | 010001 3 | dae085952c5beee38f25f09bc37a4ca2434c31f78055469d0d5f0bf3337e3a70ba6c91734f195b742e211a5fe283befdf66820008e6ef2c8ca54a91922838fce07d9e33a331ce20dac36803e777d5ee2195ed28d6a4045e28623a6a60b0661e45f7c4f84ae2b1dfad0cf1ec30605158323382a819e730c09a33fad704dd67501 4 | f774be43ea198aa2f089274e4fffd7d0092ee7b35a1d2f854cdb166f698caab72fdeb099e690e78438b2e043e452d4d2f19d7f44ba6b286642f0ce5204966ff98ecd9e3b448877324631365dc860797429b9414a21a7e166d504cace156588b9a145657eeb1afb43b8ff65d8d6d93cea2ba4ef8aab047885c4de64ffef0b49c3 5 | -------------------------------------------------------------------------------- /tests/rsa-sig.key: -------------------------------------------------------------------------------- 1 | c6c877dfd3b441f8fb1b8dc504093a51c2efe4883fe0a6379205acc6e673709905e4d767ddf46143c535cc6d7f10b616f520d8346320ef69ff4a2c4f4a148edc65f7ad24ed7d4fe23bb862a0ae71f4f7904abac0397abf3213df91326b1a25554b3b18cf54584d8bf220169fc92b2aa511e8313983e72b4c9110b3a1aea087aebef95873865608e8faea9ef10e7f7f3a66ca8def2d499c3149c127491e0e4339fd6abe10bfc6c13e43d522004f1485767328eabe35d6ffa8df4c15f0fbcd4eb1c07cc6d85e275139ac69e2962273ae987236926dd6c1144fce3e7ae567fa58ea60620dfafc52f95299fea601739fce27ee71eea978d0074f21e7086f60ba8331 2 | 010001 3 | cc365b5702714bf203e8c49b0b8afa8dad586e929cf5edca38ad07fa45efd5c2d89022d29f40283a57e50ca24c5f28c8e911a74faaf796f112e7e48195956f9a4df7668a5342523b27179cec958f363211ee11d0ec0e0e1b92ca007a61e8c9ac14e00229b9a7624850199e6667afa1a44db8f3c5de0a8eef0e6de050ac0ac633 4 | f931a3c12f0e3a5276f712b7706590ba02e14a97ff9b8ce3152af0fc4d9cdc690ea9bc4c82cb16c7d23136cbdab58fbec69880a88bca85c4214df01045082cbe9f4192e3e39c79896533c37dad9eb9e73c2643b9c0a704a4f93d81573537963d6b6e5140a24c702d9f26e06a2095de906daa8824172a6b39f563b7153907050b 5 | -------------------------------------------------------------------------------- /tests/skip_gnuk_only_tests.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | @pytest.fixture(scope="module",autouse=True) 4 | def check_gnuk(card): 5 | if not card.is_gnuk: 6 | pytest.skip("Gnuk only feature", allow_module_level=True) 7 | -------------------------------------------------------------------------------- /tests/test_001_personalize_card.py: -------------------------------------------------------------------------------- 1 | from card_test_personalize_card import * 2 | -------------------------------------------------------------------------------- /tests/test_002_personalize_reset.py: -------------------------------------------------------------------------------- 1 | from card_test_personalize_reset import * 2 | -------------------------------------------------------------------------------- /tests/test_003_remove_keys.py: -------------------------------------------------------------------------------- 1 | from card_test_remove_keys import * 2 | -------------------------------------------------------------------------------- /tests/test_004_reset_pw3.py: -------------------------------------------------------------------------------- 1 | from card_test_reset_pw3 import * 2 | -------------------------------------------------------------------------------- /tests/test_005_personalize_admin_less.py: -------------------------------------------------------------------------------- 1 | """ 2 | test_005_personalize_admin_less.py - test admin-less mode 3 | 4 | Copyright (C) 2016, 2018, 2019 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from skip_gnuk_only_tests import * 24 | 25 | from card_test_personalize_admin_less import * 26 | from card_test_personalize_reset import * 27 | from card_test_remove_keys import * 28 | from card_test_reset_pw3 import * 29 | -------------------------------------------------------------------------------- /tests/test_009_keygen.py: -------------------------------------------------------------------------------- 1 | """ 2 | test_005_keygen.py - test key generation 3 | 4 | Copyright (C) 2018, 2019 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from card_test_keygen import * 24 | from card_test_remove_keys import * 25 | -------------------------------------------------------------------------------- /tests/test_011_kdf_full.py: -------------------------------------------------------------------------------- 1 | """ 2 | test_007_kdf_full.py - test KDF data object 3 | 4 | Copyright (C) 2018, 2019 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from skip_gnuk_only_tests import * 24 | 25 | from card_test_kdf_full import * 26 | from card_test_personalize_card import * 27 | from card_test_personalize_reset import * 28 | from card_test_remove_keys import * 29 | from card_test_reset_pw3 import * 30 | -------------------------------------------------------------------------------- /tests/test_016_kdf_single.py: -------------------------------------------------------------------------------- 1 | """ 2 | test_012_kdf_single.py - test KDF data object 3 | 4 | Copyright (C) 2018, 2019 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from skip_gnuk_only_tests import * 24 | 25 | from card_test_kdf_single import * 26 | from card_test_personalize_card import * 27 | from card_test_personalize_reset import * 28 | from card_test_remove_keys import * 29 | from card_test_reset_pw3 import * 30 | -------------------------------------------------------------------------------- /tests/test_021_personalize_admin_less.py: -------------------------------------------------------------------------------- 1 | from test_005_personalize_admin_less import * 2 | -------------------------------------------------------------------------------- /tests/test_025_kdf_none.py: -------------------------------------------------------------------------------- 1 | """ 2 | test_017_kdf_none.py - test KDF data object 3 | 4 | Copyright (C) 2018 g10 Code GmbH 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from skip_gnuk_only_tests import * 24 | 25 | from card_const import * 26 | from constants_for_test import * 27 | 28 | def test_verify_pw3(card): 29 | v = card.verify(3, FACTORY_PASSPHRASE_PW3) 30 | assert v 31 | 32 | def test_kdf_put_none(card): 33 | r = card.cmd_put_data(0x00, 0xf9, b"") 34 | if r: 35 | card.configure_with_kdf() 36 | assert r 37 | 38 | def test_verify_pw3_1(card): 39 | v = card.verify(3, FACTORY_PASSPHRASE_PW3) 40 | assert v 41 | -------------------------------------------------------------------------------- /tests/util.py: -------------------------------------------------------------------------------- 1 | def get_data_object(card, tag): 2 | tagh = tag >> 8 3 | tagl = tag & 0xff 4 | return card.cmd_get_data(tagh, tagl) 5 | 6 | def check_null(data_object): 7 | return data_object == None or len(data_object) == 0 8 | -------------------------------------------------------------------------------- /tool/asm-thumb/README: -------------------------------------------------------------------------------- 1 | These assembler program are source code of program fragments in 2 | stlinkv2.py. 3 | -------------------------------------------------------------------------------- /tool/asm-thumb/blank_check.S: -------------------------------------------------------------------------------- 1 | /* ARM Thumb Assembler code */ 2 | // arm-none-eabi-gcc -Wa,-amhls=blank_check.lst -c blank_check.S 3 | 4 | .cpu cortex-m0 5 | .thumb 6 | ldr r1, .START_ADDR 7 | ldr r2, .END_ADDR 8 | 0: ldr r0, [r1] 9 | add r0, r0, #1 10 | bne 1f 11 | add r1, r1, #4 12 | cmp r1, r2 13 | bne 0b 14 | 1: bkpt #0x00 15 | // success: r0=0 16 | // fail: r0!=0 17 | .align 2 18 | .START_ADDR: .word 0x08000000 19 | .END_ADDR: .word 0x08020000 20 | -------------------------------------------------------------------------------- /tool/asm-thumb/flash_write.S: -------------------------------------------------------------------------------- 1 | /* ARM Thumb Assembler code */ 2 | // arm-none-eabi-gcc -Wa,-amhls=flash_write.lst -c flash_write.S 3 | 4 | #define FLASH_CR_PG 0x0001 // == FLASH_SR_BSY 5 | #define FLASH_CR_ERRORS 0x0014 // == PGERR | WRPRTERR 6 | #define FLASH_SR_BSY 0x0001 7 | 8 | #define FLASH_SR_OFFSET 0x0c 9 | #define FLASH_CR_OFFSET 0x10 10 | 11 | .cpu cortex-m0 12 | .thumb 13 | ldr r2, .SIZE 14 | ldr r0, .SRC_ADDR 15 | ldr r1, .TARGET_ADDR 16 | ldr r4, .FLASH_BASE_ADDR 17 | mov r5, #FLASH_CR_PG 18 | mov r6, #FLASH_CR_ERRORS 19 | mov r7, #0 20 | str r5, [r4, #FLASH_CR_OFFSET] 21 | 0: ldrh r3, [r0, r7] 22 | strh r3, [r1, r7] 23 | 1: ldr r3, [r4, #FLASH_SR_OFFSET] 24 | tst r3, r5 25 | bne 1b 26 | tst r3, r6 27 | bne 2f 28 | add r7, r7, #0x02 29 | cmp r7, r2 30 | bne 0b 31 | 2: mov r7, #0 32 | str r7, [r4, #FLASH_CR_OFFSET] 33 | bkpt #0x00 34 | .align 2 35 | .FLASH_BASE_ADDR: .word 0x40022000 36 | .SRC_ADDR: .word 0x2000003C 37 | .TARGET_ADDR: .word 0x08000000 38 | .SIZE: .word 0x00000000 39 | -------------------------------------------------------------------------------- /tool/asm-thumb/opt_bytes_write.S: -------------------------------------------------------------------------------- 1 | /* ARM Thumb Assembler code */ 2 | // arm-none-eabi-gcc -Wa,-amhls=opt_bytes_write.lst -c opt_bytes_write.S 3 | 4 | #define FLASH_CR_OPTPG 0x0010 5 | #define FLASH_SR_BSY 0x0001 6 | 7 | #define FLASH_SR_OFFSET 0x0c 8 | #define FLASH_CR_OFFSET 0x10 9 | 10 | .cpu cortex-m0 11 | .thumb 12 | ldr r0, .OPTION_BYTES 13 | ldr r1, .TARGET_ADDR 14 | ldr r2, .FLASH_BASE_ADDR 15 | mov r3, #FLASH_CR_OPTPG 16 | mov r4, #FLASH_SR_BSY 17 | str r3, [r2, #FLASH_CR_OFFSET] 18 | strh r0, [r1] 19 | 1: ldr r0, [r2, #FLASH_SR_OFFSET] 20 | tst r0, r4 21 | bne 1b 22 | add r1, #2 23 | mov r0, #255 24 | strh r0, [r1] 25 | 2: ldr r0, [r2, #FLASH_SR_OFFSET] 26 | tst r0, r4 27 | bne 2b 28 | mov r0, #0 29 | str r0, [r2, #FLASH_CR_OFFSET] 30 | bkpt #0x00 31 | .align 2 32 | .FLASH_BASE_ADDR: .word 0x40022000 33 | .TARGET_ADDR: .word 0x1FFFF800 34 | .OPTION_BYTES: .word 0x00000000 35 | -------------------------------------------------------------------------------- /tool/calc_precompute_table_ecc.py: -------------------------------------------------------------------------------- 1 | from ecdsa import curves, ecdsa 2 | G = ecdsa.generator_secp256k1 3 | # G = ecdsa.generator_256 4 | 5 | def print_nG(n): 6 | nG = n*G 7 | nGx_str = "%064x" % nG.x() 8 | nGy_str = "%064x" % nG.y() 9 | print256(nGx_str) 10 | print256(nGy_str) 11 | print() 12 | 13 | def print256(s): 14 | print("0x%s, 0x%s, 0x%s, 0x%s," % (s[56:64], s[48:56], s[40:48], s[32:40])) 15 | print("0x%s, 0x%s, 0x%s, 0x%s" % (s[24:32], s[16:24], s[8:16], s[0:8])) 16 | print() 17 | 18 | 19 | for i in range(1,16): 20 | n = (i & 1) + (i & 2) * 0x8000000000000000 + (i & 4) * 0x40000000000000000000000000000000 + (i & 8) * 0x200000000000000000000000000000000000000000000000 21 | print("%064x" % n) 22 | print_nG(n) 23 | 24 | for i in range(1,16): 25 | n = (i & 1) + (i & 2) * 0x8000000000000000 + (i & 4) * 0x40000000000000000000000000000000 + (i & 8) * 0x200000000000000000000000000000000000000000000000 26 | n = n * 0x100000000 27 | print("%064x" % n) 28 | print_nG(n) 29 | -------------------------------------------------------------------------------- /tool/dump_mem.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | 3 | """ 4 | dump_mem.py - dump memory with DfuSe for STM32 Processor. 5 | 6 | Copyright (C) 2010 Free Software Initiative of Japan 7 | Author: NIIBE Yutaka 8 | 9 | This file is a part of Gnuk, a GnuPG USB Token implementation. 10 | 11 | Gnuk is free software: you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 17 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 18 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 19 | License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see . 23 | """ 24 | 25 | import sys 26 | from dfuse import * 27 | 28 | dev, config, intf = get_device() 29 | dfu = DFU_STM32(dev, config, intf) 30 | print(dfu.ll_get_string(intf.iInterface)) 31 | s = dfu.ll_get_status() 32 | dfu.ll_clear_status() 33 | s = dfu.ll_get_status() 34 | print(s) 35 | dfu.dfuse_set_address_pointer(int(sys.argv[1], 16)) 36 | s = dfu.ll_get_status() 37 | dfu.ll_clear_status() 38 | s = dfu.ll_get_status() 39 | dfu.ll_clear_status() 40 | s = dfu.ll_get_status() 41 | print(s) 42 | block = dfu.dfuse_read_memory() 43 | count = 0 44 | for d in block: 45 | print("%02x" % d) 46 | if count & 0x0f == 0x0f: 47 | print 48 | count += 1 49 | dfu.ll_clear_status() 50 | s = dfu.ll_get_status() 51 | -------------------------------------------------------------------------------- /tool/get_raw_public_key.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | 3 | import sys, binascii 4 | from subprocess import check_output 5 | 6 | def get_gpg_public_key(keygrip): 7 | result = check_output(["gpg-connect-agent", "READKEY %s" % keygrip, "/bye"]) 8 | key = "" 9 | while True: 10 | i = result.find('%') 11 | if i < 0: 12 | key += result 13 | break 14 | hex_str = result[i+1:i+3] 15 | key += result[0:i] 16 | key += chr(int(hex_str,16)) 17 | result = result[i+3:] 18 | 19 | pos = key.index("D (10:public-key(3:rsa(1:n257:") + 31 # skip NUL too 20 | pos_last = key.index(")(1:e3:") 21 | key = key[pos:pos_last] 22 | if len(key) != 256: 23 | raise ValueError(binascii.hexlify(key)) 24 | return key 25 | 26 | if __name__ == '__main__': 27 | keygrip = sys.argv[1] 28 | k = get_gpg_public_key(keygrip) 29 | shorthand = keygrip[0:8] + ".bin" 30 | f = open(shorthand,"w") 31 | f.write(k) 32 | f.close() 33 | -------------------------------------------------------------------------------- /tool/gnuk-emulation-setup: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # gnuk-emulation-setup - Generate flash image for Gnuk 4 | # 5 | # Copyright (C) 2017 Free Software Initiative of Japan 6 | # Author: NIIBE Yutaka 7 | # 8 | # This file is a part of Gnuk, a GnuPG USB Token implementation. 9 | # 10 | # Gnuk is free software: you can redistribute it and/or modify it 11 | # under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # Gnuk is distributed in the hope that it will be useful, but WITHOUT 16 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17 | # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 18 | # License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | if test "$1" = "--help"; then 24 | echo "Usage:" 25 | echo " $0 [output-file]" 26 | echo " Generate Gnuk flash image" 27 | echo " $0 --help" 28 | echo " Show this message" 29 | exit 0 30 | fi 31 | 32 | OUTPUT_FILE=${1:-$HOME/.gnuk-flash-image} 33 | 34 | # Generate 8192-byte flash data into OUTPUT_FILE 35 | 36 | exec > $OUTPUT_FILE 37 | 38 | for i in $(seq 512); do 39 | /bin/echo -n -e '\xff\xff\xff\xff\xff\xff\xff\xff' 40 | done 41 | 42 | /bin/echo -n -e '\x00\x00\xff\xff\xff\xff\xff\xff' 43 | 44 | for i in $(seq 511); do 45 | /bin/echo -n -e '\xff\xff\xff\xff\xff\xff\xff\xff' 46 | done 47 | 48 | chmod og-rw $OUTPUT_FILE 49 | -------------------------------------------------------------------------------- /tool/gnuk_get_random.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python3 2 | 3 | from gnuk_token import get_gnuk_device, gnuk_token 4 | from binascii import hexlify 5 | import sys 6 | 7 | if __name__ == '__main__': 8 | count = 0 9 | gnuk = get_gnuk_device() 10 | gnuk.cmd_select_openpgp() 11 | looping = (len(sys.argv) > 1) 12 | while True: 13 | try: 14 | challenge = gnuk.cmd_get_challenge().tostring() 15 | except Exception as e: 16 | print(count) 17 | raise e 18 | print(hexlify(challenge)) 19 | count = count + 1 20 | if not looping: 21 | break 22 | -------------------------------------------------------------------------------- /tool/gnuk_remove_keys_libusb.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | 3 | """ 4 | gnuk_remove_keys_libusb.py - a tool to remove keys in Gnuk Token 5 | 6 | Copyright (C) 2012, 2018 Free Software Initiative of Japan 7 | Author: NIIBE Yutaka 8 | 9 | This file is a part of Gnuk, a GnuPG USB Token implementation. 10 | 11 | Gnuk is free software: you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 17 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 18 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 19 | License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see . 23 | """ 24 | 25 | import sys, os 26 | 27 | from gnuk_token import gnuk_devices, gnuk_token, parse_kdf_data 28 | from kdf_calc import kdf_calc 29 | 30 | # Assume only single CCID device is attached to computer and it's Gnuk Token 31 | 32 | DEFAULT_PW3 = "12345678" 33 | BY_ADMIN = 3 34 | 35 | def main(passwd): 36 | gnuk = None 37 | for (dev, config, intf) in gnuk_devices(): 38 | try: 39 | gnuk = gnuk_token(dev, config, intf) 40 | print("Device: %s" % dev.filename) 41 | print("Configuration: %d" % config.value) 42 | print("Interface: %d" % intf.interfaceNumber) 43 | break 44 | except: 45 | pass 46 | if not gnuk: 47 | raise ValueError("No ICC present") 48 | if gnuk.icc_get_status() == 2: 49 | raise ValueError("No ICC present") 50 | elif gnuk.icc_get_status() == 1: 51 | gnuk.icc_power_on() 52 | gnuk.cmd_select_openpgp() 53 | # Compute passwd data 54 | kdf_data = gnuk.cmd_get_data(0x00, 0xf9).tostring() 55 | if kdf_data == b"": 56 | passwd_data = passwd.encode('UTF-8') 57 | else: 58 | algo, subalgo, iters, salt_user, salt_reset, salt_admin, \ 59 | hash_user, hash_admin = parse_kdf_data(kdf_data) 60 | if salt_admin: 61 | salt = salt_admin 62 | else: 63 | salt = salt_user 64 | passwd_data = kdf_calc(passwd, salt, iters) 65 | # And authenticate with the passwd data 66 | gnuk.cmd_verify(BY_ADMIN, passwd_data) 67 | # Do remove keys and related data objects 68 | gnuk.cmd_put_data_remove(0x00, 0xc7) # FP_SIG 69 | gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_SIG 70 | gnuk.cmd_put_data_key_import_remove(1) 71 | gnuk.cmd_put_data_remove(0x00, 0xc8) # FP_DEC 72 | gnuk.cmd_put_data_remove(0x00, 0xcf) # KGTIME_DEC 73 | gnuk.cmd_put_data_key_import_remove(2) 74 | gnuk.cmd_put_data_remove(0x00, 0xc9) # FP_AUT 75 | gnuk.cmd_put_data_remove(0x00, 0xd0) # KGTIME_AUT 76 | gnuk.cmd_put_data_key_import_remove(3) 77 | gnuk.icc_power_off() 78 | return 0 79 | 80 | 81 | if __name__ == '__main__': 82 | passwd = DEFAULT_PW3 83 | if len(sys.argv) > 1 and sys.argv[1] == '-p': 84 | from getpass import getpass 85 | passwd = getpass("Admin password: ") 86 | sys.argv.pop(1) 87 | main(passwd) 88 | -------------------------------------------------------------------------------- /tool/intel_hex.py: -------------------------------------------------------------------------------- 1 | """ 2 | intel_hex.py - Intel Hex file reader. 3 | 4 | Copyright (C) 2010 Free Software Initiative of Japan 5 | Author: NIIBE Yutaka 6 | 7 | You can use/distribute/modify/etc. this for any purpose. 8 | """ 9 | 10 | import binascii 11 | 12 | class intel_hex(object): 13 | def __init__(self, filename): 14 | self.start_address = 0 15 | self.address = 0 16 | self.memory = {} 17 | self.lineno = 0 18 | file = open(filename, 'r') 19 | for line in file: 20 | self.lineno += 1 21 | if self.parse_line(line): 22 | break 23 | file.close() 24 | self.pack() 25 | 26 | def pack(self): 27 | memory = {} 28 | prev_addr = 0 29 | prev_data_len = 0 30 | for addr in sorted(self.memory.keys()): 31 | data = self.memory[addr] 32 | if addr == prev_addr + prev_data_len: 33 | memory[prev_addr] += data 34 | prev_data_len += len(data) 35 | else: 36 | memory[addr] = data 37 | prev_addr = addr 38 | prev_data_len = len(data) 39 | self.memory = memory 40 | 41 | def calc_checksum(self, byte_count, offset, type_code, data): 42 | s = byte_count 43 | s += (offset >> 8) 44 | s += offset & 0xff 45 | s += type_code 46 | for d in data: 47 | s += (ord(d) & 0xff) 48 | s &= 0xff 49 | if s != 0: 50 | s = 256 - s 51 | return s 52 | 53 | def add_data(self, count, offset, data): 54 | address = self.address + offset 55 | try: 56 | self.memory[address] 57 | except: 58 | pass 59 | else: 60 | raise ValueError("data overwritten (%d)" % self.lineno) 61 | self.memory[address] = data 62 | 63 | def parse_line(self, line): 64 | if line[0] != ':': 65 | raise ValueError("invalid line (%d)" % self.lineno) 66 | count = int(line[1:3], 16) 67 | offset = int(line[3:7], 16) 68 | type_code = int(line[7:9], 16) 69 | data = binascii.unhexlify(line[9:(9+count*2)]) 70 | check_sum = int(line[(9+count*2):], 16) 71 | if check_sum != self.calc_checksum(count, offset, type_code, data): 72 | raise ValueError("invalid checksum (%d)" % self.lineno) 73 | if type_code == 0x00: 74 | self.add_data(count, offset, data) 75 | return 0 76 | elif type_code == 0x01: 77 | return 1 78 | elif type_code == 0x04: 79 | if count != 2: 80 | raise ValueError("invalid count (%d): (%d) Expected 2" \ 81 | % (self.lineno, count)) 82 | self.address = ((ord(data[0])&0xff)<<24) + ((ord(data[1])&0xff)<<16) 83 | return 0 84 | elif type_code == 0x05: 85 | if count != 4: 86 | raise ValueError("invalid count (%d): (%d) Expected 4" \ 87 | % (self.lineno, count)) 88 | self.start_address \ 89 | = ((ord(data[0])&0xff)<<24) + ((ord(data[1])&0xff)<<16) \ 90 | + ((ord(data[2])&0xff)<<8) + ((ord(data[3])&0xff)) 91 | return 0 92 | else: 93 | raise ValueError("invalid type code (%d): (%d)" \ 94 | % (self.lineno, type_code)) 95 | -------------------------------------------------------------------------------- /tool/kdf_calc.py: -------------------------------------------------------------------------------- 1 | """ 2 | kdf_calc.py - a library for calculating hash by KDF 3 | 4 | Copyright (C) 2018 Free Software Initiative of Japan 5 | Author: NIIBE Yutaka 6 | 7 | This file is a part of Gnuk, a GnuPG USB Token implementation. 8 | 9 | Gnuk is free software: you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 | License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | """ 22 | 23 | from cffi import FFI 24 | 25 | DEF_gcry_kdf_derive=""" 26 | typedef unsigned int gpg_error_t; 27 | gpg_error_t gcry_kdf_derive (const void *passphrase, size_t passphraselen, 28 | int algo, int subalgo, const void *salt, 29 | size_t saltlen, unsigned long iterations, 30 | size_t keysize, void *keybuffer); 31 | """ 32 | 33 | GCRY_KDF_ITERSALTED_S2K = 19 34 | GCRY_MD_SHA256 = 8 35 | 36 | def kdf_calc(pw_string, salt_byte, iterations): 37 | ffi = FFI() 38 | ffi.cdef(DEF_gcry_kdf_derive) 39 | libgcrypt = ffi.dlopen("libgcrypt.so.20") 40 | if isinstance(pw_string, str): 41 | pw_byte = pw_string.encode('UTF-8') 42 | else: 43 | pw_byte = pw_string 44 | pw=ffi.new("char []", pw_byte) 45 | salt = ffi.new("char []", salt_byte) 46 | kb = ffi.new("char []", 32) 47 | r = libgcrypt.gcry_kdf_derive(pw, len(pw_string), GCRY_KDF_ITERSALTED_S2K, 48 | GCRY_MD_SHA256, salt, 8, iterations, 32, kb) 49 | if r != 0: 50 | raise ValueError("libgcrypt error", r) 51 | return ffi.unpack(kb, 32) 52 | -------------------------------------------------------------------------------- /tool/openocd-script/lock.tcl: -------------------------------------------------------------------------------- 1 | init 2 | reset 3 | halt 4 | stm32x lock 0 5 | reset 6 | shutdown 7 | -------------------------------------------------------------------------------- /tool/openocd-script/options_read.tcl: -------------------------------------------------------------------------------- 1 | init 2 | reset 3 | halt 4 | stm32f1x options_read 0 5 | shutdown 6 | -------------------------------------------------------------------------------- /tool/openocd-script/unlock.tcl: -------------------------------------------------------------------------------- 1 | init 2 | reset 3 | halt 4 | stm32f1x unlock 0 5 | reset 6 | shutdown 7 | -------------------------------------------------------------------------------- /tool/openocd-script/write.tcl: -------------------------------------------------------------------------------- 1 | init 2 | reset 3 | halt 4 | flash write_image erase gnuk.elf 5 | shutdown 6 | -------------------------------------------------------------------------------- /tool/rsa.py: -------------------------------------------------------------------------------- 1 | from binascii import hexlify, unhexlify 2 | from os import urandom 3 | 4 | def read_key_from_file(file): 5 | f = open(file) 6 | n_str = f.readline()[:-1] 7 | e_str = f.readline()[:-1] 8 | p_str = f.readline()[:-1] 9 | q_str = f.readline()[:-1] 10 | f.close() 11 | e = int(e_str, 16) 12 | p = int(p_str, 16) 13 | q = int(q_str, 16) 14 | n = int(n_str, 16) 15 | if n != p * q: 16 | raise ValueError("wrong key", p, q, n) 17 | return (unhexlify(n_str), unhexlify(e_str), unhexlify(p_str), unhexlify(q_str), e, p, q, n) 18 | 19 | # egcd and modinv are from wikibooks 20 | # https://en.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Extended_Euclidean_algorithm 21 | 22 | def egcd(a, b): 23 | if a == 0: 24 | return (b, 0, 1) 25 | else: 26 | g, y, x = egcd(b % a, a) 27 | return (g, x - (b // a) * y, y) 28 | 29 | def modinv(a, m): 30 | g, x, y = egcd(a, m) 31 | if g != 1: 32 | raise Exception('modular inverse does not exist') 33 | else: 34 | return x % m 35 | 36 | def pkcs1_pad_for_sign(digestinfo): 37 | byte_repr = b'\x00' + b'\x01' \ 38 | + bytes.ljust(b'', 256 - 19 - 32 - 3, b'\xff') \ 39 | + b'\x00' + digestinfo 40 | return int(hexlify(byte_repr), 16) 41 | 42 | def compute_signature(key, digestinfo): 43 | e = key[4] 44 | p = key[5] 45 | q = key[6] 46 | n = key[7] 47 | p1 = p - 1 48 | q1 = q - 1 49 | h = p1 * q1 50 | d = modinv(e, h) 51 | dp = d % p1 52 | dq = d % q1 53 | qp = modinv(q, p) 54 | 55 | input = pkcs1_pad_for_sign(digestinfo) 56 | t1 = pow(input, dp, p) 57 | t2 = pow(input, dq, q) 58 | t = ((t1 - t2) * qp) % p 59 | sig = t2 + t * q 60 | return sig 61 | 62 | def integer_to_bytes_256(i): 63 | s = hex(i)[2:] 64 | s = s.rstrip('L') 65 | if len(s) & 1: 66 | s = '0' + s 67 | return bytes.rjust(unhexlify(s), 256, b'\x00') 68 | 69 | def get_raw_pubkey(key): 70 | return key[0] 71 | -------------------------------------------------------------------------------- /tool/rsa_example.key: -------------------------------------------------------------------------------- 1 | 9cf7192b51a574d1ad3ccb08ba09b87f228573893eee355529ff243e90fd4b86f79a82097cc7922c0485bed1616b1656a9b0b19ef78ea8ec34c384019adc5d5bf4db2d2a0a2d9cf14277bdcb7056f48b81214e3f7f7742231e29673966f9b1106862112cc798dba8d4a138bb5abfc6d4c12d53a5d39b2f783da916da20852ee139bbafda61d429caf2a4f30847ce7e7ae32ab4061e27dd9e4d00d60910249db8d8559dd85f7ca59659ef400c8f6318700f4e97f0c6f4165de80641490433c88da8682befe68eb311f54af2b07d97ac74edb5399cf054764211694fbb8d1d333f3269f235abe025067f811ff83a2224826219b309ea3e6c968f42b3e52f245dc9 2 | 010001 3 | b5ab7b159220b18e363258f61ebde08bae83d6ce2dbfe4adc143628c527887acde9de09bf9b49f438019004d71855f30c2d69b6c29bb9882ab641b3387409fe9199464a7faa4b5230c56d9e17cd9ed074bc00180ebed62bae3af28e6ff2ac2654ad968834c5d5c88f8d9d3cc5e167b10453b049d4e454a5761fb0ac717185907 4 | dd2fffa9814296156a6926cd17b65564187e424dcadce9b032246ad7e46448bb0f9e0ff3c64f987424b1a40bc694e2e9ac4fb1930d163582d7acf20653a1c44b97846c1c5fd8a7b19bb225fb39c30e25410483deaf8c2538d222b748c4d8103b11cec04f666a5c0dbcbf5d5f625f158f65746c3fafe6418145f7cffa5fadeeaf 5 | -------------------------------------------------------------------------------- /tool/sexp.py: -------------------------------------------------------------------------------- 1 | # SEXP (S-expressions) Basic Transport Support 2 | # 3 | # See: http://people.csail.mit.edu/rivest/sexp.html 4 | # 5 | """ 6 | sexp.py - a library for SEXP 7 | 8 | Copyright (C) 2013 Free Software Initiative of Japan 9 | Author: NIIBE Yutaka 10 | 11 | This file is a part of Gnuk, a GnuPG USB Token implementation. 12 | 13 | Gnuk is free software: you can redistribute it and/or modify it 14 | under the terms of the GNU General Public License as published by 15 | the Free Software Foundation, either version 3 of the License, or 16 | (at your option) any later version. 17 | 18 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 19 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 20 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 21 | License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program. If not, see . 25 | """ 26 | 27 | import re 28 | 29 | WHITESPACE='[ \n\t\v\r\f]+' 30 | re_ws = re.compile(WHITESPACE) 31 | DIGITS='[0-9]+' 32 | re_digit = re.compile(DIGITS) 33 | 34 | def skip_whitespace(string, pos): 35 | m = re_ws.match(string, pos) 36 | if m: 37 | return m.start() 38 | else: 39 | return pos 40 | 41 | def sexp_match(string, ch, pos): 42 | pos = skip_whitespace(string,pos) 43 | if string[pos] == ch: 44 | return pos+1 45 | else: 46 | raise ValueError("expect '%s'" % ch) 47 | 48 | def sexp_parse_simple_string(string, pos): 49 | pos = skip_whitespace(string,pos) 50 | m = re_digit.match(string, pos) 51 | if m: 52 | length = int(string[m.start():m.end()],10) 53 | pos = sexp_match(string, ':', m.end()) 54 | return (string[pos:pos+length], pos+length) 55 | else: 56 | raise ValueError('expect digit') 57 | 58 | def sexp_parse_list(string,pos): 59 | l = [] 60 | while True: 61 | pos = skip_whitespace(string,pos) 62 | if string[pos] == ')': 63 | return (l, pos) 64 | else: 65 | (sexp, pos) = sexp_parse(string,pos) 66 | l.append(sexp) 67 | 68 | def sexp_parse(string, pos=0): 69 | pos = skip_whitespace(string,pos) 70 | if string[pos] == '(': 71 | (l, pos) = sexp_parse_list(string,pos+1) 72 | pos = sexp_match(string, ')', pos) 73 | return (l, pos) 74 | elif string[pos] == '[': 75 | pos = skip_whitespace(string,pos) 76 | (dsp, pos) = sexp_parse_simple_string(string,pos+1) 77 | pos = sexp_match(string, ']', pos) 78 | pos = skip_whitespace(string,pos) 79 | (ss, pos) = sexp_parse_simple_string(string, pos) 80 | return ((dsp, ss), pos) 81 | else: 82 | return sexp_parse_simple_string(string, pos) 83 | 84 | def sexp(string): 85 | (sexp, pos) = sexp_parse(string) 86 | return sexp 87 | -------------------------------------------------------------------------------- /tool/usb_strings.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | 3 | """ 4 | usb_strings.py - a tool to dump USB string 5 | 6 | Copyright (C) 2012, 2015, 2017 Free Software Initiative of Japan 7 | Author: NIIBE Yutaka 8 | 9 | This file is a part of Gnuk, a GnuPG USB Token implementation. 10 | 11 | Gnuk is free software: you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | Gnuk is distributed in the hope that it will be useful, but WITHOUT 17 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 18 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 19 | License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see . 23 | """ 24 | 25 | from gnuk_token import * 26 | import usb, sys 27 | 28 | field = ['', 'Vendor', 'Product', 'Serial', 'Revision', 'Config', 'Sys', 'Board'] 29 | 30 | def main(n): 31 | for dev in gnuk_devices_by_vidpid(): 32 | handle = dev.open() 33 | try: 34 | for i in range(1,n): 35 | s = handle.getString(i, 512) 36 | print("%10s: %s" % (field[i], s.decode('UTF-8'))) 37 | except: 38 | pass 39 | del dev 40 | 41 | if __name__ == '__main__': 42 | if len(sys.argv) > 1: 43 | n = int(sys.argv[1]) 44 | else: 45 | n = 8 # Gnuk has eight strings 46 | main(n) 47 | --------------------------------------------------------------------------------