app_store_server_library/crypto/
mod.rs1#[cfg(feature = "rust_crypto")]
4pub mod rust_crypto;
5
6#[cfg(feature = "aws_lc")]
7pub mod aws_lc;
8
9#[cfg(feature = "ring")]
10pub mod ring;
11
12pub mod jws;
13
14use std::fmt::Debug;
15use std::sync::{Arc, OnceLock};
16
17#[cfg(any(feature = "aws_lc", feature = "ring"))]
19pub(crate) fn decode_pem(pem: &str) -> Result<Vec<u8>, &'static str> {
20 use base64::prelude::*;
21
22 let lines: Vec<&str> = pem.lines().collect();
23
24 let start = lines
26 .iter()
27 .position(|l| l.starts_with("-----BEGIN"))
28 .ok_or("missing BEGIN marker")?;
29 let end = lines
30 .iter()
31 .position(|l| l.starts_with("-----END"))
32 .ok_or("missing END marker")?;
33
34 if end <= start + 1 {
35 return Err("no content between markers");
36 }
37
38 let b64: String = lines[start + 1..end].concat();
40
41 BASE64_STANDARD
42 .decode(&b64)
43 .map_err(|_| "invalid base64")
44}
45
46#[cfg(any(feature = "aws_lc", feature = "ring"))]
48pub(crate) fn ecdsa_raw_to_der(rs: &[u8; 64]) -> Result<Vec<u8>, CryptoError> {
49 use asn1_rs::{Integer, Sequence, ToDer};
50
51 let to_error = |e: asn1_rs::SerializeError| CryptoError::SigningError(e.to_string());
52
53 let r = Integer::from_const_array::<32>(rs[..32].try_into().expect("32 bytes"));
54 let s = Integer::from_const_array::<32>(rs[32..].try_into().expect("32 bytes"));
55
56 Sequence::from_iter_to_der([r, s].into_iter())
57 .map_err(to_error)?
58 .to_der_vec()
59 .map_err(to_error)
60}
61
62#[derive(thiserror::Error, Debug)]
64pub enum CryptoError {
65 #[error("Key error: {0}")]
66 KeyError(String),
67
68 #[error("Signing error: {0}")]
69 SigningError(String),
70
71 #[error("Verification error: {0}")]
72 VerificationError(String),
73}
74
75pub trait P256SigningSuite: Send + Sync + Debug {
77 fn private_key(&self, pem: &str) -> Result<Box<dyn P256PrivateKey>, CryptoError>;
79
80 fn public_key(&self, spki_der: &[u8]) -> Result<Box<dyn P256PublicKey>, CryptoError>;
82}
83
84pub trait P256PrivateKey: Send + Sync + Debug {
85 fn signature(&self, message: &[u8]) -> Result<P256Signature, CryptoError>;
90}
91
92pub type P256Signature = ([u8; 64], Vec<u8>);
94
95pub trait P256PublicKey: Send + Sync + Debug {
96 fn is_valid_signature(&self, signature: &[u8; 64], message: &[u8]) -> Result<(), CryptoError>;
101}
102
103#[derive(Debug, Clone)]
114pub struct CryptoProvider {
115 pub p256_signing: &'static dyn P256SigningSuite,
117}
118
119static PROCESS_DEFAULT: OnceLock<Arc<CryptoProvider>> = OnceLock::new();
120
121impl CryptoProvider {
122 pub fn install_default(self) -> Result<(), Arc<Self>> {
127 PROCESS_DEFAULT.set(Arc::new(self))
128 }
129
130 pub fn get_default() -> Option<&'static Arc<Self>> {
134 PROCESS_DEFAULT.get()
135 }
136
137 pub fn default_provider() -> &'static Arc<Self> {
140 PROCESS_DEFAULT.get_or_init(|| Arc::new(Self::from_crate_features()))
141 }
142
143 #[allow(unreachable_code)]
144 fn from_crate_features() -> Self {
145 #[cfg(feature = "rust_crypto")]
146 {
147 return rust_crypto::DEFAULT_PROVIDER;
148 }
149
150 #[cfg(feature = "aws_lc")]
151 {
152 return aws_lc::DEFAULT_PROVIDER;
153 }
154
155 #[cfg(feature = "ring")]
156 {
157 return ring::DEFAULT_PROVIDER;
158 }
159
160 panic!("No crypto backend. Enable 'rust_crypto', 'aws_lc' or 'ring' feature.");
161 }
162}
163
164#[cfg(all(test, any(feature = "aws_lc", feature = "ring")))]
165mod der_tests {
166 use super::ecdsa_raw_to_der;
167
168 #[test]
171 fn der_integers_are_minimally_encoded_and_positive() {
172 let mut rs = [0u8; 64];
173 rs[0] = 0xFF; rs[32 + 31] = 0x01; let der = ecdsa_raw_to_der(&rs).expect("encode");
177
178 assert_eq!(der[0], 0x30);
180 assert_eq!(der[1] as usize, der.len() - 2);
181 assert_eq!(der[2], 0x02);
182 assert_eq!(der[3], 33, "r must be padded to 33 bytes");
183 assert_eq!(der[4], 0x00, "pad byte keeps r positive");
184 assert_eq!(der[5], 0xFF);
185 assert_eq!(&der[der.len() - 3..], &[0x02, 0x01, 0x01], "s is one byte");
186 }
187
188 #[test]
191 fn zero_component_encodes_as_a_single_zero_byte() {
192 let der = ecdsa_raw_to_der(&[0u8; 64]).expect("encode");
193
194 assert_eq!(der, vec![0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00]);
196 }
197}