Skip to main content

Crate keyroost_openpgp

Crate keyroost_openpgp 

Source
Expand description

OpenPGP Card (v3.4) APDU command/response layer.

Phase 4 of extending keyroost toward ykman parity. The OpenPGP applet is a CCID/APDU smartcard applet on YubiKeys and Trussed devices (Solo 2 / Nitrokey 3, via opcard), reachable over the existing PC/SC transport — no second transport stack. This crate is the pure-Rust command/response layer (APDU builders + the application-related-data TLV parser); the actual card exchange lives in keyroost-transport.

Reference: OpenPGP Card spec v3.4, and Nitrokey/opcard-rs.

§What is and isn’t here

This is the byte layer: it turns intentions into APDU byte vectors and turns response byte slices into typed structures. It performs no I/O. Card transmit, the 61xx / GET RESPONSE reassembly loop, PIN entry, and the higher-level key-management operations are deliberately left for the transport phase; see the TODO(transport) notes on Instruction and the builders that are intentionally absent.

Unlike the OATH applet (Yubico’s SIMPLE-TLV, short-form lengths only), the OpenPGP applet uses ISO 7816-4 BER-TLV: two-byte (“high”) tags and long-form lengths. The parser here handles both forms; see parse_tlvs.

Structs§

AppRelatedData
Selected fields pulled out of the Application Related Data (6E) object.
PublicKey
The RSA public key parsed from a GENERATE / READ PUBLIC KEY response.
PwStatus
PW status bytes (C4), parsed from the 7-byte form.
RsaAttributes
RSA key attributes parsed from an algorithm-attributes object (C1/C2/C3).
RsaPrivateKeyParts
RSA private key material needed to import a key into a card slot.
Tlv
A single parsed BER-TLV borrowed from the response buffer.

Enums§

Instruction
OpenPGP Card instruction bytes (OpenPGP Card spec v3.4, §7.2).
KeyCrt
Selects which on-card key slot a GENERATE / READ PUBLIC KEY operation refers to. The wire form is a 2-byte Control Reference Template — the slot’s CRT tag followed by an empty value (B6 00, B8 00, or A4 00).
ParseError
Error returned by the response parsers.
RsaImportFormat
The RSA private-key import format a card accepts, taken from byte 5 of its algorithm-attributes object (C1/C2/C3; OpenPGP Card spec v3.4 §4.4.3.10).

Constants§

AID_PREFIX
OpenPGP application AID prefix used to SELECT the applet by DF name: RID D2 76 00 01 24 (PGP) + application 01 (OpenPGP). The full 16-byte AID on the card additionally carries the spec version, manufacturer, and a serial number — but select addresses the applet with this 6-byte prefix.
CRT_TAG_AUTH
CRT tag selecting the authentication key.
CRT_TAG_DECRYPT
CRT tag selecting the decryption (confidentiality) key.
CRT_TAG_SIGN
CRT tag selecting the signature key (OpenPGP Card v3.4, §7.2.14, table).
GENERATE_KEY
GENERATE ASYMMETRIC KEY PAIR P1: generate a fresh key pair.
INS_PUT_DATA_ODD
Build the full PUT DATA APDU that imports an RSA private key into crt’s slot: 00 DB 3F FF <extended Lc> <4D extended header list> (odd PUT DATA; see INS_PUT_DATA_ODD).
INS_SELECT
ISO 7816 SELECT instruction (used to activate the applet).
P1_SELECT_BY_NAME
SELECT P1: select by DF name (AID).
PSO_COMPUTE_SIGNATURE
PSO P1-P2 selecting compute digital signature (9E 9A).
PSO_DECIPHER
PSO P1-P2 selecting decipher (80 86).
PW1_OTHER
VERIFY P2: PW1 in the “other” context (decipher, internal authenticate).
PW1_SIGN
VERIFY P2: PW1 in the signing context (valid for PSO:CDS).
PW3_ADMIN
VERIFY P2: PW3 (admin) PIN.
READ_PUBLIC_KEY
GENERATE ASYMMETRIC KEY PAIR P1: read an existing public key.
RESET_RC_BY_ADMIN
RESET RETRY COUNTER P1: reset PW1 after PW3 (admin) has been verified; the body carries the new PW1 only. (The resetting-code variant, P1 0x00, which carries resetting_code || new_pw1, is not modelled — the admin path is what the transport layer uses.)
SW_MORE_DATA
High byte of the “more data available” status (61xx).
SW_OK
Status word: success.
TAG_AID
Application Identifier (full 16-byte AID).
TAG_ALGO_ATTR_AUT
Algorithm attributes — authentication key.
TAG_ALGO_ATTR_DEC
Algorithm attributes — decryption key.
TAG_ALGO_ATTR_SIG
Algorithm attributes — signature key (inside TAG_DISCRETIONARY).
TAG_APPLICATION_RELATED_DATA
Application Related Data (constructed; the big aggregate object).
TAG_CARDHOLDER_RELATED_DATA
Cardholder Related Data (constructed: contains 5B, 5F2D, 5F35).
TAG_CA_FINGERPRINTS
CA fingerprints — 60 bytes = 3×20.
TAG_DISCRETIONARY
Discretionary data objects (constructed; inside TAG_APPLICATION_RELATED_DATA).
TAG_DS_COUNTER
Digital signature counter (3-byte big-endian; inside TAG_SECURITY_SUPPORT).
TAG_EC_PUBLIC_POINT
EC public point (inside TAG_PUBLIC_KEY) for ECDSA/ECDH/EdDSA keys.
TAG_EXTENDED_CAPABILITIES
Extended capabilities (inside TAG_DISCRETIONARY).
TAG_FINGERPRINTS
Fingerprints — 60 bytes = 3×20 (Sig, Dec, Aut).
TAG_FPR_AUTH
Fingerprint — authentication key (C9, 20 bytes); a standalone PUT DATA target.
TAG_FPR_DEC
Fingerprint — decryption key (C8, 20 bytes); a standalone PUT DATA target.
TAG_FPR_SIGN
Fingerprint — signature key (C7, 20 bytes); a standalone PUT DATA target.
TAG_GENERATION_TIMES
Key generation timestamps.
TAG_HISTORICAL_BYTES
Historical bytes.
TAG_LANGUAGE
Language preference (inside TAG_CARDHOLDER_RELATED_DATA).
TAG_LOGIN_DATA
Login data.
TAG_NAME
Cardholder Name (inside TAG_CARDHOLDER_RELATED_DATA).
TAG_PUBLIC_KEY
Public-key data object (constructed) returned by GENERATE / READ PUBLIC KEY.
TAG_PW_STATUS
PW status bytes (inside TAG_DISCRETIONARY, also a standalone GET DATA).
TAG_RSA_EXPONENT
RSA public exponent e (inside TAG_PUBLIC_KEY).
TAG_RSA_MODULUS
RSA modulus n (inside TAG_PUBLIC_KEY).
TAG_SECURITY_SUPPORT
Security support template (constructed; contains TAG_DS_COUNTER).
TAG_SEX
Sex (inside TAG_CARDHOLDER_RELATED_DATA).
TAG_TIME_AUTH
Generation timestamp — authentication key (D0, 4-byte big-endian Unix time).
TAG_TIME_DEC
Generation timestamp — decryption key (CF, 4-byte big-endian Unix time).
TAG_TIME_SIGN
Generation timestamp — signature key (CE, 4-byte big-endian Unix time).
TAG_URL
URL of the public key.

Functions§

activate_file
ACTIVATE FILE (00 44 00 00) — the second half of the reset: re-initialize the terminated applet to factory defaults (PW1 123456, PW3 12345678, all key slots empty). Case-1 APDU.
change_reference_data
CHANGE REFERENCE DATA (INS 24) — change a PIN from old to new.
extended_header_list
Build just the 0x4D Extended Header List object for an RSA key import (OpenPGP Card spec v3.4, §4.4.3.12). Returned without the APDU wrapper so it can be unit-tested directly; see import_rsa_key for the full command.
find_nested
Recursively locate the value of the first TLV with tag, descending into constructed objects.
find_tag
Find the value of the first TLV with tag in a flat bag.
generate_key
GENERATE ASYMMETRIC KEY PAIR with P1 = 80 (generate a fresh key pair).
get_application_related_data
GET DATA 006E — the Application Related Data aggregate: 00 CA 00 6E 00.
get_data
GET DATA for the data object identified by the 2-byte tag (placed in P1-P2). Case-2 APDU with Le = 0 (“up to 256 bytes”); larger objects are continued with get_response in the transport phase.
get_pw_status
GET DATA 00C4 — the standalone PW status bytes: 00 CA 00 C4 00.
get_response
GET RESPONSE (case-2): retrieve the next chunk after a 61xx status word.
import_rsa_key
import_rsa_key_chained
Command-chaining form of import_rsa_key: the same 4D Extended Header List, but emitted as a sequence of chained 0xDB PUT DATA APDUs (see put_data_odd_chained) instead of one extended-length APDU.
parse_application_related_data
Parse the Application Related Data (6E) blob.
parse_generated_public_key
Parse the public key from a GENERATE / READ PUBLIC KEY response.
parse_pw_status
Parse the 7-byte PW status (C4) value.
parse_rsa_algorithm_attributes
Parse the RSA algorithm attributes (01 | n_bits | e_bits | [format]).
parse_signature_counter
Parse the digital-signature counter from a Security Support Template (7A).
parse_tlvs
Parse a flat sequence of BER-TLVs from buf.
pso_compute_signature
PERFORM SECURITY OPERATION: COMPUTE DIGITAL SIGNATURE (P1-P2 = 9E 9A).
pso_decipher
PERFORM SECURITY OPERATION: DECIPHER (P1-P2 = 80 86).
pso_decipher_chained
Build PSO:DECIPHER as an ISO 7816 command-chaining sequence — the fallback for readers/cards that won’t accept a single extended-Lc APDU.
put_cardholder_name
PUT DATA 005B — write the cardholder name (TAG_NAME).
put_data
PUT DATA for the data object identified by the 2-byte tag (placed in P1-P2), carrying value as the body.
put_data_odd_chained
Build an “odd” PUT DATA (0xDB) as an ISO 7816 command-chaining sequence: split data into chunks of at most max_chunk bytes, every chunk but the last carrying the chaining class bit (CLA 0x10) and the final one CLA 0x00. Each chunk is a case-3 APDU CLA DB <p1> <p2> <Lc> <chunk>.
put_fingerprint
PUT DATA C7/C8/C9 — write the 20-byte v4 fingerprint of the key in crt’s slot (see KeyCrt::fpr_tag).
put_generation_time
PUT DATA CE/CF/D0 — write the 4-byte big-endian Unix generation timestamp of the key in crt’s slot (see KeyCrt::time_tag).
put_url
PUT DATA 5F50 — write the URL of the public key (TAG_URL).
read_public_key
GENERATE ASYMMETRIC KEY PAIR with P1 = 81 (read the existing public key, no generation).
reset_retry_counter
RESET RETRY COUNTER (00 2C 02 81) — unblock the user PIN (PW1) and set it to new_pw1, after PW3 (admin) has been verified in the same session. This is how a card whose user PIN is blocked (retry counter at 0) is recovered without a factory reset. Builds a case-3 APDU 00 2C 02 81 <Lc> <new_pw1>.
rsa_v4_fingerprint
Compute the OpenPGP v4 fingerprint (RFC 4880 §12.2) of an RSA public key from its big-endian modulus, exponent, and the key’s creation_time (Unix seconds).
rsa_v4_fingerprint_from
Convenience wrapper around rsa_v4_fingerprint taking a parsed PublicKey (e.g. straight from parse_generated_public_key).
select
SELECT the OpenPGP applet by DF name: 00 A4 04 00 06 D2 76 00 01 24 01.
terminate_df
TERMINATE DF (00 E6 00 00) — the first half of an OpenPGP applet factory reset. Case-1 APDU (no body, no Le). When the applet is unblocked this needs PW3, but once PW1 and PW3 are blocked (both retry counters at 0) the card accepts it unconditionally — that’s how a forgotten-PIN card is reset. After this the applet is in the “terminated” state and only activate_file (or re-SELECT) is accepted.
verify
VERIFY — present pin against the password reference pw_ref (one of PW1_SIGN, PW1_OTHER, PW3_ADMIN).

Type Aliases§

Fingerprint
A 20-byte (SHA-1-sized) OpenPGP key fingerprint.