diff --git a/.codespellexcludelines b/.codespellexcludelines index 3539a607437..cd204a1a2f4 100644 --- a/.codespellexcludelines +++ b/.codespellexcludelines @@ -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 */ diff --git a/wolfssl/wolfcrypt/chacha20_poly1305.h b/wolfssl/wolfcrypt/chacha20_poly1305.h index ca5754543f5..3af10755bbc 100644 --- a/wolfssl/wolfcrypt/chacha20_poly1305.h +++ b/wolfssl/wolfcrypt/chacha20_poly1305.h @@ -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( diff --git a/wrapper/rust/wolfssl-wolfcrypt/README.md b/wrapper/rust/wolfssl-wolfcrypt/README.md index 87db938645c..20c0c93c8bf 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/README.md +++ b/wrapper/rust/wolfssl-wolfcrypt/README.md @@ -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 diff --git a/wrapper/rust/wolfssl-wolfcrypt/build.rs b/wrapper/rust/wolfssl-wolfcrypt/build.rs index 9023d692600..78adbbc3b2f 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/build.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/build.rs @@ -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"); diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs b/wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs index 38b9efedb7c..a9221b89e5e 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs @@ -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(()) + } +} diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_chacha20_poly1305.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_chacha20_poly1305.rs index 5b6f740a4d1..3f6698d6ba9 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_chacha20_poly1305.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_chacha20_poly1305.rs @@ -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); +}