libcrux_chacha20poly1305/lib.rs
1//! This crate implements the ChaCha20Poly1305 AEAD algorithm, as well as the extended nonce
2//! variant XChaCha20Poly1305.
3//!
4//! To encrypt something using ChaCha20Poly1305, use:
5//!
6//! ```rust
7//! # fn main(){
8//! # use libcrux_secrets::{Classify, ClassifyRef, Declassify, DeclassifyRef, U8};
9//! # let key_bytes = [0u8.classify(); 32];
10//! # const MSG_LEN: usize = 19;
11//! #
12//! use libcrux_chacha20poly1305::*;
13//! use libcrux_traits::aead::typed_owned::Aead as _;
14//!
15//! let msg: &[U8; MSG_LEN] = b"squeamish ossifrage".classify_ref();
16//! let mut ciphertext = [0u8; MSG_LEN];
17//! let mut tag = Tag::from([0u8.classify(); TAG_LEN]);
18//!
19//! let key = Key::from(key_bytes);
20//! let nonce = Nonce::from([123u8.classify(); NONCE_LEN]);
21//!
22//! key.encrypt(&mut ciphertext, &mut tag, &nonce, &[/* no aad */], msg)
23//! .expect("Encryption error");
24//!
25//! // Ciphertext and tag contain encrypted data
26//! assert_eq!(
27//! ciphertext,
28//! [ 181, 223, 66, 115, 105, 181, 98, 178,
29//! 247, 139, 196, 238, 169, 225, 143, 94,
30//! 174, 123, 232 ]
31//! );
32//! assert_eq!(
33//! tag.as_ref().declassify_ref(),
34//! &[ 155, 112, 155, 212, 133, 38, 145, 115,
35//! 27, 221, 245, 237, 125, 28, 22, 101 ]
36//! );
37//! # }
38//! ```
39//!
40//! and to decrypt, do
41//!
42//! ```rust
43//! # fn main(){
44//! # use libcrux_secrets::{Classify, Declassify, DeclassifyRef};
45//! # let key_bytes = [0u8; 32].classify();
46//! # let ciphertext = [181, 223, 66, 115, 105, 181, 98, 178, 247, 139, 196, 238, 169, 225, 143, 94, 174, 123, 232];
47//! # let tag_bytes = [155, 112, 155, 212, 133, 38, 145, 115, 27, 221, 245, 237, 125, 28, 22, 101].classify();
48//! # const MSG_LEN: usize = 19;
49//! #
50//! use libcrux_chacha20poly1305::*;
51//! use libcrux_traits::aead::typed_owned::Aead as _;
52//!
53//! let mut plaintext = [0u8.classify(); MSG_LEN];
54//! let mut tag = Tag::from(tag_bytes);
55//!
56//! let key = Key::from(key_bytes);
57//! let nonce = Nonce::from([123u8.classify(); NONCE_LEN]);
58//!
59//! key.decrypt(&mut plaintext, &nonce, &[/* no aad */], &ciphertext, &tag)
60//! .expect("Encryption error");
61//!
62//! assert_eq!(plaintext.declassify_ref(), b"squeamish ossifrage");
63//! # }
64//! ```
65
66#![no_std]
67
68use libcrux_traits::aead::{typed_owned, typed_refs};
69
70pub mod xchacha20_poly1305;
71
72mod hacl {
73 pub(crate) use libcrux_poly1305::hacl::mac_poly1305;
74
75 pub(crate) mod aead_chacha20poly1305;
76 pub(crate) mod chacha20;
77}
78
79mod impl_aead_trait;
80mod impl_hacl;
81
82pub use impl_aead_trait::ChaCha20Poly1305;
83pub use impl_hacl::*;
84
85/// The length of ChaCha20-Poly1305 keys.
86pub const KEY_LEN: usize = 32;
87
88/// The length of Poly1305 MAC tags.
89pub const TAG_LEN: usize = 16;
90
91/// The length of ChaCha20-Poly1305 nonces.
92pub const NONCE_LEN: usize = 12;
93
94/// An owned ChaCha20Poly1305 key.
95pub type Key = typed_owned::Key<ChaCha20Poly1305>;
96/// An owned ChaCha20Poly1305 tag.
97pub type Tag = typed_owned::Tag<ChaCha20Poly1305>;
98/// An owned ChaCha20Poly1305 nonce.
99pub type Nonce = typed_owned::Nonce<ChaCha20Poly1305>;
100
101/// A reference to a ChaCha20Poly1305 key.
102pub type KeyRef<'a> = typed_refs::KeyRef<'a, ChaCha20Poly1305>;
103/// A reference to a ChaCha20Poly1305 tag.
104pub type TagRef<'a> = typed_refs::TagRef<'a, ChaCha20Poly1305>;
105/// A mutable reference to a ChaCha20Poly1305 tag.
106pub type TagMut<'a> = typed_refs::TagMut<'a, ChaCha20Poly1305>;
107/// A reference to a ChaCha20Poly1305 nonce.
108pub type NonceRef<'a> = typed_refs::NonceRef<'a, ChaCha20Poly1305>;
109
110/// Describes the error conditions of the ChaCha20-Poly1305 AEAD.
111#[derive(Debug)]
112pub enum AeadError {
113 /// Indicates that the plaintext argument is too large for the library to handle.
114 PlaintextTooLarge,
115 /// Indicates that the ciphertext argument is too large for the library to handle.
116 CiphertextTooLarge,
117 /// Indicates that the associated data argument is too large for the library to handle.
118 AadTooLarge,
119 /// This indicates that the provided destination ciphertext does not fit the ciphertext and tag.
120 CiphertextTooShort,
121 /// This indicates that the provided destination plaintext is shorter than `ctxt.len() - TAG_LEN`
122 /// and thus will not fit the decrypted plaintext
123 PlaintextTooShort,
124 /// Indicates that the ciphertext is not a valid encryption under the given key and nonce.
125 InvalidCiphertext,
126}
127
128impl core::fmt::Display for AeadError {
129 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
130 let msg = match self {
131 AeadError::PlaintextTooLarge => {
132 "The plaintext argument is too large for the library to handle"
133 }
134 AeadError::CiphertextTooLarge => {
135 "The ciphertext argument is too large for the library to handle"
136 }
137 AeadError::AadTooLarge => {
138 "The associated data argument is too large for the library to handle"
139 }
140 AeadError::CiphertextTooShort => {
141 "The provided destination ciphertext does not fit the ciphertext and tag"
142 }
143 AeadError::PlaintextTooShort => {
144 "The provided destination plaintext is too short to fit the decrypted plaintext"
145 }
146 AeadError::InvalidCiphertext => {
147 "The ciphertext is not a valid encryption under the given key and nonce."
148 }
149 };
150
151 f.write_str(msg)
152 }
153}
154
155/// Describes the error conditions of the Poly1305 MAC.
156#[derive(Debug)]
157pub enum MacError {
158 /// Indicates that the message argument is too large for the library to handle.
159 MessageTooLarge,
160
161 /// Indicates that the MAC tag is invalid for that key and message.
162 InvalidMacTag,
163}
164
165impl core::fmt::Display for MacError {
166 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
167 let msg = match self {
168 MacError::MessageTooLarge => {
169 "The message argument is too large for the library to handle"
170 }
171 MacError::InvalidMacTag => "The MAC tag is invalid for that key and message",
172 };
173
174 f.write_str(msg)
175 }
176}