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