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