1use super::Provide;
8use crate::authenticators::ApplicationIdentity;
9use crate::key_info_managers::{KeyIdentity, KeyInfoManagerClient};
10use crate::providers::ProviderIdentity;
11use crate::providers::cryptoauthlib::key_slot_storage::KeySlotStorage;
12use derivative::Derivative;
13use log::{error, trace, warn};
14use parsec_interface::operations::list_providers::ProviderInfo;
15use parsec_interface::operations::list_providers::Uuid;
16use parsec_interface::operations::{list_clients, list_keys};
17use parsec_interface::requests::{Opcode, ProviderId, ResponseStatus, Result};
18use std::collections::HashSet;
19use std::io::{Error, ErrorKind};
20
21use parsec_interface::operations::{
22 psa_aead_decrypt, psa_aead_encrypt, psa_cipher_decrypt, psa_cipher_encrypt, psa_destroy_key,
23 psa_export_key, psa_export_public_key, psa_generate_key, psa_generate_random, psa_hash_compare,
24 psa_hash_compute, psa_import_key, psa_raw_key_agreement, psa_sign_hash, psa_sign_message,
25 psa_verify_hash, psa_verify_message,
26};
27
28mod access_keys;
29mod aead;
30mod asym_sign;
31mod cipher;
32mod generate_random;
33mod hash;
34mod key_agreement;
35mod key_management;
36mod key_slot;
37mod key_slot_storage;
38
39#[derive(Derivative)]
41#[derivative(Debug)]
42pub struct Provider {
43 #[derivative(Debug = "ignore")]
44 device: rust_cryptoauthlib::AteccDevice,
45 provider_id: ProviderId,
46 provider_identity: ProviderIdentity,
48 #[derivative(Debug = "ignore")]
49 key_info_store: KeyInfoManagerClient,
50 key_slots: KeySlotStorage,
51 supported_opcodes: HashSet<Opcode>,
52}
53
54impl Provider {
55 pub const DEFAULT_PROVIDER_NAME: &'static str = "cryptoauthlib-provider";
57
58 pub const PROVIDER_UUID: &'static str = "b8ba81e2-e9f7-4bdd-b096-a29d0019960c";
60
61 fn new(
63 provider_name: String,
64 key_info_store: KeyInfoManagerClient,
65 atca_iface: rust_cryptoauthlib::AtcaIfaceCfg,
66 access_key_file_name: Option<String>,
67 ) -> Option<Provider> {
68 let device = match rust_cryptoauthlib::setup_atecc_device(atca_iface) {
70 Ok(dev) => dev,
71 Err(err) => {
72 error!("ATECC device initialization failed: {}", err);
73 return None;
74 }
75 };
76
77 if !device.is_configuration_locked() {
79 error!("Error: configuration is not locked.");
80 return None;
81 }
82
83 let mut cryptoauthlib_provider = Provider {
84 device,
85 provider_id: ProviderId::CryptoAuthLib,
86 provider_identity: ProviderIdentity {
87 name: provider_name,
88 uuid: String::from(Self::PROVIDER_UUID),
89 },
90 key_info_store,
91 key_slots: KeySlotStorage::new(),
92 supported_opcodes: HashSet::new(),
93 };
94
95 let mut atecc_config_vec = Vec::<rust_cryptoauthlib::AtcaSlot>::new();
97 let err = cryptoauthlib_provider
98 .device
99 .get_config(&mut atecc_config_vec);
100 if rust_cryptoauthlib::AtcaStatus::AtcaSuccess != err {
101 error!("atecc_get_config failed: {}", err);
102 return None;
103 }
104
105 if let Err(err) = cryptoauthlib_provider
107 .key_slots
108 .set_hw_config(&atecc_config_vec)
109 {
110 error!("Applying hardware configuration failed: {}", err);
111 return None;
112 }
113
114 let mut to_remove: Vec<KeyIdentity> = Vec::new();
118 match cryptoauthlib_provider.key_info_store.get_all() {
119 Ok(key_identities) => {
120 for key_identity in key_identities.iter() {
121 match cryptoauthlib_provider
122 .key_info_store
123 .does_not_exist(key_identity)
124 {
125 Ok(x) => x,
126 Err(err) => {
127 warn!(
128 "Error getting the Key ID for KeyIdentity:\n{}\n(error: {}), continuing...",
129 key_identity, err
130 );
131 to_remove.push(key_identity.clone());
132 continue;
133 }
134 };
135 let key_info_id = match cryptoauthlib_provider
136 .key_info_store
137 .get_key_id::<u8>(key_identity)
138 {
139 Ok(x) => x,
140 Err(err) => {
141 warn!(
142 "Could not get key info id for KeyIdentity {:?} because {}",
143 key_identity, err
144 );
145 to_remove.push(key_identity.clone());
146 continue;
147 }
148 };
149 let key_info_attributes = match cryptoauthlib_provider
150 .key_info_store
151 .get_key_attributes(key_identity)
152 {
153 Ok(x) => x,
154 Err(err) => {
155 warn!(
156 "Could not get key attributes for KeyIdentity {:?} because {}",
157 key_identity, err
158 );
159 to_remove.push(key_identity.clone());
160 continue;
161 }
162 };
163 match cryptoauthlib_provider
164 .key_slots
165 .key_validate_and_mark_busy(key_info_id, &key_info_attributes)
166 {
167 Ok(None) => (),
168 Ok(Some(warning)) => {
169 warn!("{} for KeyIdentity {:?}", warning, key_identity)
170 }
171 Err(err) => {
172 warn!("{} for KeyIdentity {:?}", err, key_identity);
173 to_remove.push(key_identity.clone());
174 continue;
175 }
176 }
177 }
178 }
179 Err(err) => {
180 error!("Key Info Manager error: {}", err);
181 return None;
182 }
183 };
184 for key_identity in to_remove.iter() {
185 if let Err(err) = cryptoauthlib_provider
186 .key_info_store
187 .remove_key_info(key_identity)
188 {
189 error!("Key Info Manager error: {}", err);
190 return None;
191 }
192 }
193
194 if cryptoauthlib_provider.set_opcodes().is_none() {
195 warn!("Failed to setup opcodes for cryptoauthlib_provider");
196 }
197
198 let err = cryptoauthlib_provider.set_access_keys(access_key_file_name);
199 match err {
200 Some(rust_cryptoauthlib::AtcaStatus::AtcaSuccess) => (),
201 _ => {
202 warn!("Unable to set access keys. This is dangerous for a hardware interface.");
203 }
204 }
205
206 Some(cryptoauthlib_provider)
207 }
208
209 fn set_opcodes(&mut self) -> Option<()> {
210 match self.device.get_device_type() {
211 rust_cryptoauthlib::AtcaDeviceType::ATECC508A
212 | rust_cryptoauthlib::AtcaDeviceType::ATECC608A
213 | rust_cryptoauthlib::AtcaDeviceType::ATECC108A => {
214 if self.supported_opcodes.insert(Opcode::PsaGenerateKey)
215 && self.supported_opcodes.insert(Opcode::PsaDestroyKey)
216 && self.supported_opcodes.insert(Opcode::PsaHashCompute)
217 && self.supported_opcodes.insert(Opcode::PsaHashCompare)
218 && self.supported_opcodes.insert(Opcode::PsaGenerateRandom)
219 && self.supported_opcodes.insert(Opcode::PsaImportKey)
220 && self.supported_opcodes.insert(Opcode::PsaSignHash)
221 && self.supported_opcodes.insert(Opcode::PsaVerifyHash)
222 && self.supported_opcodes.insert(Opcode::PsaCipherEncrypt)
223 && self.supported_opcodes.insert(Opcode::PsaCipherDecrypt)
224 && self.supported_opcodes.insert(Opcode::PsaSignMessage)
225 && self.supported_opcodes.insert(Opcode::PsaVerifyMessage)
226 && self.supported_opcodes.insert(Opcode::PsaExportPublicKey)
227 && self.supported_opcodes.insert(Opcode::PsaExportKey)
228 && self.supported_opcodes.insert(Opcode::PsaAeadEncrypt)
229 && self.supported_opcodes.insert(Opcode::PsaAeadDecrypt)
230 && self.supported_opcodes.insert(Opcode::PsaRawKeyAgreement)
231 {
232 Some(())
233 } else {
234 None
235 }
236 }
237 rust_cryptoauthlib::AtcaDeviceType::AtcaTestDevSuccess
238 | rust_cryptoauthlib::AtcaDeviceType::AtcaTestDevFail
239 | rust_cryptoauthlib::AtcaDeviceType::AtcaTestDevFailUnimplemented => {
240 let _ = self.supported_opcodes.insert(Opcode::PsaGenerateRandom);
241 Some(())
242 }
243 _ => None,
244 }
245 }
246}
247
248impl Provide for Provider {
249 fn describe(&self) -> Result<(ProviderInfo, HashSet<Opcode>)> {
250 trace!("describe ingress");
251 Ok((
252 ProviderInfo {
253 uuid: Uuid::parse_str(Provider::PROVIDER_UUID)
255 .or(Err(ResponseStatus::InvalidEncoding))?,
256 description: String::from(
257 "User space hardware provider, utilizing MicrochipTech CryptoAuthentication Library for ATECCx08 chips",
258 ),
259 vendor: String::from("Arm"),
260 version_maj: 0,
261 version_min: 1,
262 version_rev: 0,
263 id: ProviderId::CryptoAuthLib,
264 },
265 self.supported_opcodes.iter().copied().collect(),
266 ))
267 }
268
269 fn list_keys(
270 &self,
271 application_identity: &ApplicationIdentity,
272 _op: list_keys::Operation,
273 ) -> Result<list_keys::Result> {
274 Ok(list_keys::Result {
275 keys: self.key_info_store.list_keys(application_identity)?,
276 })
277 }
278
279 fn list_clients(&self, _op: list_clients::Operation) -> Result<list_clients::Result> {
280 Ok(list_clients::Result {
281 clients: self
282 .key_info_store
283 .list_clients()?
284 .into_iter()
285 .map(|application_identity| application_identity.name().clone())
286 .collect(),
287 })
288 }
289
290 fn psa_hash_compute(
291 &self,
292 op: psa_hash_compute::Operation,
293 ) -> Result<psa_hash_compute::Result> {
294 trace!("psa_hash_compute ingress");
295 if !self.supported_opcodes.contains(&Opcode::PsaHashCompute) {
296 Err(ResponseStatus::PsaErrorNotSupported)
297 } else {
298 self.psa_hash_compute_internal(op)
299 }
300 }
301
302 fn psa_hash_compare(
303 &self,
304 op: psa_hash_compare::Operation,
305 ) -> Result<psa_hash_compare::Result> {
306 trace!("psa_hash_compare ingress");
307 if !self.supported_opcodes.contains(&Opcode::PsaHashCompare) {
308 Err(ResponseStatus::PsaErrorNotSupported)
309 } else {
310 self.psa_hash_compare_internal(op)
311 }
312 }
313
314 fn psa_generate_random(
315 &self,
316 op: psa_generate_random::Operation,
317 ) -> Result<psa_generate_random::Result> {
318 trace!("psa_generate_random ingress");
319 if !self.supported_opcodes.contains(&Opcode::PsaGenerateRandom) {
320 Err(ResponseStatus::PsaErrorNotSupported)
321 } else {
322 self.psa_generate_random_internal(op)
323 }
324 }
325
326 fn psa_generate_key(
327 &self,
328 application_identity: &ApplicationIdentity,
329 op: psa_generate_key::Operation,
330 ) -> Result<psa_generate_key::Result> {
331 trace!("psa_generate_key ingress");
332 if !self.supported_opcodes.contains(&Opcode::PsaGenerateKey) {
333 Err(ResponseStatus::PsaErrorNotSupported)
334 } else {
335 self.psa_generate_key_internal(application_identity, op)
336 }
337 }
338
339 fn psa_destroy_key(
340 &self,
341 application_identity: &ApplicationIdentity,
342 op: psa_destroy_key::Operation,
343 ) -> Result<psa_destroy_key::Result> {
344 trace!("psa_destroy_key ingress");
345 if !self.supported_opcodes.contains(&Opcode::PsaDestroyKey) {
346 Err(ResponseStatus::PsaErrorNotSupported)
347 } else {
348 self.psa_destroy_key_internal(application_identity, op)
349 }
350 }
351
352 fn psa_import_key(
353 &self,
354 application_identity: &ApplicationIdentity,
355 op: psa_import_key::Operation,
356 ) -> Result<psa_import_key::Result> {
357 trace!("psa_import_key ingress");
358 if !self.supported_opcodes.contains(&Opcode::PsaImportKey) {
359 Err(ResponseStatus::PsaErrorNotSupported)
360 } else {
361 self.psa_import_key_internal(application_identity, op)
362 }
363 }
364
365 fn psa_sign_hash(
366 &self,
367 application_identity: &ApplicationIdentity,
368 op: psa_sign_hash::Operation,
369 ) -> Result<psa_sign_hash::Result> {
370 trace!("psa_sign_hash ingress");
371 if !self.supported_opcodes.contains(&Opcode::PsaSignHash) {
372 Err(ResponseStatus::PsaErrorNotSupported)
373 } else {
374 self.psa_sign_hash_internal(application_identity, op)
375 }
376 }
377
378 fn psa_verify_hash(
379 &self,
380 application_identity: &ApplicationIdentity,
381 op: psa_verify_hash::Operation,
382 ) -> Result<psa_verify_hash::Result> {
383 trace!("psa_verify_hash ingress");
384 if !self.supported_opcodes.contains(&Opcode::PsaVerifyHash) {
385 Err(ResponseStatus::PsaErrorNotSupported)
386 } else {
387 self.psa_verify_hash_internal(application_identity, op)
388 }
389 }
390
391 fn psa_cipher_encrypt(
392 &self,
393 application_identity: &ApplicationIdentity,
394 op: psa_cipher_encrypt::Operation,
395 ) -> Result<psa_cipher_encrypt::Result> {
396 trace!("psa_cipher_encrypt ingress");
397 if !self.supported_opcodes.contains(&Opcode::PsaCipherEncrypt) {
398 Err(ResponseStatus::PsaErrorNotSupported)
399 } else {
400 self.psa_cipher_encrypt_internal(application_identity, op)
401 }
402 }
403
404 fn psa_cipher_decrypt(
405 &self,
406 application_identity: &ApplicationIdentity,
407 op: psa_cipher_decrypt::Operation,
408 ) -> Result<psa_cipher_decrypt::Result> {
409 trace!("psa_cipher_decrypt ingress");
410 if !self.supported_opcodes.contains(&Opcode::PsaCipherDecrypt) {
411 Err(ResponseStatus::PsaErrorNotSupported)
412 } else {
413 self.psa_cipher_decrypt_internal(application_identity, op)
414 }
415 }
416
417 fn psa_sign_message(
418 &self,
419 application_identity: &ApplicationIdentity,
420 op: psa_sign_message::Operation,
421 ) -> Result<psa_sign_message::Result> {
422 trace!("psa_sign_message ingress");
423 if !self.supported_opcodes.contains(&Opcode::PsaSignMessage) {
424 Err(ResponseStatus::PsaErrorNotSupported)
425 } else {
426 self.psa_sign_message_internal(application_identity, op)
427 }
428 }
429
430 fn psa_verify_message(
431 &self,
432 application_identity: &ApplicationIdentity,
433 op: psa_verify_message::Operation,
434 ) -> Result<psa_verify_message::Result> {
435 trace!("psa_verify_message ingress");
436 if !self.supported_opcodes.contains(&Opcode::PsaVerifyMessage) {
437 Err(ResponseStatus::PsaErrorNotSupported)
438 } else {
439 self.psa_verify_message_internal(application_identity, op)
440 }
441 }
442
443 fn psa_export_public_key(
444 &self,
445 application_identity: &ApplicationIdentity,
446 op: psa_export_public_key::Operation,
447 ) -> Result<psa_export_public_key::Result> {
448 trace!("psa_export_public_key ingress");
449 if !self.supported_opcodes.contains(&Opcode::PsaExportPublicKey) {
450 Err(ResponseStatus::PsaErrorNotSupported)
451 } else {
452 self.psa_export_public_key_internal(application_identity, op)
453 }
454 }
455
456 fn psa_export_key(
457 &self,
458 application_identity: &ApplicationIdentity,
459 op: psa_export_key::Operation,
460 ) -> Result<psa_export_key::Result> {
461 trace!("psa_export_key ingress");
462 if !self.supported_opcodes.contains(&Opcode::PsaExportKey) {
463 Err(ResponseStatus::PsaErrorNotSupported)
464 } else {
465 self.psa_export_key_internal(application_identity, op)
466 }
467 }
468
469 fn psa_aead_encrypt(
470 &self,
471 application_identity: &ApplicationIdentity,
472 op: psa_aead_encrypt::Operation,
473 ) -> Result<psa_aead_encrypt::Result> {
474 trace!("psa_aead_encrypt ingress");
475 if !self.supported_opcodes.contains(&Opcode::PsaAeadEncrypt) {
476 Err(ResponseStatus::PsaErrorNotSupported)
477 } else {
478 self.psa_aead_encrypt_internal(application_identity, op)
479 }
480 }
481
482 fn psa_aead_decrypt(
483 &self,
484 application_identity: &ApplicationIdentity,
485 op: psa_aead_decrypt::Operation,
486 ) -> Result<psa_aead_decrypt::Result> {
487 trace!("psa_aead_decrypt ingress");
488 if !self.supported_opcodes.contains(&Opcode::PsaAeadDecrypt) {
489 Err(ResponseStatus::PsaErrorNotSupported)
490 } else {
491 self.psa_aead_decrypt_internal(application_identity, op)
492 }
493 }
494
495 fn psa_raw_key_agreement(
496 &self,
497 application_identity: &ApplicationIdentity,
498 op: psa_raw_key_agreement::Operation,
499 ) -> Result<psa_raw_key_agreement::Result> {
500 trace!("psa_raw_key_agreement ingress");
501 if !self.supported_opcodes.contains(&Opcode::PsaRawKeyAgreement) {
502 Err(ResponseStatus::PsaErrorNotSupported)
503 } else {
504 self.psa_raw_key_agreement_internal(application_identity, op)
505 }
506 }
507}
508
509#[derive(Default, Derivative)]
511#[derivative(Debug)]
512pub struct ProviderBuilder {
513 provider_name: Option<String>,
514 #[derivative(Debug = "ignore")]
515 key_info_store: Option<KeyInfoManagerClient>,
516 device_type: Option<String>,
517 iface_type: Option<String>,
518 wake_delay: Option<u16>,
519 rx_retries: Option<i32>,
520 slave_address: Option<u8>,
521 bus: Option<u8>,
522 baud: Option<u32>,
523 access_key_file_name: Option<String>,
524}
525
526impl ProviderBuilder {
527 pub fn new() -> ProviderBuilder {
529 ProviderBuilder {
530 provider_name: None,
531 key_info_store: None,
532 device_type: None,
533 iface_type: None,
534 wake_delay: None,
535 rx_retries: None,
536 slave_address: None,
537 bus: None,
538 baud: None,
539 access_key_file_name: None,
540 }
541 }
542
543 pub fn with_provider_name(mut self, provider_name: String) -> ProviderBuilder {
545 self.provider_name = Some(provider_name);
546
547 self
548 }
549
550 pub fn with_key_info_store(mut self, key_info_store: KeyInfoManagerClient) -> ProviderBuilder {
552 self.key_info_store = Some(key_info_store);
553
554 self
555 }
556
557 pub fn with_device_type(mut self, device_type: String) -> ProviderBuilder {
559 self.device_type = Some(device_type);
560
561 self
562 }
563
564 pub fn with_iface_type(mut self, iface_type: String) -> ProviderBuilder {
566 self.iface_type = Some(iface_type);
567
568 self
569 }
570
571 pub fn with_wake_delay(mut self, wake_delay: Option<u16>) -> ProviderBuilder {
573 self.wake_delay = wake_delay;
574
575 self
576 }
577
578 pub fn with_rx_retries(mut self, rx_retries: Option<i32>) -> ProviderBuilder {
580 self.rx_retries = rx_retries;
581
582 self
583 }
584
585 pub fn with_slave_address(mut self, slave_address: Option<u8>) -> ProviderBuilder {
587 self.slave_address = slave_address;
588
589 self
590 }
591
592 pub fn with_bus(mut self, bus: Option<u8>) -> ProviderBuilder {
594 self.bus = bus;
595
596 self
597 }
598
599 pub fn with_baud(mut self, baud: Option<u32>) -> ProviderBuilder {
601 self.baud = baud;
602
603 self
604 }
605
606 pub fn with_access_key_file(mut self, access_key_file_name: Option<String>) -> ProviderBuilder {
608 self.access_key_file_name = access_key_file_name;
609
610 self
611 }
612
613 pub fn build(self) -> std::io::Result<Provider> {
615 let iface_cfg = match self.iface_type {
616 Some(x) => match x.as_str() {
617 "i2c" => {
618 let atcai2c_iface_cfg = rust_cryptoauthlib::AtcaIfaceI2c::default()
619 .set_slave_address(self.slave_address.ok_or_else(|| {
620 Error::new(ErrorKind::InvalidData, "missing atecc i2c slave address")
621 })?)
622 .set_bus(self.bus.ok_or_else(|| {
623 Error::new(ErrorKind::InvalidData, "missing atecc i2c bus")
624 })?)
625 .set_baud(self.baud.ok_or_else(|| {
626 Error::new(ErrorKind::InvalidData, "missing atecc i2c baud rate")
627 })?);
628 rust_cryptoauthlib::AtcaIfaceCfg::default()
629 .set_iface_type("i2c".to_owned())
630 .set_devtype(self.device_type.ok_or_else(|| {
631 Error::new(ErrorKind::InvalidData, "missing atecc device type")
632 })?)
633 .set_wake_delay(self.wake_delay.ok_or_else(|| {
634 Error::new(ErrorKind::InvalidData, "missing atecc wake delay")
635 })?)
636 .set_rx_retries(self.rx_retries.ok_or_else(|| {
637 Error::new(
638 ErrorKind::InvalidData,
639 "missing rx retries number for atecc",
640 )
641 })?)
642 .set_iface(
643 rust_cryptoauthlib::AtcaIface::default().set_atcai2c(atcai2c_iface_cfg),
644 )
645 }
646 "test-interface" => rust_cryptoauthlib::AtcaIfaceCfg::default()
647 .set_iface_type("test-interface".to_owned())
648 .set_devtype(self.device_type.ok_or_else(|| {
649 Error::new(ErrorKind::InvalidData, "missing atecc device type")
650 })?),
651 _ => {
652 return Err(Error::new(
653 ErrorKind::InvalidData,
654 "Unsupported inteface type",
655 ));
656 }
657 },
658 None => return Err(Error::new(ErrorKind::InvalidData, "Missing inteface type")),
659 };
660 Provider::new(
661 self.provider_name
662 .ok_or_else(|| Error::new(ErrorKind::InvalidData, "missing provider name"))?,
663 self.key_info_store
664 .ok_or_else(|| Error::new(ErrorKind::InvalidData, "missing key info store"))?,
665 iface_cfg,
666 self.access_key_file_name,
667 )
668 .ok_or_else(|| {
669 Error::new(
670 ErrorKind::InvalidData,
671 "CryptoAuthLib Provider initialization failed",
672 )
673 })
674 }
675}