• 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 #![deny(
16     missing_docs,
17     clippy::indexing_slicing,
18     clippy::unwrap_used,
19     clippy::panic,
20     clippy::expect_used
21 )]
22 
23 //! Rust ffi wrapper of ldt_np_adv, can be called from C/C++ Clients
24 
25 extern crate alloc;
26 
27 use core::slice;
28 use crypto_provider_default::CryptoProviderImpl;
29 use ldt::LdtCipher;
30 use ldt_np_adv::{
31     build_np_adv_decrypter_from_key_seed, salt_padder, AuthenticatedNpLdtDecryptCipher,
32     LdtAdvDecryptError, NpLdtEncryptCipher, V0Salt, V0_IDENTITY_TOKEN_LEN,
33 };
34 use np_hkdf::NpKeySeedHkdf;
35 
36 mod handle_map;
37 
38 pub(crate) type LdtAdvDecrypter = AuthenticatedNpLdtDecryptCipher<CryptoProviderImpl>;
39 pub(crate) type LdtAdvEncrypter = NpLdtEncryptCipher<CryptoProviderImpl>;
40 
41 const SUCCESS: i32 = 0;
42 
43 #[repr(C)]
44 struct NpLdtKeySeed {
45     bytes: [u8; 32],
46 }
47 
48 #[repr(C)]
49 struct NpMetadataKeyHmac {
50     bytes: [u8; 32],
51 }
52 
53 #[repr(C)]
54 struct NpLdtSalt {
55     bytes: [u8; 2],
56 }
57 
58 #[repr(C)]
59 struct NpLdtEncryptHandle {
60     handle: u64,
61 }
62 
63 #[repr(C)]
64 struct NpLdtDecryptHandle {
65     handle: u64,
66 }
67 
68 #[no_mangle]
NpLdtDecryptCreate( key_seed: NpLdtKeySeed, metadata_key_hmac: NpMetadataKeyHmac, ) -> NpLdtDecryptHandle69 extern "C" fn NpLdtDecryptCreate(
70     key_seed: NpLdtKeySeed,
71     metadata_key_hmac: NpMetadataKeyHmac,
72 ) -> NpLdtDecryptHandle {
73     let cipher = build_np_adv_decrypter_from_key_seed(
74         &NpKeySeedHkdf::new(&key_seed.bytes),
75         metadata_key_hmac.bytes,
76     );
77     let handle = handle_map::get_dec_handle_map().insert::<CryptoProviderImpl>(Box::new(cipher));
78     NpLdtDecryptHandle { handle }
79 }
80 
81 #[no_mangle]
NpLdtEncryptCreate(key_seed: NpLdtKeySeed) -> NpLdtEncryptHandle82 extern "C" fn NpLdtEncryptCreate(key_seed: NpLdtKeySeed) -> NpLdtEncryptHandle {
83     let cipher = LdtAdvEncrypter::new(
84         &NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed.bytes).v0_ldt_key(),
85     );
86     let handle = handle_map::get_enc_handle_map().insert::<CryptoProviderImpl>(Box::new(cipher));
87     NpLdtEncryptHandle { handle }
88 }
89 
90 #[no_mangle]
NpLdtEncryptClose(handle: NpLdtEncryptHandle) -> i3291 extern "C" fn NpLdtEncryptClose(handle: NpLdtEncryptHandle) -> i32 {
92     map_to_error_code(|| {
93         handle_map::get_enc_handle_map()
94             .remove(&handle.handle)
95             .ok_or(CloseCipherError::InvalidHandle)
96             .map(|_| SUCCESS)
97     })
98 }
99 
100 #[no_mangle]
NpLdtDecryptClose(handle: NpLdtDecryptHandle) -> i32101 extern "C" fn NpLdtDecryptClose(handle: NpLdtDecryptHandle) -> i32 {
102     map_to_error_code(|| {
103         handle_map::get_dec_handle_map()
104             .remove(&handle.handle)
105             .ok_or(CloseCipherError::InvalidHandle)
106             .map(|_| SUCCESS)
107     })
108 }
109 
110 #[no_mangle]
NpLdtEncrypt( handle: NpLdtEncryptHandle, buffer: *mut u8, buffer_len: usize, salt: NpLdtSalt, ) -> i32111 extern "C" fn NpLdtEncrypt(
112     handle: NpLdtEncryptHandle,
113     buffer: *mut u8,
114     buffer_len: usize,
115     salt: NpLdtSalt,
116 ) -> i32 {
117     map_to_error_code(|| {
118         let data = unsafe { slice::from_raw_parts_mut(buffer, buffer_len) };
119         let padder = salt_padder::<CryptoProviderImpl>(V0Salt::from(salt.bytes));
120         handle_map::get_enc_handle_map()
121             .get(&handle.handle)
122             .map(|cipher| {
123                 cipher.encrypt(data, &padder).map(|_| 0).map_err(|e| match e {
124                     ldt::LdtError::InvalidLength(_) => EncryptError::InvalidLength,
125                 })
126             })
127             .unwrap_or(Err(EncryptError::InvalidHandle))
128     })
129 }
130 
131 #[no_mangle]
NpLdtDecryptAndVerify( handle: NpLdtDecryptHandle, buffer: *mut u8, buffer_len: usize, salt: NpLdtSalt, ) -> i32132 extern "C" fn NpLdtDecryptAndVerify(
133     handle: NpLdtDecryptHandle,
134     buffer: *mut u8,
135     buffer_len: usize,
136     salt: NpLdtSalt,
137 ) -> i32 {
138     map_to_error_code(|| {
139         let data = unsafe { slice::from_raw_parts_mut(buffer, buffer_len) };
140         let padder = salt_padder::<CryptoProviderImpl>(V0Salt::from(salt.bytes));
141 
142         #[allow(clippy::indexing_slicing)]
143         handle_map::get_dec_handle_map()
144             .get(&handle.handle)
145             .map(|cipher| {
146                 cipher
147                     .decrypt_and_verify(data, &padder)
148                     .map_err(|e| match e {
149                         LdtAdvDecryptError::InvalidLength(_) => DecryptError::InvalidLength,
150                         LdtAdvDecryptError::MacMismatch => DecryptError::HmacDoesntMatch,
151                     })
152                     .map(|(token, plaintext)| {
153                         // slicing is safe: token and plaintext sum to data's len
154                         data[..V0_IDENTITY_TOKEN_LEN].copy_from_slice(token.as_slice());
155                         data[V0_IDENTITY_TOKEN_LEN..].copy_from_slice(plaintext.as_slice());
156                         SUCCESS
157                     })
158             })
159             .unwrap_or(Err(DecryptError::InvalidHandle))
160     })
161 }
162 
map_to_error_code<T, E: ErrorEnum<T>, F: Fn() -> Result<T, E>>(f: F) -> T163 fn map_to_error_code<T, E: ErrorEnum<T>, F: Fn() -> Result<T, E>>(f: F) -> T {
164     f().unwrap_or_else(|e| e.to_error_code())
165 }
166 
167 trait ErrorEnum<C> {
to_error_code(&self) -> C168     fn to_error_code(&self) -> C;
169 }
170 
171 enum CloseCipherError {
172     InvalidHandle,
173 }
174 
175 impl ErrorEnum<i32> for CloseCipherError {
to_error_code(&self) -> i32176     fn to_error_code(&self) -> i32 {
177         match self {
178             Self::InvalidHandle => -3,
179         }
180     }
181 }
182 
183 enum EncryptError {
184     InvalidLength,
185     InvalidHandle,
186 }
187 
188 impl ErrorEnum<i32> for EncryptError {
to_error_code(&self) -> i32189     fn to_error_code(&self) -> i32 {
190         match self {
191             Self::InvalidLength => -1,
192             Self::InvalidHandle => -3,
193         }
194     }
195 }
196 
197 enum DecryptError {
198     HmacDoesntMatch,
199     InvalidLength,
200     InvalidHandle,
201 }
202 
203 impl ErrorEnum<i32> for DecryptError {
to_error_code(&self) -> i32204     fn to_error_code(&self) -> i32 {
205         match self {
206             Self::InvalidLength => -1,
207             Self::HmacDoesntMatch => -2,
208             Self::InvalidHandle => -3,
209         }
210     }
211 }
212