openpgp_card/
lib.rs

1// SPDX-FileCopyrightText: 2021-2024 Heiko Schaefer <heiko@schaefer.name>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Client library for
5//! [OpenPGP card](https://en.wikipedia.org/wiki/OpenPGP_card)
6//! devices (such as Gnuk, Nitrokey, YubiKey, or Java smartcards running an
7//! OpenPGP card application).
8//!
9//! This library aims to offer
10//! - low-level access to all features in the OpenPGP
11//!   [card specification](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.1.pdf)
12//!   via the [crate::ocard] package,
13//! - without relying on a particular
14//!   [OpenPGP implementation](https://www.openpgp.org/software/developer/).
15//!
16//! The library exposes two modes of access to cards:
17//! - low-level, unmediated, access to card functionality (see [crate::ocard]), and
18//! - a more opinionated, typed wrapper API that performs some amount of caching [Card].
19//!
20//! Note that this library can't directly access cards by itself.
21//! Instead, users need to supply a backend that implements the
22//! [`card_backend::CardBackend`] and [`card_backend::CardTransaction`] traits.
23//! For example [card-backend-pcsc](https://crates.io/crates/card-backend-pcsc)
24//! offers a backend implementation that uses [PC/SC](https://en.wikipedia.org/wiki/PC/SC) to
25//! communicate with Smart Cards.
26//!
27//! See the [architecture diagram](https://gitlab.com/openpgp-card/openpgp-card#architecture)
28//! for an overview of the ecosystem around this crate.
29
30extern crate core;
31
32mod errors;
33pub mod ocard;
34pub mod state;
35
36use card_backend::{CardBackend, SmartcardError};
37use secrecy::SecretString;
38
39pub use crate::errors::Error;
40use crate::ocard::algorithm::{AlgoSimple, AlgorithmAttributes, AlgorithmInformation};
41use crate::ocard::crypto::{CardUploadableKey, PublicKeyMaterial};
42use crate::ocard::data::{
43    ApplicationIdentifier, CardholderRelatedData, ExtendedCapabilities, ExtendedLengthInfo,
44    Fingerprint, HistoricalBytes, KdfDo, KeyGenerationTime, KeyInformation, KeySet, Lang,
45    PWStatusBytes, Sex, TouchPolicy, UserInteractionFlag,
46};
47use crate::ocard::{kdf::map_pin, KeyType};
48use crate::state::{Admin, Open, Sign, State, Transaction, User};
49
50/// For caching DOs in a Transaction
51enum Cached<T> {
52    Uncached,
53    None,
54    Value(T),
55}
56
57/// A PIN in an OpenPGP card application.
58///
59/// - Pw1 is the "User PIN"
60/// - Rc is the "Resetting Code"
61/// - Pw3 is the "Admin PIN"
62pub(crate) enum PinType {
63    Pw1,
64    Rc,
65    Pw3,
66}
67
68/// Optional PIN, used as a parameter to `Card<Transaction>::into_*_card`.
69///
70/// Effectively acts like a `Option<SecretString>`, but with a number of `From`
71/// implementations for convenience.
72pub struct OptionalPin(Option<SecretString>);
73
74impl From<Option<SecretString>> for OptionalPin {
75    fn from(value: Option<SecretString>) -> Self {
76        OptionalPin(value)
77    }
78}
79
80impl From<SecretString> for OptionalPin {
81    fn from(value: SecretString) -> Self {
82        OptionalPin(Some(value))
83    }
84}
85
86/// Representation of an OpenPGP card.
87///
88/// A card transitions between [`State`]s by starting a transaction (that groups together a number
89/// of operations into an atomic sequence) and via PIN presentation.
90///
91/// Depending on the [`State`] of the card and the access privileges that are associated with that
92/// state, different operations can be performed. In many cases, client software will want to
93/// transition between states while performing one workflow for the user.
94pub struct Card<S>
95where
96    S: State,
97{
98    state: S,
99}
100
101impl Card<Open> {
102    /// Takes an iterator over [`CardBackend`]s, tries to SELECT the OpenPGP card
103    /// application on each of them, and checks if its application id matches
104    /// `ident`.
105    /// Returns a [`Card<Open>`] for the first match, if any.
106    pub fn open_by_ident(
107        cards: impl Iterator<Item = Result<Box<dyn CardBackend + Send + Sync>, SmartcardError>>,
108        ident: &str,
109    ) -> Result<Self, Error> {
110        for b in cards.filter_map(|c| c.ok()) {
111            let mut card = Self::new(b)?;
112
113            let aid = {
114                let mut tx = card.transaction()?;
115                tx.state.ard().application_id()?
116            };
117
118            if aid.ident() == ident.to_ascii_uppercase() {
119                return Ok(card);
120            }
121        }
122
123        Err(Error::NotFound(format!("Couldn't find card {}", ident)))
124    }
125
126    /// Returns a [`Card<Open>`] based on `backend` (after SELECTing the
127    /// OpenPGP card application).
128    pub fn new<B>(backend: B) -> Result<Self, Error>
129    where
130        B: Into<Box<dyn CardBackend + Send + Sync>>,
131    {
132        let pgp = crate::ocard::OpenPGP::new(backend)?;
133
134        Ok(Card::<Open> {
135            state: Open { pgp },
136        })
137    }
138
139    /// Starts a transaction on the underlying backend (if the backend
140    /// implementation supports transactions, otherwise the backend
141    /// will operate without transaction guarantees).
142    ///
143    /// The resulting [`Card<Transaction>`] object allows performing
144    /// operations on the card.
145    pub fn transaction(&mut self) -> Result<Card<Transaction>, Error> {
146        let opt = self.state.pgp.transaction()?;
147
148        Card::<Transaction>::new(opt)
149    }
150
151    /// Retrieve the underlying [`CardBackend`].
152    ///
153    /// This is useful to take the card object into a different context
154    /// (e.g. to perform operations on the card with the `yubikey-management`
155    /// crate, without closing the connection to the card).
156    pub fn into_backend(self) -> Box<dyn CardBackend + Send + Sync> {
157        self.state.pgp.into_card()
158    }
159}
160
161impl<'a> Card<Transaction<'a>> {
162    /// Internal constructor
163    fn new(mut opt: crate::ocard::Transaction<'a>) -> Result<Self, Error> {
164        let ard = opt.application_related_data()?;
165
166        Ok(Self {
167            state: Transaction::new(opt, ard),
168        })
169    }
170
171    // FIXME: remove later?
172    pub fn card(&mut self) -> &mut crate::ocard::Transaction<'a> {
173        &mut self.state.opt
174    }
175
176    /// Drop cached "application related data" and "kdf do" in this [Card] instance.
177    ///
178    /// This is necessary e.g. after importing or generating keys on a card, to
179    /// drop the now obsolete cached [`crate::ocard::data::ApplicationRelatedData`] and [`KdfDo`].
180    pub fn invalidate_cache(&mut self) -> Result<(), Error> {
181        self.state.invalidate_cache();
182        Ok(())
183    }
184
185    /// True if the reader for this card supports PIN verification with a pin pad.
186    pub fn feature_pinpad_verify(&mut self) -> bool {
187        self.state.opt.feature_pinpad_verify()
188    }
189
190    /// True if the reader for this card supports PIN modification with a pin pad.
191    pub fn feature_pinpad_modify(&mut self) -> bool {
192        self.state.opt.feature_pinpad_modify()
193    }
194
195    /// Verify the User PIN (for operations such as decryption)
196    pub fn verify_user_pin(&mut self, pin: SecretString) -> Result<(), Error> {
197        let pin = map_pin(pin, PinType::Pw1, self.state.kdf_do())?;
198
199        self.state.opt.verify_pw1_user(pin)?;
200        self.state.pw1 = true;
201        Ok(())
202    }
203
204    /// Verify the User PIN with a physical PIN pad (if available,
205    /// see [`Self::feature_pinpad_verify`]).
206    pub fn verify_user_pinpad(&mut self, pinpad_prompt: &dyn Fn()) -> Result<(), Error> {
207        pinpad_prompt();
208
209        self.state.opt.verify_pw1_user_pinpad()?;
210        self.state.pw1 = true;
211        Ok(())
212    }
213
214    /// Verify the User PIN for signing operations.
215    ///
216    /// (Note that depending on the configuration of the card, this may enable
217    /// performing just one signing operation, or an unlimited amount of
218    /// signing operations).
219    pub fn verify_user_signing_pin(&mut self, pin: SecretString) -> Result<(), Error> {
220        let pin = map_pin(pin, PinType::Pw1, self.state.kdf_do())?;
221
222        self.state.opt.verify_pw1_sign(pin)?;
223
224        // FIXME: depending on card mode, pw1_sign is only usable once
225
226        self.state.pw1_sign = true;
227        Ok(())
228    }
229
230    /// Verify the User PIN for signing operations with a physical PIN pad
231    /// (if available, see [`Self::feature_pinpad_verify`]).
232    pub fn verify_user_signing_pinpad(&mut self, pinpad_prompt: &dyn Fn()) -> Result<(), Error> {
233        pinpad_prompt();
234
235        self.state.opt.verify_pw1_sign_pinpad()?;
236
237        // FIXME: depending on card mode, pw1_sign is only usable once
238
239        self.state.pw1_sign = true;
240        Ok(())
241    }
242
243    /// Verify the Admin PIN.
244    pub fn verify_admin_pin(&mut self, pin: SecretString) -> Result<(), Error> {
245        let pin = map_pin(pin, PinType::Pw3, self.state.kdf_do())?;
246
247        self.state.opt.verify_pw3(pin)?;
248        self.state.pw3 = true;
249        Ok(())
250    }
251
252    /// Verify the Admin PIN with a physical PIN pad
253    /// (if available, see [`Self::feature_pinpad_verify`]).
254    pub fn verify_admin_pinpad(&mut self, pinpad_prompt: &dyn Fn()) -> Result<(), Error> {
255        pinpad_prompt();
256
257        self.state.opt.verify_pw3_pinpad()?;
258        self.state.pw3 = true;
259        Ok(())
260    }
261
262    /// Ask the card if the user password has been successfully verified.
263    ///
264    /// NOTE: on some cards this functionality seems broken and may decrease
265    /// the pin's error count!
266    pub fn check_user_verified(&mut self) -> Result<(), Error> {
267        self.state.opt.check_pw1_user()
268    }
269
270    /// Ask the card if the admin password has been successfully verified.
271    ///
272    /// NOTE: on some cards this functionality seems broken and may decrease
273    /// the pin's error count!
274    pub fn check_admin_verified(&mut self) -> Result<(), Error> {
275        self.state.opt.check_pw3()
276    }
277
278    /// Change the User PIN, based on the old User PIN.
279    pub fn change_user_pin(&mut self, old: SecretString, new: SecretString) -> Result<(), Error> {
280        let old = map_pin(old, PinType::Pw1, self.state.kdf_do())?;
281        let new = map_pin(new, PinType::Pw1, self.state.kdf_do())?;
282
283        self.state.opt.change_pw1(old, new)
284    }
285
286    /// Change the User PIN, based on the old User PIN, with a physical PIN
287    /// pad (if available, see [`Self::feature_pinpad_modify`]).
288    pub fn change_user_pin_pinpad(&mut self, pinpad_prompt: &dyn Fn()) -> Result<(), Error> {
289        pinpad_prompt();
290        self.state.opt.change_pw1_pinpad()
291    }
292
293    /// Change the User PIN, based on the resetting code `rst`.
294    pub fn reset_user_pin(&mut self, rst: SecretString, new: SecretString) -> Result<(), Error> {
295        let rst = map_pin(rst, PinType::Rc, self.state.kdf_do())?;
296        let new = map_pin(new, PinType::Pw1, self.state.kdf_do())?;
297
298        self.state.opt.reset_retry_counter_pw1(new, Some(rst))
299    }
300
301    /// Change the Admin PIN, based on the old Admin PIN.
302    pub fn change_admin_pin(&mut self, old: SecretString, new: SecretString) -> Result<(), Error> {
303        let old = map_pin(old, PinType::Pw3, self.state.kdf_do())?;
304        let new = map_pin(new, PinType::Pw3, self.state.kdf_do())?;
305
306        self.state.opt.change_pw3(old, new)
307    }
308
309    /// Change the Admin PIN, based on the old Admin PIN, with a physical PIN
310    /// pad (if available, see [`Self::feature_pinpad_modify`]).
311    pub fn change_admin_pin_pinpad(&mut self, pinpad_prompt: &dyn Fn()) -> Result<(), Error> {
312        pinpad_prompt();
313        self.state.opt.change_pw3_pinpad()
314    }
315
316    /// Get a view of the card in the [`Card<User>`] state, and authenticate
317    /// for that state with `pin`, if available.
318    ///
319    /// If `pin` is not None, `verify_user` is called with that pin.
320    pub fn to_user_card<'b, P>(&'b mut self, pin: P) -> Result<Card<User<'a, 'b>>, Error>
321    where
322        P: Into<OptionalPin>,
323    {
324        let pin: OptionalPin = pin.into();
325
326        if let Some(pin) = pin.0 {
327            self.verify_user_pin(pin)?;
328        }
329
330        Ok(Card::<User> {
331            state: User { tx: self },
332        })
333    }
334
335    /// Get a view of the card in the [`Card<Sign>`] state, and authenticate
336    /// for that state with `pin`, if available.
337    ///
338    /// If `pin` is not None, `verify_user_for_signing` is called with that pin.
339    pub fn to_signing_card<'b, P>(&'b mut self, pin: P) -> Result<Card<Sign<'a, 'b>>, Error>
340    where
341        P: Into<OptionalPin>,
342    {
343        let pin: OptionalPin = pin.into();
344
345        if let Some(pin) = pin.0 {
346            self.verify_user_signing_pin(pin)?;
347        }
348
349        Ok(Card::<Sign> {
350            state: Sign { tx: self },
351        })
352    }
353
354    /// Get a view of the card in the [`Card<Admin>`] state, and authenticate
355    /// for that state with `pin`, if available.
356    ///
357    /// If `pin` is not None, `verify_admin` is called with that pin.
358    pub fn to_admin_card<'b, P>(&'b mut self, pin: P) -> Result<Card<Admin<'a, 'b>>, Error>
359    where
360        P: Into<OptionalPin>,
361    {
362        let pin: OptionalPin = pin.into();
363
364        if let Some(pin) = pin.0 {
365            self.verify_admin_pin(pin)?;
366        }
367
368        Ok(Card::<Admin> {
369            state: Admin { tx: self },
370        })
371    }
372
373    // --- application data ---
374
375    /// The Application Identifier is unique for each card.
376    /// It includes a manufacturer code and serial number.
377    ///
378    /// (This is an immutable field on the card. The value is cached in the
379    /// underlying Card object. It can be retrieved without incurring a call
380    /// to the card)
381    pub fn application_identifier(&self) -> Result<ApplicationIdentifier, Error> {
382        // Use immutable data cache from underlying Card object
383        self.state.opt.application_identifier()
384    }
385
386    /// The "Extended Capabilities" data object describes features of a card
387    /// to the caller.
388    /// This includes the availability and length of various data fields.
389    ///
390    /// (This is an immutable field on the card. The value is cached in the
391    /// underlying Card object. It can be retrieved without incurring a call
392    /// to the card)
393    pub fn extended_capabilities(&self) -> Result<ExtendedCapabilities, Error> {
394        // Use immutable data cache from underlying Card object
395        self.state.opt.extended_capabilities()
396    }
397
398    /// The "Historical Bytes" data object describes features of a card
399    /// to the caller.
400    /// The information in this field is probably not relevant for most
401    /// users of this library, however, some of it is used for the internal
402    /// operation of the `openpgp-card` library.
403    ///
404    /// (This is an immutable field on the card. The value is cached in the
405    /// underlying Card object. It can be retrieved without incurring a call
406    /// to the card)
407    pub fn historical_bytes(&self) -> Result<HistoricalBytes, Error> {
408        // Use immutable data cache from underlying Card object
409        match self.state.opt.historical_bytes()? {
410            Some(hb) => Ok(hb),
411            None => Err(Error::NotFound(
412                "Card doesn't have historical bytes DO".to_string(),
413            )),
414        }
415    }
416
417    /// The "Extended Length Information" data object was introduced in
418    /// version 3.0 of the OpenPGP card standard.
419    ///
420    /// The information in this field should not be relevant for
421    /// users of this library.
422    /// However, it is used for the internal operation of the `openpgp-card`
423    /// library.
424    ///
425    /// (This is an immutable field on the card. The value is cached in the
426    /// underlying Card object. It can be retrieved without incurring a call
427    /// to the card)
428    pub fn extended_length_information(&self) -> Result<Option<ExtendedLengthInfo>, Error> {
429        // Use immutable data cache from underlying Card object
430        self.state.opt.extended_length_info()
431    }
432
433    // fn general_feature_management() -> Option<bool> {
434    //     unimplemented!()
435    // }
436
437    // fn discretionary_data_objects() {
438    //     unimplemented!()
439    // }
440
441    /// PW Status Bytes
442    pub fn pw_status_bytes(&mut self) -> Result<PWStatusBytes, Error> {
443        self.state.ard().pw_status_bytes()
444    }
445
446    /// Get algorithm attributes for a key slot.
447    pub fn algorithm_attributes(
448        &mut self,
449        key_type: KeyType,
450    ) -> Result<AlgorithmAttributes, Error> {
451        self.state.ard().algorithm_attributes(key_type)
452    }
453
454    /// Get the Fingerprints for the three basic [`KeyType`]s.
455    ///
456    /// (The fingerprints for the three basic key slots are stored in a
457    /// shared field on the card, thus they can be retrieved in one go)
458    pub fn fingerprints(&mut self) -> Result<KeySet<Fingerprint>, Error> {
459        self.state.ard().fingerprints()
460    }
461
462    /// Get the Fingerprint for one [`KeyType`].
463    ///
464    /// This function allows retrieval for all slots, including
465    /// [`KeyType::Attestation`], if available.
466    pub fn fingerprint(&mut self, key_type: KeyType) -> Result<Option<Fingerprint>, Error> {
467        let fp = match key_type {
468            KeyType::Signing => self.fingerprints()?.signature().cloned(),
469            KeyType::Decryption => self.fingerprints()?.decryption().cloned(),
470            KeyType::Authentication => self.fingerprints()?.authentication().cloned(),
471            KeyType::Attestation => self.state.ard().attestation_key_fingerprint()?,
472        };
473
474        Ok(fp)
475    }
476
477    /// Get the Key Creation Times for the three basic [`KeyType`]s.
478    ///
479    /// (The creation time for the three basic key slots are stored in a
480    /// shared field on the card, thus they can be retrieved in one go)
481    pub fn key_generation_times(&mut self) -> Result<KeySet<KeyGenerationTime>, Error> {
482        self.state.ard().key_generation_times()
483    }
484
485    /// Get the Key Creation Time for one [`KeyType`].
486    ///
487    /// This function allows retrieval for all slots, including
488    /// [`KeyType::Attestation`], if available.
489    pub fn key_generation_time(
490        &mut self,
491        key_type: KeyType,
492    ) -> Result<Option<KeyGenerationTime>, Error> {
493        let ts = match key_type {
494            KeyType::Signing => self.key_generation_times()?.signature().cloned(),
495            KeyType::Decryption => self.key_generation_times()?.decryption().cloned(),
496            KeyType::Authentication => self.key_generation_times()?.authentication().cloned(),
497            KeyType::Attestation => self.state.ard().attestation_key_generation_time()?,
498        };
499
500        Ok(ts)
501    }
502
503    pub fn key_information(&mut self) -> Result<Option<KeyInformation>, Error> {
504        self.state.ard().key_information()
505    }
506
507    /// Get the [`UserInteractionFlag`] for a key slot.
508    /// This includes the [`TouchPolicy`], if the card supports touch
509    /// confirmation.
510    pub fn user_interaction_flag(
511        &mut self,
512        key_type: KeyType,
513    ) -> Result<Option<UserInteractionFlag>, Error> {
514        match key_type {
515            KeyType::Signing => self.state.ard().uif_pso_cds(),
516            KeyType::Decryption => self.state.ard().uif_pso_dec(),
517            KeyType::Authentication => self.state.ard().uif_pso_aut(),
518            KeyType::Attestation => self.state.ard().uif_attestation(),
519        }
520    }
521
522    /// List of CA-Fingerprints of “Ultimately Trusted Keys”.
523    /// May be used to verify Public Keys from servers.
524    pub fn ca_fingerprints(&mut self) -> Result<[Option<Fingerprint>; 3], Error> {
525        self.state.ard().ca_fingerprints()
526    }
527
528    /// Get optional "Private use" data from the card.
529    ///
530    /// The presence and maximum length of these DOs is announced
531    /// in [`ExtendedCapabilities`].
532    ///
533    /// If available, there are 4 data fields for private use:
534    ///
535    /// - `1`: read accessible without PIN verification
536    /// - `2`: read accessible without PIN verification
537    /// - `3`: read accessible with User PIN verification
538    /// - `4`: read accessible with Admin PIN verification
539    pub fn private_use_do(&mut self, num: u8) -> Result<Vec<u8>, Error> {
540        self.state.opt.private_use_do(num)
541    }
542
543    /// Login Data
544    ///
545    /// This DO can be used to store any information used for the Log-In
546    /// process in a client/server authentication (e.g. user name of a
547    /// network).
548    /// The maximum length of this DO is announced in Extended Capabilities.
549    pub fn login_data(&mut self) -> Result<Vec<u8>, Error> {
550        self.state.opt.login_data()
551    }
552
553    // --- URL (5f50) ---
554
555    /// Get "cardholder" URL from the card.
556    ///
557    /// "The URL should contain a link to a set of public keys in OpenPGP format, related to
558    /// the card."
559    pub fn url(&mut self) -> Result<String, Error> {
560        Ok(String::from_utf8_lossy(&self.state.opt.url()?).to_string())
561    }
562
563    /// Cardholder related data (contains the fields: Name, Language preferences and Sex)
564    pub fn cardholder_related_data(&mut self) -> Result<CardholderRelatedData, Error> {
565        self.state.opt.cardholder_related_data()
566    }
567
568    // Unicode codepoints are a superset of iso-8859-1 characters
569    fn latin1_to_string(s: &[u8]) -> String {
570        s.iter().map(|&c| c as char).collect()
571    }
572
573    /// Get cardholder name.
574    ///
575    /// This is an ISO 8859-1 (Latin 1) String of up to 39 characters.
576    ///
577    /// Note that the standard specifies that this field should be encoded
578    /// according to ISO/IEC 7501-1:
579    ///
580    /// "The data element consists of surname (e. g. family name and given
581    /// name(s)) and forename(s) (including name suffix, e. g., Jr. and number).
582    /// Each item is separated by a ´<´ filler character (3C), the family- and
583    /// fore-name(s) are separated by two ´<<´ filler characters."
584    ///
585    /// This library doesn't perform this encoding.
586    pub fn cardholder_name(&mut self) -> Result<String, Error> {
587        let crd = self.state.opt.cardholder_related_data()?;
588
589        match crd.name() {
590            Some(name) => Ok(Self::latin1_to_string(name)),
591            None => Ok("".to_string()),
592        }
593    }
594
595    /// Get the current digital signature count (how many signatures have been issued by the card)
596    pub fn digital_signature_count(&mut self) -> Result<u32, Error> {
597        Ok(self
598            .state
599            .opt
600            .security_support_template()?
601            .signature_count())
602    }
603
604    /// SELECT DATA ("select a DO in the current template").
605    pub fn select_data(&mut self, num: u8, tag: &[u8]) -> Result<(), Error> {
606        self.state.opt.select_data(num, tag)
607    }
608
609    /// Get cardholder certificate.
610    ///
611    /// Call select_data() before calling this fn to select a particular
612    /// certificate (if the card supports multiple certificates).
613    pub fn cardholder_certificate(&mut self) -> Result<Vec<u8>, Error> {
614        self.state.opt.cardholder_certificate()
615    }
616
617    /// "GET NEXT DATA" for the DO cardholder certificate.
618    ///
619    /// Cardholder certificate data for multiple slots can be read from the card by first calling
620    /// cardholder_certificate(), followed by up to two calls to  next_cardholder_certificate().
621    pub fn next_cardholder_certificate(&mut self) -> Result<Vec<u8>, Error> {
622        self.state.opt.next_cardholder_certificate()
623    }
624
625    /// Get KDF DO configuration (from cache).
626    pub fn kdf_do(&mut self) -> Result<KdfDo, Error> {
627        if let Some(kdf) = self.state.kdf_do() {
628            Ok(kdf.clone())
629        } else {
630            Err(Error::NotFound("No KDF DO found".to_string()))
631        }
632    }
633
634    /// Algorithm Information (list of supported Algorithm attributes).
635    pub fn algorithm_information(&mut self) -> Result<Option<AlgorithmInformation>, Error> {
636        // The DO "Algorithm Information" (Tag FA) shall be present if
637        // Algorithm attributes can be changed
638        let ec = self.extended_capabilities()?;
639        if !ec.algo_attrs_changeable() {
640            // Algorithm attributes can not be changed,
641            // list_supported_algo is not supported
642            return Ok(None);
643        }
644
645        self.state.opt.algorithm_information()
646    }
647
648    /// "MANAGE SECURITY ENVIRONMENT".
649    /// Make `key_ref` usable for the operation normally done by the key
650    /// designated by `for_operation`
651    pub fn manage_security_environment(
652        &mut self,
653        for_operation: KeyType,
654        key_ref: KeyType,
655    ) -> Result<(), Error> {
656        self.state
657            .opt
658            .manage_security_environment(for_operation, key_ref)
659    }
660
661    // ----------
662
663    /// Get "Attestation Certificate (Yubico)"
664    pub fn attestation_certificate(&mut self) -> Result<Vec<u8>, Error> {
665        self.state.opt.attestation_certificate()
666    }
667
668    /// Firmware Version, YubiKey specific (?)
669    pub fn firmware_version(&mut self) -> Result<Vec<u8>, Error> {
670        self.state.opt.firmware_version()
671    }
672
673    /// Set "identity", Nitrokey Start specific (possible values: 0, 1, 2).
674    /// <https://docs.nitrokey.com/start/windows/multiple-identities.html>
675    ///
676    /// A Nitrokey Start can present as 3 different virtual OpenPGP cards.
677    /// This command enables one of those virtual cards.
678    ///
679    /// Each virtual card identity behaves like a separate, independent OpenPGP card.
680    pub fn set_identity(&mut self, id: u8) -> Result<(), Error> {
681        // FIXME: what is in the returned data - is it ever useful?
682        let _ = self.state.opt.set_identity(id)?;
683
684        Ok(())
685    }
686
687    // ----------
688
689    /// Get the raw public key material for a key slot on the card
690    pub fn public_key_material(&mut self, key_type: KeyType) -> Result<PublicKeyMaterial, Error> {
691        self.state.opt.public_key(key_type)
692    }
693
694    // ----------
695
696    /// Reset all state on this OpenPGP card
697    pub fn factory_reset(&mut self) -> Result<(), Error> {
698        self.state.opt.factory_reset()
699    }
700}
701
702impl<'app> Card<User<'app, '_>> {
703    /// Helper fn to easily access underlying openpgp_card object
704    fn card(&mut self) -> &mut crate::ocard::Transaction<'app> {
705        &mut self.state.tx.state.opt
706    }
707
708    // FIXME
709
710    // pub fn decryptor(
711    //     &mut self,
712    //     touch_prompt: &'open (dyn Fn() + Send + Sync),
713    // ) -> Result<CardDecryptor<'_, 'app>, Error> {
714    //     let pk = self
715    //         .state
716    //         .tx
717    //         .public_key(KeyType::Decryption)?
718    //         .expect("Couldn't get decryption pubkey from card");
719    //
720    //     Ok(CardDecryptor::with_pubkey(self.card(), pk, touch_prompt))
721    // }
722    //
723    // pub fn decryptor_from_public(
724    //     &mut self,
725    //     pubkey: PublicKey,
726    //     touch_prompt: &'open (dyn Fn() + Send + Sync),
727    // ) -> CardDecryptor<'_, 'app> {
728    //     CardDecryptor::with_pubkey(self.card(), pubkey, touch_prompt)
729    // }
730    //
731    // pub fn authenticator(
732    //     &mut self,
733    //     touch_prompt: &'open (dyn Fn() + Send + Sync),
734    // ) -> Result<CardSigner<'_, 'app>, Error> {
735    //     let pk = self
736    //         .state
737    //         .tx
738    //         .public_key(KeyType::Authentication)?
739    //         .expect("Couldn't get authentication pubkey from card");
740    //
741    //     Ok(CardSigner::with_pubkey_for_auth(
742    //         self.card(),
743    //         pk,
744    //         touch_prompt,
745    //     ))
746    // }
747    // pub fn authenticator_from_public(
748    //     &mut self,
749    //     pubkey: PublicKey,
750    //     touch_prompt: &'open (dyn Fn() + Send + Sync),
751    // ) -> CardSigner<'_, 'app> {
752    //     CardSigner::with_pubkey_for_auth(self.card(), pubkey, touch_prompt)
753    // }
754
755    /// Set optional "Private use" data on the card.
756    ///
757    /// The presence and maximum length of these DOs is announced
758    /// in [`ExtendedCapabilities`].
759    ///
760    /// If available, there are 4 data fields for private use:
761    ///
762    /// - `1`: write accessible with User PIN verification
763    /// - `2`: write accessible with Admin PIN verification
764    /// - `3`: write accessible with User PIN verification
765    /// - `4`: write accessible with Admin PIN verification
766    pub fn set_private_use_do(&mut self, num: u8, data: Vec<u8>) -> Result<(), Error> {
767        self.card().set_private_use_do(num, data)
768    }
769}
770
771impl<'app, 'open> Card<Sign<'app, 'open>> {
772    /// Helper fn to easily access underlying openpgp_card object
773    fn card(&mut self) -> &mut crate::ocard::Transaction<'app> {
774        &mut self.state.tx.state.opt
775    }
776
777    // FIXME
778
779    // pub fn signer(
780    //     &mut self,
781    //     touch_prompt: &'open (dyn Fn() + Send + Sync),
782    // ) -> Result<CardSigner<'_, 'app>, Error> {
783    //     // FIXME: depending on the setting in "PW1 Status byte", only one
784    //     // signature can be made after verification for signing
785    //
786    //     let pk = self
787    //         .state
788    //         .tx
789    //         .public_key(KeyType::Signing)?
790    //         .expect("Couldn't get signing pubkey from card");
791    //
792    //     Ok(CardSigner::with_pubkey(self.card(), pk, touch_prompt))
793    // }
794    //
795    // pub fn signer_from_public(
796    //     &mut self,
797    //     pubkey: PublicKey,
798    //     touch_prompt: &'open (dyn Fn() + Send + Sync),
799    // ) -> CardSigner<'_, 'app> {
800    //     // FIXME: depending on the setting in "PW1 Status byte", only one
801    //     // signature can be made after verification for signing
802    //
803    //     CardSigner::with_pubkey(self.card(), pubkey, touch_prompt)
804    // }
805
806    /// Generate Attestation (Yubico)
807    pub fn generate_attestation(
808        &mut self,
809        key_type: KeyType,
810        touch_prompt: &'open (dyn Fn() + Send + Sync),
811    ) -> Result<(), Error> {
812        // Touch is required if:
813        // - the card supports the feature
814        // - and the policy is set to a value other than 'Off'
815        if let Some(uif) = self.state.tx.state.ard().uif_attestation()? {
816            if uif.touch_policy().touch_required() {
817                (touch_prompt)();
818            }
819        }
820
821        self.card().generate_attestation(key_type)
822    }
823}
824
825impl<'app> Card<Admin<'app, '_>> {
826    pub fn as_transaction(&'_ mut self) -> &mut Card<Transaction<'app>> {
827        self.state.tx
828    }
829
830    /// Helper fn to easily access underlying openpgp_card object
831    fn card(&mut self) -> &mut crate::ocard::Transaction<'app> {
832        &mut self.state.tx.state.opt
833    }
834}
835
836impl Card<Admin<'_, '_>> {
837    /// Set cardholder name.
838    ///
839    /// This is an ISO 8859-1 (Latin 1) String of max. 39 characters.
840    ///
841    /// Note that the standard specifies that this field should be encoded according
842    /// to ISO/IEC 7501-1:
843    ///
844    /// "The data element consists of surname (e. g. family name and given
845    /// name(s)) and forename(s) (including name suffix, e. g., Jr. and number).
846    /// Each item is separated by a ´<´ filler character (3C), the family- and
847    /// fore-name(s) are separated by two ´<<´ filler characters."
848    ///
849    /// This library doesn't perform this encoding.
850    pub fn set_cardholder_name(&mut self, name: &str) -> Result<(), Error> {
851        // All chars must be in ASCII7
852        if !name.is_ascii() {
853            return Err(Error::InternalError("Invalid char in name".into()));
854        };
855
856        // FIXME: encode spaces and do ordering
857
858        if name.len() >= 40 {
859            return Err(Error::InternalError("name too long".into()));
860        }
861
862        self.card().set_name(name.as_bytes())
863    }
864
865    pub fn set_lang(&mut self, lang: &[Lang]) -> Result<(), Error> {
866        if lang.len() > 8 {
867            return Err(Error::InternalError("lang too long".into()));
868        }
869
870        self.card().set_lang(lang)
871    }
872
873    pub fn set_sex(&mut self, sex: Sex) -> Result<(), Error> {
874        self.card().set_sex(sex)
875    }
876
877    /// Set optional "Private use" data on the card.
878    ///
879    /// The presence and maximum length of these DOs is announced
880    /// in [`ExtendedCapabilities`].
881    ///
882    /// If available, there are 4 data fields for private use:
883    ///
884    /// - `1`: write accessible with User PIN verification
885    /// - `2`: write accessible with Admin PIN verification
886    /// - `3`: write accessible with User PIN verification
887    /// - `4`: write accessible with Admin PIN verification
888    pub fn set_private_use_do(&mut self, num: u8, data: Vec<u8>) -> Result<(), Error> {
889        self.card().set_private_use_do(num, data)
890    }
891
892    pub fn set_login_data(&mut self, login_data: &[u8]) -> Result<(), Error> {
893        self.card().set_login(login_data)
894    }
895
896    /// Set "cardholder" URL on the card.
897    ///
898    /// "The URL should contain a link to a set of public keys in OpenPGP format, related to
899    /// the card."
900    pub fn set_url(&mut self, url: &str) -> Result<(), Error> {
901        if !url.is_ascii() {
902            return Err(Error::InternalError("Invalid char in url".into()));
903        }
904
905        // Check for max len
906        let ec = self.state.tx.extended_capabilities()?;
907
908        if url.len() <= ec.max_len_special_do().unwrap_or(u16::MAX) as usize {
909            // If we don't know the max length for URL ("special DO"),
910            // or if it's within the acceptable length:
911            // send the url update to the card.
912
913            self.card().set_url(url.as_bytes())
914        } else {
915            Err(Error::InternalError("URL too long".into()))
916        }
917    }
918
919    /// Set PW Status Bytes.
920    ///
921    /// According to the spec, length information should not be changed.
922    ///
923    /// If `long` is false, sends 1 byte to the card, otherwise 4.
924    ///
925    /// So, effectively, with `long == false` the setting `pw1_cds_multi`
926    /// can be changed.
927    /// With `long == true`, the settings `pw1_pin_block` and `pw3_pin_block`
928    /// can also be changed.
929    pub fn set_pw_status_bytes(
930        &mut self,
931        pw_status: &PWStatusBytes,
932        long: bool,
933    ) -> Result<(), Error> {
934        self.card().set_pw_status_bytes(pw_status, long)
935    }
936
937    /// Configure the "only valid for one PSO:CDS" setting in PW Status Bytes.
938    ///
939    /// If `once` is `true`, the User PIN must be verified before each
940    /// signing operation on the card.
941    /// If `once` is `false`, one User PIN verification is good for an
942    /// unlimited number of signing operations.
943    pub fn set_user_pin_signing_validity(&mut self, once: bool) -> Result<(), Error> {
944        let mut pws = self.as_transaction().pw_status_bytes()?;
945        pws.set_pw1_cds_valid_once(once);
946
947        self.set_pw_status_bytes(&pws, false)
948    }
949
950    /// Set the touch policy for a key slot (if the card supports this
951    /// feature).
952    ///
953    /// Note that the current touch policy setting (if available) can be read
954    /// via [`Card<Transaction>::user_interaction_flag`].
955    ///
956    /// (Caution: Setting the touch policy of the "Attestation" slot on YubiKey 5 devices
957    /// to a variation of "Fixed" is permanent for the lifetime of the hardware device!
958    /// It can't be undone with a factory reset!)
959    pub fn set_touch_policy(&mut self, key: KeyType, policy: TouchPolicy) -> Result<(), Error> {
960        let uif = match key {
961            KeyType::Signing => self.state.tx.state.ard().uif_pso_cds()?,
962            KeyType::Decryption => self.state.tx.state.ard().uif_pso_dec()?,
963            KeyType::Authentication => self.state.tx.state.ard().uif_pso_aut()?,
964            KeyType::Attestation => self.state.tx.state.ard().uif_attestation()?,
965        };
966
967        if let Some(mut uif) = uif {
968            uif.set_touch_policy(policy);
969
970            match key {
971                KeyType::Signing => self.card().set_uif_pso_cds(&uif)?,
972                KeyType::Decryption => self.card().set_uif_pso_dec(&uif)?,
973                KeyType::Authentication => self.card().set_uif_pso_aut(&uif)?,
974                KeyType::Attestation => self.card().set_uif_attestation(&uif)?,
975            }
976        } else {
977            return Err(Error::UnsupportedFeature(
978                "User Interaction Flag not available".into(),
979            ));
980        };
981
982        Ok(())
983    }
984
985    /// Set the User PIN on the card (also resets the User PIN error count)
986    pub fn reset_user_pin(&mut self, new: SecretString) -> Result<(), Error> {
987        let new = map_pin(new, PinType::Pw1, self.state.tx.state.kdf_do())?;
988
989        self.card().reset_retry_counter_pw1(new, None)
990    }
991
992    /// Define the "resetting code" on the card
993    pub fn set_resetting_code(&mut self, pin: SecretString) -> Result<(), Error> {
994        let pin = map_pin(pin, PinType::Rc, self.state.tx.state.kdf_do())?;
995
996        self.card().set_resetting_code(pin)
997    }
998
999    /// Set optional AES encryption/decryption key
1000    /// (32 bytes for AES256, or 16 bytes for AES128),
1001    /// if the card supports this feature.
1002    ///
1003    /// The availability of this feature is announced in
1004    /// [`Card<Transaction>::extended_capabilities`].
1005    pub fn set_pso_enc_dec_key(&mut self, key: &[u8]) -> Result<(), Error> {
1006        self.card().set_pso_enc_dec_key(key)
1007    }
1008
1009    /// Import a private key to the card into a specific key slot.
1010    ///
1011    /// (The caller needs to make sure that the content of `key` is suitable for `key_type`)
1012    pub fn import_key(
1013        &mut self,
1014        key: Box<dyn CardUploadableKey>,
1015        key_type: KeyType,
1016    ) -> Result<(), Error> {
1017        self.card().key_import(key, key_type)
1018    }
1019
1020    /// Configure the `algorithm_attributes` for key slot `key_type` based on
1021    /// the algorithm `algo`.
1022    /// This can be useful in preparation for [`Self::generate_key`].
1023    ///
1024    /// This is a convenience wrapper for [`Self::set_algorithm_attributes`]
1025    /// that determines the exact appropriate [`AlgorithmAttributes`] by
1026    /// reading information from the card.
1027    pub fn set_algorithm(&mut self, key_type: KeyType, algo: AlgoSimple) -> Result<(), Error> {
1028        let attr = algo.matching_algorithm_attributes(self.card(), key_type)?;
1029        self.set_algorithm_attributes(key_type, &attr)
1030    }
1031
1032    /// Configure the key slot `key_type` to `algorithm_attributes`.
1033    /// This can be useful in preparation for [`Self::generate_key`].
1034    ///
1035    /// Note that legal values for [`AlgorithmAttributes`] are card-specific.
1036    /// Different OpenPGP card implementations may support different
1037    /// algorithms, sometimes with differing requirements for the encoding
1038    /// (e.g. field sizes)
1039    ///
1040    /// See [`Self::set_algorithm`] for a convenience function that sets
1041    /// the algorithm attributes based on an [`AlgoSimple`].
1042    pub fn set_algorithm_attributes(
1043        &mut self,
1044        key_type: KeyType,
1045        algorithm_attributes: &AlgorithmAttributes,
1046    ) -> Result<(), Error> {
1047        self.card()
1048            .set_algorithm_attributes(key_type, algorithm_attributes)
1049    }
1050
1051    /// Generate a new cryptographic key in slot `key_type`, with the currently
1052    /// configured cryptographic algorithm
1053    /// (see [`Self::set_algorithm`] for changing the algorithm setting).
1054    pub fn generate_key(
1055        &mut self,
1056        fp_from_pub: fn(
1057            &PublicKeyMaterial,
1058            KeyGenerationTime,
1059            KeyType,
1060        ) -> Result<Fingerprint, Error>,
1061        key_type: KeyType,
1062    ) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> {
1063        self.card().generate_key(fp_from_pub, key_type)
1064    }
1065}