• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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