noxtls_psa/provider.rs
1// Copyright (c) 2019-2026, Argenox Technologies LLC
2// All rights reserved.
3//
4// SPDX-License-Identifier: GPL-2.0-only OR LicenseRef-Argenox-Commercial-License
5//
6// This file is part of the NoxTLS Library.
7//
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU General Public License as published by the
10// Free Software Foundation; version 2 of the License.
11//
12// Alternatively, this file may be used under the terms of a commercial
13// license from Argenox Technologies LLC.
14//
15// See `noxtls/LICENSE` and `noxtls/LICENSE.md` in this repository for full details.
16// CONTACT: info@argenox.com
17
18#[cfg(feature = "alloc")]
19use alloc::{collections::BTreeMap, vec::Vec};
20use noxtls_core::{Error, Result};
21use noxtls_crypto::{
22 aes_gcm_encrypt, p256_ecdh_shared_secret, p256_ecdsa_sign_sha256, rsaes_oaep_sha256_decrypt,
23 rsaes_pkcs1_v15_decrypt, rsassa_pss_sha256_sign, rsassa_sha256_sign, sha256, x25519, AesCipher,
24 P256PrivateKey, P256PublicKey, RsaPrivateKey,
25};
26
27/// Identifies a backend-managed external key object.
28#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
29pub struct PsaExternalKeyHandle {
30 id: Vec<u8>,
31}
32
33impl PsaExternalKeyHandle {
34 /// Constructs an external key handle from opaque identifier bytes.
35 ///
36 /// # Arguments
37 ///
38 /// * `id` - Opaque provider-owned key identifier bytes.
39 ///
40 /// # Returns
41 ///
42 /// A new [`PsaExternalKeyHandle`] owning the identifier bytes.
43 pub fn new(id: Vec<u8>) -> Self {
44 Self { id }
45 }
46
47 /// Borrows the opaque key identifier bytes.
48 ///
49 /// # Arguments
50 ///
51 /// * `self` - Handle whose stable identifier bytes are required.
52 ///
53 /// # Returns
54 ///
55 /// Borrowed opaque bytes identifying the provider key object.
56 pub fn as_bytes(&self) -> &[u8] {
57 &self.id
58 }
59}
60
61/// Enumerates signing algorithms supported by PSA provider mappings.
62#[derive(Copy, Clone, Debug, Eq, PartialEq)]
63pub enum PsaSignAlgorithm {
64 /// RSA PKCS#1 v1.5 signing with SHA-256 digest.
65 RsaPkcs1Sha256,
66 /// RSA PSS signing with SHA-256 digest.
67 RsaPssSha256,
68 /// ECDSA signing over P-256 with SHA-256 digest.
69 EcdsaP256Sha256,
70}
71
72/// Enumerates decrypt algorithms supported by PSA provider mappings.
73#[derive(Copy, Clone, Debug, Eq, PartialEq)]
74pub enum PsaDecryptAlgorithm {
75 /// RSA PKCS#1 v1.5 decryption.
76 RsaPkcs1v15,
77 /// RSA OAEP decryption using SHA-256.
78 RsaOaepSha256,
79}
80
81/// Enumerates derive algorithms supported by PSA provider mappings.
82#[derive(Copy, Clone, Debug, Eq, PartialEq)]
83pub enum PsaDeriveAlgorithm {
84 /// X25519 shared secret derivation.
85 X25519,
86 /// P-256 ECDH shared secret derivation.
87 EcdhP256,
88}
89
90/// Carries data required for backend sign operations.
91#[derive(Clone, Debug)]
92pub struct KeySignRequest<'a> {
93 /// Opaque provider handle to signing key object.
94 pub handle: &'a PsaExternalKeyHandle,
95 /// Algorithm selector for sign operation.
96 pub algorithm: PsaSignAlgorithm,
97 /// Input message bytes to be signed.
98 pub message: &'a [u8],
99 /// Optional PSS salt bytes for algorithms requiring explicit salt.
100 pub salt: Option<&'a [u8]>,
101}
102
103/// Carries data required for backend decrypt operations.
104#[derive(Clone, Debug)]
105pub struct KeyDecryptRequest<'a> {
106 /// Opaque provider handle to decrypt key object.
107 pub handle: &'a PsaExternalKeyHandle,
108 /// Algorithm selector for decrypt operation.
109 pub algorithm: PsaDecryptAlgorithm,
110 /// Ciphertext bytes to decrypt.
111 pub ciphertext: &'a [u8],
112 /// Optional OAEP label bytes for algorithms requiring explicit label.
113 pub label: Option<&'a [u8]>,
114}
115
116/// Carries data required for backend derive operations.
117#[derive(Clone, Debug)]
118pub struct KeyDeriveRequest<'a> {
119 /// Opaque provider handle to derive key object.
120 pub handle: &'a PsaExternalKeyHandle,
121 /// Algorithm selector for derive operation.
122 pub algorithm: PsaDeriveAlgorithm,
123 /// Peer public-key bytes in algorithm-expected encoding.
124 pub peer_public_key: &'a [u8],
125}
126
127/// Carries AES-GCM encrypt operation inputs.
128#[derive(Clone, Debug)]
129pub struct AeadEncryptRequest<'a> {
130 /// Symmetric encryption key bytes.
131 pub key: &'a [u8],
132 /// Nonce bytes for AES-GCM operation.
133 pub nonce: &'a [u8],
134 /// Associated authenticated data bytes.
135 pub aad: &'a [u8],
136 /// Plaintext bytes to encrypt.
137 pub plaintext: &'a [u8],
138}
139
140/// Carries AES-GCM encryption outputs.
141#[derive(Clone, Debug, Eq, PartialEq)]
142pub struct AeadEncryptResponse {
143 /// Produced ciphertext bytes.
144 pub ciphertext: Vec<u8>,
145 /// Produced 16-byte authentication tag.
146 pub tag: [u8; 16],
147}
148
149/// Defines backend operations required by PSA provider surface.
150pub trait PsaCryptoBackend {
151 /// Executes an asymmetric signing operation.
152 ///
153 /// # Arguments
154 ///
155 /// * `self` - Backend implementation receiving sign request.
156 /// * `request` - Sign request containing handle, algorithm, and digest.
157 ///
158 /// # Returns
159 ///
160 /// Signature bytes generated by the backend.
161 ///
162 /// # Errors
163 ///
164 /// Returns [`Error`] when handle resolution, policy checks, or crypto operation fails.
165 fn sign(&self, request: &KeySignRequest<'_>) -> Result<Vec<u8>>;
166
167 /// Executes an asymmetric decrypt operation.
168 ///
169 /// # Arguments
170 ///
171 /// * `self` - Backend implementation receiving decrypt request.
172 /// * `request` - Decrypt request containing handle, algorithm, and ciphertext.
173 ///
174 /// # Returns
175 ///
176 /// Plaintext bytes on successful decrypt.
177 ///
178 /// # Errors
179 ///
180 /// Returns [`Error`] when handle resolution, policy checks, or crypto operation fails.
181 fn decrypt(&self, request: &KeyDecryptRequest<'_>) -> Result<Vec<u8>>;
182
183 /// Executes a key-agreement derive operation.
184 ///
185 /// # Arguments
186 ///
187 /// * `self` - Backend implementation receiving derive request.
188 /// * `request` - Derive request containing handle, algorithm, and peer key.
189 ///
190 /// # Returns
191 ///
192 /// Shared secret bytes for the selected derive algorithm.
193 ///
194 /// # Errors
195 ///
196 /// Returns [`Error`] when handle resolution, policy checks, or derive operation fails.
197 fn derive(&self, request: &KeyDeriveRequest<'_>) -> Result<Vec<u8>>;
198
199 /// Fills output bytes with random data.
200 ///
201 /// # Arguments
202 ///
203 /// * `self` - Backend implementation receiving random request.
204 /// * `out` - Mutable output buffer for random bytes.
205 ///
206 /// # Returns
207 ///
208 /// `Ok(())` when the output buffer is fully written.
209 ///
210 /// # Errors
211 ///
212 /// Returns [`Error`] when backend cannot provide entropy.
213 fn random(&self, out: &mut [u8]) -> Result<()>;
214
215 /// Computes a SHA-256 digest.
216 ///
217 /// # Arguments
218 ///
219 /// * `self` - Backend implementation receiving hash request.
220 /// * `input` - Bytes to hash.
221 ///
222 /// # Returns
223 ///
224 /// A 32-byte SHA-256 digest.
225 ///
226 /// # Errors
227 ///
228 /// Returns [`Error`] when hashing fails for the backend.
229 fn sha256(&self, input: &[u8]) -> Result<[u8; 32]>;
230
231 /// Encrypts plaintext with AES-GCM.
232 ///
233 /// # Arguments
234 ///
235 /// * `self` - Backend implementation receiving AEAD request.
236 /// * `request` - AES-GCM request with key, nonce, AAD, and plaintext.
237 ///
238 /// # Returns
239 ///
240 /// Ciphertext bytes plus a 16-byte authentication tag.
241 ///
242 /// # Errors
243 ///
244 /// Returns [`Error`] when backend lacks AES-GCM support or encryption fails.
245 fn aes_gcm_encrypt(&self, request: &AeadEncryptRequest<'_>) -> Result<AeadEncryptResponse>;
246}
247
248/// Adapts a concrete backend into a stable PSA provider API.
249#[derive(Clone, Debug)]
250pub struct PsaProvider<B> {
251 backend: B,
252}
253
254impl<B> PsaProvider<B> {
255 /// Constructs a provider from a concrete backend implementation.
256 ///
257 /// # Arguments
258 ///
259 /// * `backend` - Backend implementation used by provider operations.
260 ///
261 /// # Returns
262 ///
263 /// A new [`PsaProvider`] owning the backend.
264 pub fn new(backend: B) -> Self {
265 Self { backend }
266 }
267}
268
269impl<B: PsaCryptoBackend> PsaProvider<B> {
270 /// Dispatches signing requests to the configured backend.
271 ///
272 /// # Arguments
273 ///
274 /// * `self` - Provider dispatching to backend.
275 /// * `request` - Signing request to execute.
276 ///
277 /// # Returns
278 ///
279 /// Signature bytes produced by backend.
280 ///
281 /// # Errors
282 ///
283 /// Returns backend-provided [`Error`] on failures.
284 pub fn sign(&self, request: &KeySignRequest<'_>) -> Result<Vec<u8>> {
285 self.backend.sign(request)
286 }
287
288 /// Dispatches decrypt requests with uniform decrypt failure posture.
289 ///
290 /// # Arguments
291 ///
292 /// * `self` - Provider dispatching to backend.
293 /// * `request` - Decrypt request to execute.
294 ///
295 /// # Returns
296 ///
297 /// Plaintext bytes returned by backend.
298 ///
299 /// # Errors
300 ///
301 /// Returns [`Error::CryptoFailure`] for decrypt failures to avoid oracle leakage.
302 pub fn decrypt(&self, request: &KeyDecryptRequest<'_>) -> Result<Vec<u8>> {
303 self.backend
304 .decrypt(request)
305 .map_err(|_| Error::CryptoFailure("psa cryptographic operation failed"))
306 }
307
308 /// Dispatches derive requests to the configured backend.
309 ///
310 /// # Arguments
311 ///
312 /// * `self` - Provider dispatching to backend.
313 /// * `request` - Derive request to execute.
314 ///
315 /// # Returns
316 ///
317 /// Shared secret bytes produced by backend.
318 ///
319 /// # Errors
320 ///
321 /// Returns backend-provided [`Error`] on failures.
322 pub fn derive(&self, request: &KeyDeriveRequest<'_>) -> Result<Vec<u8>> {
323 self.backend.derive(request)
324 }
325
326 /// Fills output bytes with backend-provided random data.
327 ///
328 /// # Arguments
329 ///
330 /// * `self` - Provider dispatching to backend.
331 /// * `out` - Mutable output buffer to fill.
332 ///
333 /// # Returns
334 ///
335 /// `Ok(())` when random output was written to the caller buffer.
336 ///
337 /// # Errors
338 ///
339 /// Returns backend-provided [`Error`] when random generation fails.
340 pub fn random(&self, out: &mut [u8]) -> Result<()> {
341 self.backend.random(out)
342 }
343
344 /// Computes SHA-256 using backend digest implementation.
345 ///
346 /// # Arguments
347 ///
348 /// * `self` - Provider dispatching to backend.
349 /// * `input` - Bytes to hash.
350 ///
351 /// # Returns
352 ///
353 /// 32-byte SHA-256 digest bytes.
354 ///
355 /// # Errors
356 ///
357 /// Returns backend-provided [`Error`] on hashing failures.
358 pub fn sha256(&self, input: &[u8]) -> Result<[u8; 32]> {
359 self.backend.sha256(input)
360 }
361
362 /// Encrypts plaintext with backend AES-GCM implementation.
363 ///
364 /// # Arguments
365 ///
366 /// * `self` - Provider dispatching to backend.
367 /// * `request` - AES-GCM request with key/nonce/aad/plaintext.
368 ///
369 /// # Returns
370 ///
371 /// Ciphertext bytes plus a 16-byte authentication tag.
372 ///
373 /// # Errors
374 ///
375 /// Returns backend-provided [`Error`] when encryption fails.
376 pub fn aes_gcm_encrypt(&self, request: &AeadEncryptRequest<'_>) -> Result<AeadEncryptResponse> {
377 self.backend.aes_gcm_encrypt(request)
378 }
379}
380
381/// Stores policy flags for registered key handles.
382#[derive(Copy, Clone, Debug, Eq, PartialEq)]
383struct HandlePolicy {
384 allow_sign: bool,
385 allow_decrypt: bool,
386 allow_derive: bool,
387}
388
389/// Represents the private key material variants used for software-backed tests.
390#[derive(Clone, Debug)]
391enum SoftwarePrivateMaterial {
392 Rsa(RsaPrivateKey),
393 X25519([u8; 32]),
394 P256(P256PrivateKey),
395}
396
397/// Implements an in-process backend that mirrors PSA handle semantics for tests.
398#[derive(Clone, Debug, Default)]
399pub struct PsaSoftwareBackend {
400 keys: BTreeMap<Vec<u8>, (SoftwarePrivateMaterial, HandlePolicy)>,
401}
402
403impl PsaSoftwareBackend {
404 /// Constructs an empty software backend.
405 ///
406 /// # Arguments
407 ///
408 /// * `()` - This constructor has no parameters.
409 ///
410 /// # Returns
411 ///
412 /// A new empty [`PsaSoftwareBackend`] value.
413 pub fn new() -> Self {
414 Self {
415 keys: BTreeMap::new(),
416 }
417 }
418
419 /// Registers an RSA private key with handle-level usage policy.
420 ///
421 /// # Arguments
422 ///
423 /// * `handle` - Opaque key handle used for future operations.
424 /// * `key` - RSA private key material owned by backend.
425 /// * `allow_sign` - Whether sign operations are authorized for this handle.
426 /// * `allow_decrypt` - Whether decrypt operations are authorized for this handle.
427 ///
428 /// # Returns
429 ///
430 /// `Ok(())` after key registration succeeds.
431 ///
432 /// # Errors
433 ///
434 /// Returns [`Error::PolicyViolation`] if the handle is already registered.
435 pub fn register_rsa_key(
436 &mut self,
437 handle: PsaExternalKeyHandle,
438 key: RsaPrivateKey,
439 allow_sign: bool,
440 allow_decrypt: bool,
441 ) -> Result<()> {
442 self.insert_key(
443 handle,
444 SoftwarePrivateMaterial::Rsa(key),
445 HandlePolicy {
446 allow_sign,
447 allow_decrypt,
448 allow_derive: false,
449 },
450 )
451 }
452
453 /// Registers an X25519 private key with derive-policy controls.
454 ///
455 /// # Arguments
456 ///
457 /// * `handle` - Opaque key handle used for future derive operations.
458 /// * `key` - X25519 private scalar bytes.
459 /// * `allow_derive` - Whether derive operations are authorized for this handle.
460 ///
461 /// # Returns
462 ///
463 /// `Ok(())` after key registration succeeds.
464 ///
465 /// # Errors
466 ///
467 /// Returns [`Error::PolicyViolation`] if the handle is already registered.
468 pub fn register_x25519_key(
469 &mut self,
470 handle: PsaExternalKeyHandle,
471 key: [u8; 32],
472 allow_derive: bool,
473 ) -> Result<()> {
474 self.insert_key(
475 handle,
476 SoftwarePrivateMaterial::X25519(key),
477 HandlePolicy {
478 allow_sign: false,
479 allow_decrypt: false,
480 allow_derive,
481 },
482 )
483 }
484
485 /// Registers a P-256 private key with derive/sign policy controls.
486 ///
487 /// # Arguments
488 ///
489 /// * `handle` - Opaque key handle used for future operations.
490 /// * `key` - P-256 private key material.
491 /// * `allow_sign` - Whether sign operations are authorized for this handle.
492 /// * `allow_derive` - Whether derive operations are authorized for this handle.
493 ///
494 /// # Returns
495 ///
496 /// `Ok(())` after key registration succeeds.
497 ///
498 /// # Errors
499 ///
500 /// Returns [`Error::StateError`] if the handle is already registered.
501 pub fn register_p256_key(
502 &mut self,
503 handle: PsaExternalKeyHandle,
504 key: P256PrivateKey,
505 allow_sign: bool,
506 allow_derive: bool,
507 ) -> Result<()> {
508 self.insert_key(
509 handle,
510 SoftwarePrivateMaterial::P256(key),
511 HandlePolicy {
512 allow_sign,
513 allow_decrypt: false,
514 allow_derive,
515 },
516 )
517 }
518
519 /// Inserts a key record while enforcing unique handle ownership.
520 ///
521 /// # Arguments
522 ///
523 /// * `handle` - Opaque key handle used as map key.
524 /// * `material` - Private material variant to store.
525 /// * `policy` - Allowed operation policy for this handle.
526 ///
527 /// # Returns
528 ///
529 /// `Ok(())` when the record is inserted.
530 ///
531 /// # Errors
532 ///
533 /// Returns [`Error::PolicyViolation`] when handle already exists.
534 fn insert_key(
535 &mut self,
536 handle: PsaExternalKeyHandle,
537 material: SoftwarePrivateMaterial,
538 policy: HandlePolicy,
539 ) -> Result<()> {
540 if self.keys.contains_key(handle.as_bytes()) {
541 return Err(Error::StateError("psa key handle already registered"));
542 }
543 self.keys.insert(handle.id, (material, policy));
544 Ok(())
545 }
546
547 /// Resolves a key record and policy by handle identifier.
548 ///
549 /// # Arguments
550 ///
551 /// * `handle` - Opaque handle whose key material is required.
552 ///
553 /// # Returns
554 ///
555 /// Borrowed private material and policy tuple for the handle.
556 ///
557 /// # Errors
558 ///
559 /// Returns [`Error::PolicyViolation`] when the handle is unknown.
560 fn resolve_key(
561 &self,
562 handle: &PsaExternalKeyHandle,
563 ) -> Result<&(SoftwarePrivateMaterial, HandlePolicy)> {
564 self.keys
565 .get(handle.as_bytes())
566 .ok_or(Error::StateError("psa key handle invalid"))
567 }
568}
569
570impl PsaCryptoBackend for PsaSoftwareBackend {
571 /// Executes signing operations using software cryptographic primitives.
572 ///
573 /// # Arguments
574 ///
575 /// * `self` - Software backend state containing registered keys.
576 /// * `request` - Sign request with handle, algorithm, and digest.
577 ///
578 /// # Returns
579 ///
580 /// Signature bytes from RSA sign operations.
581 ///
582 /// # Errors
583 ///
584 /// Returns policy or crypto errors for unknown handles, denied usage, or bad key type.
585 fn sign(&self, request: &KeySignRequest<'_>) -> Result<Vec<u8>> {
586 let (material, policy) = self.resolve_key(request.handle)?;
587 if !policy.allow_sign {
588 return Err(Error::StateError("psa sign not permitted by key policy"));
589 }
590 match (request.algorithm, material) {
591 (PsaSignAlgorithm::RsaPkcs1Sha256, SoftwarePrivateMaterial::Rsa(key)) => {
592 rsassa_sha256_sign(key, request.message)
593 }
594 (PsaSignAlgorithm::RsaPssSha256, SoftwarePrivateMaterial::Rsa(key)) => {
595 let salt = request.salt.ok_or(Error::InvalidLength(
596 "rsa-pss-sha256 signing requires a salt",
597 ))?;
598 rsassa_pss_sha256_sign(key, request.message, salt)
599 }
600 (PsaSignAlgorithm::EcdsaP256Sha256, SoftwarePrivateMaterial::P256(key)) => {
601 let (r, s) = p256_ecdsa_sign_sha256(key, request.message)?;
602 let mut signature = Vec::with_capacity(64);
603 signature.extend_from_slice(&r);
604 signature.extend_from_slice(&s);
605 Ok(signature)
606 }
607 _ => Err(Error::UnsupportedFeature("psa sign algorithm/key mismatch")),
608 }
609 }
610
611 /// Executes decrypt operations using software cryptographic primitives.
612 ///
613 /// # Arguments
614 ///
615 /// * `self` - Software backend state containing registered keys.
616 /// * `request` - Decrypt request with handle, algorithm, and ciphertext.
617 ///
618 /// # Returns
619 ///
620 /// Plaintext bytes decrypted from input ciphertext.
621 ///
622 /// # Errors
623 ///
624 /// Returns policy or crypto errors for unknown handles, denied usage, or bad key type.
625 fn decrypt(&self, request: &KeyDecryptRequest<'_>) -> Result<Vec<u8>> {
626 let (material, policy) = self.resolve_key(request.handle)?;
627 if !policy.allow_decrypt {
628 return Err(Error::StateError("psa decrypt not permitted by key policy"));
629 }
630 match (request.algorithm, material) {
631 (PsaDecryptAlgorithm::RsaPkcs1v15, SoftwarePrivateMaterial::Rsa(key)) => {
632 rsaes_pkcs1_v15_decrypt(key, request.ciphertext)
633 }
634 (PsaDecryptAlgorithm::RsaOaepSha256, SoftwarePrivateMaterial::Rsa(key)) => {
635 rsaes_oaep_sha256_decrypt(key, request.ciphertext, request.label.unwrap_or(&[]))
636 }
637 _ => Err(Error::UnsupportedFeature(
638 "psa decrypt algorithm/key mismatch",
639 )),
640 }
641 }
642
643 /// Executes derive operations using software X25519 primitive.
644 ///
645 /// # Arguments
646 ///
647 /// * `self` - Software backend state containing registered keys.
648 /// * `request` - Derive request with handle, algorithm, and peer key.
649 ///
650 /// # Returns
651 ///
652 /// Shared secret bytes from X25519 derive operation.
653 ///
654 /// # Errors
655 ///
656 /// Returns policy or parse errors for unknown handles, denied usage, or invalid peer key.
657 fn derive(&self, request: &KeyDeriveRequest<'_>) -> Result<Vec<u8>> {
658 let (material, policy) = self.resolve_key(request.handle)?;
659 if !policy.allow_derive {
660 return Err(Error::StateError("psa derive not permitted by key policy"));
661 }
662 match (request.algorithm, material) {
663 (PsaDeriveAlgorithm::X25519, SoftwarePrivateMaterial::X25519(private)) => {
664 if request.peer_public_key.len() != 32 {
665 return Err(Error::ParseFailure("x25519 peer public key length invalid"));
666 }
667 let mut peer = [0u8; 32];
668 peer.copy_from_slice(request.peer_public_key);
669 Ok(x25519(private, &peer).to_vec())
670 }
671 (PsaDeriveAlgorithm::EcdhP256, SoftwarePrivateMaterial::P256(private)) => {
672 let peer = P256PublicKey::from_uncompressed(request.peer_public_key)?;
673 Ok(p256_ecdh_shared_secret(private, &peer)?.to_vec())
674 }
675 _ => Err(Error::UnsupportedFeature(
676 "psa derive algorithm/key mismatch",
677 )),
678 }
679 }
680
681 /// Produces deterministic random bytes for validation-only posture.
682 ///
683 /// # Arguments
684 ///
685 /// * `self` - Software backend state (not used by this implementation).
686 /// * `out` - Mutable output buffer to fill with deterministic bytes.
687 ///
688 /// # Returns
689 ///
690 /// `Ok(())` once all output bytes are filled.
691 ///
692 /// # Errors
693 ///
694 /// This function does not return errors in the software backend.
695 fn random(&self, out: &mut [u8]) -> Result<()> {
696 for (idx, byte) in out.iter_mut().enumerate() {
697 *byte = (idx as u8).wrapping_mul(17).wrapping_add(0x5A);
698 }
699 Ok(())
700 }
701
702 /// Computes SHA-256 digest with software primitive implementation.
703 ///
704 /// # Arguments
705 ///
706 /// * `self` - Software backend state (not used by this implementation).
707 /// * `input` - Input bytes to hash.
708 ///
709 /// # Returns
710 ///
711 /// 32-byte SHA-256 digest.
712 ///
713 /// # Errors
714 ///
715 /// Returns crypto error if digest primitive reports a failure.
716 fn sha256(&self, input: &[u8]) -> Result<[u8; 32]> {
717 Ok(sha256(input))
718 }
719
720 /// Encrypts using AES-GCM software primitive.
721 ///
722 /// # Arguments
723 ///
724 /// * `self` - Software backend state (not used by this implementation).
725 /// * `request` - Encryption request with key, nonce, AAD, and plaintext.
726 ///
727 /// # Returns
728 ///
729 /// Ciphertext bytes plus 16-byte authentication tag.
730 ///
731 /// # Errors
732 ///
733 /// Returns [`Error::UnsupportedFeature`] because software AES-GCM path is not wired here.
734 fn aes_gcm_encrypt(&self, request: &AeadEncryptRequest<'_>) -> Result<AeadEncryptResponse> {
735 let cipher = AesCipher::new(request.key)?;
736 let (ciphertext, tag) =
737 aes_gcm_encrypt(&cipher, request.nonce, request.aad, request.plaintext)?;
738 Ok(AeadEncryptResponse { ciphertext, tag })
739 }
740}
741
742/// Type alias for default software-backed PSA provider.
743pub type PsaSoftwareProvider = PsaProvider<PsaSoftwareBackend>;