Skip to content

Commit 9007d12

Browse files
Rust wrapper: add wolfssl_wolfcrypt::chacha20_poly1305 module
1 parent 80c1228 commit 9007d12

File tree

5 files changed

+453
-0
lines changed

5 files changed

+453
-0
lines changed

wrapper/rust/include.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/build.rs
1313
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/headers.h
1414
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/aes.rs
1515
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/blake2.rs
16+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs
1617
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/cmac.rs
1718
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs
1819
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/dh.rs
@@ -30,6 +31,7 @@ EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/sha.rs
3031
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/sys.rs
3132
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs
3233
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2.rs
34+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_chacha20_poly1305.rs
3335
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_cmac.rs
3436
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_curve25519.rs
3537
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_dh.rs

wrapper/rust/wolfssl-wolfcrypt/build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ fn scan_cfg() -> Result<()> {
130130
check_cfg(&binding, "wc_InitBlake2b", "blake2b");
131131
check_cfg(&binding, "wc_InitBlake2s", "blake2s");
132132

133+
/* chacha20_poly1305 */
134+
check_cfg(&binding, "wc_ChaCha20Poly1305_Encrypt", "chacha20_poly1305");
135+
133136
/* cmac */
134137
check_cfg(&binding, "wc_InitCmac", "cmac");
135138

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
/*
2+
* Copyright (C) 2025 wolfSSL Inc.
3+
*
4+
* This file is part of wolfSSL.
5+
*
6+
* wolfSSL is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* wolfSSL is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, write to the Free Software
18+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
19+
*/
20+
21+
/*!
22+
This module provides a Rust wrapper for the wolfCrypt library's
23+
ChaCha20-Poly1305 functionality.
24+
*/
25+
26+
#![cfg(chacha20_poly1305)]
27+
28+
use crate::sys;
29+
use std::mem::MaybeUninit;
30+
31+
pub struct ChaCha20Poly1305 {
32+
wc_ccp: sys::ChaChaPoly_Aead,
33+
}
34+
35+
impl ChaCha20Poly1305 {
36+
pub const KEYSIZE: usize = sys::CHACHA20_POLY1305_AEAD_KEYSIZE as usize;
37+
pub const IV_SIZE: usize = sys::CHACHA20_POLY1305_AEAD_IV_SIZE as usize;
38+
pub const AUTH_TAG_SIZE: usize = sys::CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE as usize;
39+
40+
/// Decrypt an input message from `ciphertext` using the ChaCha20 stream
41+
/// cipher into the `plaintext` output buffer. It also performs Poly-1305
42+
/// authentication, comparing the given `auth_tag` to an authentication
43+
/// generated with the `aad` (additional authentication data). If Err is
44+
/// returned, the output data, `plaintext` is undefined. However, callers
45+
/// must unconditionally zeroize the output buffer to guard against
46+
/// leakage of cleartext data.
47+
///
48+
/// # Parameters
49+
///
50+
/// * `key`: Encryption key (must be 32 bytes).
51+
/// * `iv`: Initialization Vector (must be 12 bytes).
52+
/// * `aad`: Additional authenticated data (can be any length).
53+
/// * `ciphertext`: Input buffer containing encrypted cipher text.
54+
/// * `auth_tag`: Input buffer containing authentication tag (must be 16
55+
/// bytes).
56+
/// * `plaintext`: Output buffer containing decrypted plain text.
57+
///
58+
/// # Returns
59+
///
60+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
61+
/// library error code value.
62+
pub fn decrypt(key: &[u8], iv: &[u8], aad: &[u8], ciphertext: &[u8],
63+
auth_tag: &[u8], plaintext: &mut [u8]) -> Result<(), i32> {
64+
if key.len() != Self::KEYSIZE {
65+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
66+
}
67+
if iv.len() != Self::IV_SIZE {
68+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
69+
}
70+
if auth_tag.len() != Self::AUTH_TAG_SIZE {
71+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
72+
}
73+
let aad_size = aad.len() as u32;
74+
let ciphertext_size = ciphertext.len() as u32;
75+
let rc = unsafe {
76+
sys::wc_ChaCha20Poly1305_Decrypt(key.as_ptr(), iv.as_ptr(),
77+
aad.as_ptr(), aad_size, ciphertext.as_ptr(),
78+
ciphertext_size, auth_tag.as_ptr(), plaintext.as_mut_ptr())
79+
};
80+
if rc != 0 {
81+
return Err(rc);
82+
}
83+
Ok(())
84+
}
85+
86+
/// Encrypt an input message from `plaintext` using the ChaCha20 stream
87+
/// cipher into the `ciphertext` output buffer performing Poly-1305
88+
/// authentication on the cipher text and storing the generated
89+
/// authentication tag in the `auth_tag` output buffer.
90+
///
91+
/// # Parameters
92+
///
93+
/// * `key`: Encryption key (must be 32 bytes).
94+
/// * `iv`: Initialization Vector (must be 12 bytes).
95+
/// * `aad`: Additional authenticated data (can be any length).
96+
/// * `plaintext`: Input plain text to encrypt.
97+
/// * `ciphertext`: Output buffer for encrypted cipher text.
98+
/// * `auth_tag`: Output buffer for authentication tag (must be 16 bytes).
99+
///
100+
/// # Returns
101+
///
102+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
103+
/// library error code value.
104+
pub fn encrypt(key: &[u8], iv: &[u8], aad: &[u8], plaintext: &[u8],
105+
ciphertext: &mut [u8], auth_tag: &mut [u8]) -> Result<(), i32> {
106+
if key.len() != Self::KEYSIZE {
107+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
108+
}
109+
if iv.len() != Self::IV_SIZE {
110+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
111+
}
112+
if auth_tag.len() != Self::AUTH_TAG_SIZE {
113+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
114+
}
115+
let aad_size = aad.len() as u32;
116+
let plaintext_size = plaintext.len() as u32;
117+
let rc = unsafe {
118+
sys::wc_ChaCha20Poly1305_Encrypt(key.as_ptr(), iv.as_ptr(),
119+
aad.as_ptr(), aad_size, plaintext.as_ptr(), plaintext_size,
120+
ciphertext.as_mut_ptr(), auth_tag.as_mut_ptr())
121+
};
122+
if rc != 0 {
123+
return Err(rc);
124+
}
125+
Ok(())
126+
}
127+
128+
/// Create a new ChaCha20Poly1305 instance.
129+
///
130+
/// # Parameters
131+
///
132+
/// * `key`: Encryption key (must be 32 bytes).
133+
/// * `iv`: Initialization Vector (must be 12 bytes).
134+
/// * `encrypt`: Whether the instance will be used to encrypt (true) or
135+
/// decrypt (false).
136+
///
137+
/// Returns either Ok(chacha20poly1305) on success or Err(e) containing the
138+
/// wolfSSL library error code value.
139+
pub fn new(key: &[u8], iv: &[u8], encrypt: bool) -> Result<Self, i32> {
140+
if key.len() != Self::KEYSIZE {
141+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
142+
}
143+
if iv.len() != Self::IV_SIZE {
144+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
145+
}
146+
let mut wc_ccp: MaybeUninit<sys::ChaChaPoly_Aead> = MaybeUninit::uninit();
147+
let rc = unsafe {
148+
sys::wc_ChaCha20Poly1305_Init(wc_ccp.as_mut_ptr(), key.as_ptr(),
149+
iv.as_ptr(), if encrypt {1} else {0})
150+
};
151+
if rc != 0 {
152+
return Err(rc);
153+
}
154+
let wc_ccp = unsafe { wc_ccp.assume_init() };
155+
let chacha20poly1305 = ChaCha20Poly1305 { wc_ccp };
156+
Ok(chacha20poly1305)
157+
}
158+
159+
/// Update AAD (additional authenticated data).
160+
///
161+
/// This function should be called before `update_data()`.
162+
///
163+
/// # Parameters
164+
///
165+
/// * `aad`: Additional authenticated data.
166+
///
167+
/// # Returns
168+
///
169+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
170+
/// library error code value.
171+
pub fn update_aad(&mut self, aad: &[u8]) -> Result<(), i32> {
172+
let aad_size = aad.len() as u32;
173+
let rc = unsafe {
174+
sys::wc_ChaCha20Poly1305_UpdateAad(&mut self.wc_ccp,
175+
aad.as_ptr(), aad_size)
176+
};
177+
if rc != 0 {
178+
return Err(rc);
179+
}
180+
Ok(())
181+
}
182+
183+
/// Update data (add additional input data to decrypt or encrypt).
184+
///
185+
/// This function can be called multiple times. If AAD is used, the
186+
/// `update_aad()` function must be called before this function. The
187+
/// `finalize()` function should be called after adding all input data to
188+
/// finalize the operation and compute the authentication tag.
189+
///
190+
/// # Parameters
191+
///
192+
/// * `din`: Additional input data to decrypt or encrypt.
193+
/// * `dout`: Buffer in which to store output data (must be the same length
194+
/// as the input buffer).
195+
///
196+
/// # Returns
197+
///
198+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
199+
/// library error code value.
200+
pub fn update_data(&mut self, din: &[u8], dout: &mut [u8]) -> Result<(), i32> {
201+
if din.len() != dout.len() {
202+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
203+
}
204+
let din_size = din.len() as u32;
205+
let rc = unsafe {
206+
sys::wc_ChaCha20Poly1305_UpdateData(&mut self.wc_ccp,
207+
din.as_ptr(), dout.as_mut_ptr(), din_size)
208+
};
209+
if rc != 0 {
210+
return Err(rc);
211+
}
212+
Ok(())
213+
}
214+
215+
/// Finalize the decrypt/encrypt operation.
216+
///
217+
/// This function consumes the `ChaCha20Poly1305` instance. The
218+
/// `update_data()` function must be called before calling this function to
219+
/// add all input data.
220+
///
221+
/// # Parameters
222+
///
223+
/// * `auth_tag`: Output buffer for authentication tag (must be 16 bytes).
224+
///
225+
/// # Returns
226+
///
227+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
228+
/// library error code value.
229+
pub fn finalize(mut self, auth_tag: &mut [u8]) -> Result<(), i32> {
230+
if auth_tag.len() != Self::AUTH_TAG_SIZE {
231+
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
232+
}
233+
let rc = unsafe {
234+
sys::wc_ChaCha20Poly1305_Final(&mut self.wc_ccp,
235+
auth_tag.as_mut_ptr())
236+
};
237+
if rc != 0 {
238+
return Err(rc);
239+
}
240+
Ok(())
241+
}
242+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub mod sys;
2323

2424
pub mod aes;
2525
pub mod blake2;
26+
pub mod chacha20_poly1305;
2627
pub mod cmac;
2728
pub mod curve25519;
2829
pub mod dh;

0 commit comments

Comments
 (0)