Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions wrapper/rust/wolfssl-wolfcrypt/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ New features:

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

Fixes and improvements:

Expand Down
50 changes: 49 additions & 1 deletion wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,13 @@ impl ChaCha20Poly1305 {
///
/// This function consumes the `ChaCha20Poly1305` instance. The
/// `update_data()` function must be called before calling this function to
/// add all input data.
/// add all input data (if present).
///
/// Note that for decryption operations, the authentication tag is computed
/// and returned but is *not* checked so it is up to the caller to compare
/// to the expected tag. Use `finalize_verify()` instead for decryption
/// operations to finalize and compare against the expected authentication
/// tag in one operation.
///
/// # Parameters
///
Expand All @@ -248,6 +254,48 @@ impl ChaCha20Poly1305 {
}
Ok(())
}

/// Finalize the decrypt/encrypt operation and verify the authentication
/// tag against `auth_tag`.
///
/// This function consumes the `ChaCha20Poly1305` instance. The
/// `update_data()` function must be called before calling this function to
/// add all input data (if present). The authentication tag is computed
/// internally and compared against the expected `auth_tag` in constant
/// time. This is typically used when decrypting to verify the transmitted
/// authentication tag.
///
/// # Parameters
///
/// * `auth_tag`: Expected authentication tag to verify against (must be 16
/// bytes).
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value. A tag mismatch is reported as Err with the
/// `MAC_CMP_FAILED_E` error code.
pub fn finalize_verify(mut self, auth_tag: &[u8]) -> Result<(), i32> {
if auth_tag.len() != Self::AUTH_TAG_SIZE {
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
}
let mut calculated_tag = [0u8; Self::AUTH_TAG_SIZE];
let rc = unsafe {
sys::wc_ChaCha20Poly1305_Final(&mut self.wc_ccp,
calculated_tag.as_mut_ptr())
};
if rc != 0 {
return Err(rc);
}
let rc = unsafe {
sys::wc_ChaCha20Poly1305_CheckTag(auth_tag.as_ptr(),
calculated_tag.as_ptr())
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}

impl ChaCha20Poly1305 {
Expand Down
64 changes: 64 additions & 0 deletions wrapper/rust/wolfssl-wolfcrypt/tests/test_chacha20_poly1305.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,70 @@ fn test_chacha20_poly1305_2() {
assert_eq!(out_auth_tag_2, auth_tag_2);
}

#[test]
fn test_chacha20_poly1305_finalize_verify() {
let key1 = [
0x80u8, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
];

let iv1 = [
0x07u8, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43,
0x44, 0x45, 0x46, 0x47
];

let aad1 = [
0x50u8, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7
];

let plaintext1 = [
0x4cu8, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
0x74, 0x2e
];

/* Encrypt to obtain cipher text and authentication tag. */
let mut ccp = ChaCha20Poly1305::new(&key1, &iv1, true).expect("Error with new()");
ccp.update_aad(&aad1).expect("Error with update_aad()");
let mut cipher1 = [0u8; 114];
ccp.update_data(&plaintext1, &mut cipher1).expect("Error with update_data()");
let mut auth_tag_1 = [0u8; ChaCha20Poly1305::AUTH_TAG_SIZE];
ccp.finalize(&mut auth_tag_1).expect("Error with finalize()");

/* Decrypt and verify the correct authentication tag. */
let mut ccp = ChaCha20Poly1305::new(&key1, &iv1, false).expect("Error with new()");
ccp.update_aad(&aad1).expect("Error with update_aad()");
let mut out_plaintext1 = [0u8; 114];
ccp.update_data(&cipher1, &mut out_plaintext1).expect("Error with update_data()");
ccp.finalize_verify(&auth_tag_1).expect("Error with finalize_verify()");
assert_eq!(out_plaintext1, plaintext1);

/* Decrypt and verify a tampered authentication tag, which must fail. */
let mut bad_auth_tag = auth_tag_1;
bad_auth_tag[0] ^= 0xff;
let mut ccp = ChaCha20Poly1305::new(&key1, &iv1, false).expect("Error with new()");
ccp.update_aad(&aad1).expect("Error with update_aad()");
let mut out_plaintext1 = [0u8; 114];
ccp.update_data(&cipher1, &mut out_plaintext1).expect("Error with update_data()");
let rc = ccp.finalize_verify(&bad_auth_tag);
assert_eq!(rc, Err(sys::wolfCrypt_ErrorCodes_MAC_CMP_FAILED_E));
}

#[test]
#[cfg(xchacha20_poly1305)]
fn test_xchacha20_poly1305() {
Expand Down
Loading