pqcrypto_kyber/
kyber768.rs1#[cfg(feature = "serialization")]
22use serde::{Deserialize, Serialize};
23#[cfg(feature = "serialization")]
24use serde_big_array::BigArray;
25
26use crate::ffi;
27use pqcrypto_traits::kem as primitive;
28use pqcrypto_traits::{Error, Result};
29
30macro_rules! simple_struct {
31 ($type: ident, $size: expr) => {
32 #[derive(Clone, Copy)]
33 #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
34 pub struct $type(
35 #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size],
36 );
37
38 impl $type {
39 fn new() -> Self {
45 $type([0u8; $size])
46 }
47 }
48
49 impl primitive::$type for $type {
50 #[inline]
52 fn as_bytes(&self) -> &[u8] {
53 &self.0
54 }
55
56 fn from_bytes(bytes: &[u8]) -> Result<Self> {
58 if bytes.len() != $size {
59 Err(Error::BadLength {
60 name: stringify!($type),
61 actual: bytes.len(),
62 expected: $size,
63 })
64 } else {
65 let mut array = [0u8; $size];
66 array.copy_from_slice(bytes);
67 Ok($type(array))
68 }
69 }
70 }
71
72 impl PartialEq for $type {
73 fn eq(&self, other: &Self) -> bool {
75 self.0
76 .iter()
77 .zip(other.0.iter())
78 .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) })
79 .is_ok()
80 }
81 }
82 };
83}
84
85simple_struct!(PublicKey, ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_PUBLICKEYBYTES);
86simple_struct!(SecretKey, ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_SECRETKEYBYTES);
87simple_struct!(
88 Ciphertext,
89 ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_CIPHERTEXTBYTES
90);
91simple_struct!(SharedSecret, ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_BYTES);
92
93pub const fn public_key_bytes() -> usize {
95 ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_PUBLICKEYBYTES
96}
97
98pub const fn secret_key_bytes() -> usize {
100 ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_SECRETKEYBYTES
101}
102
103pub const fn ciphertext_bytes() -> usize {
105 ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_CIPHERTEXTBYTES
106}
107
108pub const fn shared_secret_bytes() -> usize {
110 ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_BYTES
111}
112
113macro_rules! gen_keypair {
114 ($variant:ident) => {{
115 let mut pk = PublicKey::new();
116 let mut sk = SecretKey::new();
117 assert_eq!(
118 unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) },
119 0
120 );
121 (pk, sk)
122 }};
123}
124
125pub fn keypair() -> (PublicKey, SecretKey) {
127 #[cfg(all(enable_x86_avx2, feature = "avx2"))]
128 {
129 if std::is_x86_feature_detected!("avx2") {
130 return gen_keypair!(PQCLEAN_KYBER768_AVX2_crypto_kem_keypair);
131 }
132 }
133 #[cfg(all(enable_aarch64_neon, feature = "neon"))]
134 {
135 if true {
139 return gen_keypair!(PQCLEAN_KYBER768_AARCH64_crypto_kem_keypair);
140 }
141 }
142 gen_keypair!(PQCLEAN_KYBER768_CLEAN_crypto_kem_keypair)
143}
144
145macro_rules! encap {
146 ($variant:ident, $pk:ident) => {{
147 let mut ss = SharedSecret::new();
148 let mut ct = Ciphertext::new();
149 assert_eq!(
150 unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) },
151 0,
152 );
153 (ss, ct)
154 }};
155}
156
157pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) {
159 #[cfg(all(enable_x86_avx2, feature = "avx2"))]
160 {
161 if std::is_x86_feature_detected!("avx2") {
162 return encap!(PQCLEAN_KYBER768_AVX2_crypto_kem_enc, pk);
163 }
164 }
165 #[cfg(all(enable_aarch64_neon, feature = "neon"))]
166 {
167 if true {
168 return encap!(PQCLEAN_KYBER768_AARCH64_crypto_kem_enc, pk);
169 }
170 }
171 encap!(PQCLEAN_KYBER768_CLEAN_crypto_kem_enc, pk)
172}
173
174macro_rules! decap {
175 ($variant:ident, $ct:ident, $sk:ident) => {{
176 let mut ss = SharedSecret::new();
177 assert_eq!(
178 unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) },
179 0
180 );
181 ss
182 }};
183}
184
185pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret {
187 #[cfg(all(enable_x86_avx2, feature = "avx2"))]
188 {
189 if std::is_x86_feature_detected!("avx2") {
190 return decap!(PQCLEAN_KYBER768_AVX2_crypto_kem_dec, ct, sk);
191 }
192 }
193 #[cfg(all(enable_aarch64_neon, feature = "neon"))]
194 {
195 if true {
196 return decap!(PQCLEAN_KYBER768_AARCH64_crypto_kem_dec, ct, sk);
197 }
198 }
199 decap!(PQCLEAN_KYBER768_CLEAN_crypto_kem_dec, ct, sk)
200}
201
202#[cfg(test)]
203mod test {
204 use super::*;
205
206 #[test]
207 pub fn test_kem() {
208 let (pk, sk) = keypair();
209 let (ss1, ct) = encapsulate(&pk);
210 let ss2 = decapsulate(&ct, &sk);
211 assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!");
212 }
213}