1use std::convert::TryFrom;
13use std::fmt;
14
15use crate::ocard::crypto::EccType;
16use crate::ocard::keys;
17use crate::ocard::{oid, KeyType, Transaction};
18use crate::Error;
19
20#[derive(Clone, Copy, Debug)]
22pub enum AlgoSimple {
23 RSA1k,
24 RSA2k,
25 RSA3k,
26 RSA4k,
27 NIST256,
28 NIST384,
29 NIST521,
30 Curve25519,
31}
32
33impl TryFrom<&str> for AlgoSimple {
34 type Error = Error;
35
36 fn try_from(algo: &str) -> Result<Self, Self::Error> {
37 use AlgoSimple::*;
38
39 Ok(match algo {
40 "RSA1k" => RSA1k,
41 "RSA2k" => RSA2k,
42 "RSA3k" => RSA3k,
43 "RSA4k" => RSA4k,
44 "NIST256" => NIST256,
45 "NIST384" => NIST384,
46 "NIST521" => NIST521,
47 "Curve25519" => Curve25519,
48 _ => return Err(Error::UnsupportedAlgo(format!("unexpected algo {algo}"))),
49 })
50 }
51}
52
53impl AlgoSimple {
54 pub fn matching_algorithm_attributes(
61 &self,
62 tx: &mut Transaction,
63 key_type: KeyType,
64 ) -> Result<AlgorithmAttributes, Error> {
65 let ard = tx.application_related_data()?;
66 let algorithm_attributes = ard.algorithm_attributes(key_type)?;
67
68 let algo_info = tx.algorithm_information_cached().ok().flatten();
69
70 self.determine_algo_attributes(key_type, algorithm_attributes, algo_info)
71 }
72
73 fn ecc_type(key_type: KeyType) -> EccType {
75 match key_type {
76 KeyType::Signing | KeyType::Authentication | KeyType::Attestation => EccType::ECDSA,
77 KeyType::Decryption => EccType::ECDH,
78 }
79 }
80
81 fn ecc_type_25519(key_type: KeyType) -> EccType {
83 match key_type {
84 KeyType::Signing | KeyType::Authentication | KeyType::Attestation => EccType::EdDSA,
85 KeyType::Decryption => EccType::ECDH,
86 }
87 }
88
89 fn curve_for_25519(key_type: KeyType) -> Curve {
91 match key_type {
92 KeyType::Signing | KeyType::Authentication | KeyType::Attestation => Curve::Ed25519,
93 KeyType::Decryption => Curve::Curve25519,
94 }
95 }
96
97 pub(crate) fn determine_algo_attributes(
105 &self,
106 key_type: KeyType,
107 algorithm_attributes: AlgorithmAttributes,
108 algo_info: Option<AlgorithmInformation>,
109 ) -> Result<AlgorithmAttributes, Error> {
110 let algo = match self {
111 Self::RSA1k => AlgorithmAttributes::Rsa(keys::determine_rsa_attrs(
112 1024,
113 key_type,
114 algorithm_attributes,
115 algo_info,
116 )?),
117 Self::RSA2k => AlgorithmAttributes::Rsa(keys::determine_rsa_attrs(
118 2048,
119 key_type,
120 algorithm_attributes,
121 algo_info,
122 )?),
123 Self::RSA3k => AlgorithmAttributes::Rsa(keys::determine_rsa_attrs(
124 3072,
125 key_type,
126 algorithm_attributes,
127 algo_info,
128 )?),
129 Self::RSA4k => AlgorithmAttributes::Rsa(keys::determine_rsa_attrs(
130 4096,
131 key_type,
132 algorithm_attributes,
133 algo_info,
134 )?),
135 Self::NIST256 => AlgorithmAttributes::Ecc(keys::determine_ecc_attrs(
136 Curve::NistP256r1.oid(),
137 Self::ecc_type(key_type),
138 key_type,
139 algo_info,
140 )?),
141 Self::NIST384 => AlgorithmAttributes::Ecc(keys::determine_ecc_attrs(
142 Curve::NistP384r1.oid(),
143 Self::ecc_type(key_type),
144 key_type,
145 algo_info,
146 )?),
147 Self::NIST521 => AlgorithmAttributes::Ecc(keys::determine_ecc_attrs(
148 Curve::NistP521r1.oid(),
149 Self::ecc_type(key_type),
150 key_type,
151 algo_info,
152 )?),
153 Self::Curve25519 => AlgorithmAttributes::Ecc(keys::determine_ecc_attrs(
154 Self::curve_for_25519(key_type).oid(),
155 Self::ecc_type_25519(key_type),
156 key_type,
157 algo_info,
158 )?),
159 };
160
161 Ok(algo)
162 }
163}
164
165#[derive(Debug, Clone, Eq, PartialEq)]
173pub struct AlgorithmInformation(pub(crate) Vec<(KeyType, AlgorithmAttributes)>);
174
175#[derive(Clone, Eq, PartialEq)]
184pub enum AlgorithmAttributes {
185 Rsa(RsaAttributes),
186 Ecc(EccAttributes),
187 Unknown(Vec<u8>),
188}
189
190impl fmt::Debug for AlgorithmAttributes {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 match self {
193 Self::Rsa(rsa) => {
194 write!(
195 f,
196 "RSA {} [e {}{}]",
197 rsa.len_n,
198 rsa.len_e,
199 if rsa.import_format != 0 {
200 format!(", format {}", rsa.import_format)
201 } else {
202 "".to_string()
203 }
204 )
205 }
206 Self::Ecc(ecc) => {
207 write!(
208 f,
209 "{:?} ({:?}){}",
210 ecc.ecc_type,
211 ecc.curve,
212 if ecc.import_format == Some(0xff) {
213 " with pub"
214 } else {
215 ""
216 }
217 )
218 }
219 Self::Unknown(u) => {
220 write!(f, "Unknown: {u:?}")
221 }
222 }
223 }
224}
225
226impl fmt::Display for AlgorithmAttributes {
227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228 match self {
229 Self::Rsa(rsa) => {
230 write!(f, "RSA {}", rsa.len_n)
231 }
232 Self::Ecc(ecc) => {
233 write!(f, "{:?} ({:?})", ecc.ecc_type, ecc.curve)
234 }
235 Self::Unknown(u) => {
236 write!(f, "Unknown: {u:?}")
237 }
238 }
239 }
240}
241
242impl AlgorithmAttributes {
243 pub(crate) fn to_data_object(&self) -> Result<Vec<u8>, Error> {
246 match self {
247 AlgorithmAttributes::Rsa(rsa) => Self::rsa_algo_attrs(rsa),
248 AlgorithmAttributes::Ecc(ecc) => Self::ecc_algo_attrs(ecc.oid(), ecc.ecc_type()),
249 _ => Err(Error::UnsupportedAlgo(format!("Unexpected Algo {self:?}"))),
250 }
251 }
252
253 fn rsa_algo_attrs(algo_attrs: &RsaAttributes) -> Result<Vec<u8>, Error> {
255 let mut algo_attributes = vec![0x01];
257
258 algo_attributes.extend(algo_attrs.len_n().to_be_bytes());
260
261 algo_attributes.push(0x00);
263 algo_attributes.push(algo_attrs.len_e() as u8);
264
265 algo_attributes.push(algo_attrs.import_format());
266
267 Ok(algo_attributes)
268 }
269
270 fn ecc_algo_attrs(oid: &[u8], ecc_type: EccType) -> Result<Vec<u8>, Error> {
272 let algo_id = match ecc_type {
273 EccType::EdDSA => 0x16,
274 EccType::ECDH => 0x12,
275 EccType::ECDSA => 0x13,
276 };
277
278 let mut algo_attributes = vec![algo_id];
279 algo_attributes.extend(oid);
280 Ok(algo_attributes)
283 }
284}
285
286#[derive(Debug, Clone, Eq, PartialEq)]
288pub struct RsaAttributes {
289 len_n: u16,
290 len_e: u16,
291 import_format: u8,
292}
293
294impl RsaAttributes {
295 pub fn new(len_n: u16, len_e: u16, import_format: u8) -> Self {
296 Self {
297 len_n,
298 len_e,
299 import_format,
300 }
301 }
302
303 pub fn len_n(&self) -> u16 {
304 self.len_n
305 }
306
307 pub fn len_e(&self) -> u16 {
308 self.len_e
309 }
310
311 pub fn import_format(&self) -> u8 {
312 self.import_format
313 }
314}
315
316#[derive(Debug, Clone, Eq, PartialEq)]
318pub struct EccAttributes {
319 ecc_type: EccType,
320 curve: Curve,
321 import_format: Option<u8>,
322}
323
324impl EccAttributes {
325 pub fn new(ecc_type: EccType, curve: Curve, import_format: Option<u8>) -> Self {
326 Self {
327 ecc_type,
328 curve,
329 import_format,
330 }
331 }
332
333 pub fn ecc_type(&self) -> EccType {
334 self.ecc_type
335 }
336
337 pub fn curve(&self) -> &Curve {
338 &self.curve
339 }
340
341 pub fn oid(&self) -> &[u8] {
342 self.curve.oid()
343 }
344
345 pub fn import_format(&self) -> Option<u8> {
346 self.import_format
347 }
348}
349
350#[derive(Debug, Clone, Eq, PartialEq)]
352pub enum Curve {
353 NistP256r1,
354 NistP384r1,
355 NistP521r1,
356 BrainpoolP256r1,
357 BrainpoolP384r1,
358 BrainpoolP512r1,
359 Secp256k1,
360 Ed25519,
361 Curve25519,
362 Ed448,
363 X448,
364
365 Unknown(Vec<u8>),
366}
367
368impl Curve {
369 pub fn oid(&self) -> &[u8] {
370 use Curve::*;
371 match self {
372 NistP256r1 => oid::NIST_P256R1,
373 NistP384r1 => oid::NIST_P384R1,
374 NistP521r1 => oid::NIST_P521R1,
375 BrainpoolP256r1 => oid::BRAINPOOL_P256R1,
376 BrainpoolP384r1 => oid::BRAINPOOL_P384R1,
377 BrainpoolP512r1 => oid::BRAINPOOL_P512R1,
378 Secp256k1 => oid::SECP256K1,
379 Ed25519 => oid::ED25519,
380 Curve25519 => oid::CV25519,
381 Ed448 => oid::ED448,
382 X448 => oid::X448,
383
384 Unknown(oid) => oid,
385 }
386 }
387}
388
389impl TryFrom<&[u8]> for Curve {
390 type Error = Error;
391
392 fn try_from(oid: &[u8]) -> Result<Self, Self::Error> {
393 use Curve::*;
394
395 let curve = match oid {
396 oid::NIST_P256R1 => NistP256r1,
397 oid::NIST_P384R1 => NistP384r1,
398 oid::NIST_P521R1 => NistP521r1,
399
400 oid::BRAINPOOL_P256R1 => BrainpoolP256r1,
401 oid::BRAINPOOL_P384R1 => BrainpoolP384r1,
402 oid::BRAINPOOL_P512R1 => BrainpoolP512r1,
403
404 oid::SECP256K1 => Secp256k1,
405
406 oid::ED25519 => Ed25519,
407 oid::CV25519 => Curve25519,
408
409 oid::ED448 => Ed448,
410 oid::X448 => X448,
411
412 _ => Unknown(oid.to_vec()),
413 };
414
415 Ok(curve)
416 }
417}