1use openpgp_card::ocard::crypto::{CardUploadableKey, EccKey, EccType, PrivateKeyMaterial, RSAKey};
6use openpgp_card::ocard::data::{Fingerprint, KeyGenerationTime};
7use openpgp_card::Error;
8use pgp::crypto::ecc_curve::ECCCurve;
9use pgp::types::{
10 EcdhPublicParams, EcdsaPublicParams, EddsaLegacyPublicParams, KeyDetails, PlainSecretParams,
11 PublicKeyTrait, PublicParams, SecretParams,
12};
13use rsa::traits::{PrivateKeyParts, PublicKeyParts};
14use rsa::BigUint;
15
16enum Sec {
18 Key(pgp::packet::SecretKey),
19 SubKey(pgp::packet::SecretSubkey),
20}
21
22impl Sec {
23 fn public_params(&self) -> &PublicParams {
24 match self {
25 Sec::Key(sk) => sk.public_key().public_params(),
26 Sec::SubKey(ssk) => ssk.public_key().public_params(),
27 }
28 }
29
30 fn secret_params(&self) -> &SecretParams {
31 match self {
32 Sec::Key(sk) => sk.secret_params(),
33 Sec::SubKey(ssk) => ssk.secret_params(),
34 }
35 }
36}
37
38pub struct UploadableKey {
42 key: Sec,
43 unlocked: Option<PlainSecretParams>,
44}
45
46impl From<pgp::packet::SecretKey> for UploadableKey {
47 fn from(value: pgp::packet::SecretKey) -> Self {
48 Self {
49 key: Sec::Key(value),
50 unlocked: None,
51 }
52 }
53}
54
55impl From<pgp::packet::SecretSubkey> for UploadableKey {
56 fn from(value: pgp::packet::SecretSubkey) -> Self {
57 Self {
58 key: Sec::SubKey(value),
59 unlocked: None,
60 }
61 }
62}
63
64impl UploadableKey {
65 pub fn is_locked(&self) -> bool {
66 match self.key.secret_params() {
67 SecretParams::Plain(_) => false,
68 SecretParams::Encrypted(_) => true,
69 }
70 }
71
72 pub fn try_unlock(&mut self, pw: &str) -> Result<bool, Error> {
77 match self.key.secret_params() {
78 SecretParams::Plain(_) => Ok(false),
79 SecretParams::Encrypted(esp) => {
80 match &self.key {
81 Sec::Key(sk) => {
83 if let Ok(psp) = esp.unlock(&pw.into(), sk.public_key(), None) {
84 self.unlocked = Some(psp);
85 return Ok(true);
86 }
87 }
88 Sec::SubKey(ssk) => {
89 if let Ok(psp) = esp.unlock(&pw.into(), ssk.public_key(), None) {
90 self.unlocked = Some(psp);
91 return Ok(true);
92 }
93 }
94 }
95
96 Err(Error::InternalError("Could not unlock key".to_string()))
97 }
98 }
99 }
100}
101
102impl CardUploadableKey for UploadableKey {
103 fn private_key(&self) -> Result<PrivateKeyMaterial, Error> {
104 fn to_privatekeymaterial(
105 psp: &PlainSecretParams,
106 pp: &PublicParams,
107 ) -> Result<PrivateKeyMaterial, Error> {
108 match (psp, pp) {
109 (PlainSecretParams::RSA(secret), PublicParams::RSA(public)) => {
110 let (d, p, q, _u) = secret.to_bytes();
111
112 let rsa_key = Rsa::new(
113 public.key.e().to_bytes_be(),
114 d,
115 public.key.n().to_bytes_be(),
116 p,
117 q,
118 )?;
119 Ok(PrivateKeyMaterial::R(Box::new(rsa_key)))
120 }
121 (PlainSecretParams::ECDSA(s), PublicParams::ECDSA(p)) => {
122 let (curve, public, private) = match (p, s) {
123 (
124 EcdsaPublicParams::P256 { key },
125 pgp::crypto::ecdsa::SecretKey::P256(secret),
126 ) => (
127 ECCCurve::P256,
128 key.to_sec1_bytes(),
129 secret.to_bytes().to_vec(),
130 ),
131 (
132 EcdsaPublicParams::P384 { key },
133 pgp::crypto::ecdsa::SecretKey::P384(secret),
134 ) => (
135 ECCCurve::P384,
136 key.to_sec1_bytes(),
137 secret.to_bytes().to_vec(),
138 ),
139 (
140 EcdsaPublicParams::P521 { key },
141 pgp::crypto::ecdsa::SecretKey::P521(secret),
142 ) => (
143 ECCCurve::P521,
144 key.to_sec1_bytes(),
145 secret.to_bytes().to_vec(),
146 ),
147 (
148 EcdsaPublicParams::Secp256k1 { .. },
149 pgp::crypto::ecdsa::SecretKey::Secp256k1(_),
150 ) => {
151 return Err(Error::UnsupportedAlgo(
152 "ECDSA with curve Secp256k1 is unsupported".to_string(),
153 ))
154 }
155 _ => {
156 return Err(Error::UnsupportedAlgo(format!(
157 "ECDSA with unsupported algorithm(s) {p:?} / {s:?}"
158 )))
159 }
160 };
161
162 let ecc = Ecc::new(curve, private, public.to_vec(), EccType::ECDSA);
163 Ok(PrivateKeyMaterial::E(Box::new(ecc)))
164 }
165 (
166 PlainSecretParams::Ed25519Legacy(m),
167 PublicParams::EdDSALegacy(EddsaLegacyPublicParams::Ed25519 { key }),
168 ) => {
169 let mut public = Vec::with_capacity(33);
170 public.push(0x40);
171 public.extend_from_slice(key.as_bytes());
172
173 let ecc = Ecc::new(
174 ECCCurve::Ed25519.clone(),
175 m.as_bytes().to_vec(),
176 public,
177 EccType::EdDSA,
178 );
179 Ok(PrivateKeyMaterial::E(Box::new(ecc)))
180 }
181 (
182 PlainSecretParams::ECDH(pgp::crypto::ecdh::SecretKey::Curve25519(secret)),
183 PublicParams::ECDH(EcdhPublicParams::Curve25519 { p, .. }),
184 ) => {
185 let reversed_private = secret.to_bytes_rev();
187
188 let mut public = Vec::with_capacity(33);
189 public.push(0x40);
190 public.extend_from_slice(p.as_ref());
191
192 let ecc = Ecc::new(
193 ECCCurve::Curve25519.clone(),
194 reversed_private.to_vec(),
195 public.to_vec(),
196 EccType::ECDH,
197 );
198 Ok(PrivateKeyMaterial::E(Box::new(ecc)))
199 }
200 (
201 PlainSecretParams::ECDH(pgp::crypto::ecdh::SecretKey::P256 { secret }),
202 PublicParams::ECDH(EcdhPublicParams::P256 { p, .. }),
203 ) => {
204 let ecc = Ecc::new(
205 ECCCurve::P256.clone(),
206 secret.to_bytes().to_vec(),
207 p.to_sec1_bytes().to_vec(),
208 EccType::ECDH,
209 );
210 Ok(PrivateKeyMaterial::E(Box::new(ecc)))
211 }
212 (
213 PlainSecretParams::ECDH(pgp::crypto::ecdh::SecretKey::P384 { secret }),
214 PublicParams::ECDH(EcdhPublicParams::P384 { p, .. }),
215 ) => {
216 let ecc = Ecc::new(
217 ECCCurve::P384.clone(),
218 secret.to_bytes().to_vec(),
219 p.to_sec1_bytes().to_vec(),
220 EccType::ECDH,
221 );
222 Ok(PrivateKeyMaterial::E(Box::new(ecc)))
223 }
224 (
225 PlainSecretParams::ECDH(pgp::crypto::ecdh::SecretKey::P521 { secret }),
226 PublicParams::ECDH(EcdhPublicParams::P521 { p, .. }),
227 ) => {
228 let ecc = Ecc::new(
229 ECCCurve::P521.clone(),
230 secret.to_bytes().to_vec(),
231 p.to_sec1_bytes().to_vec(),
232 EccType::ECDH,
233 );
234 Ok(PrivateKeyMaterial::E(Box::new(ecc)))
235 }
236
237 _ => Err(Error::UnsupportedAlgo(format!(
238 "Unsupported key material {pp:?}"
239 ))),
240 }
241 }
242
243 let pp = self.key.public_params();
244
245 let psp = match self.key.secret_params() {
246 SecretParams::Plain(psp) => psp,
247 SecretParams::Encrypted(_) => {
248 if let Some(psp) = &self.unlocked {
249 psp
250 } else {
251 return Err(Error::InternalError(
252 "Secret key packet wasn't unlocked".to_string(),
253 ));
254 }
255 }
256 };
257
258 to_privatekeymaterial(psp, pp)
259 }
260
261 fn timestamp(&self) -> KeyGenerationTime {
262 let ts = match &self.key {
263 Sec::Key(sk) => sk.public_key().created_at(),
264 Sec::SubKey(ssk) => ssk.public_key().created_at(),
265 };
266
267 let ts = ts.timestamp() as u32;
268 ts.into()
269 }
270
271 fn fingerprint(&self) -> Result<Fingerprint, Error> {
272 let fp = match &self.key {
273 Sec::Key(sk) => sk.fingerprint(),
274 Sec::SubKey(ssk) => ssk.fingerprint(),
275 };
276
277 Fingerprint::try_from(fp.as_bytes())
278 }
279}
280
281struct Rsa {
282 e: Vec<u8>,
283 n: Vec<u8>,
284 p: Vec<u8>,
285 q: Vec<u8>,
286 pq: Vec<u8>,
287 dp1: Vec<u8>,
288 dq1: Vec<u8>,
289}
290
291impl Rsa {
292 fn new(e: Vec<u8>, d: Vec<u8>, n: Vec<u8>, p: Vec<u8>, q: Vec<u8>) -> Result<Self, Error> {
293 let key = rsa::RsaPrivateKey::from_components(
294 BigUint::from_bytes_be(&n),
295 BigUint::from_bytes_be(&e),
296 BigUint::from_bytes_be(&d),
297 vec![BigUint::from_bytes_be(&p), BigUint::from_bytes_be(&q)],
298 )
299 .map_err(|e| Error::InternalError(format!("rsa error {e:?}")))?;
300
301 let pq = key
302 .qinv()
303 .ok_or_else(|| Error::InternalError("pq value missing".into()))?
304 .to_biguint()
305 .ok_or_else(|| Error::InternalError("conversion to bigunit failed".into()))?
306 .to_bytes_be();
307
308 let dp1 = key
309 .dp()
310 .ok_or_else(|| Error::InternalError("dp1 value missing".into()))?
311 .to_bytes_be();
312
313 let dq1 = key
314 .dq()
315 .ok_or_else(|| Error::InternalError("dq1 value missing".into()))?
316 .to_bytes_be();
317
318 Ok(Self {
319 e,
320 n,
321 p,
322 q,
323 pq,
324 dp1,
325 dq1,
326 })
327 }
328}
329
330impl RSAKey for Rsa {
331 fn e(&self) -> &[u8] {
332 self.e.as_ref()
333 }
334
335 fn p(&self) -> &[u8] {
336 self.p.as_ref()
337 }
338
339 fn q(&self) -> &[u8] {
340 self.q.as_ref()
341 }
342
343 fn pq(&self) -> Box<[u8]> {
344 Box::from(self.pq.as_ref())
345 }
346
347 fn dp1(&self) -> Box<[u8]> {
348 Box::from(self.dp1.as_ref())
349 }
350
351 fn dq1(&self) -> Box<[u8]> {
352 Box::from(self.dq1.as_ref())
353 }
354
355 fn n(&self) -> &[u8] {
356 self.n.as_ref()
357 }
358}
359
360struct Ecc {
363 curve: ECCCurve,
364 private: Vec<u8>,
365 public: Vec<u8>,
366 ecc_type: EccType,
367
368 oid: Vec<u8>,
369}
370
371impl Ecc {
372 fn new(curve: ECCCurve, private: Vec<u8>, public: Vec<u8>, ecc_type: EccType) -> Self {
373 let oid = curve.oid();
374
375 Ecc {
376 curve,
377 private,
378 public,
379 ecc_type,
380 oid,
381 }
382 }
383}
384
385fn pad(mut v: Vec<u8>, len: usize) -> Vec<u8> {
386 while v.len() < len {
387 v.insert(0, 0)
388 }
389
390 v
391}
392
393impl EccKey for Ecc {
394 fn oid(&self) -> &[u8] {
395 &self.oid
396 }
397
398 fn private(&self) -> Vec<u8> {
399 match self.curve {
400 ECCCurve::P256 => pad(self.private.clone(), 0x20),
401 ECCCurve::P384 => pad(self.private.clone(), 0x30),
402 ECCCurve::P521 => pad(self.private.clone(), 0x42),
403 ECCCurve::Curve25519 | ECCCurve::Ed25519 => pad(self.private.clone(), 0x20),
404 _ => self.private.clone(),
405 }
406 }
407
408 fn public(&self) -> Vec<u8> {
409 self.public.clone()
411 }
412
413 fn ecc_type(&self) -> EccType {
414 self.ecc_type
415 }
416}