Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d41a488eda | ||
|
|
375a18ebac | ||
|
|
20216ac4ba | ||
|
|
d27d8b0c5b | ||
|
|
a619527482 | ||
|
|
85ff92c4de | ||
|
|
b1121718db | ||
|
|
2905dcc8c0 | ||
|
|
c9855f7214 | ||
|
|
853b8f29a2 | ||
|
|
d5378ffa41 | ||
|
|
4400eba974 | ||
|
|
0cc656c6c0 | ||
|
|
c9b32ab5d0 | ||
|
|
f9ffd39661 | ||
|
|
bfc12d6856 | ||
|
|
11874b52de | ||
|
|
b4e928588e | ||
|
|
33a2222cd8 | ||
|
|
923e05a36c | ||
|
|
b5cc4d6fd7 | ||
|
|
25291f978f | ||
|
|
ad66170379 | ||
|
|
86e38419ac | ||
|
|
1a5e6a7edc | ||
|
|
7cf166d615 | ||
|
|
413c3e0208 | ||
|
|
7410498df1 | ||
|
|
7aee18110e | ||
|
|
7aca7b323a | ||
|
|
4651a0e224 | ||
|
|
d018e3b9b9 | ||
|
|
1c272842a7 | ||
|
|
0141e0ab4e | ||
|
|
e7d8695394 | ||
|
|
6876edea5a | ||
|
|
2e655d6341 | ||
|
|
2f4cca19c4 | ||
|
|
5eb74d8ca3 | ||
|
|
7b0d5a6700 | ||
|
|
427260663f | ||
|
|
047a443536 | ||
|
|
7a9ee8145d | ||
|
|
2535d0e537 | ||
|
|
6fe7d7991b | ||
|
|
d061958f90 | ||
|
|
3112200eb6 | ||
|
|
69a406832d | ||
|
|
cd4ceb0a61 | ||
|
|
450ec5dec1 | ||
|
|
c7abd1a067 | ||
|
|
c6d87756ab | ||
|
|
0916489388 | ||
|
|
b1e83c92e9 | ||
|
|
d01e06aa11 | ||
|
|
464107b13f | ||
|
|
e431b25fc1 | ||
|
|
e4ed917c1c | ||
|
|
ade3e6d2fb | ||
|
|
d12d18261f | ||
|
|
525b4439c9 |
@@ -51,6 +51,8 @@ target_sources(pico_hsm PUBLIC
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/src/fs/low_flash.c
|
${CMAKE_CURRENT_LIST_DIR}/src/fs/low_flash.c
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/rng/random.c
|
${CMAKE_CURRENT_LIST_DIR}/src/rng/random.c
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/rng/neug.c
|
${CMAKE_CURRENT_LIST_DIR}/src/rng/neug.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/hsm/crypto_utils.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/hsm/dkek.c
|
||||||
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/sha256.c
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/sha256.c
|
||||||
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/aes.c
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/aes.c
|
||||||
@@ -117,7 +119,7 @@ pico_add_extra_outputs(pico_hsm)
|
|||||||
|
|
||||||
#target_compile_definitions(pico_hsm PRIVATE MBEDTLS_ECDSA_DETERMINISTIC=1)
|
#target_compile_definitions(pico_hsm PRIVATE MBEDTLS_ECDSA_DETERMINISTIC=1)
|
||||||
|
|
||||||
target_link_libraries(pico_hsm PRIVATE pico_stdlib tinyusb_device tinyusb_board pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id)
|
target_link_libraries(pico_hsm PRIVATE pico_stdlib tinyusb_device tinyusb_board pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc)
|
||||||
|
|
||||||
#
|
#
|
||||||
#project(flash_nuke C CXX ASM)
|
#project(flash_nuke C CXX ASM)
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -23,11 +23,15 @@ This is a project to create a Hardware Security Module (HSM) with a Raspberry Pi
|
|||||||
- DKEK n-of-m threshold scheme.
|
- DKEK n-of-m threshold scheme.
|
||||||
- USB/CCID support with OpenSC, openssl, etc.
|
- USB/CCID support with OpenSC, openssl, etc.
|
||||||
- Extended APDU support.
|
- Extended APDU support.
|
||||||
|
- Private keys and certificates import from WKY or PKCS#12 files.[^2][^3]
|
||||||
|
- Transport PIN for provisioning and forcing to set a new PIN.[^2]
|
||||||
|
|
||||||
[^1]: PKCS11 modules (`pkcs11-tool` and `sc-tool`) do not support CMAC and key derivation. It must be processed through raw APDU command (`opensc-tool -s`).
|
[^1]: PKCS11 modules (`pkcs11-tool` and `sc-tool`) do not support CMAC and key derivation. It must be processed through raw APDU command (`opensc-tool -s`).
|
||||||
|
[^2]: Available via SCS3 tool. See [SCS3](/doc/rsa_4096.md "SCS3") for more information.
|
||||||
|
[^3]: Imports are available only if the Pico HSM is previously initialized with a DKEK and the DKEK shares are available during the import process.
|
||||||
|
|
||||||
## Security considerations
|
## Security considerations
|
||||||
All secret keys (asymmetric and symmetric) are stored encrypted in the flash memory of the Raspberry Pico. DKEK 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. All keys (including DKEK) are loaded and cleared every time to avoid potential flaws.
|
All secret keys (asymmetric and symmetric) are stored encrypted in the flash memory of the Raspberry Pico. DKEK 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 DKEK) are loaded and cleared every time to avoid potential security flaws.
|
||||||
|
|
||||||
At the same time, DKEK 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 HSM in plain text if no secure channel is provided.
|
At the same time, DKEK 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 HSM in plain text if no secure channel is provided.
|
||||||
|
|
||||||
@@ -80,6 +84,18 @@ For backup, restore and DKEK share management, check [doc/backup-and-restore.md]
|
|||||||
|
|
||||||
For AES key generation, encryption and decryption, check [doc/aes.md](/doc/aes.md).
|
For AES key generation, encryption and decryption, check [doc/aes.md](/doc/aes.md).
|
||||||
|
|
||||||
|
For 4096 bits RSA support, check [doc/rsa_4096_support.md](/doc/rsa_4096.md).
|
||||||
|
|
||||||
|
## Key generation time
|
||||||
|
Generating EC keys is almost instant. RSA keypair generation takes some time, specially for `2048` and `4096` bits.
|
||||||
|
|
||||||
|
| RSA key length (bits) | Average time (seconds) |
|
||||||
|
| :---: | :---: |
|
||||||
|
| 1024 | 16 |
|
||||||
|
| 2048 | 124 |
|
||||||
|
| 3072 | N/A |
|
||||||
|
| 4096 | N/A |
|
||||||
|
|
||||||
## Driver
|
## Driver
|
||||||
|
|
||||||
Pico HSM uses the `sc-hsm` driver provided by [OpenSC](https://github.com/OpenSC/OpenSC/ "OpenSC") or the `sc-hsm-embedded` driver provided by [CardContact](https://github.com/CardContact/sc-hsm-embedded "CardContact"). 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.
|
Pico HSM uses the `sc-hsm` driver provided by [OpenSC](https://github.com/OpenSC/OpenSC/ "OpenSC") or the `sc-hsm-embedded` driver provided by [CardContact](https://github.com/CardContact/sc-hsm-embedded "CardContact"). 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.
|
||||||
@@ -90,6 +106,8 @@ The way to communicate is exactly the same as with other cards, such as OpenPGP
|
|||||||
|
|
||||||
For an advanced usage, see the docs and examples.
|
For an advanced usage, see the docs and examples.
|
||||||
|
|
||||||
|
Pico HSM also supports SCS3 tool. See [SCS3](/doc/rsa_4096.md "SCS3") for more information.
|
||||||
|
|
||||||
### Important
|
### 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](https://github.com/polhenarejos/pico-hsm/releases "Release section")) or configure the project with the proper VID/PID with `USB_VID` and `USB_PID` parameters in `CMake` (see [Build section](#build "Build section")). Note that you cannot distribute the patched/compiled binary if you do not own the VID/PID or have an explicit authorization.
|
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](https://github.com/polhenarejos/pico-hsm/releases "Release section")) or configure the project with the proper VID/PID with `USB_VID` and `USB_PID` parameters in `CMake` (see [Build section](#build "Build section")). Note that you cannot distribute the patched/compiled binary if you do not own the VID/PID or have an explicit authorization.
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
VERSION_MAJOR="1"
|
VERSION_MAJOR="1"
|
||||||
VERSION_MINOR="6"
|
VERSION_MINOR="10"
|
||||||
|
|
||||||
rm -rf release/*
|
rm -rf release/*
|
||||||
cd build
|
cd build_release
|
||||||
|
|
||||||
for board in adafruit_feather_rp2040 adafruit_itsybitsy_rp2040 adafruit_qtpy_rp2040 adafruit_trinkey_qt2040 arduino_nano_rp2040_connect melopero_shake_rp2040 pimoroni_interstate75 pimoroni_keybow2040 pimoroni_pga2040 pimoroni_picolipo_4mb pimoroni_picolipo_16mb pimoroni_picosystem pimoroni_plasma2040 pimoroni_tiny2040 pybstick26_rp2040 sparkfun_micromod sparkfun_promicro sparkfun_thingplus vgaboard waveshare_rp2040_lcd_0.96 waveshare_rp2040_plus_4mb waveshare_rp2040_plus_16mb waveshare_rp2040_zero
|
for board in adafruit_feather_rp2040 adafruit_itsybitsy_rp2040 adafruit_qtpy_rp2040 adafruit_trinkey_qt2040 arduino_nano_rp2040_connect melopero_shake_rp2040 pimoroni_interstate75 pimoroni_keybow2040 pimoroni_pga2040 pimoroni_picolipo_4mb pimoroni_picolipo_16mb pimoroni_picosystem pimoroni_plasma2040 pimoroni_tiny2040 pybstick26_rp2040 sparkfun_micromod sparkfun_promicro sparkfun_thingplus vgaboard waveshare_rp2040_lcd_0.96 waveshare_rp2040_plus_4mb waveshare_rp2040_plus_16mb waveshare_rp2040_zero
|
||||||
do
|
do
|
||||||
@@ -18,4 +18,4 @@ done
|
|||||||
rm -rf *
|
rm -rf *
|
||||||
PICO_SDK_PATH=~/Devel/pico/pico-sdk cmake ..
|
PICO_SDK_PATH=~/Devel/pico/pico-sdk cmake ..
|
||||||
make -kj20
|
make -kj20
|
||||||
mv pico_hsm.uf2 ../release/pico_hsm-$VERSION_MAJOR.$VERSION_MINOR.uf2
|
mv pico_hsm.uf2 ../release/pico_hsm_pico_generic-$VERSION_MAJOR.$VERSION_MINOR.uf2
|
||||||
49
doc/rsa_4096.md
Normal file
49
doc/rsa_4096.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# RSA 4096 support
|
||||||
|
|
||||||
|
Generating 4096 bits key in the Pico HSM is highly expensive. It may take minutes or hours to finish the generation. Therefore, it is extremely recommendable to generate the key in the host and import it into the Pico HSM.
|
||||||
|
|
||||||
|
## SCS3 tool
|
||||||
|
|
||||||
|
Unfortunately, there is no pkcs11 tool or equivalent capable to perform the import. Since it uses the SC-HSM driver, it also supports the communication with the [SCS3 tool](https://www.openscdp.org/scsh3/ "SCS3 tool"). It can be downloaded from [here](https://www.openscdp.org/scsh3/download.html "here").
|
||||||
|
|
||||||
|
However, SCS3 only works with those HSM manufactured by CardContact. The check is performed by means of trust store against the manufacturing certificates. For obvious reasons, these certificates can only be signed with the private keys of the Certificate Authorities listed in the trust store.
|
||||||
|
|
||||||
|
Pico HSM is shipped with its own CA certificates. To load this certificate onto the trust store of SCS3, the following line has to be appended to `SmartCardHSM.rootCerts` variable, near line `235` in the file `scs3/scsh/sc-hsm/SmartCardHSM.js`.
|
||||||
|
|
||||||
|
```
|
||||||
|
ESCVCAHSM00001: new CVC(new ByteString("7F218201657F4E82012D5F290100420E45534356434148534D30303030317F4981DD060A04007F000702020202038118FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF8218FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC831864210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1843104188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E7948118518FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831863104088FCDFCCE87EDD285920615E651D76452D857ECBB408C327ADB48A2A514C1C9BD77CC9783607A741493A742744AD1738701015F200E45534356434148534D30303030317F4C12060904007F0007030102025305C0000000045F25060202000302065F24060300010203015F37307297777664B60C57A2C45E7BFD12E520143EDE9038BFB302739106F2730D760665D74649910C519089848D4FB6E51340", HEX))
|
||||||
|
```
|
||||||
|
|
||||||
|
Therefore, the whole variable becomes:
|
||||||
|
|
||||||
|
```
|
||||||
|
SmartCardHSM.rootCerts = {
|
||||||
|
DESRCACC100001: new CVC(new ByteString("7F218201B47F4E82016C5F290100420E44455352434143433130303030317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A78641046D025A8026CDBA245F10DF1B72E9880FFF746DAB40A43A3D5C6BEBF27707C30F6DEA72430EE3287B0665C1EAA6EAA4FA26C46303001983F82BD1AA31E03DA0628701015F200E44455352434143433130303030317F4C10060B2B0601040181C31F0301015301C05F25060102010100095F24060302010100085F37409DBB382B1711D2BAACB0C623D40C6267D0B52BA455C01F56333DC9554810B9B2878DAF9EC3ADA19C7B065D780D6C9C3C2ECEDFD78DEB18AF40778ADF89E861CA", HEX)),
|
||||||
|
UTSRCACC100001: new CVC(new ByteString("7F218201B47F4E82016C5F290100420E55545352434143433130303030317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7864104A041FEB2FD116B2AD19CA6B7EACD71C9892F941BB88D67DCEEC92501F070011957E22122BA6C2CF5FF02936F482E35A6129CCBBA8E9383836D3106879C408EF08701015F200E55545352434143433130303030317F4C10060B2B0601040181C31F0301015301C05F25060102010100095F24060302010100085F3740914DD0FA00615C44048D1467435400423A4AD1BD37FD98D6DE84FD8037489582325C72956D4FDFABC6EDBA48184A754F37F1BE5142DD1C27D66569308CE19AAF", HEX)),
|
||||||
|
ESCVCAHSM00001: new CVC(new ByteString("7F218201657F4E82012D5F290100420E45534356434148534D30303030317F4981DD060A04007F000702020202038118FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF8218FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC831864210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1843104188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E7948118518FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831863104088FCDFCCE87EDD285920615E651D76452D857ECBB408C327ADB48A2A514C1C9BD77CC9783607A741493A742744AD1738701015F200E45534356434148534D30303030317F4C12060904007F0007030102025305C0000000045F25060202000302065F24060300010203015F37307297777664B60C57A2C45E7BFD12E520143EDE9038BFB302739106F2730D760665D74649910C519089848D4FB6E51340", HEX))
|
||||||
|
}
|
||||||
|
````
|
||||||
|
|
||||||
|
After this ammendment, the KeyManager can be invoked (CTRL+M) and it will output something similar to:
|
||||||
|
```
|
||||||
|
>load("keymanager/keymanager.js");
|
||||||
|
|
||||||
|
SmartCard-HSM Version 1.6 on JCOP Free memory 217104 byte
|
||||||
|
Issuer Certificate : CVC id-AT DV (official domestic) CAR=ESCVCAHSM00001 CHR=ESDVCAHSM00001 CED=27 / de març / 2022 CXD=31 / de desembre / 2025
|
||||||
|
Device Certificate : CVC id-AT Terminal CAR=ESDVCAHSM00001 CHR=ESTERMHSM00001 CED=27 / de març / 2022 CXD=31 / de desembre / 2023
|
||||||
|
Default Key Domain : 0F89B400975EDD2D425ABF85F2FBD318779B3D85475E65D4
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Please right-click on nodes in the outline to see possible actions.
|
||||||
|
For most operations you will need to authenticate first using a
|
||||||
|
mechanism from the User PIN context menu.
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
The SCS3 tool is ready to import private keys and certificates, wraped in WKY files or in PKCS#12 format. Also, all stored keys can be exported, combined with their respective certificates. Note that the user has to be previously logged in.
|
||||||
|
|
||||||
|
## DKEK requirement
|
||||||
|
|
||||||
|
In order to perform the import, private keys must be wrapped with the same DKEK present in the Pico HSM. Thus, the Pico HSM must be previously initialized with at minimum of 1 DKEK share. This share will be used to wrap the private key before import.
|
||||||
|
|
||||||
|
Note that the DKEK share shall be available before the import. In this way, all custodians must be present during the import process, since they will have to introduce their respective DKEK.
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
VERSION_MAJOR="1"
|
VERSION_MAJOR="1"
|
||||||
VERSION_MINOR="4"
|
VERSION_MINOR="0A"
|
||||||
|
|
||||||
echo "----------------------------"
|
echo "----------------------------"
|
||||||
echo "VID/PID patcher for Pico HSM"
|
echo "VID/PID patcher for Pico HSM"
|
||||||
|
|||||||
@@ -78,55 +78,15 @@ void process_fci(const file_t *pe) {
|
|||||||
res_APDU[1] = res_APDU_size-2;
|
res_APDU[1] = res_APDU_size-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t cvca[] = {
|
|
||||||
0x6A, 0x01,
|
|
||||||
0x7f, 0x21, 0x82, 0x01, 0x65, 0x7f, 0x4e, 0x82, 0x01, 0x2d, 0x5f,
|
|
||||||
0x29, 0x01, 0x00, 0x42, 0x0e, 0x45, 0x53, 0x48, 0x53, 0x4d, 0x43,
|
|
||||||
0x56, 0x43, 0x41, 0x32, 0x30, 0x34, 0x30, 0x31, 0x7f, 0x49, 0x81,
|
|
||||||
0xdd, 0x06, 0x0a, 0x04, 0x00, 0x7f, 0x00, 0x07, 0x02, 0x02, 0x02,
|
|
||||||
0x02, 0x03, 0x81, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x82, 0x18, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x83,
|
|
||||||
0x18, 0x64, 0x21, 0x05, 0x19, 0xe5, 0x9c, 0x80, 0xe7, 0x0f, 0xa7,
|
|
||||||
0xe9, 0xab, 0x72, 0x24, 0x30, 0x49, 0xfe, 0xb8, 0xde, 0xec, 0xc1,
|
|
||||||
0x46, 0xb9, 0xb1, 0x84, 0x31, 0x04, 0x18, 0x8d, 0xa8, 0x0e, 0xb0,
|
|
||||||
0x30, 0x90, 0xf6, 0x7c, 0xbf, 0x20, 0xeb, 0x43, 0xa1, 0x88, 0x00,
|
|
||||||
0xf4, 0xff, 0x0a, 0xfd, 0x82, 0xff, 0x10, 0x12, 0x07, 0x19, 0x2b,
|
|
||||||
0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed, 0x6b, 0x24,
|
|
||||||
0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11, 0x85,
|
|
||||||
0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0x99, 0xde, 0xf8, 0x36, 0x14, 0x6b, 0xc9, 0xb1, 0xb4,
|
|
||||||
0xd2, 0x28, 0x31, 0x86, 0x31, 0x04, 0x4d, 0x28, 0x34, 0x67, 0xb5,
|
|
||||||
0x43, 0xfd, 0x84, 0x22, 0x09, 0xbd, 0xd2, 0xd6, 0x26, 0x27, 0x2d,
|
|
||||||
0x53, 0xa7, 0xdf, 0x52, 0x8f, 0xc2, 0xde, 0x7c, 0x9a, 0xcd, 0x1f,
|
|
||||||
0xf2, 0x10, 0x42, 0x7c, 0x13, 0x44, 0x03, 0xb0, 0xa5, 0xdf, 0x8a,
|
|
||||||
0xd4, 0x59, 0xd1, 0x86, 0x4b, 0xde, 0x33, 0xb1, 0x60, 0x17, 0x87,
|
|
||||||
0x01, 0x01, 0x5f, 0x20, 0x0e, 0x45, 0x53, 0x48, 0x53, 0x4d, 0x43,
|
|
||||||
0x56, 0x43, 0x41, 0x32, 0x30, 0x34, 0x30, 0x31, 0x7f, 0x4c, 0x12,
|
|
||||||
0x06, 0x09, 0x04, 0x00, 0x7f, 0x00, 0x07, 0x03, 0x01, 0x02, 0x02,
|
|
||||||
0x53, 0x05, 0xc0, 0x00, 0x00, 0x00, 0x04, 0x5f, 0x25, 0x06, 0x02,
|
|
||||||
0x02, 0x00, 0x02, 0x01, 0x09, 0x5f, 0x24, 0x06, 0x03, 0x00, 0x01,
|
|
||||||
0x02, 0x03, 0x01, 0x5f, 0x37, 0x30, 0x26, 0x2d, 0x6f, 0xa6, 0xd0,
|
|
||||||
0x52, 0x01, 0xf1, 0x41, 0x1e, 0xe9, 0x33, 0x29, 0x19, 0x42, 0x42,
|
|
||||||
0x9b, 0xb0, 0xeb, 0xf7, 0x46, 0x20, 0xcb, 0x81, 0xfe, 0xda, 0xd7,
|
|
||||||
0xab, 0x2b, 0xdc, 0xa7, 0x38, 0xf4, 0xc8, 0xec, 0x4c, 0x66, 0xb4,
|
|
||||||
0x0a, 0x2d, 0x16, 0xfb, 0xf3, 0x79, 0xe9, 0x93, 0xc8, 0x25
|
|
||||||
};
|
|
||||||
const uint8_t token_info[] = {
|
|
||||||
0x28, 0x00, //litle endian
|
|
||||||
0x30, 0x26, 0x2, 0x1, 0x1, 0x4, 0x4, 0xd, 0x0, 0x0, 0x0, 0xc, 0xd, 0x50, 0x6f, 0x6c, 0x20, 0x48, 0x65, 0x6e, 0x61, 0x72, 0x65, 0x6a, 0x6f, 0x73, 0x80, 0x8, 0x48, 0x53, 0x4d, 0x20, 0x32, 0x30, 0x34, 0x30, 0x3, 0x2, 0x4, 0xf0
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const uint8_t sc_hsm_aid[];
|
extern const uint8_t sc_hsm_aid[];
|
||||||
extern int parse_token_info(const file_t *f, int mode);
|
extern int parse_token_info(const file_t *f, int mode);
|
||||||
|
extern int parse_cvca(const file_t *f, int mode);
|
||||||
|
|
||||||
file_t file_entries[] = {
|
file_t file_entries[] = {
|
||||||
/* 0 */ { .fid = 0x3f00 , .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = 0, .acl = {0} }, // MF
|
/* 0 */ { .fid = 0x3f00 , .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = 0, .acl = {0} }, // MF
|
||||||
/* 1 */ { .fid = 0x2f00 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.DIR
|
/* 1 */ { .fid = 0x2f00 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.DIR
|
||||||
/* 2 */ { .fid = 0x2f01 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.ATR
|
/* 2 */ { .fid = 0x2f01 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.ATR
|
||||||
/* 3 */ { .fid = 0x2f02 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF,.data = (uint8_t *)cvca, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.GDO
|
/* 3 */ { .fid = 0x2f02 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC,.data = (uint8_t *)parse_cvca, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.GDO
|
||||||
/* 4 */ { .fid = 0x2f03 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC,.data = (uint8_t *)parse_token_info, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.TokenInfo
|
/* 4 */ { .fid = 0x2f03 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC,.data = (uint8_t *)parse_token_info, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.TokenInfo
|
||||||
/* 5 */ { .fid = 0x5015 , .parent = 0, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = 0, .acl = {0} }, //DF.PKCS15
|
/* 5 */ { .fid = 0x5015 , .parent = 0, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = 0, .acl = {0} }, //DF.PKCS15
|
||||||
/* 6 */ { .fid = 0x5031 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.ODF
|
/* 6 */ { .fid = 0x5031 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.ODF
|
||||||
@@ -139,15 +99,16 @@ file_t file_entries[] = {
|
|||||||
/* 13 */ { .fid = 0x1089 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //max retries PIN (SOPIN)
|
/* 13 */ { .fid = 0x1089 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //max retries PIN (SOPIN)
|
||||||
/* 14 */ { .fid = 0x108A , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //retries PIN (SOPIN)
|
/* 14 */ { .fid = 0x108A , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //retries PIN (SOPIN)
|
||||||
/* 15 */ { .fid = EF_DKEK , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //DKEK
|
/* 15 */ { .fid = EF_DKEK , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //DKEK
|
||||||
/* 16 */ { .fid = EF_PRKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PrKDFs
|
/* 16 */ { .fid = EF_DEVOPS , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //Device options
|
||||||
/* 17 */ { .fid = EF_PUKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PuKDFs
|
/* 17 */ { .fid = EF_PRKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PrKDFs
|
||||||
/* 18 */ { .fid = EF_CDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.CDFs
|
/* 18 */ { .fid = EF_PUKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PuKDFs
|
||||||
/* 19 */ { .fid = EF_AODFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.AODFs
|
/* 19 */ { .fid = EF_CDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.CDFs
|
||||||
/* 20 */ { .fid = EF_DODFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.DODFs
|
/* 20 */ { .fid = EF_AODFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.AODFs
|
||||||
/* 21 */ { .fid = EF_SKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.SKDFs
|
/* 21 */ { .fid = EF_DODFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.DODFs
|
||||||
///* 22 */ { .fid = 0x0000, .parent = 0, .name = openpgpcard_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} },
|
/* 22 */ { .fid = EF_SKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.SKDFs
|
||||||
/* 23 */ { .fid = 0x0000, .parent = 5, .name = sc_hsm_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} },
|
///* 23 */ { .fid = 0x0000, .parent = 0, .name = openpgpcard_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} },
|
||||||
/* 24 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = {0} } //end
|
/* 24 */ { .fid = 0x0000, .parent = 5, .name = sc_hsm_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} },
|
||||||
|
/* 25 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = {0} } //end
|
||||||
};
|
};
|
||||||
|
|
||||||
const file_t *MF = &file_entries[0];
|
const file_t *MF = &file_entries[0];
|
||||||
|
|||||||
@@ -60,6 +60,7 @@
|
|||||||
#define EF_AODFS 0x6043
|
#define EF_AODFS 0x6043
|
||||||
#define EF_DODFS 0x6044
|
#define EF_DODFS 0x6044
|
||||||
#define EF_SKDFS 0x6045
|
#define EF_SKDFS 0x6045
|
||||||
|
#define EF_DEVOPS 0x100E
|
||||||
|
|
||||||
#define MAX_DEPTH 4
|
#define MAX_DEPTH 4
|
||||||
|
|
||||||
|
|||||||
142
src/hsm/crypto_utils.c
Normal file
142
src/hsm/crypto_utils.c
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
|
||||||
|
* Copyright (c) 2022 Pol Henarejos.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pico/unique_id.h>
|
||||||
|
#include "mbedtls/md.h"
|
||||||
|
#include "mbedtls/sha256.h"
|
||||||
|
#include "mbedtls/aes.h"
|
||||||
|
#include "crypto_utils.h"
|
||||||
|
#include "sc_hsm.h"
|
||||||
|
#include "libopensc/card-sc-hsm.h"
|
||||||
|
|
||||||
|
void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]) {
|
||||||
|
uint8_t o1[32];
|
||||||
|
hash_multi(pin, len, o1);
|
||||||
|
for (int i = 0; i < sizeof(o1); i++)
|
||||||
|
o1[i] ^= pin[i%len];
|
||||||
|
hash_multi(o1, sizeof(o1), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hash_multi(const uint8_t *input, size_t len, uint8_t output[32]) {
|
||||||
|
mbedtls_sha256_context ctx;
|
||||||
|
mbedtls_sha256_init(&ctx);
|
||||||
|
int iters = 256;
|
||||||
|
pico_unique_board_id_t unique_id;
|
||||||
|
|
||||||
|
pico_get_unique_board_id(&unique_id);
|
||||||
|
|
||||||
|
mbedtls_sha256_starts (&ctx, 0);
|
||||||
|
mbedtls_sha256_update (&ctx, unique_id.id, sizeof(unique_id.id));
|
||||||
|
|
||||||
|
while (iters > len)
|
||||||
|
{
|
||||||
|
mbedtls_sha256_update (&ctx, input, len);
|
||||||
|
iters -= len;
|
||||||
|
}
|
||||||
|
if (iters > 0) // remaining iterations
|
||||||
|
mbedtls_sha256_update (&ctx, input, iters);
|
||||||
|
mbedtls_sha256_finish (&ctx, output);
|
||||||
|
mbedtls_sha256_free (&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hash256(const uint8_t *input, size_t len, uint8_t output[32]) {
|
||||||
|
mbedtls_sha256_context ctx;
|
||||||
|
mbedtls_sha256_init(&ctx);
|
||||||
|
|
||||||
|
mbedtls_sha256_starts (&ctx, 0);
|
||||||
|
mbedtls_sha256_update (&ctx, input, len);
|
||||||
|
|
||||||
|
mbedtls_sha256_finish (&ctx, output);
|
||||||
|
mbedtls_sha256_free (&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_t *output) {
|
||||||
|
mbedtls_md_context_t ctx;
|
||||||
|
mbedtls_md_init(&ctx);
|
||||||
|
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md);
|
||||||
|
mbedtls_md_setup(&ctx, md_info, 0);
|
||||||
|
mbedtls_md_starts(&ctx);
|
||||||
|
mbedtls_md_update(&ctx, input, len);
|
||||||
|
mbedtls_md_finish(&ctx, output);
|
||||||
|
mbedtls_md_free(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len) {
|
||||||
|
mbedtls_aes_context aes;
|
||||||
|
mbedtls_aes_init(&aes);
|
||||||
|
uint8_t tmp_iv[IV_SIZE];
|
||||||
|
size_t iv_offset = 0;
|
||||||
|
memset(tmp_iv, 0, IV_SIZE);
|
||||||
|
if (iv)
|
||||||
|
memcpy(tmp_iv, iv, IV_SIZE);
|
||||||
|
int r = mbedtls_aes_setkey_enc(&aes, key, key_size);
|
||||||
|
if (r != 0)
|
||||||
|
return HSM_EXEC_ERROR;
|
||||||
|
if (mode == HSM_AES_MODE_CBC)
|
||||||
|
return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, len, tmp_iv, data, data);
|
||||||
|
return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, tmp_iv, data, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len) {
|
||||||
|
mbedtls_aes_context aes;
|
||||||
|
mbedtls_aes_init(&aes);
|
||||||
|
uint8_t tmp_iv[IV_SIZE];
|
||||||
|
size_t iv_offset = 0;
|
||||||
|
memset(tmp_iv, 0, IV_SIZE);
|
||||||
|
if (iv)
|
||||||
|
memcpy(tmp_iv, iv, IV_SIZE);
|
||||||
|
int r = mbedtls_aes_setkey_dec(&aes, key, key_size);
|
||||||
|
if (r != 0)
|
||||||
|
return HSM_EXEC_ERROR;
|
||||||
|
if (mode == HSM_AES_MODE_CBC)
|
||||||
|
return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, len, tmp_iv, data, data);
|
||||||
|
r = mbedtls_aes_setkey_enc(&aes, key, key_size); //CFB requires set_enc instead set_dec
|
||||||
|
return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_DECRYPT, len, &iv_offset, tmp_iv, data, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int aes_encrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) {
|
||||||
|
return aes_encrypt(key, iv, 256, HSM_AES_MODE_CFB, data, len);
|
||||||
|
}
|
||||||
|
int aes_decrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) {
|
||||||
|
return aes_decrypt(key, iv, 256, HSM_AES_MODE_CFB, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ec_curve_mbed_id {
|
||||||
|
struct sc_lv_data curve;
|
||||||
|
mbedtls_ecp_group_id id;
|
||||||
|
};
|
||||||
|
struct ec_curve_mbed_id ec_curves_mbed[] = {
|
||||||
|
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24}, MBEDTLS_ECP_DP_SECP192R1 },
|
||||||
|
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32}, MBEDTLS_ECP_DP_SECP256R1 },
|
||||||
|
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 48}, MBEDTLS_ECP_DP_SECP384R1 },
|
||||||
|
{ { (unsigned char *) "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 66}, MBEDTLS_ECP_DP_SECP521R1 },
|
||||||
|
{ { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32}, MBEDTLS_ECP_DP_BP256R1 },
|
||||||
|
{ { (unsigned char *) "\x8C\xB9\x1E\x82\xA3\x38\x6D\x28\x0F\x5D\x6F\x7E\x50\xE6\x41\xDF\x15\x2F\x71\x09\xED\x54\x56\xB4\x12\xB1\xDA\x19\x7F\xB7\x11\x23\xAC\xD3\xA7\x29\x90\x1D\x1A\x71\x87\x47\x00\x13\x31\x07\xEC\x53", 48}, MBEDTLS_ECP_DP_BP384R1 },
|
||||||
|
{ { (unsigned char *) "\xAA\xDD\x9D\xB8\xDB\xE9\xC4\x8B\x3F\xD4\xE6\xAE\x33\xC9\xFC\x07\xCB\x30\x8D\xB3\xB3\xC9\xD2\x0E\xD6\x63\x9C\xCA\x70\x33\x08\x71\x7D\x4D\x9B\x00\x9B\xC6\x68\x42\xAE\xCD\xA1\x2A\xE6\xA3\x80\xE6\x28\x81\xFF\x2F\x2D\x82\xC6\x85\x28\xAA\x60\x56\x58\x3A\x48\xF3", 64}, MBEDTLS_ECP_DP_BP512R1 },
|
||||||
|
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xEE\x37", 24}, MBEDTLS_ECP_DP_SECP192K1 },
|
||||||
|
{ { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFC\x2F", 32}, MBEDTLS_ECP_DP_SECP256K1 },
|
||||||
|
{ { NULL, 0 }, MBEDTLS_ECP_DP_NONE }
|
||||||
|
};
|
||||||
|
|
||||||
|
mbedtls_ecp_group_id ec_get_curve_from_prime(const uint8_t *prime, size_t prime_len) {
|
||||||
|
for (struct ec_curve_mbed_id *ec = ec_curves_mbed; ec->id != MBEDTLS_ECP_DP_NONE; ec++) {
|
||||||
|
if (prime_len == ec->curve.len && memcmp(prime, ec->curve.value, prime_len) == 0) {
|
||||||
|
return ec->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MBEDTLS_ECP_DP_NONE;
|
||||||
|
}
|
||||||
46
src/hsm/crypto_utils.h
Normal file
46
src/hsm/crypto_utils.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
|
||||||
|
* Copyright (c) 2022 Pol Henarejos.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CRYPTO_UTILS_H_
|
||||||
|
#define _CRYPTO_UTILS_H_
|
||||||
|
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "mbedtls/ecp.h"
|
||||||
|
#include "mbedtls/md.h"
|
||||||
|
|
||||||
|
#define HSM_KEY_RSA 0x1
|
||||||
|
#define HSM_KEY_EC 0x10
|
||||||
|
#define HSM_KEY_AES 0x100
|
||||||
|
#define HSM_KEY_AES_128 0x300
|
||||||
|
#define HSM_KEY_AES_192 0x500
|
||||||
|
#define HSM_KEY_AES_256 0x900
|
||||||
|
|
||||||
|
#define HSM_AES_MODE_CBC 1
|
||||||
|
#define HSM_AES_MODE_CFB 2
|
||||||
|
|
||||||
|
extern void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]);
|
||||||
|
extern void hash_multi(const uint8_t *input, size_t len, uint8_t output[32]);
|
||||||
|
extern void hash256(const uint8_t *input, size_t len, uint8_t output[32]);
|
||||||
|
extern void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_t *output);
|
||||||
|
extern int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len);
|
||||||
|
extern int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len);
|
||||||
|
extern int aes_encrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len);
|
||||||
|
extern int aes_decrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len);
|
||||||
|
extern mbedtls_ecp_group_id ec_get_curve_from_prime(const uint8_t *prime, size_t prime_len);
|
||||||
|
|
||||||
|
#endif
|
||||||
41
src/hsm/cvcerts.h
Normal file
41
src/hsm/cvcerts.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef CVCERTS_H_
|
||||||
|
#define CVCERTS_H_
|
||||||
|
|
||||||
|
static const unsigned char termca[] = {
|
||||||
|
0xfa, 0x00,
|
||||||
|
0x7f,0x21,0x81,0xf6,0x7f,0x4e,0x81,0xbf,0x5f,0x29,0x01,0x00,0x42,0x0e,0x45,0x53,
|
||||||
|
0x44,0x56,0x43,0x41,0x48,0x53,0x4d,0x30,0x30,0x30,0x30,0x31,0x7f,0x49,0x3f,0x06,
|
||||||
|
0x0a,0x04,0x00,0x7f,0x00,0x07,0x02,0x02,0x02,0x02,0x03,0x86,0x31,0x04,0x0f,0x89,
|
||||||
|
0xb4,0x00,0x97,0x5e,0xdd,0x2d,0x42,0x5a,0xbf,0x85,0xf2,0xfb,0xd3,0x18,0x77,0x9b,
|
||||||
|
0x3d,0x85,0x47,0x5e,0x65,0xd4,0xd8,0x58,0x69,0xd3,0x04,0x14,0xb7,0x1f,0x16,0x1e,
|
||||||
|
0xb0,0x40,0xd9,0xf7,0xa7,0xe3,0x73,0xa3,0x15,0xc7,0xd9,0x9a,0x51,0xf5,0x5f,0x20,
|
||||||
|
0x0e,0x45,0x53,0x54,0x45,0x52,0x4d,0x48,0x53,0x4d,0x30,0x30,0x30,0x30,0x31,0x7f,
|
||||||
|
0x4c,0x12,0x06,0x09,0x04,0x00,0x7f,0x00,0x07,0x03,0x01,0x02,0x02,0x53,0x05,0x00,
|
||||||
|
0x00,0x00,0x00,0x04,0x5f,0x25,0x06,0x02,0x02,0x00,0x03,0x02,0x07,0x5f,0x24,0x06,
|
||||||
|
0x02,0x03,0x01,0x02,0x03,0x01,0x65,0x2f,0x73,0x2d,0x06,0x09,0x04,0x00,0x7f,0x00,
|
||||||
|
0x07,0x03,0x01,0x03,0x01,0x80,0x20,0x68,0x53,0x30,0xc7,0x9a,0x47,0xad,0xfd,0x37,
|
||||||
|
0xaa,0xe8,0x53,0xf4,0xbd,0x77,0x3a,0x40,0x89,0x3a,0x79,0x7e,0x3c,0x27,0x18,0x3b,
|
||||||
|
0x39,0x67,0xdf,0x8d,0x4f,0xe5,0x99,0x5f,0x37,0x30,0x10,0xff,0x17,0x96,0x0d,0x93,
|
||||||
|
0x07,0xc0,0x69,0x8e,0x3a,0xa0,0x44,0x69,0x70,0x88,0xe6,0x9c,0xb4,0xd3,0x16,0x9a,
|
||||||
|
0x22,0x4e,0x5c,0x77,0xa9,0xe7,0x83,0x75,0x9a,0xd2,0x7e,0x92,0xf2,0x04,0x93,0xb1,
|
||||||
|
0xe9,0xc9,0xe5,0x10,0xc9,0x94,0xff,0x9d,0xe2,0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char dica[] = {
|
||||||
|
0xc9, 0x00,
|
||||||
|
0x7f,0x21,0x81,0xc5,0x7f,0x4e,0x81,0x8e,0x5f,0x29,0x01,0x00,0x42,0x0e,0x45,0x53,
|
||||||
|
0x43,0x56,0x43,0x41,0x48,0x53,0x4d,0x30,0x30,0x30,0x30,0x31,0x7f,0x49,0x3f,0x06,
|
||||||
|
0x0a,0x04,0x00,0x7f,0x00,0x07,0x02,0x02,0x02,0x02,0x03,0x86,0x31,0x04,0x93,0x7e,
|
||||||
|
0xdf,0xf1,0xa6,0xd2,0x40,0x7e,0xb4,0x71,0xb2,0x97,0x50,0xdb,0x7e,0xe1,0x70,0xfb,
|
||||||
|
0x6c,0xcd,0x06,0x47,0x2a,0x3e,0x9c,0x8d,0x59,0x56,0x57,0xbe,0x11,0x11,0x0a,0x08,
|
||||||
|
0x81,0x54,0xed,0x22,0xc0,0x83,0xac,0xa1,0x2e,0x39,0x7b,0xd4,0x65,0x1f,0x5f,0x20,
|
||||||
|
0x0e,0x45,0x53,0x44,0x56,0x43,0x41,0x48,0x53,0x4d,0x30,0x30,0x30,0x30,0x31,0x7f,
|
||||||
|
0x4c,0x12,0x06,0x09,0x04,0x00,0x7f,0x00,0x07,0x03,0x01,0x02,0x02,0x53,0x05,0x80,
|
||||||
|
0x00,0x00,0x00,0x04,0x5f,0x25,0x06,0x02,0x02,0x00,0x03,0x02,0x07,0x5f,0x24,0x06,
|
||||||
|
0x02,0x05,0x01,0x02,0x03,0x01,0x5f,0x37,0x30,0x8b,0xb2,0x01,0xb6,0x24,0xfe,0xe5,
|
||||||
|
0x4e,0x65,0x3a,0x02,0xa2,0xb2,0x27,0x2d,0x3d,0xb4,0xb0,0xc9,0xdd,0xbf,0x10,0x6d,
|
||||||
|
0x99,0x49,0x46,0xd6,0xd0,0x72,0xc1,0xf3,0x4c,0xab,0x4f,0x32,0x14,0x7c,0xb0,0x99,
|
||||||
|
0xb7,0x33,0x70,0xd6,0x00,0xff,0x73,0x0c,0x5d
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
474
src/hsm/dkek.c
Normal file
474
src/hsm/dkek.c
Normal file
@@ -0,0 +1,474 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
|
||||||
|
* Copyright (c) 2022 Pol Henarejos.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "common.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "dkek.h"
|
||||||
|
#include "crypto_utils.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "sc_hsm.h"
|
||||||
|
#include "mbedtls/md.h"
|
||||||
|
#include "mbedtls/cmac.h"
|
||||||
|
#include "mbedtls/rsa.h"
|
||||||
|
#include "mbedtls/ecdsa.h"
|
||||||
|
|
||||||
|
static uint8_t dkek[IV_SIZE+32];
|
||||||
|
static uint8_t tmp_dkek[32];
|
||||||
|
extern bool has_session_pin;
|
||||||
|
extern uint8_t session_pin[32];
|
||||||
|
|
||||||
|
int load_dkek() {
|
||||||
|
if (has_session_pin == false)
|
||||||
|
return HSM_NO_LOGIN;
|
||||||
|
file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF);
|
||||||
|
if (!tf)
|
||||||
|
return HSM_ERR_FILE_NOT_FOUND;
|
||||||
|
memcpy(dkek, file_read(tf->data+sizeof(uint16_t)), IV_SIZE+32);
|
||||||
|
int ret = aes_decrypt_cfb_256(session_pin, dkek, dkek+IV_SIZE, 32);
|
||||||
|
if (ret != 0)
|
||||||
|
return HSM_EXEC_ERROR;
|
||||||
|
return HSM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release_dkek() {
|
||||||
|
memset(dkek, 0, sizeof(dkek));
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_dkek() {
|
||||||
|
release_dkek();
|
||||||
|
memset(tmp_dkek, 0, sizeof(tmp_dkek));
|
||||||
|
}
|
||||||
|
|
||||||
|
int store_dkek_key() {
|
||||||
|
aes_encrypt_cfb_256(session_pin, dkek, dkek+IV_SIZE, 32);
|
||||||
|
file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF);
|
||||||
|
if (!tf)
|
||||||
|
return HSM_ERR_FILE_NOT_FOUND;
|
||||||
|
flash_write_data_to_file(tf, dkek, sizeof(dkek));
|
||||||
|
low_flash_available();
|
||||||
|
release_dkek();
|
||||||
|
return HSM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int save_dkek_key(const uint8_t *key) {
|
||||||
|
const uint8_t *iv = random_bytes_get(32);
|
||||||
|
memcpy(dkek, iv, IV_SIZE);
|
||||||
|
if (!key)
|
||||||
|
key = tmp_dkek;
|
||||||
|
memcpy(dkek+IV_SIZE, key, 32);
|
||||||
|
return store_dkek_key();
|
||||||
|
}
|
||||||
|
|
||||||
|
void import_dkek_share(const uint8_t *share) {
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
tmp_dkek[i] ^= share[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int dkek_kcv(uint8_t *kcv) { //kcv 8 bytes
|
||||||
|
uint8_t hsh[32];
|
||||||
|
int r = load_dkek();
|
||||||
|
if (r != HSM_OK)
|
||||||
|
return r;
|
||||||
|
hash256(dkek+IV_SIZE, 32, hsh);
|
||||||
|
release_dkek();
|
||||||
|
memcpy(kcv, hsh, 8);
|
||||||
|
return HSM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dkek_kenc(uint8_t *kenc) { //kenc 32 bytes
|
||||||
|
uint8_t buf[32+4];
|
||||||
|
int r = load_dkek();
|
||||||
|
if (r != HSM_OK)
|
||||||
|
return r;
|
||||||
|
memcpy(buf, dkek+IV_SIZE, 32);
|
||||||
|
release_dkek();
|
||||||
|
memcpy(buf+32, "\x0\x0\x0\x1", 4);
|
||||||
|
hash256(buf, sizeof(buf), kenc);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
return HSM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dkek_kmac(uint8_t *kmac) { //kmac 32 bytes
|
||||||
|
uint8_t buf[32+4];
|
||||||
|
int r = load_dkek();
|
||||||
|
if (r != HSM_OK)
|
||||||
|
return r;
|
||||||
|
memcpy(buf, dkek+IV_SIZE, 32);
|
||||||
|
release_dkek();
|
||||||
|
memcpy(buf+32, "\x0\x0\x0\x2", 4);
|
||||||
|
hash256(buf, sizeof(buf), kmac);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
return HSM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dkek_encrypt(uint8_t *data, size_t len) {
|
||||||
|
int r;
|
||||||
|
if ((r = load_dkek()) != HSM_OK)
|
||||||
|
return r;
|
||||||
|
r = aes_encrypt_cfb_256(dkek+IV_SIZE, dkek, data, len);
|
||||||
|
release_dkek();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dkek_decrypt(uint8_t *data, size_t len) {
|
||||||
|
int r;
|
||||||
|
if ((r = load_dkek()) != HSM_OK)
|
||||||
|
return r;
|
||||||
|
r = aes_decrypt_cfb_256(dkek+IV_SIZE, dkek, data, len);
|
||||||
|
release_dkek();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) {
|
||||||
|
if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES))
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
|
||||||
|
uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes padding)
|
||||||
|
memset(kb, 0, sizeof(kb));
|
||||||
|
int kb_len = 0;
|
||||||
|
uint8_t *algo = NULL;
|
||||||
|
uint8_t algo_len = 0;
|
||||||
|
uint8_t *allowed = NULL;
|
||||||
|
uint8_t allowed_len = 0;
|
||||||
|
uint8_t kenc[32];
|
||||||
|
memset(kenc, 0, sizeof(kenc));
|
||||||
|
dkek_kenc(kenc);
|
||||||
|
|
||||||
|
uint8_t kcv[8];
|
||||||
|
memset(kcv, 0, sizeof(kcv));
|
||||||
|
dkek_kcv(kcv);
|
||||||
|
|
||||||
|
uint8_t kmac[32];
|
||||||
|
memset(kmac, 0, sizeof(kmac));
|
||||||
|
dkek_kmac(kmac);
|
||||||
|
|
||||||
|
if (key_type & HSM_KEY_AES) {
|
||||||
|
if (key_type & HSM_KEY_AES_128)
|
||||||
|
kb_len = 16;
|
||||||
|
else if (key_type & HSM_KEY_AES_192)
|
||||||
|
kb_len = 24;
|
||||||
|
else if (key_type & HSM_KEY_AES_256)
|
||||||
|
kb_len = 32;
|
||||||
|
|
||||||
|
if (kb_len != 16 && kb_len != 24 && kb_len != 32)
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
if (*out_len < 8+1+10+6+4+(2+32+14)+16)
|
||||||
|
return HSM_WRONG_LENGTH;
|
||||||
|
|
||||||
|
put_uint16_t(kb_len, kb+8);
|
||||||
|
memcpy(kb+10, key_ctx, kb_len);
|
||||||
|
kb_len += 2;
|
||||||
|
|
||||||
|
algo = "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8)
|
||||||
|
algo_len = 10;
|
||||||
|
allowed = "\x00\x04\x10\x11\x18\x99"; //(2+4)
|
||||||
|
allowed_len = 6;
|
||||||
|
}
|
||||||
|
else if (key_type & HSM_KEY_RSA) {
|
||||||
|
if (*out_len < 8+1+12+6+(8+2*4+2*4096/8+3+13)+16) //13 bytes pading
|
||||||
|
return HSM_WRONG_LENGTH;
|
||||||
|
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx;
|
||||||
|
kb_len = 0;
|
||||||
|
put_uint16_t(mbedtls_rsa_get_len(rsa)*8, kb+8+kb_len); kb_len += 2;
|
||||||
|
|
||||||
|
put_uint16_t(mbedtls_mpi_size(&rsa->D), kb+8+kb_len); kb_len += 2;
|
||||||
|
mbedtls_mpi_write_binary(&rsa->D, kb+8+kb_len, mbedtls_mpi_size(&rsa->D)); kb_len += mbedtls_mpi_size(&rsa->D);
|
||||||
|
put_uint16_t(mbedtls_mpi_size(&rsa->N), kb+8+kb_len); kb_len += 2;
|
||||||
|
mbedtls_mpi_write_binary(&rsa->N, kb+8+kb_len, mbedtls_mpi_size(&rsa->N)); kb_len += mbedtls_mpi_size(&rsa->N);
|
||||||
|
put_uint16_t(mbedtls_mpi_size(&rsa->E), kb+8+kb_len); kb_len += 2;
|
||||||
|
mbedtls_mpi_write_binary(&rsa->E, kb+8+kb_len, mbedtls_mpi_size(&rsa->E)); kb_len += mbedtls_mpi_size(&rsa->E);
|
||||||
|
|
||||||
|
algo = "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02";
|
||||||
|
algo_len = 12;
|
||||||
|
}
|
||||||
|
else if (key_type & HSM_KEY_EC) {
|
||||||
|
if (*out_len < 8+1+12+6+(8+2*8+9*66+2+4)+16) //4 bytes pading
|
||||||
|
return HSM_WRONG_LENGTH;
|
||||||
|
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx;
|
||||||
|
kb_len = 0;
|
||||||
|
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.P)*8, kb+8+kb_len); kb_len += 2;
|
||||||
|
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.A), kb+8+kb_len); kb_len += 2;
|
||||||
|
mbedtls_mpi_write_binary(&ecdsa->grp.A, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.A)); kb_len += mbedtls_mpi_size(&ecdsa->grp.A);
|
||||||
|
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.B), kb+8+kb_len); kb_len += 2;
|
||||||
|
mbedtls_mpi_write_binary(&ecdsa->grp.B, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.B)); kb_len += mbedtls_mpi_size(&ecdsa->grp.B);
|
||||||
|
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.P), kb+8+kb_len); kb_len += 2;
|
||||||
|
mbedtls_mpi_write_binary(&ecdsa->grp.P, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.P)); kb_len += mbedtls_mpi_size(&ecdsa->grp.P);
|
||||||
|
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.N), kb+8+kb_len); kb_len += 2;
|
||||||
|
mbedtls_mpi_write_binary(&ecdsa->grp.N, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.N)); kb_len += mbedtls_mpi_size(&ecdsa->grp.N);
|
||||||
|
put_uint16_t(1+mbedtls_mpi_size(&ecdsa->grp.G.X)+mbedtls_mpi_size(&ecdsa->grp.G.Y), kb+8+kb_len); kb_len += 2;
|
||||||
|
kb[8+kb_len++] = 0x4;
|
||||||
|
mbedtls_mpi_write_binary(&ecdsa->grp.G.X, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.G.X)); kb_len += mbedtls_mpi_size(&ecdsa->grp.G.X);
|
||||||
|
mbedtls_mpi_write_binary(&ecdsa->grp.G.Y, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.G.Y)); kb_len += mbedtls_mpi_size(&ecdsa->grp.G.Y);
|
||||||
|
put_uint16_t(mbedtls_mpi_size(&ecdsa->d), kb+8+kb_len); kb_len += 2;
|
||||||
|
mbedtls_mpi_write_binary(&ecdsa->d, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->d)); kb_len += mbedtls_mpi_size(&ecdsa->d);
|
||||||
|
put_uint16_t(1+mbedtls_mpi_size(&ecdsa->Q.X)+mbedtls_mpi_size(&ecdsa->Q.Y), kb+8+kb_len); kb_len += 2;
|
||||||
|
kb[8+kb_len++] = 0x4;
|
||||||
|
mbedtls_mpi_write_binary(&ecdsa->Q.X, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->Q.X)); kb_len += mbedtls_mpi_size(&ecdsa->Q.X);
|
||||||
|
mbedtls_mpi_write_binary(&ecdsa->Q.Y, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->Q.Y)); kb_len += mbedtls_mpi_size(&ecdsa->Q.Y);
|
||||||
|
|
||||||
|
algo = "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03";
|
||||||
|
algo_len = 12;
|
||||||
|
}
|
||||||
|
memset(out, 0, *out_len);
|
||||||
|
*out_len = 0;
|
||||||
|
|
||||||
|
memcpy(out+*out_len, kcv, 8);
|
||||||
|
*out_len += 8;
|
||||||
|
|
||||||
|
if (key_type & HSM_KEY_AES)
|
||||||
|
out[*out_len] = 15;
|
||||||
|
else if (key_type & HSM_KEY_RSA)
|
||||||
|
out[*out_len] = 5;
|
||||||
|
else if (key_type & HSM_KEY_EC)
|
||||||
|
out[*out_len] = 12;
|
||||||
|
*out_len += 1;
|
||||||
|
|
||||||
|
if (algo) {
|
||||||
|
memcpy(out+*out_len, algo, algo_len);
|
||||||
|
*out_len += algo_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*out_len += 2;
|
||||||
|
|
||||||
|
if (allowed) {
|
||||||
|
memcpy(out+*out_len, allowed, allowed_len);
|
||||||
|
*out_len += allowed_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*out_len += 2;
|
||||||
|
//add 4 zeros
|
||||||
|
*out_len += 4;
|
||||||
|
|
||||||
|
memcpy(kb, random_bytes_get(8), 8);
|
||||||
|
kb_len += 8; //8 random bytes
|
||||||
|
int kb_len_pad = ((int)(kb_len/16))*16;
|
||||||
|
if (kb_len % 16 > 0)
|
||||||
|
kb_len_pad = ((int)(kb_len/16)+1)*16;
|
||||||
|
//key already copied at kb+10
|
||||||
|
if (kb_len < kb_len_pad) {
|
||||||
|
kb[kb_len] = 0x80;
|
||||||
|
}
|
||||||
|
int r = aes_encrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, kb_len_pad);
|
||||||
|
if (r != HSM_OK)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
memcpy(out+*out_len, kb, kb_len_pad);
|
||||||
|
*out_len += kb_len_pad;
|
||||||
|
|
||||||
|
r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, out, *out_len, out+*out_len);
|
||||||
|
|
||||||
|
*out_len += 16;
|
||||||
|
if (r != 0)
|
||||||
|
return r;
|
||||||
|
return HSM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dkek_type_key(const uint8_t *in) {
|
||||||
|
if (in[8] == 5 || in[8] == 6)
|
||||||
|
return HSM_KEY_RSA;
|
||||||
|
else if (in[8] == 12)
|
||||||
|
return HSM_KEY_EC;
|
||||||
|
else if (in[8] == 15)
|
||||||
|
return HSM_KEY_AES;
|
||||||
|
return 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out) {
|
||||||
|
uint8_t kcv[8];
|
||||||
|
memset(kcv, 0, sizeof(kcv));
|
||||||
|
dkek_kcv(kcv);
|
||||||
|
|
||||||
|
uint8_t kmac[32];
|
||||||
|
memset(kmac, 0, sizeof(kmac));
|
||||||
|
dkek_kmac(kmac);
|
||||||
|
|
||||||
|
uint8_t kenc[32];
|
||||||
|
memset(kenc, 0, sizeof(kenc));
|
||||||
|
dkek_kenc(kenc);
|
||||||
|
|
||||||
|
if (memcmp(kcv, in, 8) != 0)
|
||||||
|
return HSM_WRONG_DKEK;
|
||||||
|
|
||||||
|
uint8_t signature[16];
|
||||||
|
int r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, in, in_len-16, signature);
|
||||||
|
if (r != 0)
|
||||||
|
return HSM_WRONG_SIGNATURE;
|
||||||
|
if (memcmp(signature, in+in_len-16, 16) != 0)
|
||||||
|
return HSM_WRONG_SIGNATURE;
|
||||||
|
|
||||||
|
int key_type = in[8];
|
||||||
|
if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15)
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
|
||||||
|
if ((key_type == 5 || key_type == 6) && memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0)
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
|
||||||
|
if (key_type == 12 && memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0)
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
|
||||||
|
if (key_type == 15 && memcmp(in+9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0)
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
|
||||||
|
size_t ofs = 9;
|
||||||
|
|
||||||
|
//OID
|
||||||
|
size_t len = get_uint16_t(in, ofs);
|
||||||
|
ofs += len+2;
|
||||||
|
|
||||||
|
//Allowed algorithms
|
||||||
|
len = get_uint16_t(in, ofs);
|
||||||
|
ofs += len+2;
|
||||||
|
|
||||||
|
//Access conditions
|
||||||
|
len = get_uint16_t(in, ofs);
|
||||||
|
ofs += len+2;
|
||||||
|
|
||||||
|
//Key OID
|
||||||
|
len = get_uint16_t(in, ofs);
|
||||||
|
ofs += len+2;
|
||||||
|
|
||||||
|
if ((in_len-16-ofs) % 16 != 0)
|
||||||
|
return HSM_WRONG_PADDING;
|
||||||
|
uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes padding)
|
||||||
|
memset(kb, 0, sizeof(kb));
|
||||||
|
memcpy(kb, in+ofs, in_len-16-ofs);
|
||||||
|
r = aes_decrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, in_len-16-ofs);
|
||||||
|
if (r != HSM_OK)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
int key_size = get_uint16_t(kb, 8);
|
||||||
|
if (key_size_out)
|
||||||
|
*key_size_out = key_size;
|
||||||
|
ofs = 10;
|
||||||
|
if (key_type == 5 || key_type == 6) {
|
||||||
|
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx;
|
||||||
|
mbedtls_rsa_init(rsa);
|
||||||
|
if (key_type == 5) {
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||||
|
r = mbedtls_mpi_read_binary(&rsa->D, kb+ofs, len); ofs += len;
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_rsa_free(rsa);
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||||
|
r = mbedtls_mpi_read_binary(&rsa->N, kb+ofs, len); ofs += len;
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_rsa_free(rsa);
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key_type == 6) {
|
||||||
|
//DP-1
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||||
|
|
||||||
|
//DQ-1
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||||
|
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||||
|
r = mbedtls_mpi_read_binary(&rsa->P, kb+ofs, len); ofs += len;
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_rsa_free(rsa);
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PQ
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||||
|
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||||
|
r = mbedtls_mpi_read_binary(&rsa->Q, kb+ofs, len); ofs += len;
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_rsa_free(rsa);
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
}
|
||||||
|
//N
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||||
|
r = mbedtls_mpi_read_binary(&rsa->E, kb+ofs, len); ofs += len;
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_rsa_free(rsa);
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_type == 5) {
|
||||||
|
r = mbedtls_rsa_import(rsa, &rsa->N, NULL, NULL, &rsa->D, &rsa->E);
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_rsa_free(rsa);
|
||||||
|
return HSM_EXEC_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key_type == 6) {
|
||||||
|
r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E);
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_rsa_free(rsa);
|
||||||
|
return HSM_EXEC_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = mbedtls_rsa_complete(rsa);
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_rsa_free(rsa);
|
||||||
|
return HSM_EXEC_ERROR;
|
||||||
|
}
|
||||||
|
r = mbedtls_rsa_check_privkey(rsa);
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_rsa_free(rsa);
|
||||||
|
return HSM_EXEC_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key_type == 12) {
|
||||||
|
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx;
|
||||||
|
mbedtls_ecdsa_init(ecdsa);
|
||||||
|
|
||||||
|
//A
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||||
|
|
||||||
|
//B
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||||
|
|
||||||
|
//P
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||||
|
mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(kb+ofs, len);
|
||||||
|
if (ec_id == MBEDTLS_ECP_DP_NONE) {
|
||||||
|
mbedtls_ecdsa_free(ecdsa);
|
||||||
|
return HSM_WRONG_DATA;
|
||||||
|
}
|
||||||
|
ofs += len;
|
||||||
|
|
||||||
|
//N
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||||
|
|
||||||
|
//G
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||||
|
|
||||||
|
//d
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||||
|
r = mbedtls_ecp_read_key(ec_id, ecdsa, kb+ofs, len);
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_ecdsa_free(ecdsa);
|
||||||
|
return HSM_EXEC_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key_type == 15) {
|
||||||
|
memcpy(key_ctx, kb+ofs, key_size);
|
||||||
|
}
|
||||||
|
return HSM_OK;
|
||||||
|
}
|
||||||
36
src/hsm/dkek.h
Normal file
36
src/hsm/dkek.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
|
||||||
|
* Copyright (c) 2022 Pol Henarejos.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DKEK_H_
|
||||||
|
#define _DKEK_H_
|
||||||
|
|
||||||
|
extern int load_dkek();
|
||||||
|
extern int save_dkek_key(const uint8_t *key);
|
||||||
|
extern int store_dkek_key();
|
||||||
|
extern void init_dkek();
|
||||||
|
extern void release_dkek();
|
||||||
|
extern void import_dkek_share(const uint8_t *share);
|
||||||
|
extern int dkek_kcv(uint8_t *kcv);
|
||||||
|
extern int dkek_encrypt(uint8_t *data, size_t len);
|
||||||
|
extern int dkek_decrypt(uint8_t *data, size_t len);
|
||||||
|
extern int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len);
|
||||||
|
extern int dkek_type_key(const uint8_t *in);
|
||||||
|
extern int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out);
|
||||||
|
|
||||||
|
#define MAX_DKEK_ENCODE_KEY_BUFFER (8+1+12+6+(8+2*4+2*4096/8+3+13)+16)
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "pico/multicore.h"
|
#include "pico/multicore.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "hsm2040.h"
|
#include "hsm2040.h"
|
||||||
|
#include "hardware/rtc.h"
|
||||||
|
|
||||||
extern void do_flash();
|
extern void do_flash();
|
||||||
extern void low_flash_init();
|
extern void low_flash_init();
|
||||||
@@ -1570,6 +1571,7 @@ void tud_mount_cb()
|
|||||||
|
|
||||||
void led_blinking_task()
|
void led_blinking_task()
|
||||||
{
|
{
|
||||||
|
#ifdef PICO_DEFAULT_LED_PIN
|
||||||
static uint32_t start_ms = 0;
|
static uint32_t start_ms = 0;
|
||||||
static uint8_t led_state = false;
|
static uint8_t led_state = false;
|
||||||
static uint8_t led_color = PICO_DEFAULT_LED_PIN;
|
static uint8_t led_color = PICO_DEFAULT_LED_PIN;
|
||||||
@@ -1587,6 +1589,7 @@ void led_blinking_task()
|
|||||||
|
|
||||||
gpio_put(led_color, led_state);
|
gpio_put(led_color, led_state);
|
||||||
led_state ^= 1; // toggle
|
led_state ^= 1; // toggle
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void led_off_all()
|
void led_off_all()
|
||||||
@@ -1596,8 +1599,10 @@ void led_off_all()
|
|||||||
gpio_put(TINY2040_LED_G_PIN, 1);
|
gpio_put(TINY2040_LED_G_PIN, 1);
|
||||||
gpio_put(TINY2040_LED_B_PIN, 1);
|
gpio_put(TINY2040_LED_B_PIN, 1);
|
||||||
#else
|
#else
|
||||||
|
#ifdef PICO_DEFAULT_LED_PIN
|
||||||
gpio_put(PICO_DEFAULT_LED_PIN, 0);
|
gpio_put(PICO_DEFAULT_LED_PIN, 0);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void neug_task();
|
extern void neug_task();
|
||||||
@@ -1619,9 +1624,12 @@ int main(void)
|
|||||||
gpio_init(TINY2040_LED_B_PIN);
|
gpio_init(TINY2040_LED_B_PIN);
|
||||||
gpio_set_dir(TINY2040_LED_B_PIN, GPIO_OUT);
|
gpio_set_dir(TINY2040_LED_B_PIN, GPIO_OUT);
|
||||||
#else
|
#else
|
||||||
|
#ifdef PICO_DEFAULT_LED_PIN
|
||||||
gpio_init(PICO_DEFAULT_LED_PIN);
|
gpio_init(PICO_DEFAULT_LED_PIN);
|
||||||
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
led_off_all();
|
led_off_all();
|
||||||
|
|
||||||
@@ -1632,6 +1640,8 @@ int main(void)
|
|||||||
random_init();
|
random_init();
|
||||||
|
|
||||||
low_flash_init();
|
low_flash_init();
|
||||||
|
|
||||||
|
rtc_init();
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
|||||||
774
src/hsm/sc_hsm.c
774
src/hsm/sc_hsm.c
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,6 @@ extern const uint8_t sc_hsm_aid[];
|
|||||||
|
|
||||||
#define SW_BYTES_REMAINING_00() set_res_sw (0x61, 0x00)
|
#define SW_BYTES_REMAINING_00() set_res_sw (0x61, 0x00)
|
||||||
#define SW_WARNING_STATE_UNCHANGED() set_res_sw (0x62, 0x00)
|
#define SW_WARNING_STATE_UNCHANGED() set_res_sw (0x62, 0x00)
|
||||||
#define SW_PIN_BLOCKED() set_res_sw (0x63, 0x00)
|
|
||||||
#define SW_EXEC_ERROR() set_res_sw (0x64, 0x00)
|
#define SW_EXEC_ERROR() set_res_sw (0x64, 0x00)
|
||||||
#define SW_MEMORY_FAILURE() set_res_sw (0x65, 0x81)
|
#define SW_MEMORY_FAILURE() set_res_sw (0x65, 0x81)
|
||||||
#define SW_WRONG_LENGTH() set_res_sw (0x67, 0x00)
|
#define SW_WRONG_LENGTH() set_res_sw (0x67, 0x00)
|
||||||
@@ -34,7 +33,7 @@ extern const uint8_t sc_hsm_aid[];
|
|||||||
#define SW_LOGICAL_CHANNEL_NOT_SUPPORTED() set_res_sw (0x68, 0x81)
|
#define SW_LOGICAL_CHANNEL_NOT_SUPPORTED() set_res_sw (0x68, 0x81)
|
||||||
#define SW_SECURE_MESSAGING_NOT_SUPPORTED() set_res_sw (0x68, 0x82)
|
#define SW_SECURE_MESSAGING_NOT_SUPPORTED() set_res_sw (0x68, 0x82)
|
||||||
#define SW_SECURITY_STATUS_NOT_SATISFIED() set_res_sw (0x69, 0x82)
|
#define SW_SECURITY_STATUS_NOT_SATISFIED() set_res_sw (0x69, 0x82)
|
||||||
#define SW_FILE_INVALID() set_res_sw (0x69, 0x83)
|
#define SW_PIN_BLOCKED() set_res_sw (0x69, 0x83)
|
||||||
#define SW_DATA_INVALID() set_res_sw (0x69, 0x84)
|
#define SW_DATA_INVALID() set_res_sw (0x69, 0x84)
|
||||||
#define SW_CONDITIONS_NOT_SATISFIED() set_res_sw (0x69, 0x85)
|
#define SW_CONDITIONS_NOT_SATISFIED() set_res_sw (0x69, 0x85)
|
||||||
#define SW_COMMAND_NOT_ALLOWED() set_res_sw (0x69, 0x86)
|
#define SW_COMMAND_NOT_ALLOWED() set_res_sw (0x69, 0x86)
|
||||||
@@ -60,6 +59,11 @@ extern const uint8_t sc_hsm_aid[];
|
|||||||
#define HSM_ERR_BLOCKED -1004
|
#define HSM_ERR_BLOCKED -1004
|
||||||
#define HSM_NO_LOGIN -1005
|
#define HSM_NO_LOGIN -1005
|
||||||
#define HSM_EXEC_ERROR -1006
|
#define HSM_EXEC_ERROR -1006
|
||||||
|
#define HSM_WRONG_LENGTH -1007
|
||||||
|
#define HSM_WRONG_DATA -1008
|
||||||
|
#define HSM_WRONG_DKEK -1009
|
||||||
|
#define HSM_WRONG_SIGNATURE -1010
|
||||||
|
#define HSM_WRONG_PADDING -1011
|
||||||
|
|
||||||
#define ALGO_RSA_RAW 0x20 /* RSA signature with external padding */
|
#define ALGO_RSA_RAW 0x20 /* RSA signature with external padding */
|
||||||
#define ALGO_RSA_DECRYPT 0x21 /* RSA decrypt */
|
#define ALGO_RSA_DECRYPT 0x21 /* RSA decrypt */
|
||||||
@@ -84,6 +88,18 @@ extern const uint8_t sc_hsm_aid[];
|
|||||||
#define ALGO_AES_CMAC 0x18
|
#define ALGO_AES_CMAC 0x18
|
||||||
#define ALGO_AES_DERIVE 0x99
|
#define ALGO_AES_DERIVE 0x99
|
||||||
|
|
||||||
|
#define HSM_OPT_RRC 0x1
|
||||||
|
#define HSM_OPT_TRANSPORT_PIN 0x2
|
||||||
|
#define HSM_OPT_SESSION_PIN 0x4
|
||||||
|
#define HSM_OPT_SESSION_PIN_EXPL 0xC
|
||||||
|
#define HSM_OPT_REPLACE_PKA 0x8
|
||||||
|
#define HSM_OPT_COMBINED_AUTH 0x10
|
||||||
|
#define HSM_OPT_RRC_RESET_ONLY 0x20
|
||||||
|
|
||||||
|
#define P15_KEYTYPE_RSA 0x30
|
||||||
|
#define P15_KEYTYPE_ECC 0xA0
|
||||||
|
#define P15_KEYTYPE_AES 0xA8
|
||||||
|
|
||||||
extern int pin_reset_retries(const file_t *pin, bool);
|
extern int pin_reset_retries(const file_t *pin, bool);
|
||||||
extern int pin_wrong_retry(const file_t *pin);
|
extern int pin_wrong_retry(const file_t *pin);
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef __VERSION_H_
|
#ifndef __VERSION_H_
|
||||||
#define __VERSION_H_
|
#define __VERSION_H_
|
||||||
|
|
||||||
#define HSM_VERSION 0x0104
|
#define HSM_VERSION 0x010A
|
||||||
|
|
||||||
#define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff)
|
#define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff)
|
||||||
#define HSM_VERSION_MINOR (HSM_VERSION & 0xff)
|
#define HSM_VERSION_MINOR (HSM_VERSION & 0xff)
|
||||||
|
|||||||
@@ -19,6 +19,9 @@
|
|||||||
#ifndef _RANDOM_H_
|
#ifndef _RANDOM_H_
|
||||||
#define _RANDOM_H_
|
#define _RANDOM_H_
|
||||||
|
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
void random_init (void);
|
void random_init (void);
|
||||||
void random_fini (void);
|
void random_fini (void);
|
||||||
|
|
||||||
|
|||||||
@@ -1,273 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2009-2015 Frank Morgner
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*/
|
|
||||||
#ifndef _CCID_TYPES_H
|
|
||||||
#define _CCID_TYPES_H
|
|
||||||
|
|
||||||
#include "pico/types.h"
|
|
||||||
#include "hardware/structs/usb.h"
|
|
||||||
|
|
||||||
#define USB_REQ_CCID 0xA1
|
|
||||||
|
|
||||||
#define CCID_CONTROL_ABORT 0x01
|
|
||||||
#define CCID_CONTROL_GET_CLOCK_FREQUENCIES 0x02
|
|
||||||
#define CCID_CONTROL_GET_DATA_RATES 0x03
|
|
||||||
|
|
||||||
#define CCID_OPERATION_VERIFY 0x00;
|
|
||||||
#define CCID_OPERATION_MODIFY 0x01;
|
|
||||||
#define CCID_ENTRY_VALIDATE 0x02
|
|
||||||
|
|
||||||
#define CCID_BERROR_CMD_ABORTED 0xff /** Host aborted the current activity */
|
|
||||||
#define CCID_BERROR_ICC_MUTE 0xfe /** CCID timed out while talking to the ICC */
|
|
||||||
#define CCID_BERROR_XFR_PARITY_ERROR 0xfd /** Parity error while talking to the ICC */
|
|
||||||
#define CCID_BERROR_XFR_OVERRUN 0xfc /** Overrun error while talking to the ICC */
|
|
||||||
#define CCID_BERROR_HW_ERROR 0xfb /** An all inclusive hardware error occurred */
|
|
||||||
#define CCID_BERROR_BAD_ATR_TS 0xf
|
|
||||||
#define CCID_BERROR_BAD_ATR_TCK 0xf
|
|
||||||
#define CCID_BERROR_ICC_PROTOCOL_NOT_SUPPORTED 0xf6
|
|
||||||
#define CCID_BERROR_ICC_CLASS_NOT_SUPPORTED 0xf5
|
|
||||||
#define CCID_BERROR_PROCEDURE_BYTE_CONFLICT 0xf4
|
|
||||||
#define CCID_BERROR_DEACTIVATED_PROTOCOL 0xf3
|
|
||||||
#define CCID_BERROR_BUSY_WITH_AUTO_SEQUENCE 0xf2 /** Automatic Sequence Ongoing */
|
|
||||||
#define CCID_BERROR_PIN_TIMEOUT 0xf0
|
|
||||||
#define CCID_BERROR_PIN_CANCELLED 0xef
|
|
||||||
#define CCID_BERROR_CMD_SLOT_BUSY 0xe0 /** A second command was sent to a slot which was already processing a command. */
|
|
||||||
#define CCID_BERROR_CMD_NOT_SUPPORTED 0x00
|
|
||||||
#define CCID_BERROR_OK 0x00
|
|
||||||
|
|
||||||
#define CCID_BSTATUS_OK_ACTIVE 0x00 /** No error. An ICC is present and active */
|
|
||||||
#define CCID_BSTATUS_OK_INACTIVE 0x01 /** No error. ICC is present and inactive */
|
|
||||||
#define CCID_BSTATUS_OK_NOICC 0x02 /** No error. No ICC is present */
|
|
||||||
#define CCID_BSTATUS_ERROR_ACTIVE 0x40 /** Failed. An ICC is present and active */
|
|
||||||
#define CCID_BSTATUS_ERROR_INACTIVE 0x41 /** Failed. ICC is present and inactive */
|
|
||||||
#define CCID_BSTATUS_ERROR_NOICC 0x42 /** Failed. No ICC is present */
|
|
||||||
|
|
||||||
#define CCID_WLEVEL_DIRECT __constant_cpu_to_le16(0) /** APDU begins and ends with this command */
|
|
||||||
#define CCID_WLEVEL_CHAIN_NEXT_XFRBLOCK __constant_cpu_to_le16(1) /** APDU begins with this command, and continue in the next PC_to_RDR_XfrBlock */
|
|
||||||
#define CCID_WLEVEL_CHAIN_END __constant_cpu_to_le16(2) /** abData field continues a command APDU and ends the APDU command */
|
|
||||||
#define CCID_WLEVEL_CHAIN_CONTINUE __constant_cpu_to_le16(3) /** abData field continues a command APDU and another block is to follow */
|
|
||||||
#define CCID_WLEVEL_RESPONSE_IN_DATABLOCK __constant_cpu_to_le16(0x10) /** empty abData field, continuation of response APDU is expected in the next RDR_to_PC_DataBlock */
|
|
||||||
|
|
||||||
#define CCID_PIN_ENCODING_BIN 0x00
|
|
||||||
#define CCID_PIN_ENCODING_BCD 0x01
|
|
||||||
#define CCID_PIN_ENCODING_ASCII 0x02
|
|
||||||
#define CCID_PIN_UNITS_BYTES 0x80
|
|
||||||
#define CCID_PIN_JUSTIFY_RIGHT 0x04
|
|
||||||
#define CCID_PIN_CONFIRM_NEW 0x01
|
|
||||||
#define CCID_PIN_INSERT_OLD 0x02
|
|
||||||
#define CCID_PIN_NO_MSG 0x00
|
|
||||||
#define CCID_PIN_MSG1 0x01
|
|
||||||
#define CCID_PIN_MSG2 0x02
|
|
||||||
#define CCID_PIN_MSG_REF 0x03
|
|
||||||
#define CCID_PIN_MSG_DEFAULT 0xff
|
|
||||||
|
|
||||||
#define CCID_SLOTS_UNCHANGED 0x00
|
|
||||||
#define CCID_SLOT1_CARD_PRESENT 0x01
|
|
||||||
#define CCID_SLOT1_CHANGED 0x02
|
|
||||||
#define CCID_SLOT2_CARD_PRESENT 0x04
|
|
||||||
#define CCID_SLOT2_CHANGED 0x08
|
|
||||||
#define CCID_SLOT3_CARD_PRESENT 0x10
|
|
||||||
#define CCID_SLOT3_CHANGED 0x20
|
|
||||||
#define CCID_SLOT4_CARD_PRESENT 0x40
|
|
||||||
#define CCID_SLOT4_CHANGED 0x80
|
|
||||||
|
|
||||||
#define CCID_EXT_APDU_MAX (4 + 3 + 0xffff + 3)
|
|
||||||
#define CCID_SHORT_APDU_MAX (4 + 1 + 0xff + 1)
|
|
||||||
|
|
||||||
typedef struct TU_ATTR_PACKED {
|
|
||||||
uint8_t bLength;
|
|
||||||
uint8_t bDescriptorType;
|
|
||||||
uint16_t bcdCCID;
|
|
||||||
uint8_t bMaxSlotIndex;
|
|
||||||
uint8_t bVoltageSupport;
|
|
||||||
uint32_t dwProtocols;
|
|
||||||
uint32_t dwDefaultClock;
|
|
||||||
uint32_t dwMaximumClock;
|
|
||||||
uint8_t bNumClockSupport;
|
|
||||||
uint32_t dwDataRate;
|
|
||||||
uint32_t dwMaxDataRate;
|
|
||||||
uint8_t bNumDataRatesSupported;
|
|
||||||
uint32_t dwMaxIFSD;
|
|
||||||
uint32_t dwSynchProtocols;
|
|
||||||
uint32_t dwMechanical;
|
|
||||||
uint32_t dwFeatures;
|
|
||||||
uint32_t dwMaxCCIDMessageLength;
|
|
||||||
uint8_t bClassGetResponse;
|
|
||||||
uint8_t bclassEnvelope;
|
|
||||||
uint16_t wLcdLayout;
|
|
||||||
uint8_t bPINSupport;
|
|
||||||
uint8_t bMaxCCIDBusySlots;
|
|
||||||
} class_desc_ccid_t;
|
|
||||||
|
|
||||||
struct abProtocolDataStructure_T0 {
|
|
||||||
uint8_t bmFindexDindex;
|
|
||||||
uint8_t bmTCCKST0;
|
|
||||||
uint8_t bGuardTimeT0;
|
|
||||||
uint8_t bWaitingIntegerT0;
|
|
||||||
uint8_t bClockStop;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct abProtocolDataStructure_T1 {
|
|
||||||
uint8_t bmFindexDindex;
|
|
||||||
uint8_t bmTCCKST1;
|
|
||||||
uint8_t bGuardTimeT1;
|
|
||||||
uint8_t bWaitingIntegersT1;
|
|
||||||
uint8_t bClockStop;
|
|
||||||
uint8_t bIFSC;
|
|
||||||
uint8_t bNadValue;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct abPINDataStucture_Verification {
|
|
||||||
uint8_t bTimeOut;
|
|
||||||
uint8_t bmFormatString;
|
|
||||||
uint8_t bmPINBlockString;
|
|
||||||
uint8_t bmPINLengthFormat;
|
|
||||||
uint16_t wPINMaxExtraDigit;
|
|
||||||
uint8_t bEntryValidationCondition;
|
|
||||||
uint8_t bNumberMessage;
|
|
||||||
uint16_t wLangId;
|
|
||||||
uint8_t bMsgIndex;
|
|
||||||
uint8_t bTeoPrologue1;
|
|
||||||
uint16_t bTeoPrologue2;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct abPINDataStucture_Modification {
|
|
||||||
uint8_t bTimeOut;
|
|
||||||
uint8_t bmFormatString;
|
|
||||||
uint8_t bmPINBlockString;
|
|
||||||
uint8_t bmPINLengthFormat;
|
|
||||||
uint8_t bInsertionOffsetOld;
|
|
||||||
uint8_t bInsertionOffsetNew;
|
|
||||||
uint16_t wPINMaxExtraDigit;
|
|
||||||
uint8_t bConfirmPIN;
|
|
||||||
uint8_t bEntryValidationCondition;
|
|
||||||
uint8_t bNumberMessage;
|
|
||||||
uint16_t wLangId;
|
|
||||||
uint8_t bMsgIndex1;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct PC_to_RDR_XfrBlock {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t bBWI;
|
|
||||||
uint16_t wLevelParameter;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct PC_to_RDR_IccPowerOff {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t abRFU1;
|
|
||||||
uint16_t abRFU2;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct PC_to_RDR_GetSlotStatus {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t abRFU1;
|
|
||||||
uint16_t abRFU2;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct PC_to_RDR_GetParameters {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t abRFU1;
|
|
||||||
uint16_t abRFU2;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct PC_to_RDR_ResetParameters {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t abRFU1;
|
|
||||||
uint16_t abRFU2;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct PC_to_RDR_SetParameters {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t bProtocolNum;
|
|
||||||
uint16_t abRFU;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct PC_to_RDR_Secure {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t bBWI;
|
|
||||||
uint16_t wLevelParameter;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct PC_to_RDR_IccPowerOn {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t bPowerSelect;
|
|
||||||
uint16_t abRFU;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct RDR_to_PC_SlotStatus {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t bStatus;
|
|
||||||
uint8_t bError;
|
|
||||||
uint8_t bClockStatus;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct RDR_to_PC_DataBlock {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t bStatus;
|
|
||||||
uint8_t bError;
|
|
||||||
uint8_t bChainParameter;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct RDR_to_PC_Parameters {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint32_t dwLength;
|
|
||||||
uint8_t bSlot;
|
|
||||||
uint8_t bSeq;
|
|
||||||
uint8_t bStatus;
|
|
||||||
uint8_t bError;
|
|
||||||
uint8_t bProtocolNum;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct RDR_to_PC_NotifySlotChange {
|
|
||||||
uint8_t bMessageType;
|
|
||||||
uint8_t bmSlotICCState; /* we support 1 slots, so we need 2*1 bits = 1 byte */
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user