mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-01-26 20:52:19 +01:00
Rust wrapper: add one-shot XChaCha20-Poly1305 encrypt/decrypt functions
This commit is contained in:
@@ -13,6 +13,7 @@ rsource "Kconfig.tls-generic"
|
||||
const uint8_t* hashIn, int hashSz)
|
||||
XMEMCPY(hash + (curveSz - hashSz), hashIn, hashSz);
|
||||
0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, /* creen would be i */
|
||||
0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, /* creen would be i */
|
||||
\pagenumbering{alph}
|
||||
DES3_KEY_SIZE = 24, /* 3 des ede */
|
||||
/* functions added to support above needed, removed TOOM and KARATSUBA */
|
||||
|
||||
@@ -129,8 +129,8 @@ WOLFSSL_API WARN_UNUSED_RESULT int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* ae
|
||||
WOLFSSL_API int wc_XChaCha20Poly1305_Init(
|
||||
ChaChaPoly_Aead* aead,
|
||||
const byte *ad, word32 ad_len,
|
||||
const byte *inKey, word32 inKeySz,
|
||||
const byte *inIV, word32 inIVSz,
|
||||
const byte *nonce, word32 nonce_len,
|
||||
const byte *key, word32 key_len,
|
||||
int isEncrypt);
|
||||
|
||||
WOLFSSL_API int wc_XChaCha20Poly1305_Encrypt(
|
||||
|
||||
@@ -24,18 +24,21 @@ functionality:
|
||||
|
||||
* AES
|
||||
* CBC, CCM, CFB, CTR, EAX, ECB, GCM, OFB, XTS
|
||||
* BLAKE2
|
||||
* CMAC
|
||||
* ChaCha20-Poly1305
|
||||
* Curve25519
|
||||
* DH
|
||||
* ECC
|
||||
* Ed448
|
||||
* Ed25519
|
||||
* Ed448
|
||||
* HKDF
|
||||
* HMAC
|
||||
* PBKDF2
|
||||
* PKCS #12 PBKDF
|
||||
* PRF
|
||||
* RSA
|
||||
* RNG
|
||||
* RSA
|
||||
* SHA
|
||||
* SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA3-224, SHA3-256, SHA3-384,
|
||||
SHA3-512, SHAKE128, SHAKE256
|
||||
|
||||
@@ -132,6 +132,7 @@ fn scan_cfg() -> Result<()> {
|
||||
|
||||
/* chacha20_poly1305 */
|
||||
check_cfg(&binding, "wc_ChaCha20Poly1305_Encrypt", "chacha20_poly1305");
|
||||
check_cfg(&binding, "wc_XChaCha20Poly1305_Encrypt", "xchacha20_poly1305");
|
||||
|
||||
/* cmac */
|
||||
check_cfg(&binding, "wc_InitCmac", "cmac");
|
||||
|
||||
@@ -33,8 +33,11 @@ pub struct ChaCha20Poly1305 {
|
||||
}
|
||||
|
||||
impl ChaCha20Poly1305 {
|
||||
/// Key size for ChaCha20-Poly1305 stream cipher.
|
||||
pub const KEYSIZE: usize = sys::CHACHA20_POLY1305_AEAD_KEYSIZE as usize;
|
||||
/// IV size for ChaCha20-Poly1305 stream cipher.
|
||||
pub const IV_SIZE: usize = sys::CHACHA20_POLY1305_AEAD_IV_SIZE as usize;
|
||||
/// Authentication tag size for ChaCha20-Poly1305 stream cipher.
|
||||
pub const AUTH_TAG_SIZE: usize = sys::CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE as usize;
|
||||
|
||||
/// Decrypt an input message from `ciphertext` using the ChaCha20 stream
|
||||
@@ -240,3 +243,100 @@ impl ChaCha20Poly1305 {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(xchacha20_poly1305)]
|
||||
pub struct XChaCha20Poly1305 {
|
||||
}
|
||||
|
||||
#[cfg(xchacha20_poly1305)]
|
||||
impl XChaCha20Poly1305 {
|
||||
/// Key size for XChaCha20-Poly1305 stream cipher.
|
||||
pub const KEYSIZE: usize = sys::CHACHA20_POLY1305_AEAD_KEYSIZE as usize;
|
||||
/// IV size for XChaCha20-Poly1305 stream cipher.
|
||||
pub const IV_SIZE: usize = sys::XCHACHA20_POLY1305_AEAD_NONCE_SIZE as usize;
|
||||
/// Authentication tag size for XChaCha20-Poly1305 stream cipher.
|
||||
pub const AUTH_TAG_SIZE: usize = sys::CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE as usize;
|
||||
|
||||
/// Decrypt an input message from `ciphertext` using the XChaCha20 stream
|
||||
/// cipher into the `plaintext` output buffer. It also performs Poly-1305
|
||||
/// authentication. The authentication tag is expected to be located in the
|
||||
/// last 16 bytes of the `ciphertext` buffer.
|
||||
/// If Err is returned, the output data, `plaintext` is undefined.
|
||||
/// However, callers must unconditionally zeroize the output buffer to
|
||||
/// guard against leakage of cleartext data.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `key`: Encryption key (must be 32 bytes).
|
||||
/// * `iv`: Initialization Vector (must be 24 bytes).
|
||||
/// * `aad`: Additional authenticated data (can be any length).
|
||||
/// * `ciphertext`: Input buffer containing encrypted cipher text.
|
||||
/// * `plaintext`: Output buffer containing decrypted plain text.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
|
||||
/// library error code value.
|
||||
pub fn decrypt(key: &[u8], iv: &[u8], aad: &[u8], ciphertext: &[u8],
|
||||
plaintext: &mut [u8]) -> Result<(), i32> {
|
||||
if key.len() != Self::KEYSIZE {
|
||||
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
|
||||
}
|
||||
if iv.len() != Self::IV_SIZE {
|
||||
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
|
||||
}
|
||||
let rc = unsafe {
|
||||
sys::wc_XChaCha20Poly1305_Decrypt(
|
||||
plaintext.as_mut_ptr(), plaintext.len(),
|
||||
ciphertext.as_ptr(), ciphertext.len(),
|
||||
aad.as_ptr(), aad.len(),
|
||||
iv.as_ptr(), iv.len(),
|
||||
key.as_ptr(), key.len())
|
||||
};
|
||||
if rc != 0 {
|
||||
return Err(rc);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Encrypt an input message from `plaintext` using the XChaCha20 stream
|
||||
/// cipher into the `ciphertext` output buffer performing Poly-1305
|
||||
/// authentication on the cipher text.
|
||||
/// The authentication tag is stored in the last 16 bytes of the
|
||||
/// `ciphertext` buffer, so the `ciphertext` buffer must be large enough
|
||||
/// for both the cipher text and authentication tag.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `key`: Encryption key (must be 32 bytes).
|
||||
/// * `iv`: Initialization Vector (must be 24 bytes).
|
||||
/// * `aad`: Additional authenticated data (can be any length).
|
||||
/// * `plaintext`: Input plain text to encrypt.
|
||||
/// * `ciphertext`: Output buffer for encrypted cipher text.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
|
||||
/// library error code value.
|
||||
pub fn encrypt(key: &[u8], iv: &[u8], aad: &[u8], plaintext: &[u8],
|
||||
ciphertext: &mut [u8]) -> Result<(), i32> {
|
||||
if key.len() != Self::KEYSIZE {
|
||||
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
|
||||
}
|
||||
if iv.len() != Self::IV_SIZE {
|
||||
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
|
||||
}
|
||||
let rc = unsafe {
|
||||
sys::wc_XChaCha20Poly1305_Encrypt(
|
||||
ciphertext.as_mut_ptr(), ciphertext.len(),
|
||||
plaintext.as_ptr(), plaintext.len(),
|
||||
aad.as_ptr(), aad.len(),
|
||||
iv.as_ptr(), iv.len(),
|
||||
key.as_ptr(), key.len())
|
||||
};
|
||||
if rc != 0 {
|
||||
return Err(rc);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,3 +203,73 @@ fn test_chacha20_poly1305_2() {
|
||||
assert_eq!(out_plaintext2, plaintext2);
|
||||
assert_eq!(out_auth_tag_2, auth_tag_2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(xchacha20_poly1305)]
|
||||
fn test_xchacha20_poly1305() {
|
||||
const PLAINTEXT: &[u8] = &[
|
||||
0x4cu8, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
|
||||
0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, /* Ladies and Gentl */
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, /* emen of the clas */
|
||||
0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
|
||||
0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, /* s of '99: If I c */
|
||||
0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
|
||||
0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, /* ould offer you o */
|
||||
0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
|
||||
0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, /* nly one tip for */
|
||||
0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
|
||||
0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, /* the future, suns */
|
||||
0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
|
||||
0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, /* creen would be i */
|
||||
0x74, 0x2e ]; /* t. */
|
||||
|
||||
let aad = [
|
||||
0x50u8, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
|
||||
0xc4, 0xc5, 0xc6, 0xc7
|
||||
]; /* PQRS........ */
|
||||
|
||||
let key = [
|
||||
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 iv = [
|
||||
0x40u8, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* @ABCDEFGHIJKLMNO */
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57 /* PQRSTUVW */
|
||||
];
|
||||
|
||||
let expected_ciphertext = [
|
||||
0xbdu8, 0x6d, 0x17, 0x9d, 0x3e, 0x83, 0xd4, 0x3b,
|
||||
0x95, 0x76, 0x57, 0x94, 0x93, 0xc0, 0xe9, 0x39,
|
||||
0x57, 0x2a, 0x17, 0x00, 0x25, 0x2b, 0xfa, 0xcc,
|
||||
0xbe, 0xd2, 0x90, 0x2c, 0x21, 0x39, 0x6c, 0xbb,
|
||||
0x73, 0x1c, 0x7f, 0x1b, 0x0b, 0x4a, 0xa6, 0x44,
|
||||
0x0b, 0xf3, 0xa8, 0x2f, 0x4e, 0xda, 0x7e, 0x39,
|
||||
0xae, 0x64, 0xc6, 0x70, 0x8c, 0x54, 0xc2, 0x16,
|
||||
0xcb, 0x96, 0xb7, 0x2e, 0x12, 0x13, 0xb4, 0x52,
|
||||
0x2f, 0x8c, 0x9b, 0xa4, 0x0d, 0xb5, 0xd9, 0x45,
|
||||
0xb1, 0x1b, 0x69, 0xb9, 0x82, 0xc1, 0xbb, 0x9e,
|
||||
0x3f, 0x3f, 0xac, 0x2b, 0xc3, 0x69, 0x48, 0x8f,
|
||||
0x76, 0xb2, 0x38, 0x35, 0x65, 0xd3, 0xff, 0xf9,
|
||||
0x21, 0xf9, 0x66, 0x4c, 0x97, 0x63, 0x7d, 0xa9,
|
||||
0x76, 0x88, 0x12, 0xf6, 0x15, 0xc6, 0x8b, 0x13,
|
||||
0xb5, 0x2e
|
||||
];
|
||||
|
||||
let expected_tag = [
|
||||
0xc0u8, 0x87, 0x59, 0x24, 0xc1, 0xc7, 0x98, 0x79,
|
||||
0x47, 0xde, 0xaf, 0xd8, 0x78, 0x0a, 0xcf, 0x49
|
||||
];
|
||||
|
||||
let mut ciphertext_buffer = [0u8; PLAINTEXT.len() + XChaCha20Poly1305::AUTH_TAG_SIZE];
|
||||
XChaCha20Poly1305::encrypt(&key, &iv, &aad, PLAINTEXT, &mut ciphertext_buffer).expect("Error with encrypt()");
|
||||
assert_eq!(ciphertext_buffer[0..expected_ciphertext.len()], expected_ciphertext);
|
||||
assert_eq!(ciphertext_buffer[expected_ciphertext.len()..], expected_tag);
|
||||
let mut plaintext_buffer = [0u8; PLAINTEXT.len()];
|
||||
XChaCha20Poly1305::decrypt(&key, &iv, &aad, &ciphertext_buffer, &mut plaintext_buffer).expect("Error with decrypt()");
|
||||
assert_eq!(plaintext_buffer, PLAINTEXT);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user