Skip to content

Commit 5dd7717

Browse files
authored
Merge pull request #10933 from holtrop-wolfssl/f-6445
Rust wrapper: Add ChaCha20Poly1305::finalize_verify()
2 parents c1ee61c + c3903cd commit 5dd7717

3 files changed

Lines changed: 114 additions & 1 deletion

File tree

wrapper/rust/wolfssl-wolfcrypt/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ New features:
66

77
- Add DH::prime_size() to query the DH prime size, which is the minimum output
88
buffer size DH::shared_secret() requires
9+
- Add ChaCha20Poly1305::finalize_verify()
910

1011
Fixes and improvements:
1112

wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,13 @@ impl ChaCha20Poly1305 {
225225
///
226226
/// This function consumes the `ChaCha20Poly1305` instance. The
227227
/// `update_data()` function must be called before calling this function to
228-
/// add all input data.
228+
/// add all input data (if present).
229+
///
230+
/// Note that for decryption operations, the authentication tag is computed
231+
/// and returned but is *not* checked so it is up to the caller to compare
232+
/// to the expected tag. Use `finalize_verify()` instead for decryption
233+
/// operations to finalize and compare against the expected authentication
234+
/// tag in one operation.
229235
///
230236
/// # Parameters
231237
///
@@ -248,6 +254,48 @@ impl ChaCha20Poly1305 {
248254
}
249255
Ok(())
250256
}
257+
258+
/// Finalize the decrypt/encrypt operation and verify the authentication
259+
/// tag against `auth_tag`.
260+
///
261+
/// This function consumes the `ChaCha20Poly1305` instance. The
262+
/// `update_data()` function must be called before calling this function to
263+
/// add all input data (if present). The authentication tag is computed
264+
/// internally and compared against the expected `auth_tag` in constant
265+
/// time. This is typically used when decrypting to verify the transmitted
266+
/// authentication tag.
267+
///
268+
/// # Parameters
269+
///
270+
/// * `auth_tag`: Expected authentication tag to verify against (must be 16
271+
/// bytes).
272+
///
273+
/// # Returns
274+
///
275+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
276+
/// library error code value. A tag mismatch is reported as Err with the
277+
/// `MAC_CMP_FAILED_E` error code.
278+
pub fn finalize_verify(mut self, auth_tag: &[u8]) -> Result<(), i32> {
279+
if auth_tag.len() != Self::AUTH_TAG_SIZE {
280+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
281+
}
282+
let mut calculated_tag = [0u8; Self::AUTH_TAG_SIZE];
283+
let rc = unsafe {
284+
sys::wc_ChaCha20Poly1305_Final(&mut self.wc_ccp,
285+
calculated_tag.as_mut_ptr())
286+
};
287+
if rc != 0 {
288+
return Err(rc);
289+
}
290+
let rc = unsafe {
291+
sys::wc_ChaCha20Poly1305_CheckTag(auth_tag.as_ptr(),
292+
calculated_tag.as_ptr())
293+
};
294+
if rc != 0 {
295+
return Err(rc);
296+
}
297+
Ok(())
298+
}
251299
}
252300

253301
impl ChaCha20Poly1305 {

wrapper/rust/wolfssl-wolfcrypt/tests/test_chacha20_poly1305.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,70 @@ fn test_chacha20_poly1305_2() {
205205
assert_eq!(out_auth_tag_2, auth_tag_2);
206206
}
207207

208+
#[test]
209+
fn test_chacha20_poly1305_finalize_verify() {
210+
let key1 = [
211+
0x80u8, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
212+
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
213+
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
214+
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
215+
];
216+
217+
let iv1 = [
218+
0x07u8, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43,
219+
0x44, 0x45, 0x46, 0x47
220+
];
221+
222+
let aad1 = [
223+
0x50u8, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
224+
0xc4, 0xc5, 0xc6, 0xc7
225+
];
226+
227+
let plaintext1 = [
228+
0x4cu8, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
229+
0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
230+
0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
231+
0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
232+
0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
233+
0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
234+
0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
235+
0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
236+
0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
237+
0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
238+
0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
239+
0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
240+
0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
241+
0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
242+
0x74, 0x2e
243+
];
244+
245+
/* Encrypt to obtain cipher text and authentication tag. */
246+
let mut ccp = ChaCha20Poly1305::new(&key1, &iv1, true).expect("Error with new()");
247+
ccp.update_aad(&aad1).expect("Error with update_aad()");
248+
let mut cipher1 = [0u8; 114];
249+
ccp.update_data(&plaintext1, &mut cipher1).expect("Error with update_data()");
250+
let mut auth_tag_1 = [0u8; ChaCha20Poly1305::AUTH_TAG_SIZE];
251+
ccp.finalize(&mut auth_tag_1).expect("Error with finalize()");
252+
253+
/* Decrypt and verify the correct authentication tag. */
254+
let mut ccp = ChaCha20Poly1305::new(&key1, &iv1, false).expect("Error with new()");
255+
ccp.update_aad(&aad1).expect("Error with update_aad()");
256+
let mut out_plaintext1 = [0u8; 114];
257+
ccp.update_data(&cipher1, &mut out_plaintext1).expect("Error with update_data()");
258+
ccp.finalize_verify(&auth_tag_1).expect("Error with finalize_verify()");
259+
assert_eq!(out_plaintext1, plaintext1);
260+
261+
/* Decrypt and verify a tampered authentication tag, which must fail. */
262+
let mut bad_auth_tag = auth_tag_1;
263+
bad_auth_tag[0] ^= 0xff;
264+
let mut ccp = ChaCha20Poly1305::new(&key1, &iv1, false).expect("Error with new()");
265+
ccp.update_aad(&aad1).expect("Error with update_aad()");
266+
let mut out_plaintext1 = [0u8; 114];
267+
ccp.update_data(&cipher1, &mut out_plaintext1).expect("Error with update_data()");
268+
let rc = ccp.finalize_verify(&bad_auth_tag);
269+
assert_eq!(rc, Err(sys::wolfCrypt_ErrorCodes_MAC_CMP_FAILED_E));
270+
}
271+
208272
#[test]
209273
#[cfg(xchacha20_poly1305)]
210274
fn test_xchacha20_poly1305() {

0 commit comments

Comments
 (0)