1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #![no_std]
16 #![deny(
17 missing_docs,
18 clippy::indexing_slicing,
19 clippy::unwrap_used,
20 clippy::panic,
21 clippy::expect_used
22 )]
23 // These features are needed to support no_std + alloc
24 #![feature(lang_items)]
25 #![feature(alloc_error_handler)]
26
27 //! Rust ffi wrapper of ldt_np_adv, can be called from C/C++ Clients
28
29 mod handle_map;
30
31 extern crate alloc;
32
33 use crate::handle_map::get_dec_handle_map;
34 use alloc::boxed::Box;
35 use core::slice;
36 use handle_map::get_enc_handle_map;
37 use ldt_np_adv::{
38 build_np_adv_decrypter_from_key_seed, salt_padder, LdtAdvDecryptError, LdtEncrypterXtsAes128,
39 LdtNpAdvDecrypterXtsAes128, LegacySalt,
40 };
41 use np_hkdf::NpKeySeedHkdf;
42
43 // Pull in the needed deps for std vs no_std
44 cfg_if::cfg_if! {
45 // Test pulls in std which causes duplicate errors
46 if #[cfg(any(feature = "std", test, feature = "boringssl", feature = "openssl"))] {
47 extern crate std;
48 } else {
49 // Allow using Box in no_std
50 mod no_std;
51 }
52 }
53
54 // Fail early for invalid combination of feature flags, we need at least one crypto library specified
55 #[cfg(all(
56 not(feature = "openssl"),
57 not(feature = "crypto_provider_rustcrypto"),
58 not(feature = "boringssl")
59 ))]
60 compile_error!("Either the \"openssl\", \"boringssl\"or \"default\" features flag needs to be set in order to specify cryptographic library");
61
62 // Need to have one of the crypto provider impls
63 cfg_if::cfg_if! {
64 if #[cfg(feature = "openssl")] {
65 use crypto_provider_openssl::Openssl as CryptoProviderImpl;
66 } else if #[cfg(feature = "boringssl")]{
67 use crypto_provider_boringssl::Boringssl as CryptoProviderImpl;
68 } else {
69 use crypto_provider_rustcrypto::RustCrypto as CryptoProviderImpl;
70 }
71 }
72
73 pub(crate) type LdtAdvDecrypter = LdtNpAdvDecrypterXtsAes128<CryptoProviderImpl>;
74 pub(crate) type LdtAdvEncrypter = LdtEncrypterXtsAes128<CryptoProviderImpl>;
75
76 const SUCCESS: i32 = 0;
77
78 #[repr(C)]
79 struct NpLdtKeySeed {
80 bytes: [u8; 32],
81 }
82
83 #[repr(C)]
84 struct NpMetadataKeyHmac {
85 bytes: [u8; 32],
86 }
87
88 #[repr(C)]
89 struct NpLdtSalt {
90 bytes: [u8; 2],
91 }
92
93 #[repr(C)]
94 struct NpLdtEncryptHandle {
95 handle: u64,
96 }
97
98 #[repr(C)]
99 struct NpLdtDecryptHandle {
100 handle: u64,
101 }
102
103 #[no_mangle]
NpLdtDecryptCreate( key_seed: NpLdtKeySeed, metadata_key_hmac: NpMetadataKeyHmac, ) -> NpLdtDecryptHandle104 extern "C" fn NpLdtDecryptCreate(
105 key_seed: NpLdtKeySeed,
106 metadata_key_hmac: NpMetadataKeyHmac,
107 ) -> NpLdtDecryptHandle {
108 let cipher = build_np_adv_decrypter_from_key_seed(
109 &NpKeySeedHkdf::new(&key_seed.bytes),
110 metadata_key_hmac.bytes,
111 );
112 let handle = get_dec_handle_map().insert::<CryptoProviderImpl>(Box::new(cipher));
113 NpLdtDecryptHandle { handle }
114 }
115
116 #[no_mangle]
NpLdtEncryptCreate(key_seed: NpLdtKeySeed) -> NpLdtEncryptHandle117 extern "C" fn NpLdtEncryptCreate(key_seed: NpLdtKeySeed) -> NpLdtEncryptHandle {
118 let cipher = LdtAdvEncrypter::new(
119 &NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed.bytes).legacy_ldt_key(),
120 );
121 let handle = get_enc_handle_map().insert::<CryptoProviderImpl>(Box::new(cipher));
122 NpLdtEncryptHandle { handle }
123 }
124
125 #[no_mangle]
NpLdtEncryptClose(handle: NpLdtEncryptHandle) -> i32126 extern "C" fn NpLdtEncryptClose(handle: NpLdtEncryptHandle) -> i32 {
127 map_to_error_code(|| {
128 get_enc_handle_map()
129 .remove(&handle.handle)
130 .ok_or(CloseCipherError::InvalidHandle)
131 .map(|_| 0)
132 })
133 }
134
135 #[no_mangle]
NpLdtDecryptClose(handle: NpLdtDecryptHandle) -> i32136 extern "C" fn NpLdtDecryptClose(handle: NpLdtDecryptHandle) -> i32 {
137 map_to_error_code(|| {
138 get_dec_handle_map()
139 .remove(&handle.handle)
140 .ok_or(CloseCipherError::InvalidHandle)
141 .map(|_| 0)
142 })
143 }
144
145 #[no_mangle]
146 // continue to use LdtAdvDecrypter::encrypt() for now, but we should expose a higher level API
147 // and get rid of this.
148 #[allow(deprecated)]
NpLdtEncrypt( handle: NpLdtEncryptHandle, buffer: *mut u8, buffer_len: usize, salt: NpLdtSalt, ) -> i32149 extern "C" fn NpLdtEncrypt(
150 handle: NpLdtEncryptHandle,
151 buffer: *mut u8,
152 buffer_len: usize,
153 salt: NpLdtSalt,
154 ) -> i32 {
155 map_to_error_code(|| {
156 let data = unsafe { slice::from_raw_parts_mut(buffer, buffer_len) };
157 let padder = salt_padder::<16, CryptoProviderImpl>(LegacySalt::from(salt.bytes));
158 get_enc_handle_map()
159 .get(&handle.handle)
160 .map(|cipher| {
161 cipher
162 .encrypt(data, &padder)
163 .map(|_| 0)
164 .map_err(|e| match e {
165 ldt::LdtError::InvalidLength(_) => EncryptError::InvalidLength,
166 })
167 })
168 .unwrap_or(Err(EncryptError::InvalidHandle))
169 })
170 }
171
172 #[no_mangle]
NpLdtDecryptAndVerify( handle: NpLdtDecryptHandle, buffer: *mut u8, buffer_len: usize, salt: NpLdtSalt, ) -> i32173 extern "C" fn NpLdtDecryptAndVerify(
174 handle: NpLdtDecryptHandle,
175 buffer: *mut u8,
176 buffer_len: usize,
177 salt: NpLdtSalt,
178 ) -> i32 {
179 map_to_error_code(|| {
180 let data = unsafe { slice::from_raw_parts_mut(buffer, buffer_len) };
181 let padder = salt_padder::<16, CryptoProviderImpl>(LegacySalt::from(salt.bytes));
182
183 get_dec_handle_map()
184 .get(&handle.handle)
185 .map(|cipher| {
186 cipher
187 .decrypt_and_verify(data, &padder)
188 .map_err(|e| match e {
189 LdtAdvDecryptError::InvalidLength(_) => DecryptError::InvalidLength,
190 LdtAdvDecryptError::MacMismatch => DecryptError::HmacDoesntMatch,
191 })
192 .map(|plaintext| {
193 data.copy_from_slice(plaintext.as_slice());
194 SUCCESS
195 })
196 })
197 .unwrap_or(Err(DecryptError::InvalidHandle))
198 })
199 }
200
map_to_error_code<T, E: ErrorEnum<T>, F: Fn() -> Result<T, E>>(f: F) -> T201 fn map_to_error_code<T, E: ErrorEnum<T>, F: Fn() -> Result<T, E>>(f: F) -> T {
202 f().unwrap_or_else(|e| e.to_error_code())
203 }
204
205 trait ErrorEnum<C> {
to_error_code(&self) -> C206 fn to_error_code(&self) -> C;
207 }
208
209 enum CloseCipherError {
210 InvalidHandle,
211 }
212
213 impl ErrorEnum<i32> for CloseCipherError {
to_error_code(&self) -> i32214 fn to_error_code(&self) -> i32 {
215 match self {
216 Self::InvalidHandle => -3,
217 }
218 }
219 }
220
221 enum EncryptError {
222 InvalidLength,
223 InvalidHandle,
224 }
225
226 impl ErrorEnum<i32> for EncryptError {
to_error_code(&self) -> i32227 fn to_error_code(&self) -> i32 {
228 match self {
229 Self::InvalidLength => -1,
230 Self::InvalidHandle => -3,
231 }
232 }
233 }
234
235 enum DecryptError {
236 HmacDoesntMatch,
237 InvalidLength,
238 InvalidHandle,
239 }
240
241 impl ErrorEnum<i32> for DecryptError {
to_error_code(&self) -> i32242 fn to_error_code(&self) -> i32 {
243 match self {
244 Self::InvalidLength => -1,
245 Self::HmacDoesntMatch => -2,
246 Self::InvalidHandle => -3,
247 }
248 }
249 }
250