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)
|
const uint8_t* hashIn, int hashSz)
|
||||||
XMEMCPY(hash + (curveSz - hashSz), hashIn, 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 */
|
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}
|
\pagenumbering{alph}
|
||||||
DES3_KEY_SIZE = 24, /* 3 des ede */
|
DES3_KEY_SIZE = 24, /* 3 des ede */
|
||||||
/* functions added to support above needed, removed TOOM and KARATSUBA */
|
/* 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(
|
WOLFSSL_API int wc_XChaCha20Poly1305_Init(
|
||||||
ChaChaPoly_Aead* aead,
|
ChaChaPoly_Aead* aead,
|
||||||
const byte *ad, word32 ad_len,
|
const byte *ad, word32 ad_len,
|
||||||
const byte *inKey, word32 inKeySz,
|
const byte *nonce, word32 nonce_len,
|
||||||
const byte *inIV, word32 inIVSz,
|
const byte *key, word32 key_len,
|
||||||
int isEncrypt);
|
int isEncrypt);
|
||||||
|
|
||||||
WOLFSSL_API int wc_XChaCha20Poly1305_Encrypt(
|
WOLFSSL_API int wc_XChaCha20Poly1305_Encrypt(
|
||||||
|
|||||||
@@ -24,18 +24,21 @@ functionality:
|
|||||||
|
|
||||||
* AES
|
* AES
|
||||||
* CBC, CCM, CFB, CTR, EAX, ECB, GCM, OFB, XTS
|
* CBC, CCM, CFB, CTR, EAX, ECB, GCM, OFB, XTS
|
||||||
|
* BLAKE2
|
||||||
* CMAC
|
* CMAC
|
||||||
|
* ChaCha20-Poly1305
|
||||||
|
* Curve25519
|
||||||
* DH
|
* DH
|
||||||
* ECC
|
* ECC
|
||||||
* Ed448
|
|
||||||
* Ed25519
|
* Ed25519
|
||||||
|
* Ed448
|
||||||
* HKDF
|
* HKDF
|
||||||
* HMAC
|
* HMAC
|
||||||
* PBKDF2
|
* PBKDF2
|
||||||
* PKCS #12 PBKDF
|
* PKCS #12 PBKDF
|
||||||
* PRF
|
* PRF
|
||||||
* RSA
|
|
||||||
* RNG
|
* RNG
|
||||||
|
* RSA
|
||||||
* SHA
|
* SHA
|
||||||
* SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA3-224, SHA3-256, SHA3-384,
|
* SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA3-224, SHA3-256, SHA3-384,
|
||||||
SHA3-512, SHAKE128, SHAKE256
|
SHA3-512, SHAKE128, SHAKE256
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ fn scan_cfg() -> Result<()> {
|
|||||||
|
|
||||||
/* chacha20_poly1305 */
|
/* chacha20_poly1305 */
|
||||||
check_cfg(&binding, "wc_ChaCha20Poly1305_Encrypt", "chacha20_poly1305");
|
check_cfg(&binding, "wc_ChaCha20Poly1305_Encrypt", "chacha20_poly1305");
|
||||||
|
check_cfg(&binding, "wc_XChaCha20Poly1305_Encrypt", "xchacha20_poly1305");
|
||||||
|
|
||||||
/* cmac */
|
/* cmac */
|
||||||
check_cfg(&binding, "wc_InitCmac", "cmac");
|
check_cfg(&binding, "wc_InitCmac", "cmac");
|
||||||
|
|||||||
@@ -33,8 +33,11 @@ pub struct ChaCha20Poly1305 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ChaCha20Poly1305 {
|
impl ChaCha20Poly1305 {
|
||||||
|
/// Key size for ChaCha20-Poly1305 stream cipher.
|
||||||
pub const KEYSIZE: usize = sys::CHACHA20_POLY1305_AEAD_KEYSIZE as usize;
|
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;
|
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;
|
pub const AUTH_TAG_SIZE: usize = sys::CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE as usize;
|
||||||
|
|
||||||
/// Decrypt an input message from `ciphertext` using the ChaCha20 stream
|
/// Decrypt an input message from `ciphertext` using the ChaCha20 stream
|
||||||
@@ -240,3 +243,100 @@ impl ChaCha20Poly1305 {
|
|||||||
Ok(())
|
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_plaintext2, plaintext2);
|
||||||
assert_eq!(out_auth_tag_2, auth_tag_2);
|
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