Git Product home page Git Product logo

pico-openpgp's Introduction

Pico OpenPGP

This project aims at transforming your Raspberry Pico into a Smart Card with an OpenPGP applet integrated. The Pico works as a reader with an embedded OpenPGP card, like a USB card.

OpenPGP cards are used to manage PGP keys and do cryptographic operations, such as keypair generation, signing and asymmetric deciphering. Pico OpenPGP follows the OpenPGP 3.4.1 specifications, available at GnuPG.

Features

Pico OpenPGP has implemented the following features:

  • Key generation and encrypted storage.
  • RSA key generation from 1024 to 4096 bits.
  • ECDSA key generation from 192 to 521 bits.
  • ECC curves secp256r1, secp384r1, secp521r1, brainpoolP256r1, brainpoolP384r1, brainpoolP512r1, secp256k1.
  • SHA1, SHA224, SHA256, SHA384, SHA512 digests.
  • RSA-PKCS and raw RSA signature.
  • ECDSA raw and hash signature.
  • ECDH key derivation.
  • PIN authorization.
  • PKCS11 compliant interface.
  • HRNG (hardware random number generator).
  • Device Encryption Key (DEK).
  • USB/CCID support with OpenSC, openssl, etc.
  • Extended APDU support.
  • Lifecycle card (termination and activation).
  • Press-to-confirm button.
  • User Interaction Flag for enabling/disabling press-to-confirm button.
  • Key Derivation Function (KDF) for PIN.
  • Manage Security Environment (MSE).
  • DEK for internal safe storage.
  • AES key generation.
  • AES ciphering and deciphering.
  • Cardholder certificates support.

All these features are compliant with the specification. Therefore, if you detect some behaviour that is not expected or it does not follow the rules of specs, please open an issue.

AES support

There is no known software that supports AES with OpenPGP. Nevertheless, it can be used with customized PKCS11 modules or interfacing with raw APDU packets.

During asymmetric key generation for DEC key, Pico OpenPGP also generates a 32 bits symmetric key for AES operations.

OpenPGP card 3.4 specifications describe the procedure to perform ciphering (encryption and decryption) with AES via PSO:ENCIPHER and PSO:DECIPHER. Both commands are supported by Pico OpenPGP.

About Gnuk

This project was inspired by Gnuk, a same project but focused on STM32 processor family. Despite the initial idea was to port Gnuk to the Raspberry Pico family, the underlaying architecture is widely different (although boh run on ARM). For instance, the Pico has two ARM cores, with an appropiate SDK able to leverage them. Also, Pico has an internal flash storage, which is farly larger compared to STM32 ROM storage. Finally, the Pico has a complete USB interface based on TinyUSB, which difficults to port Gnuk. These are only few examples of the difficulties of porting Gnuk to the Raspberry Pico.

As a consequence, Pico OpenPGP is designed from zero. Well, not strictly from zero, as it borrows some of the cryptographic operations implemented with MbedTLS library.

Whilst Gnuk is OpenPGP 2.0 with small set of enhancements, Pico OpenPGP aims at being OpenPGP 3.4 compliant, with new features (not present in Gnuk), such as Manage Security Environment (MSE) or UIF.

Security considerations

All secret keys (asymmetric and symmetric) are stored encrypted in the flash memory of the Raspberry Pico. DEK is used as a 256 bit AES key to protect private and secret keys. Keys are never stored in RAM except for signature and decryption operations and only during the process. All keys (including DEK) are loaded and cleared every time to avoid potential security flaws.

At the same time, DEK is encrypted with doubled salted and hashed PIN. Also, the PIN is hashed in memory during the session. Hence, PIN is never stored in plain text neither in flash nor in memory. Note that PIN is conveyed from the host to the Pico in plain text if no secure channel is provided.

If the Pico is stolen the contents of private and secret keys cannot be read without the PIN, even if the flash memory is dumped.

Download

Please, go to the Release page) and download the UF2 file for your board.

Please, go to the Release page and download the UF2 file for your board.

Note that UF2 files are shiped with a dummy VID/PID to avoid license issues (FEFF:FCFD). If you are planning to use it with OpenSC or similar, you should modify Info.plist of CCID driver to add these VID/PID or use the Pico Patcher tool.

Alternatively you can use the legacy VID/PID patcher as follows: ./patch_vidpid.sh VID:PID input_hsm_file.uf2 output_hsm_file.uf2

You can use whatever VID/PID (i.e., 234b:0000 from FISJ), but remember that you are not authorized to distribute the binary with a VID/PID that you do not own.

Note that the pure-browser option Pico Patcher tool is the most recommended.

Build

Before building, ensure you have installed the toolchain for the Pico and the Pico SDK is properly located in your drive.

git clone https://github.com/polhenarejos/pico-openpgp
cd pico-openpgp
mkdir build
cd build
PICO_SDK_PATH=/path/to/pico-sdk cmake .. -DPICO_BOARD=board_type -DUSB_VID=0x1234 -DUSB_PID=0x5678
make

Note that PICO_BOARD, USB_VID and USB_PID are optional. If not provided, pico board and VID/PID FEFF:FCFD will be used.

After make ends, the binary file pico_openpgp.uf2 will be generated. Put your pico board into loading mode, by pushing BOOTSEL button while pluging on, and copy the UF2 to the new fresh usb mass storage Pico device. Once copied, the pico mass storage will be disconnected automatically and the pico board will reset with the new firmware. A blinking led will indicate the device is ready to work.

Operation time

Keypair generation

Generating EC keys is almost instant. RSA keypair generation takes some time, specially for 3072 and 4096 bits.

Keypair generation

Generating EC keys is almost instant. RSA keypair generation takes some time, specially for 3072 and 4096 bits.

RSA key length (bits) Average time (seconds)
1024 16
2048 124
3072 600
4096 ~1000

Signature and decrypt

RSA key length (bits) Average time (seconds)
1024 1
2048 3
3072 7
4096 15

Led blink

Pico OpenPGP uses the led to indicate the current status. Four states are available:

Press to confirm

The Led is almost on all the time. It goes off for 100 miliseconds every second.

Press to confirm

Idle mode

In idle mode, the Pico OpenPGP goes to sleep. It waits for a command and it is awaken by the driver. The Led is almost off all the time. It goes on for 500 milliseconds every second.

Idle mode

Active mode

In active mode, the Pico OpenPGP is awaken and ready to receive a command. It blinks four times in a second.

Active

Processing

While processing, the Pico OpenPGP is busy and cannot receive additional commands until the current is processed. In this state, the Led blinks 20 times in a second.

Processing

Driver

Pico OpenPGP uses the openpgp driver provided by OpenSC. This driver utilizes the standardized PKCS#11 interface to communicate with the user and it can be used with many engines that accept PKCS#11 interface, such as OpenSSL, P11 library or pkcs11-tool.

It also accepts the use of GnuPG programs (gpg and gpg2) to manipulate the card. For instance, it can be used with the gpg --edit-card --expert interface to change the cryptographic keys, generate new keypairs or simply set the cardholder name.

Pico OpenPGP relies on PKCS#15 structure to store and manipulate the internal files (PINs, private keys, certificates, etc.) and directories. Therefore, it accepts the commands from pkcs15-tool. For instance, pkcs15-tool -D will list all elements stored in the Pico OpenPGP.

The way to communicate is exactly the same as with other cards, such as OpenPGP or similar.

Important

OpenSC relies on PCSC driver, which reads a list (Info.plist) that contains a pair of VID/PID of supported readers. In order to be detectable, you must patch the UF2 binary (if you just downloaded from the Release section) or configure the project with the proper VID/PID with USB_VID and USB_PID parameters in CMake (see Build section). Note that you cannot distribute the patched/compiled binary if you do not own the VID/PID or have an explicit authorization.

Credits

Pico OpenPGP uses the following libraries or portion of code:

  • MbedTLS for cryptographic operations.
  • TinyUSB for low level USB procedures.

pico-openpgp's People

Contributors

imkuang avatar polhenarejos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

pico-openpgp's Issues

keytocard fails

I haven't dug into the details yet, but maybe a re-occurence of #3? I had keytocard working in the past, but updated to latest firmware and I'm now unable to use keytocard. I'm trying to load 4k key size with keytocard because generation of 4k keys on the card takes long and gets a timeout.

keytocard fails with:
gpg: KEYTOCARD failed: Invalid value

Tried on Windows 11, Linux Mint 21, and Raspbian

patch_vid not working

Hello,
The script patch_vid seems not working (the regex is wrong). File is not modified. I had to use a hexeditor and modify the file by hand.
Regards,

gpg keytocard fails

Attempting to load keys onto the card with gpg keytocard fails with error "gpg: KEYTOCARD failed: Invalid value".
With some debugging, I can see that cmd_import_data is being called, but the data in the apdu includes multi-byte length fields not accounted for in the parsing function.

I'm using http://g10code.com/docs/openpgp-card-3.0.pdf for reference. Section 4.4.4 states DO length fields can be variable byte length:
single byte for values from 0-127 (x00 to x7F), and for 128-255 two bytes are used (x81 followed by single byte length), and for values > 255 three bytes are used (x82 followed by two byte length).

I can work on adding support for variable byte length fields, or if you prefer to keep the development I'll respect that.

APDU (with test signature priv key)
00 // CLA
DB // INS
3F FF //P1P2
00 01 1A //LC = 282
4D /DO, start of *data
82 01 16 //DO len = 278
B6 00 //key select = sign key
7F 48 // key template marker
08 // len of tags
91 04 // e len = 4
92 81 80 // p len = 128
93 81 80 // q len = 128
5F 48 // key concat marker
82 01 04 // concat len = 260
00 01 00 01 // e
D1 A9 69 C6 43 E4 5B CE 34 D6 B7 7D C9 4F 3C 9D 2C 9E B7 8D C7 5D C8 A3 49 9F A8 6F A7 55 E9 34 FD 5B CD 5D E6 36 A7 02 72 9D C2 3A 62 DC E4 E5 68 FB 9A 6F 25 4D 4B 69 4A BA 02 E8 F7 32 1B 1A 0A 94 AA 67 A3 19 E3 47 6B 4C 68 A8 32 86 26 96 24 34 95 1E 28 02 8D 97 95 6D 50 68 FA 3F D1 D2 37 DA 8D 89 E1 36 8F 27 4D 88 94 CB 79 62 9D 4A 8B C5 CD DD 50 D0 99 3F 59 60 31 CF 74 91 88 63 // p
F5 C5 5A FC 2F 6C E6 B3 41 5A 7A 1F 31 B2 72 5B 1E EE 5F E1 72 39 A1 F1 C1 04 83 EC A1 27 5F F0 0E 31 23 DE BE 47 9A 3C D0 2B 01 F4 92 C1 8B FB A8 86 1A 57 2F 73 0B A6 E0 90 CB E4 DB 33 1E 02 A0 60 86 4D 48 89 AB 97 21 7D 28 DE C7 EA B8 F4 42 3B D1 8A 85 BA A3 FE 85 46 CD CC DD C7 00 27 D9 6A A1 EC FA 52 67 9C 5A 0D 12 E1 5C 3D FE 42 B7 E4 D4 55 E2 C5 C4 A9 D0 E6 54 3A E0 04 72 FD // q

Cannot execute gnuk tests

          > Is it a VID/PID discovery problem?

Most likely. I reverse-engineered the not so well documented dependencies for the Gnuk test repository and initiated the contained tests. They should just use APDUs according to the OpenPGP spec. But I could not get so far.

The conftest.py fixture prepares the environment for each test and it failed somewhere around get_ccid_device().

I deleted the VM where I tested but it was related to [card_reader.py](https://salsa.debian.org/gnuk-team/gnuk/gnuk/-
/blob/master/tests/card_reader.py#L322) and usb.core. The iterator was empty.

I think it is not just the VID:PID (if I remember correclty, I even tested a few) but some USB/CCID quirks are done for specific card reader models.

Originally posted by @rrottmann in polhenarejos/pico-hsm#16 (comment)

Only the first signature action after power-on can be successfully executed

As the title describes, in my use, I found that if I don't re-plug the USB, only the first signature is successful, and when I perform the signature again, I will encounter the following bad PIN fail (and won't ask me to re-enter the PIN code)

ming@work:~/download$ gpg -s test.txt
File 'test.txt.gpg' exists. Overwrite? (y/N) y
ming@work:~/download$ gpg -s test.txt
File 'test.txt.gpg' exists. Overwrite? (y/N) y
gpg: signing failed: Bad PIN
gpg: signing failed: Bad PIN
ming@work:~/download$ 

After several tests, I found that if the admin password was ever entered (e.g. by executing keytocard cmd or using the admin password to unblock pin), everything works fine, but the problem still occurs after re-plugging the USB (re-powering it up).

I've analyzed and fixed the issue myself, later I'll create a pull request, this issue is created as a reminder and record.
PS: I use translation software, forgive my poor English!

Device Manger reports "Invalid Configuration Descriptor"

Hello, I believe the Pico Patcher is not working, the device is showing up as "Invalid Configuration Descriptor" and none of my software can detect it (GPG, kleopatra and opensc). As you see below in the event viewer logs it mentions "00FF2000" the default descriptor.

image

Device USB\VID_0000&PID_0006\5&2d531919&0&1 was configured.

Driver Name: usb.inf
Class Guid: {36fc9e60-c465-11cf-8056-444553540000}
Driver Date: 06/21/2006
Driver Version: 10.0.19041.4355
Driver Provider: Microsoft
Driver Section: BADDEVICE.Dev.NT
Driver Rank: 0xFF0000
Matching Device Id: USB\CONFIGURATION_DESCRIPTOR_VALIDATION_FAILURE
Outranked Drivers: usb.inf:USB\CONFIGURATION_DESCRIPTOR_VALIDATION_FAILURE:**00FF2000**
Device Updated: false
Parent Device: USB\ROOT_HUB30\4&30961835&0&0

Patching VID/PID failed

Since my build attempt failed (see other issue) I downloaded a prebuilt binary for a "pico". I then used https://www.picokeys.com/ to patch the firmware with some other VID/PID but when the board is connected the USB descriptor still identifies it as 0xFEFF:0xFCFD. The result is the same if I use patch_vidpid.sh. I guess needless to say but gpg does not recognize the key with the patched firmware.

I added a ZIP-file containing the original binary and the response

pico_openpgp_pico-2.0.zip

ykman compatible?

Hello, Just tested and patched my pico with this firmware and yubiko 4/5 vid/pid. I see this:

hkfuertes@trantor:~$ ykman list
WARNING: Failed opening device
YubiKey [OTP+FIDO+CCID] <access denied>

I have tested with an original Yubikey 5 Fido and ykman is properly configured (udev). Does this means that this firmware is not compatible with Yubico Software? if so, is there any GUI software to add my certificates (piv)? I saw the opensc, and I believe it worked for me, but I would love to use a GUI software (windows/linux)

Thank you!

gpg --card-edit -> admin -> factory-reset blocks CHV1, CHV2, CHV3 PIN retry counter

When doing a factory-reset using gpg --card-edit -> admin -> factory-reset all PIN counters get blocked. They were 3 3 3 before.
Is there an APDU custom-command needed to reset the variables?

Reset of course works with pico_nuke_waveshare_rp2040_zero-1.0.uf2 but this requires somewhat "knowledge" about flashing the pico and the need to nuke the flash.

The gpg factory-reset uses upstream documented process of the OpenPGP Card specification and would be doable by a less experienced/regular user.

CMake fails on pico_add_library

Hi there
CMake stops with this fault:

CMake Error at pico-keys-sdk/pico_keys_sdk_import.cmake:270 (pico_add_library):
Unknown CMake command "pico_add_library".
Call Stack (most recent call first):
CMakeLists.txt:48 (include)

I checked out the repo with --recursive since it seemed to use submodules.

My RP2040 development environment seem to work for other examples although it might have be set up a year ago or so.

Uncorrelated; since the build failed I downloaded a prebuilt binary for a "pico". I then used https://www.picokeys.com to patch the firmware with some other VID/PID but when the board is connected the USB descriptor still identifies it as 0xFEFF:0xFCFD. The result is the same if I use patch_vidpid.sh. I guess needless to say but gpg does not recognize the key with the patched firmware.

card not found after firmware loaded

waveshare zero device loads firmware with no errors. device plugs in and is not recognized by GPG

dmesg and debug:

[ 2133.470961] usb 1-5: Product: Pico Key
[ 2133.470966] usb 1-5: Manufacturer: Pol Henarejos
[ 2133.470970] usb 1-5: SerialNumber: E6625887D34F5237
[ 2137.594712] usb 1-5: USB disconnect, device number 16
[ 2138.051644] usb 1-5: new full-speed USB device number 17 using xhci_hcd
[ 2138.372468] usb 1-5: New USB device found, idVendor=1050, idProduct=0116, bcdDevice= 4.00
[ 2138.372488] usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2138.372495] usb 1-5: Product: Pico Key
[ 2138.372500] usb 1-5: Manufacturer: Pol Henarejos
[ 2138.372506] usb 1-5: SerialNumber: E6625887D34F5237
[cicero@zed ~]$ sudo gpg --card-edit

gpg: selecting card failed: No such device
gpg: OpenPGP card not available: No such device

gpg (GnuPG) 2.4.5

version 1.6 causes hangs in pcsc, opensc, gpg

Working with both 1.4 and 1.6:
lsusb shows device: Bus 008 Device 037: ID 234b:0000 Free Software Initiative of Japan Gnuk Token
pcscd logs device: 00000104 [140218338324992] readerfactory.c:1387:RFCleanupReaders() Stopping reader: Free Software Initiative of Japan Gnuk [Pico HSM Interface] (E6609103C3395D24) 00 00
opensc-tool -l lists device:

Detected readers (pcsc)

Nr. Card Features Name
0 Yes Free Software Initiative of Japan Gnuk [Pico HSM Interface] (E6609103C3395D24) 00 00
opensc-tool -a lists atr bytes

Works in 1.4 but hangs in 1.6
opensc-tool --serial
opensc-tool -l -v
opensc-tool -n
gpg --card-edit

versions:
pcscd: pcsc-lite version 1.9.5
opensc-tool: 0.22.0-1ubuntu2
gpg: 0.22.0-1ubuntu2

Problems with the latest firmware

I've tried to install the 1.10 1.8 1.6 and 1.4 versions of firmware. After I install the firmware above 1.6(include 1.6), the device manager showed me with a card reader and no card. But when I installed version 1.4, I can see a card reader and card. I can create key on this card but I can't move existed key to the card. Hope newer version of firmware will fix that.

Version 1.12 on Waveshare RP2040-One is unresponsive

So I flashed it, and it does get recognized, somewhat:

[277951.890078] usb 5-1.2: new full-speed USB device number 74 using xhci_hcd
[277952.028842] usb 5-1.2: config 1 interface 0 altsetting 0 endpoint 0x82 has an invalid bInterval 0, changing to 10
[277952.040403] usb 5-1.2: New USB device found, idVendor=feff, idProduct=fcfd, bcdDevice= 5.00
[277952.040410] usb 5-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[277952.040413] usb 5-1.2: Product: Pico Key
[277952.040414] usb 5-1.2: Manufacturer: Pol Henarejos
[277952.040416] usb 5-1.2: SerialNumber: DE6270431F752A27

However, it's not responding as an OpenPGP smart card, or indeed, a smart card of any kind:

$ opgpcard status
Error: No cards found
$ opensc-explorer
OpenSC Explorer version 0.23.0
No smart card readers found.

The sole (red) led on the board is flashing, but that's about all I'm getting from it.

There's something interesting happening as it's getting flashed:

[278310.013845] device offline error, dev sda, sector 260 op 0x1:(WRITE) flags 0x100000 phys_seg 1 prio class 2
[278310.013851] Buffer I/O error on dev sda1, logical block 259, lost async page write
[278310.022013] FAT-fs (sda1): unable to read boot sector to mark fs as dirty

I.e. it somehow goes to reboot before the PC thinks the write is completed, which strikes me as odd.

Any clues?

using pico-opengpg in windows

Hi
I couldnt find a way to work with the device on windows
tried gpg, gpg4win
smartcard is not recognized
is it possible?

thanks
liran

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.