aranya_crypto/aqc/
suite.rs1use core::fmt;
2
3use serde::{Deserialize, Serialize};
4use zerocopy::{Immutable, IntoBytes, KnownLayout};
5
6#[repr(u16)]
8#[derive(
9 Copy, Clone, Debug, Eq, PartialEq, Immutable, IntoBytes, KnownLayout, Serialize, Deserialize,
10)]
11#[non_exhaustive]
12pub enum CipherSuiteId {
13 TlsAes128GcmSha256 = u16::to_be(0x1301),
15 TlsAes256GcmSha384 = u16::to_be(0x1302),
17 TlsChaCha20Poly1305Sha256 = u16::to_be(0x1303),
19 TlsAes128CcmSha256 = u16::to_be(0x1304),
21 TlsAes128Ccm8Sha256 = u16::to_be(0x1305),
23}
24
25impl CipherSuiteId {
26 pub const fn all() -> &'static [Self] {
28 use CipherSuiteId::*;
29 &[
30 TlsAes128GcmSha256,
31 TlsAes256GcmSha384,
32 TlsChaCha20Poly1305Sha256,
33 TlsAes128CcmSha256,
34 TlsAes128Ccm8Sha256,
35 ]
36 }
37
38 pub const fn to_bytes(self) -> [u8; 2] {
41 zerocopy::transmute!(self)
42 }
43
44 pub const fn try_from_bytes(bytes: [u8; 2]) -> Option<Self> {
49 use CipherSuiteId::*;
50 let id = match u16::from_be_bytes(bytes) {
51 0x1301 => TlsAes128GcmSha256,
52 0x1302 => TlsAes256GcmSha384,
53 0x1303 => TlsChaCha20Poly1305Sha256,
54 0x1304 => TlsAes128CcmSha256,
55 0x1305 => TlsAes128Ccm8Sha256,
56 _ => return None,
57 };
58 Some(id)
59 }
60}
61
62impl fmt::Display for CipherSuiteId {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 use CipherSuiteId::*;
65 let name = match self {
66 TlsAes128GcmSha256 => "TLS_AES_128_GCM_SHA256",
67 TlsAes256GcmSha384 => "TLS_AES_256_GCM_SHA384",
68 TlsChaCha20Poly1305Sha256 => "TLS_CHACHA20_POLY1305_SHA256",
69 TlsAes128CcmSha256 => "TLS_AES_128_CCM_SHA256",
70 TlsAes128Ccm8Sha256 => "TLS_AES_128_CCM_8_SHA256",
71 };
72 name.fmt(f)
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn test_cipher_suite_id() {
82 use CipherSuiteId::*;
83 let tests = [
84 ([0x13, 0x01], Some(TlsAes128GcmSha256)),
85 ([0x13, 0x02], Some(TlsAes256GcmSha384)),
86 ([0x13, 0x03], Some(TlsChaCha20Poly1305Sha256)),
87 ([0x13, 0x04], Some(TlsAes128CcmSha256)),
88 ([0x13, 0x05], Some(TlsAes128Ccm8Sha256)),
89 ([0x13, 0x00], None),
90 ([0x13, 0x06], None),
91 ];
92 for (idx, (bytes, suite)) in tests.into_iter().enumerate() {
93 let got = CipherSuiteId::try_from_bytes(bytes);
94 assert_eq!(got, suite, "#{idx}");
95
96 let Some(suite) = suite else {
97 continue;
98 };
99
100 assert_eq!(suite.to_bytes(), bytes, "#{idx}");
101
102 let got = suite.as_bytes();
105 let want = suite.to_bytes();
106 assert_eq!(got, want, "#{idx}");
107 }
108 }
109
110 #[test]
111 fn test_cipher_suite_round_trip() {
112 for &suite in CipherSuiteId::all() {
113 let got = CipherSuiteId::try_from_bytes(suite.to_bytes());
114 assert_eq!(got, Some(suite), "{suite}");
115 }
116 }
117}