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}