openpgp_card/
state.rs

1// SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer <heiko@schaefer.name>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! States of a card are modeled by the types `Open`, `Transaction`, `User`, `Sign`, `Admin`.
5
6use crate::ocard::data::{ApplicationRelatedData, KdfDo};
7use crate::{Cached, Card};
8
9/// States that a `Card` can be in.
10///
11/// See the implementations for more detail.
12pub trait State {}
13
14impl State for Open {}
15impl State for Transaction<'_> {}
16impl State for User<'_, '_> {}
17impl State for Sign<'_, '_> {}
18impl State for Admin<'_, '_> {}
19
20/// An OpenPGP card in its base state, no transaction has been started.
21///
22/// A transaction can be started on the card, in this state.
23pub struct Open {
24    pub(crate) pgp: crate::ocard::OpenPGP,
25}
26
27/// State of an OpenPGP card once a transaction has been started.
28///
29/// The cards is in its base state, base authorization applies.
30/// Card-Operations that don't require PIN validation can be performed in this state.
31/// This includes many read-operations from the card.
32///
33/// (Note that a factory-reset can be performed in this base state.)
34pub struct Transaction<'a> {
35    pub(crate) opt: crate::ocard::Transaction<'a>,
36
37    // Cache of "application related data".
38    //
39    // FIXME: Should be automatically invalidated when changing data on the card!
40    // (e.g. uploading keys, etc)
41    ard: Cached<ApplicationRelatedData>,
42
43    // Cache of the card's KdfDo
44    // FIXME: invalidate when changed!
45    kdf_do: Cached<KdfDo>,
46
47    // verify status of pw1
48    // FIXME: this mechanism needs more thought
49    pub(crate) pw1: bool,
50
51    // verify status of pw1 for signing
52    // FIXME: this mechanism needs more thought
53    pub(crate) pw1_sign: bool,
54
55    // verify status of pw3
56    // FIXME: this mechanism needs more thought
57    pub(crate) pw3: bool,
58}
59
60impl<'a> Transaction<'a> {
61    pub(crate) fn new(opt: crate::ocard::Transaction<'a>, ard: ApplicationRelatedData) -> Self {
62        Transaction {
63            opt,
64            ard: Cached::Value(ard),
65            kdf_do: Cached::Uncached,
66            pw1: false,
67            pw1_sign: false,
68            pw3: false,
69        }
70    }
71
72    pub(crate) fn ard(&mut self) -> &ApplicationRelatedData {
73        if matches!(self.ard, Cached::Uncached) {
74            match self.opt.application_related_data() {
75                Ok(ard) => {
76                    self.ard = Cached::Value(ard);
77                }
78                Err(_) => {
79                    self.ard = Cached::None;
80                }
81            }
82        }
83
84        match &self.ard {
85            Cached::Value(ard) => ard,
86            Cached::Uncached => unreachable!(),
87            Cached::None => unreachable!(),
88        }
89    }
90
91    pub(crate) fn kdf_do(&mut self) -> Option<&KdfDo> {
92        if matches!(self.kdf_do, Cached::Uncached) {
93            match self.opt.kdf_do() {
94                Ok(kdf) => {
95                    self.kdf_do = Cached::Value(kdf.clone());
96                }
97                Err(_) => {
98                    self.kdf_do = Cached::None;
99                }
100            }
101        }
102
103        match &self.kdf_do {
104            Cached::None => None,
105            Cached::Value(kdf) => Some(kdf),
106            Cached::Uncached => unreachable!(),
107        }
108    }
109
110    pub(crate) fn invalidate_cache(&mut self) {
111        self.ard = Cached::Uncached;
112        self.kdf_do = Cached::Uncached;
113    }
114}
115
116/// State of an OpenPGP card after successfully verifying the User PIN
117/// (this verification allow user operations other than signing).
118///
119/// In this state, e.g. decryption operations and authentication operations can be performed.
120pub struct User<'app, 'open> {
121    pub(crate) tx: &'open mut Card<Transaction<'app>>,
122}
123
124/// State of an OpenPGP card after successfully verifying PW1 for signing.
125///
126/// In this state, signatures can be issued.
127pub struct Sign<'app, 'open> {
128    pub(crate) tx: &'open mut Card<Transaction<'app>>,
129}
130
131/// State of an OpenPGP card after successful verification the Admin PIN.
132///
133/// In this state, the card can be configured, e.g.: importing key material onto the card,
134/// or setting the cardholder name.
135pub struct Admin<'app, 'open> {
136    pub(crate) tx: &'open mut Card<Transaction<'app>>,
137}