diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..07a08ad --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,50 @@ +## Summary + +Describe in plain language what this PR does and why. + +- What problem does it solve? +- Is it a bug fix, a new feature, a cleanup/refactor…? + + +## Details / Impact + +Please include any relevant details: + +- Hardware / board(s) tested: +- Firmware / commit/base version: +- Security impact (if any): + - e.g. changes PIN handling, touches key storage, affects attestation, etc. +- Behavior changes: + - e.g. new command, new API surface, different defaults, etc. + + +## Testing + +How did you test this change? + +- Steps to reproduce / validate: +- Expected vs actual results: +- Any logs / traces (please remove secrets): + + +## Licensing confirmation (required) + +By checking the box below, you confirm ALL of the following: + +- You are the author of this contribution, or you have the right to contribute it. +- You have read `CONTRIBUTING.md`. +- You agree that this contribution may be merged, used, modified, and redistributed: + - under the AGPLv3 Community Edition, **and** + - under any proprietary / commercial / Enterprise editions of this project, + now or in the future. +- You understand that submitting this PR does not create any support obligation, + SLA, or guarantee of merge. + +**I confirm the above licensing terms:** + +- [ ] Yes, I agree + + +## Anything else? + +Optional: mention known limitations, follow-ups, or if this is related to an existing Issue. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ac193da --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,105 @@ +# Contributing + +Thank you for your interest in contributing to this project. + +This repository is published in two forms: +- a Community Edition released under AGPLv3, and +- a proprietary / commercial / Enterprise Edition offered to organizations. + +To keep that model legally clean, we need to be explicit about how contributions can be used. + +By opening a pull request, you agree to all of the following: + +1. **You have the right to contribute this code.** + You are either the original author of the contribution, or you have obtained the necessary rights/permissions to contribute it under these terms. + +2. **Dual licensing permission.** + You agree that your contribution may be: + - merged into this repository, and + - used, copied, modified, sublicensed, and redistributed + - under the AGPLv3 Community Edition, and + - under any proprietary / commercial / Enterprise editions of this project, + now or in the future. + + In other words: you are granting the project maintainer(s) the right to include + your contribution in both the open-source (AGPLv3) codebase and in closed-source / + commercially licensed builds, without any additional approval or payment. + +3. **Attribution.** + The maintainers may keep or add attribution lines such as + `Copyright (c) ` or an AUTHORS / CONTRIBUTORS list. + The maintainers may also make changes for clarity, style, security, refactoring, + or integration reasons. + +4. **No automatic SLA.** + Submitting a pull request does *not* create any support obligation, + service-level agreement, warranty, or guarantee that the contribution + will be reviewed, merged, or maintained. + +5. **Potential rejection for business reasons.** + Features that fall under "Enterprise / Commercial" functionality + (e.g. multi-tenant provisioning at scale, centralized audit trails, + corporate policy enforcement, attestation/branding flows, key escrow / dual-control, + etc.) may be declined for the public AGPLv3 tree even if technically valid. + That is normal: some functionality is intentionally offered only + under commercial terms. + +If you are not comfortable with these terms, **do not open a pull request yet.** +Instead, please open an Issue to start a discussion. + +## How to contribute (technical side) + +### 1. Bug reports / issues +- Please include: + - hardware / board revision + - firmware / commit hash + - exact steps to reproduce + - expected vs actual behavior + - logs / traces if available (strip secrets) + +Security-sensitive findings: do **not** post publicly. +Send a short report by email instead so it can be triaged responsibly. + +### 2. Small fixes / minor improvements +- You can open a PR directly for: + - bug fixes + - portability fixes / new board definitions + - clarifications in code comments + - build / tooling cleanup + - documentation of existing behavior + +Please keep PRs focused (one logical change per PR if possible). + +### 3. Larger features / behavior changes +- Please open an Issue first and describe: + - what problem you're solving (not just "add feature X") + - impact on existing flows / security model + - any new dependencies + +This helps avoid doing a bunch of work on something that won't be accepted +in the Community Edition. + +### 4. Coding style / security posture +- Aim for clarity and small, auditable changes. This code runs in places + where secrets live. +- No debug backdoors, no "just for testing" shortcuts left enabled. +- Keep external dependencies minimal and license-compatible + (MIT / Apache 2.0 / similarly permissive is usually fine). + +### 5. Commit / PR format +- Use descriptive commit messages ("Fix PIN retry counter wrap" is better than "fix stuff"). +- In the PR description, please include a short summary of what was changed and why. +- At the bottom of the PR description, **copy/paste and confirm the licensing line below**: + + > I confirm that I have read `CONTRIBUTING.md` and I agree that this contribution may be used under both the AGPLv3 Community Edition and any proprietary / commercial / Enterprise editions of this project, now or in the future. + +A PR without that confirmation may be delayed or closed without merge. + +## Thank you + +This project exists because people build on it, break it, fix it, +and push it into places it wasn't originally designed to go. + +Whether you are here for research, hacking on hardware, +rolling out secure keys for a team, or building a commercial product: +thank you for helping improve it. diff --git a/ENTERPRISE.md b/ENTERPRISE.md new file mode 100644 index 0000000..f550fed --- /dev/null +++ b/ENTERPRISE.md @@ -0,0 +1,116 @@ +# Enterprise / Commercial Edition + +This project is offered under two editions: + +## 1. Community Edition (FOSS) + +The Community Edition is released under the GNU Affero General Public License v3 (AGPLv3). + +Intended for: +- individual users and researchers +- evaluation / prototyping +- internal lab / security testing + +You are allowed to: +- read and study the source code +- modify it +- run it internally + +Obligations under AGPLv3: +- If you distribute modified firmware/binaries/libraries to third parties, you must provide the corresponding source code of your modifications. +- If you run a modified version of this project as a network-accessible service (internal or external), you must offer the source code of those modifications to the users of that service. +- No warranty, no support, no SLA. +- Enterprise features (bulk provisioning, multi-user policy enforcement, device inventory / revocation, corporate PIN rules, custom attestation/identity, etc.) are NOT included. + +The Community Edition will continue to exist. + +## 2. Enterprise / Commercial Edition + +The Enterprise / Commercial Edition is a proprietary license for organizations that need to: + +- deploy this in production at scale (multiple devices / multiple users / multiple teams) +- integrate it into their own physical product or appliance +- run it as an internal service (VM / container / private cloud "HSM / auth backend") for multiple internal teams or tenants +- enforce internal security policy (admin vs user roles, mandatory PIN rules, secure offboarding / revocation) +- avoid any AGPLv3 disclosure obligations for their own modifications and integration code + +### What the Enterprise Edition provides + +**Base license package (always included):** +- **Commercial license (proprietary).** + You may run and integrate the software/firmware in production — including virtualized / internal-cloud style deployments — without being required to disclose derivative source code under AGPLv3. +- **Official signed builds.** + You receive signed builds from the original developer so you can prove integrity and provenance. +- **Onboarding call (up to 1 hour).** + A live remote session to get you from "we have it" to "it’s actually running in our environment" with minimal guesswork. + +**Optional enterprise components (available on demand, scoped and priced per customer):** +- **Production / multi-user readiness.** + Permission to operate the system with multiple users, multiple devices and multiple teams in real environments. +- **Bulk / fleet provisioning.** + Automated enrollment for many tokens/devices/users at once (CSV / directory import), scripted onboarding of new users, initial PIN assignment / reset workflows, and role-based access (admin vs user). +- **Policy & lifecycle tooling.** + Corporate PIN policy enforcement, per-user / per-team access control, device inventory / traceability, and secure revocation / retirement when someone leaves. +- **Custom attestation / per-organization identity.** + Per-company certificate chains and attestation keys so devices can prove "this token/HSM is officially ours," including anti-cloning / unique device identity for OEM and fleet use. +- **Virtualization / internal cloud deployment support.** + Guidance and components to run this as an internal service (VM, container, private-cloud HSM/auth backend) serving multiple internal teams or tenants under your brand. +- **Post-quantum (PQC) key material handling.** + Integration/roadmap support for PQC algorithms (auth / signing) and secure PQC key storage inside the device or service. +- **Hierarchical deterministic key derivation (HD).** + Wallet-style hierarchical key trees (BIP32-like concepts adapted to this platform) for issuing per-user / per-tenant / per-purpose subkeys without exporting the root secret — e.g. embedded wallet logic, tenant isolation, firmware signing trees, large fleets. +- **Cryptographically signed audit trail / tamper-evident event logging.** + High-assurance logging of sensitive actions (key use, provisioning, PIN resets, revocations) with integrity protection for forensic / compliance needs. +- **Dual-control / two-person approval ("four-eyes").** + Require multi-party authorization for high-risk actions such as firmware signing, key export, or critical configuration changes — standard in high-assurance / regulated environments. +- **Secure key escrow / disaster recovery design.** + Split-secret or escrowed backup strategies so you don’t lose critical signing keys if a single admin disappears or hardware is lost. +- **Release-signing / supply-chain hardening pipeline.** + Reference tooling and process so every production firmware/binary is signed with hardware-backed keys, proving origin and preventing tampering in transit or at manufacturing. +- **Policy-locked hardened mode ("FIPS-style profile").** + Restricted algorithms, debug disabled, no raw key export, tamper-evident configuration for regulated / high-assurance deployments. +- **Priority support / security response SLA.** + A direct line and guaranteed response window for production-impacting security issues. +- **White-label demo / pre-sales bundle.** + Branded demo firmware + safe onboarding script so you can show "your product" to your own customers without exposing real production secrets. + +These components are NOT automatically bundled. They are available case-by-case depending on your use case and are priced separately. + +### Licensing models + +- **Internal Use License** + Internal production use within one legal entity (your company), including internal private cloud / virtualized deployments for multiple internal teams. + Optional enterprise components can be added as needed. + +- **OEM / Redistribution / Service License** + Integration into a product/appliance you ship to customers, OR operating this as a managed service / hosted feature for external clients or third parties. + Optional enterprise components (attestation branding, PQC support, HD key derivation, multi-tenant service hardening, audit trail, etc.) can be added as required. + +Pricing depends on scope, fleet size, number of users/tenants, regulatory requirements, and which optional components you select. + +### Request a quote + +Email: pol@henarejos.me +Subject: `ENTERPRISE LICENSE ` + +Please include: +- Company name and country +- Intended use: + - Internal private deployment + - OEM / external service to third parties +- Approximate scale (number of devices/tokens, number of users/tenants) +- Which optional components you are interested in (bulk provisioning, policy & lifecycle tooling, attestation branding / anti-cloning, virtualization/cloud, PQC, HD key derivation, audit trail, dual-control, key escrow, supply-chain signing, hardened mode, SLA, white-label demo) + +You will receive: +1. A short commercial license agreement naming your company. +2. Access to the base package (and any optional components agreed). +3. Scheduling of the onboarding call. + +## Why Enterprise exists + +- Companies often need hardware-backed security (HSM, FIDO2, OpenPGP, etc.) under their own control, but cannot or will not open-source their internal security workflows. +- They also need multi-user / fleet-management features that hobby users do not. +- The commercial license funds continued development, maintenance and new hardware support. + +The Community Edition remains AGPLv3. +The Enterprise Edition is for production, scale, and legal clarity. diff --git a/README.md b/README.md index 8949430..3acccca 100644 --- a/README.md +++ b/README.md @@ -366,12 +366,32 @@ This project is available under two editions: - run this in production with multiple users/devices, - integrate it into their own product/appliance, - enforce corporate policies (PIN policy, admin/user roles, revocation), + - deploy it as an internal virtualized / cloud-style service, - and *not* be required to publish derivative source code. -- Includes access to enterprise-only features (bulk provisioning, multi-user policy controls, device inventory & revocation, custom attestation/identity), official signed builds, and an onboarding call. +- Base package includes: + - commercial license (no AGPLv3 disclosure obligation for your modifications / integration) + - onboarding call + - access to officially signed builds +- Optional / on-demand enterprise components that can be added case-by-case: + - ability to operate in multi-user / multi-device environments + - device inventory, traceability and secure revocation/offboarding + - custom attestation, per-organization device identity / anti-cloning + - virtualization / internal "HSM or auth backend" service for multiple teams or tenants + - post-quantum (PQC) key material handling and secure PQC credential storage + - hierarchical deterministic key derivation (HD wallet–style key trees for per-user / per-tenant keys, firmware signing trees, etc.) + - cryptographically signed audit trail / tamper-evident logging + - dual-control / two-person approval for high-risk operations + - secure key escrow / disaster recovery strategy + - release-signing / supply-chain hardening toolchain + - policy-locked hardened mode ("FIPS-style profile") + - priority security-response SLA + - white-label demo / pre-sales bundle Typical licensing models: -- Internal use (within one legal entity). -- Redistribution / OEM (shipping this as part of your product). +- Internal use (single legal entity, including internal private cloud / virtualized deployments). +- OEM / Redistribution / Service (ship in your product OR offer it as a service to third parties). + +These options are scoped and priced individually depending on which components you actually need. For commercial licensing and enterprise features, email pol@henarejos.me Subject: `ENTERPRISE LICENSE ` diff --git a/build_pico_hsm.sh b/build_pico_hsm.sh index 61aed7b..c4753b1 100755 --- a/build_pico_hsm.sh +++ b/build_pico_hsm.sh @@ -1,7 +1,7 @@ #!/bin/bash -VERSION_MAJOR="5" -VERSION_MINOR="6" +VERSION_MAJOR="6" +VERSION_MINOR="0" NO_EDDSA=0 SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}" #if ! [[ -z "${GITHUB_SHA}" ]]; then diff --git a/pico-keys-sdk b/pico-keys-sdk index 8f907b2..c1cc33f 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 8f907b25ba28cea4f8312e627862352fc012a8a2 +Subproject commit c1cc33fd9d6b4c2c8fb18f0254130e37f978724b diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 08fa973..587bae1 100755 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -10,6 +10,8 @@ CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="pico-keys-sdk/config/esp32/partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="pico-keys-sdk/config/esp32/partitions.csv" CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y CONFIG_WL_SECTOR_SIZE_512=y CONFIG_WL_SECTOR_MODE_PERF=y COMPILER_OPTIMIZATION="Performance" diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index c69d99b..59d453e 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -26,6 +26,7 @@ #include "pico_keys.h" #include "usb.h" #include "random.h" +#include "version.h" const uint8_t sc_hsm_aid[] = { 11, @@ -44,6 +45,8 @@ const uint8_t *dev_name = NULL; uint16_t dev_name_len = 0; uint8_t PICO_PRODUCT = 1; +uint8_t PICO_VERSION_MAJOR = HSM_VERSION_MAJOR; +uint8_t PICO_VERSION_MINOR = HSM_VERSION_MINOR; static int sc_hsm_process_apdu(); diff --git a/src/hsm/version.h b/src/hsm/version.h index 9b9feb4..880a245 100644 --- a/src/hsm/version.h +++ b/src/hsm/version.h @@ -18,7 +18,7 @@ #ifndef __VERSION_H_ #define __VERSION_H_ -#define HSM_VERSION 0x0506 +#define HSM_VERSION 0x0600 #define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff) #define HSM_VERSION_MINOR (HSM_VERSION & 0xff) diff --git a/tests/const.py b/tests/const.py index 382c1f3..c6e6124 100644 --- a/tests/const.py +++ b/tests/const.py @@ -21,5 +21,5 @@ from binascii import unhexlify DEFAULT_DKEK = [0x1] * 32 -TERM_CERT = unhexlify('7F2181E57F4E819E5F290100421045535049434F48534D445630303030317F494F060A04007F00070202020203864104F571E53AA8E75C929D925081CF0F893CB5991D48BD546C1A3F22199F037E4B12D601ACD91C67C88D3C5B3D04C08EC0A372485F7A248E080EE0C6237C1B075E1C5F201045535049434F48534D54525A474E50327F4C0E060904007F0007030102025301005F25060203000300055F24060204000300045F374041BF5E970739135770DBCC5DDA81FFD8B13419A9257D44CAF8404267C644E8F435B43F5E57EB2A8CF4B198045ACD094E0CB34E6217D9C8922CFB9BBEFD4088AD') -DICA_CERT = unhexlify('7F2181E97F4E81A25F290100421045535049434F48534D434130303030317F494F060A04007F0007020202020386410421EE4A21C16A10F737F12E78E5091B266612038CDABEBB722B15BF6D41B877FBF64D9AB69C39B9831B1AE00BEF2A4E81976F7688D45189BB232A24703D8A96A55F201045535049434F48534D445630303030317F4C12060904007F000703010202530580000000005F25060202000801085F24060203000601045F37403F75C08FFFC9186B56E6147199E82BFC327CEEF72495BC567961CD54D702F13E3C2766FCD1D11BD6A9D1F4A229B76B248CEB9AF88D59A74D0AB149448705159B') +TERM_CERT = unhexlify('7f2181e57f4e819e5f290100421045535049434f48534d445630303030327f494f060a04007f000702020202038641043400e4f42ea8b78b2ab58d24c8297a4b1c13a73a631b531e58d0efb60d70dd6666c8fce4130e9b15ffa4ad29708d32764ac4b0cc0e5301898522f4c735f5a90d5f201045535049434f48534d54524c524134437f4c0e060904007f0007030102025301005f25060205010102085f24060206010102085f3740569f6fe91796f95fa77ecdb680468417eed7b4e00ccc2e091a6b56389213f913c4cf91da96fbcb12d363fead30a5598f737975d58b5170b7f45e9e87ec546883') +DICA_CERT = unhexlify('7f2181e97f4e81a25f290100421045535049434f48534d434130303030327f494f060a04007f00070202020203864104e66b473ec328caf39eaed840f9c7a4ba237e1dd19004861fa3f4f134bd2d5ea5f71c6c2e6321add4c8a7793ba41119c5783f48a5d9dfc0898d9ae9e7b14da8d65f201045535049434f48534d445630303030327f4c12060904007f000703010202530580000000045f25060205000400065f24060206000400065f3740a645594c6c338cd6bda6cad039cee54fd822b1011c0af1e4e3a2a6d03d43bdbb8be68a66a8757e7b1f963589bdd80d8e65de5055b722609041ec63f0498ddc8b') diff --git a/tests/docker/bullseye/Dockerfile b/tests/docker/bullseye/Dockerfile index 4f89b6f..4728502 100644 --- a/tests/docker/bullseye/Dockerfile +++ b/tests/docker/bullseye/Dockerfile @@ -24,11 +24,11 @@ RUN apt install -y libccid \ cmake \ vsmartcard-vpcd \ && rm -rf /var/lib/apt/lists/* -RUN pip3 install pytest pycvc cryptography pyscard==2.2.1 base58 +RUN pip3 install pytest pycvc cryptography base58 WORKDIR / RUN git clone https://github.com/OpenSC/OpenSC WORKDIR /OpenSC -RUN git checkout tags/0.25.1 +RUN git checkout tags/0.26.1 RUN ./bootstrap RUN ./configure --enable-openssl RUN make -j `nproc` @@ -37,7 +37,9 @@ RUN make clean RUN ldconfig WORKDIR / RUN git clone https://github.com/polhenarejos/pypicohsm.git -RUN pip3 install -e pypicohsm +WORKDIR /pypicohsm +RUN pip3 install . +WORKDIR / RUN git clone https://github.com/CardContact/sc-hsm-embedded WORKDIR /sc-hsm-embedded RUN autoreconf -fi diff --git a/tests/pico-hsm/test_000_info.py b/tests/pico-hsm/test_000_info.py index 79ffb33..3e885b5 100644 --- a/tests/pico-hsm/test_000_info.py +++ b/tests/pico-hsm/test_000_info.py @@ -23,7 +23,7 @@ def test_select(device): device.select_applet() def test_initialization(device): - device.initialize() + device.initialize(no_dev_cert=True) def test_termca(device): data = device.get_termca() diff --git a/tests/pico-hsm/test_004_key_domains.py b/tests/pico-hsm/test_004_key_domains.py index 4176d8d..6330c42 100644 --- a/tests/pico-hsm/test_004_key_domains.py +++ b/tests/pico-hsm/test_004_key_domains.py @@ -20,14 +20,14 @@ import pytest import hashlib from const import DEFAULT_DKEK -from picohsm import APDUResponse, SWCodes +from picokey import APDUResponse, SWCodes from picohsm.const import DEFAULT_DKEK_SHARES KEY_DOMAINS = 3 TEST_KEY_DOMAIN = 1 def test_key_domains(device): - device.initialize(key_domains=KEY_DOMAINS) + device.initialize(key_domains=KEY_DOMAINS, no_dev_cert=True) for k in range(KEY_DOMAINS): kd = device.get_key_domain(key_domain=k) assert('error' in kd) diff --git a/tests/pico-hsm/test_005_dkek.py b/tests/pico-hsm/test_005_dkek.py index fb7f72e..ee10dac 100644 --- a/tests/pico-hsm/test_005_dkek.py +++ b/tests/pico-hsm/test_005_dkek.py @@ -23,7 +23,7 @@ from picohsm.const import DEFAULT_DKEK_SHARES, DEFAULT_PIN, DEFAULT_RETRIES from const import DEFAULT_DKEK def test_dkek(device): - device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.login(DEFAULT_PIN) resp = device.import_dkek(DEFAULT_DKEK) assert('dkek' in resp) diff --git a/tests/pico-hsm/test_010_pin.py b/tests/pico-hsm/test_010_pin.py index a37d782..7c7d0e5 100644 --- a/tests/pico-hsm/test_010_pin.py +++ b/tests/pico-hsm/test_010_pin.py @@ -18,22 +18,22 @@ """ import pytest -from picohsm import APDUResponse, SWCodes +from picokey import APDUResponse, SWCodes from picohsm.const import DEFAULT_PIN, DEFAULT_RETRIES WRONG_PIN = '112233' def test_pin_init_retries(device): - device.initialize(retries=DEFAULT_RETRIES) + device.initialize(retries=DEFAULT_RETRIES, no_dev_cert=True) retries = device.get_login_retries() assert(retries == DEFAULT_RETRIES) def test_pin_login(device): - device.initialize(retries=DEFAULT_RETRIES) + device.initialize(retries=DEFAULT_RETRIES, no_dev_cert=True) device.login(DEFAULT_PIN) def test_pin_retries(device): - device.initialize(retries=DEFAULT_RETRIES) + device.initialize(retries=DEFAULT_RETRIES, no_dev_cert=True) device.login(DEFAULT_PIN) for ret in range(DEFAULT_RETRIES-1): @@ -45,7 +45,7 @@ def test_pin_retries(device): device.login(WRONG_PIN) assert(e.value.sw == SWCodes.SW_PIN_BLOCKED) - device.initialize(retries=DEFAULT_RETRIES) + device.initialize(retries=DEFAULT_RETRIES, no_dev_cert=True) retries = device.get_login_retries() assert(retries == DEFAULT_RETRIES) diff --git a/tests/pico-hsm/test_020_keypair_gen.py b/tests/pico-hsm/test_020_keypair_gen.py index d8edb73..5c91f36 100644 --- a/tests/pico-hsm/test_020_keypair_gen.py +++ b/tests/pico-hsm/test_020_keypair_gen.py @@ -21,7 +21,7 @@ import pytest from picohsm import KeyType, DOPrefixes def test_gen_initialize(device): - device.initialize() + device.initialize(no_dev_cert=True) @pytest.mark.parametrize( "curve", ['secp192r1', 'secp256r1', 'secp384r1', 'secp521r1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1', 'secp192k1', 'secp256k1', 'curve25519', 'curve448', 'ed25519', 'ed448'] diff --git a/tests/pico-hsm/test_021_key_import.py b/tests/pico-hsm/test_021_key_import.py index 34d47f7..4666f7c 100644 --- a/tests/pico-hsm/test_021_key_import.py +++ b/tests/pico-hsm/test_021_key_import.py @@ -27,7 +27,7 @@ from picohsm.const import DEFAULT_RETRIES, DEFAULT_DKEK_SHARES from const import DEFAULT_DKEK def test_prepare_dkek(device): - device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK) kcv = hashlib.sha256(b'\x00'*32).digest()[:8] diff --git a/tests/pico-hsm/test_022_key_exchange.py b/tests/pico-hsm/test_022_key_exchange.py index f579732..2e536bc 100644 --- a/tests/pico-hsm/test_022_key_exchange.py +++ b/tests/pico-hsm/test_022_key_exchange.py @@ -25,7 +25,7 @@ from picohsm.const import DEFAULT_RETRIES, DEFAULT_DKEK_SHARES from const import DEFAULT_DKEK def test_prepare_dkek(device): - device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK) kcv = hashlib.sha256(b'\x00'*32).digest()[:8] diff --git a/tests/pico-hsm/test_025_key_export.py b/tests/pico-hsm/test_025_key_export.py index a047e84..29babf8 100644 --- a/tests/pico-hsm/test_025_key_export.py +++ b/tests/pico-hsm/test_025_key_export.py @@ -18,7 +18,8 @@ """ import pytest -from picohsm import KeyType, DOPrefixes, APDUResponse, SWCodes +from picohsm import KeyType, DOPrefixes +from picokey import APDUResponse, SWCodes from binascii import hexlify import hashlib from const import DEFAULT_DKEK @@ -28,7 +29,7 @@ from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives import serialization def test_initialize(device): - device.initialize(key_domains=1) + device.initialize(key_domains=1, no_dev_cert=True) assert(device.get_key_domains() == 1) device.set_key_domain(key_domain=0, total=2) diff --git a/tests/pico-hsm/test_050_cipher.py b/tests/pico-hsm/test_050_cipher.py index 523b333..f64562f 100644 --- a/tests/pico-hsm/test_050_cipher.py +++ b/tests/pico-hsm/test_050_cipher.py @@ -27,7 +27,7 @@ from const import DEFAULT_DKEK MESSAGE = b'a secret message' def test_prepare_aes(device): - device.initialize(dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK) diff --git a/tests/pico-hsm/test_051_chachapoly.py b/tests/pico-hsm/test_051_chachapoly.py index 4150598..1794a1d 100644 --- a/tests/pico-hsm/test_051_chachapoly.py +++ b/tests/pico-hsm/test_051_chachapoly.py @@ -21,7 +21,8 @@ import pytest import os from cryptography.hazmat.primitives.ciphers import aead import cryptography.exceptions -from picohsm import APDUResponse, DOPrefixes, EncryptionMode, SWCodes +from picohsm import DOPrefixes, EncryptionMode +from picokey import APDUResponse, SWCodes from picohsm.const import DEFAULT_DKEK_SHARES from const import DEFAULT_DKEK from binascii import hexlify @@ -30,7 +31,7 @@ MESSAGE = b'a secret message' AAD = b'this is a tag for AAD' def test_prepare_chachapoly(device): - device.initialize(dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK) diff --git a/tests/pico-hsm/test_052_aes_ext.py b/tests/pico-hsm/test_052_aes_ext.py index 1cb71c4..3566081 100644 --- a/tests/pico-hsm/test_052_aes_ext.py +++ b/tests/pico-hsm/test_052_aes_ext.py @@ -20,8 +20,7 @@ import pytest import os from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes, aead -import cryptography.exceptions -from picohsm import APDUResponse, DOPrefixes, EncryptionMode, SWCodes, AES +from picohsm import EncryptionMode, AES from picohsm.const import DEFAULT_DKEK_SHARES from const import DEFAULT_DKEK from binascii import hexlify @@ -30,7 +29,7 @@ MESSAGE = b'a secret message' AAD = b'this is a tag for AAD' def test_prepare_aes(device): - device.initialize(dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK) diff --git a/tests/pico-hsm/test_060_mac.py b/tests/pico-hsm/test_060_mac.py index bdf7a38..3c37d53 100644 --- a/tests/pico-hsm/test_060_mac.py +++ b/tests/pico-hsm/test_060_mac.py @@ -28,7 +28,7 @@ from const import DEFAULT_DKEK MESSAGE = b'a secret message' def test_prepare_aes(device): - device.initialize(dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK) diff --git a/tests/pico-hsm/test_070_hkdf.py b/tests/pico-hsm/test_070_hkdf.py index 62e3983..b3ed469 100644 --- a/tests/pico-hsm/test_070_hkdf.py +++ b/tests/pico-hsm/test_070_hkdf.py @@ -29,7 +29,7 @@ from picohsm import DOPrefixes INFO = b'info message' def test_prepare_kd(device): - device.initialize(dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK) diff --git a/tests/pico-hsm/test_071_pbkdf2.py b/tests/pico-hsm/test_071_pbkdf2.py index ad9c090..a499522 100644 --- a/tests/pico-hsm/test_071_pbkdf2.py +++ b/tests/pico-hsm/test_071_pbkdf2.py @@ -29,7 +29,7 @@ from picohsm import DOPrefixes INFO = b'info message' def test_prepare_kd(device): - device.initialize(dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK) diff --git a/tests/pico-hsm/test_072_x963.py b/tests/pico-hsm/test_072_x963.py index 29f313f..eb14b93 100644 --- a/tests/pico-hsm/test_072_x963.py +++ b/tests/pico-hsm/test_072_x963.py @@ -29,7 +29,7 @@ from picohsm import DOPrefixes INFO = b'shared message' def test_prepare_kd(device): - device.initialize(dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK) diff --git a/tests/pico-hsm/test_080_pka.py b/tests/pico-hsm/test_080_pka.py index 9d80363..ed08b08 100644 --- a/tests/pico-hsm/test_080_pka.py +++ b/tests/pico-hsm/test_080_pka.py @@ -21,20 +21,20 @@ import pytest from binascii import unhexlify, hexlify from cvc.certificates import CVC from picohsm.utils import int_to_bytes -from picohsm import APDUResponse, SWCodes +from picokey import APDUResponse, SWCodes from const import TERM_CERT, DICA_CERT from cryptography.hazmat.primitives.asymmetric import ec, utils from cryptography.hazmat.primitives import hashes -AUT_KEY = unhexlify('0A40E11E672C28C558B72C25D93BCF28C08D39AFDD5A1A2FD3BAF7A6B27F0C2E') +AUT_KEY = unhexlify('579A995BD7BA35AD3D3968940FA4CDA34116E121A8AC01396234DAFB132B3FD7') aut_pk = ec.derive_private_key(int.from_bytes(AUT_KEY, 'big'), ec.BrainpoolP256R1()) -AUT_PUK = unhexlify('678201ed7f218201937f4e82014b5f290100421045535049434f48534d54525a474e50327f4982011d060a04007f000702020202038120a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e537782207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9832026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b68441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f0469978520a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a78641040cc18ce246da678239af0913a1579dda58c07be404da4a65327794fac93f57a333267979905b5d046da7020226cc4e5fc477e8fc651a0cf87095259aafa88e648701015f201045535049434f48534d54525a474e50325f37401fc90bdab2a58c3cd25f18a90baa2c21d3d087002ba240fb274ff066759297f79e130053d902d637a448c8cdcd0670fe8ebcc06d8a3ee82079f08d1ff8660393421045535049434f48534d54525a474e50325f3740e24e7e23eae3c78f9fa88391004369a293c43ef99e2279170983e1dbe707fbf0382d09de3e60ef1addd2f055947c3efcef17926065ddb7a031f4905da474ed1d') +AUT_PUK = unhexlify('678201ed7f218201937f4e82014b5f290100421045535049434f48534d54524c524134437f4982011d060a04007f000702020202038120a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e537782207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9832026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b68441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f0469978520a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7864104a8217de2cec275cdf9dcda68128aff6061199291532545ab394e2554015962e16d568012a9d01b3da60d062aeed11356467fa3af9ebf9aad3d2933ebb9d86e0f8701015f201045535049434f48534d54524c524134435f374022d9f4480995e8370f8377e8bd4a63547be7740f7836456de5196839c6689540889acd573338d68bdea3db2e31c8dd00e670a4bcccdef497a156c39170d3c837421045535049434f48534d54524c524134435f374014445d219facb3bb745867d945e46526a2a6d03441dba52911d8f9483abbe4272a0beee7cecc69c661f3459c9b5431719ebf7e11f93d903a2cf705899eb4b631') term_chr = CVC().decode(TERM_CERT).chr() def test_initialize(device): - device.initialize(puk_auts=1, puk_min_auts=1) + device.initialize(puk_auts=1, puk_min_auts=1, no_dev_cert=False) device.logout() def test_register_puk(device): @@ -102,7 +102,7 @@ def test_enumerate_puk_1(device): assert(puks[0]['status'] == 0) def test_enumerate_puk_2(device): - device.initialize(puk_auts=2, puk_min_auts=1) + device.initialize(puk_auts=2, puk_min_auts=1, no_dev_cert=True) puks = device.enumerate_puk() assert(len(puks) == 2) assert(puks[0]['status'] == -1) @@ -115,7 +115,7 @@ def test_enumerate_puk_2(device): assert(puks[1]['status'] == -1) def test_register_more_puks(device): - device.initialize(puk_auts=2, puk_min_auts=1) + device.initialize(puk_auts=2, puk_min_auts=1, no_dev_cert=True) status = device.get_puk_status() assert(status == bytes([2,2,1,0])) @@ -123,14 +123,14 @@ def test_register_more_puks(device): assert(status == bytes([2,1,1,0])) def test_is_pku(device): - device.initialize(puk_auts=1, puk_min_auts=1) + device.initialize(puk_auts=1, puk_min_auts=1, no_dev_cert=True) assert(device.is_puk() == True) - device.initialize() + device.initialize(no_dev_cert=True) assert(device.is_puk() == False) def test_check_puk_key(device): - device.initialize(puk_auts=1, puk_min_auts=1) + device.initialize(puk_auts=1, puk_min_auts=1, no_dev_cert=True) status = device.check_puk_key(term_chr) assert(status == -1) @@ -140,7 +140,7 @@ def test_check_puk_key(device): def test_register_puk_with_no_puk(device): - device.initialize() + device.initialize(no_dev_cert=True) with pytest.raises(APDUResponse) as e: device.register_puk(AUT_PUK, TERM_CERT, DICA_CERT) assert(e.value.sw == SWCodes.SW_FILE_NOT_FOUND) diff --git a/tests/pico-hsm/test_090_xkek.py b/tests/pico-hsm/test_090_xkek.py index 927d0b6..2dcdcbf 100644 --- a/tests/pico-hsm/test_090_xkek.py +++ b/tests/pico-hsm/test_090_xkek.py @@ -25,12 +25,13 @@ from cvc.asn1 import ASN1 from cvc.certificates import CVC from cvc import oid from cryptography.hazmat.primitives.asymmetric import ec -from picohsm import DOPrefixes, APDUResponse, SWCodes +from picohsm import DOPrefixes +from picokey import APDUResponse, SWCodes -KDM = unhexlify(b'30820420060B2B0601040181C31F0402016181ED7F2181E97F4E81A25F290100421045535049434F48534D434130303030317F494F060A04007F0007020202020386410421EE4A21C16A10F737F12E78E5091B266612038CDABEBB722B15BF6D41B877FBF64D9AB69C39B9831B1AE00BEF2A4E81976F7688D45189BB232A24703D8A96A55F201045535049434F48534D445630303030317F4C12060904007F000703010202530580000000005F25060202000801085F24060203000601045F37403F75C08FFFC9186B56E6147199E82BFC327CEEF72495BC567961CD54D702F13E3C2766FCD1D11BD6A9D1F4A229B76B248CEB9AF88D59A74D0AB149448705159B6281E97F2181E57F4E819E5F290100421045535049434F48534D445630303030317F494F060A04007F000702020202038641043359F5234CE62E0EB80460046D8FD1AAE018CC8B9E687B40AA2C047E352409B45153D1AD888E4E7E780A3B1FA8C69CA8998BD271C8849137149142E96816A5A45F201045535049434F48534D54524A5A58314A7F4C0E060904007F0007030102025301005F25060205000100085F24060206000100085F374016F155B01CDE7FB902C8A631FCB6938458CB570EAB088DEFE1FFACD3AEFF069020256EECCF8E962461534ED682DB87BB9801E25556F87BF524385C536D19A7D1638201F1678201ED7F218201937F4E82014B5F290100421045535049434F48534D54524A5A58314A7F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A786410443F0BAB3EB271E1B762BDB81C2CC10C21CF9E8A73241B86C9552614A8842DA00A556C20BC4250C275981FE196F8D2E8766DE06C609BA07AC3E6E1468EAC451408701015F201045535049434F48534D54524A5A58314A5F37402E79A552EA5ABE1B4244841CC55515F31CACFE9B3E0A3FC3FC178DFD5ED6ADC67E03FCC65C24A8A65658768A1A522F372E9897B87058E453A647FC58E089D30D421045535049434F48534D54524A5A58314A5F37400B54434EF57C6DD55D26B44F63940E9F15C10FBC8FC013528F76ACF917D74EF41D635D630F778862ADBD3EE8574F4ABC28B9A6044DFCB9C30D83C1A4DBE6437054400964DBAED86825DBA4E5BCEFF66DAF5739A71D4B2677FB1F53ABA23B3D1D1A686A06478C3CF7FF797FE7C8A4D090D881319BD15AABE709D3EA74A48C88E4387F') +KDM = unhexlify(b'30820420060b2b0601040181c31f0402016181ed7f2181e97f4e81a25f290100421045535049434f48534d434130303030327f494f060a04007f00070202020203864104e66b473ec328caf39eaed840f9c7a4ba237e1dd19004861fa3f4f134bd2d5ea5f71c6c2e6321add4c8a7793ba41119c5783f48a5d9dfc0898d9ae9e7b14da8d65f201045535049434f48534d445630303030327f4c12060904007f000703010202530580000000045f25060205000400065f24060206000400065f3740a645594c6c338cd6bda6cad039cee54fd822b1011c0af1e4e3a2a6d03d43bdbb8be68a66a8757e7b1f963589bdd80d8e65de5055b722609041ec63f0498ddc8b6281e97f2181e57f4e819e5f290100421045535049434f48534d445630303030327f494f060a04007f000702020202038641043359f5234ce62e0eb80460046d8fd1aae018cc8b9e687b40aa2c047e352409b45153d1ad888e4e7e780a3b1fa8c69ca8998bd271c8849137149142e96816a5a45f201045535049434f48534d54524a5a58314a7f4c0e060904007f0007030102025301005f25060205010102085f24060206010102085f37409add1c1c8a05e7bc56a8bd846c9122d9214cc43c86b6952a961dce525d830a58130cbb275e9408af38dc16160f958d2b9ac6ac4f0f1b9b863284f00121d447ce638201f1678201ed7f218201937f4e82014b5f290100421045535049434f48534d54524a5a58314a7f4982011d060a04007f000702020202038120a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e537782207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9832026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b68441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f0469978520a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a78641049de55b50b921de72bbf740d3518905ff893e8208cfe8d144de34d79da3645d1c0cb551a19d6e6a5fee050e479a65d36fdf638af741e52dad4df9960b8ed443d18701015f201045535049434f48534d54524a5a58314a5f374099dede270b9a2def89a4d12dc0314e6289bd565808683f362e9f9ac9554ec5113bf7e412ecc386af12d2a9b43f27e54e10dfc6d8f2d6b618b1776459c13c0bec421045535049434f48534d54524a5a58314a5f3740459f6385f28a84f1c57f421a7f6cb4f1177084497321be94c87998c2e01af0202bab6984411cde1aab34e4e59cc27961b85855bae6340305281ff838253b0f3554404b6a2fe6947faa91f6ffa0d707cd4cbb43192935f561be137f4b3680304fc28b41210b671b8b033e06b4ad720010bcd36b92282844616261f944f3c4f67bfda5') def test_initialize(device): - device.initialize(key_domains=1) + device.initialize(key_domains=1, no_dev_cert=True) device.logout() def test_create_xkek(device): diff --git a/tests/pico-hsm/test_095_bip_slip.py b/tests/pico-hsm/test_095_bip_slip.py index e5ae119..0abfa83 100644 --- a/tests/pico-hsm/test_095_bip_slip.py +++ b/tests/pico-hsm/test_095_bip_slip.py @@ -27,7 +27,8 @@ from cvc.certificates import CVC from cvc import oid from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives import hashes -from picohsm import EncryptionMode, APDUResponse, SWCodes, PicoHSM +from picohsm import EncryptionMode, PicoHSM +from picokey import APDUResponse, SWCodes import hashlib TEST_STRING = b'Pico Keys are awesome!' @@ -36,7 +37,7 @@ def sha256_sha256(data): return hashlib.sha256(hashlib.sha256(data).digest()).digest() def test_initialize(device): - device.initialize(dkek_shares=DEFAULT_DKEK_SHARES) + device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK) diff --git a/tests/scripts/asym_cipher.sh b/tests/scripts/asym_cipher.sh index c75bf20..2e50d6e 100755 --- a/tests/scripts/asym_cipher.sh +++ b/tests/scripts/asym_cipher.sh @@ -7,9 +7,9 @@ test $? -eq 0 || exit $? rsa_encrypt_decrypt() { openssl pkeyutl -encrypt -pubin -inkey 1.pub $2 -in $1 -out data.crypt test $? -eq 0 && echo -n "." || exit $? - TDATA=$(tr -d '\0' < <(pkcs11-tool --id 1 --pin 648219 --decrypt $3 -i data.crypt 2>/dev/null)) + TDATA=$(pkcs11-tool --id 1 --pin 648219 --decrypt $3 -i data.crypt 2>/dev/null | sed '/^OAEP parameters:/d' | tr -d '\0') test $? -eq 0 && echo -n "." || exit $? - if [[ ${TEST_STRING} != "$TDATA" ]]; then + if [[ "$TEST_STRING" != "$TDATA" ]]; then exit 1 fi test $? -eq 0 && echo -n "." || exit $? @@ -36,7 +36,7 @@ rsa_encrypt_decrypt data_pad "-pkeyopt rsa_padding_mode:none" "--mechanism RSA-X test $? -eq 0 && echo -e ".\t${OK}" || exit $? echo -n " Test RSA-PKCS-OAEP ciphering..." -rsa_encrypt_decrypt data "-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256" "--mechanism RSA-PKCS-OAEP" +rsa_encrypt_decrypt data "-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256" "--mechanism RSA-PKCS-OAEP --hash-algorithm SHA256 --mgf MGF1-SHA256" test $? -eq 0 && echo -e ".\t${OK}" || exit $? rm -rf data* 1.* diff --git a/tools/pico-hsm-tool.py b/tools/pico-hsm-tool.py index becb3e3..ed27cd8 100644 --- a/tools/pico-hsm-tool.py +++ b/tools/pico-hsm-tool.py @@ -39,13 +39,13 @@ except ModuleNotFoundError: sys.exit(-1) try: - from picohsm import PicoHSM, PinType, DOPrefixes, KeyType, EncryptionMode, utils, APDUResponse, SWCodes, AES, Platform + from picohsm import PicoHSM, PinType, DOPrefixes, KeyType, EncryptionMode, AES + from picohsm.utils import get_pki_data + from picokey import APDUResponse, Platform except ModuleNotFoundError: print('ERROR: picohsm module not found! Install picohsm package.\nTry with `pip install pypicohsm`') sys.exit(-1) -import json -import urllib.request import base64 from binascii import hexlify, unhexlify import sys @@ -175,21 +175,6 @@ def parse_args(): args = parser.parse_args() return args -def get_pki_data(url, data=None, method='GET'): - user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; ' - 'rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7' - method = 'GET' - if (data is not None): - method = 'POST' - req = urllib.request.Request(f"https://www.picokeys.com/pico/pico-hsm/{url}/", - method=method, - data=data, - headers={'User-Agent': user_agent, }) - response = urllib.request.urlopen(req) - resp = response.read().decode('utf-8') - j = json.loads(resp) - return j - def get_pki_certs(certs_dir='certs', force=False): certs = get_pki_data('certs') if (os.path.exists(certs_dir) is False): @@ -222,45 +207,9 @@ def initialize(picohsm, args): print('Are you sure?') _ = input('[Press enter to confirm]') - if (args.pin): - try: - picohsm.login(args.pin) - except APDUResponse: - pass - pin = args.pin - else: - pin = '648219' + picohsm.initialize(pin=args.pin, sopin=args.so_pin, no_dev_cert=args.no_dev_cert) - if (args.so_pin): - try: - picohsm.login(args.so_pin, who=PinType.SO_PIN) - except APDUResponse: - pass - so_pin = args.so_pin - else: - so_pin = '57621880' - - picohsm.initialize(pin=pin, sopin=so_pin) if (not args.no_dev_cert): - response = picohsm.get_contents(DOPrefixes.EE_CERTIFICATE_PREFIX, 0x00) - - cert = bytearray(response) - Y = CVC().decode(cert).pubkey().find(0x86).data() - print(f'Public Point: {hexlify(Y).decode()}') - - pbk = base64.urlsafe_b64encode(Y) - params = {'pubkey': pbk} - if (picohsm.platform in (Platform.RP2350, Platform.ESP32, Platform.EMULATION)): - params['curve'] = 'secp256k1' - data = urllib.parse.urlencode(params).encode() - j = get_pki_data('cvc', data=data) - print('Device name: '+j['devname']) - dataef = base64.urlsafe_b64decode( - j['cvcert']) + base64.urlsafe_b64decode(j['dvcert']) + base64.urlsafe_b64decode(j['cacert']) - - picohsm.select_file(0x2f02) - response = picohsm.put_contents(0x0000, data=dataef) - print('Certificate uploaded successfully!') print('') print('Note that the device is initialized with a default PIN and '