1#![deny(clippy::unwrap_used, clippy::expect_used, clippy::indexing_slicing, clippy::panic)]
2extern crate libc;
3#[macro_use]
4extern crate lazy_static;
5use libc::c_ulonglong;
6use libsodium_sys::*;
7
8lazy_static! {
9 static ref SODIUM: i32 = unsafe { sodium_init() };
10}
11
12pub mod chacha20 {
13 use super::*;
14 pub const NONCE_BYTES: usize = 8;
15 pub const KEY_BYTES: usize = 32;
16 pub struct Nonce(pub [u8; NONCE_BYTES]);
17 pub struct Key(pub [u8; KEY_BYTES]);
18 pub fn chacha20_xor(c: &mut [u8], n: &Nonce, k: &Key) {
19 lazy_static::initialize(&super::SODIUM);
20 unsafe {
21 crypto_stream_chacha20_xor(
22 c.as_mut_ptr(),
23 c.as_ptr(),
24 c.len() as c_ulonglong,
25 n.0.as_ptr(),
26 k.0.as_ptr(),
27 );
28 }
29 }
30
31 pub fn chacha20_xor_ic(c: &mut [u8], n: &Nonce, ic: u64, k: &Key) {
32 lazy_static::initialize(&super::SODIUM);
33 unsafe {
34 crypto_stream_chacha20_xor_ic(
35 c.as_mut_ptr(),
36 c.as_ptr(),
37 c.len() as c_ulonglong,
38 n.0.as_ptr(),
39 ic,
40 k.0.as_ptr(),
41 );
42 }
43 }
44}
45
46pub mod poly1305 {
47 use super::*;
48 pub const KEY_BYTES: usize = 32;
49 pub const TAG_BYTES: usize = 16;
50 pub struct Key(pub [u8; KEY_BYTES]);
51 pub struct Tag(pub [u8; TAG_BYTES]);
52 pub fn poly1305_auth(m: &[u8], key: &Key) -> Tag {
53 lazy_static::initialize(&super::SODIUM);
54 let mut tag = Tag([0; TAG_BYTES]);
55 unsafe {
56 crypto_onetimeauth(
57 tag.0.as_mut_ptr(),
58 m.as_ptr(),
59 m.len() as c_ulonglong,
60 key.0.as_ptr(),
61 );
62 }
63 tag
64 }
65 pub fn poly1305_verify(tag: &[u8], m: &[u8], key: &Key) -> bool {
66 lazy_static::initialize(&super::SODIUM);
67 if tag.len() != TAG_BYTES {
68 false
69 } else {
70 unsafe {
71 crypto_onetimeauth_verify(
72 tag.as_ptr(),
73 m.as_ptr(),
74 m.len() as c_ulonglong,
75 key.0.as_ptr(),
76 ) == 0
77 }
78 }
79 }
80}
81
82pub mod ed25519 {
83 use super::*;
84 pub const PUBLICKEY_BYTES: usize = 32;
85 pub const SECRETKEY_BYTES: usize = 64;
86 pub const SIGNATURE_BYTES: usize = 64;
87
88 #[derive(Debug, PartialEq, Eq, Clone)]
90 pub struct PublicKey {
91 pub key: [u8; PUBLICKEY_BYTES],
93 }
94
95 impl PublicKey {
96 pub fn new_zeroed() -> Self {
97 PublicKey {
98 key: [0; PUBLICKEY_BYTES],
99 }
100 }
101 }
102
103 #[derive(Clone)]
105 pub struct SecretKey {
106 pub key: [u8; SECRETKEY_BYTES],
108 }
109
110 impl SecretKey {
111 pub fn new_zeroed() -> Self {
112 SecretKey {
113 key: [0; SECRETKEY_BYTES],
114 }
115 }
116 }
117
118 pub struct Signature(pub [u8; SIGNATURE_BYTES]);
119
120 pub fn keypair() -> (PublicKey, SecretKey) {
122 unsafe {
123 lazy_static::initialize(&super::SODIUM);
124 let mut pk = PublicKey {
125 key: [0; PUBLICKEY_BYTES],
126 };
127 let mut sk = SecretKey {
128 key: [0; SECRETKEY_BYTES],
129 };
130 crypto_sign_keypair(pk.key.as_mut_ptr(), sk.key.as_mut_ptr());
131 (pk, sk)
132 }
133 }
134
135 pub fn verify_detached(sig: &[u8], m: &[u8], pk: &PublicKey) -> bool {
137 lazy_static::initialize(&super::SODIUM);
138 if sig.len() == SIGNATURE_BYTES {
139 unsafe {
140 crypto_sign_verify_detached(
141 sig.as_ptr(),
142 m.as_ptr(),
143 m.len() as c_ulonglong,
144 pk.key.as_ptr(),
145 ) == 0
146 }
147 } else {
148 false
149 }
150 }
151
152 pub fn sign_detached(m: &[u8], sk: &SecretKey) -> Signature {
154 lazy_static::initialize(&super::SODIUM);
155 let mut sig = Signature([0; SIGNATURE_BYTES]);
156 let mut sig_len = 0;
157 unsafe {
158 crypto_sign_detached(
159 sig.0.as_mut_ptr(),
160 &mut sig_len,
161 m.as_ptr(),
162 m.len() as c_ulonglong,
163 sk.key.as_ptr(),
164 );
165 }
166 sig
167 }
168}
169
170pub mod aes256gcm {
171 use super::*;
172 pub const NONCE_BYTES: usize = crypto_aead_aes256gcm_NPUBBYTES as usize;
173 pub const KEY_BYTES: usize = crypto_aead_aes256gcm_KEYBYTES as usize;
174 pub const TAG_BYTES: usize = crypto_aead_aes256gcm_ABYTES as usize;
175 pub struct Key(pub [u8; KEY_BYTES]);
176 pub struct Nonce(pub [u8; NONCE_BYTES]);
177 pub struct Tag(pub [u8; TAG_BYTES]);
178
179 pub fn aes256gcm_encrypt(ciphertext: &mut [u8], tag: &mut [u8], message: &[u8], ad: &[u8], nonce: &Nonce, key: &Key) -> bool {
180 lazy_static::initialize(&super::SODIUM);
181 if tag.len() != TAG_BYTES {
182 false
183 } else {
184 unsafe {
185 let ret = crypto_aead_aes256gcm_encrypt_detached(
186 ciphertext.as_mut_ptr(),
187 tag.as_mut_ptr(),
188 std::ptr::null_mut(),
189 message.as_ptr(),
190 message.len() as c_ulonglong,
191 ad.as_ptr(),
192 ad.len() as c_ulonglong,
193 std::ptr::null_mut(),
194 nonce.0.as_ptr(),
195 key.0.as_ptr(),
196 );
197 ret == 0
198 }
199 }
200 }
201
202 pub fn aes256gcm_decrypt(message: &mut [u8], tag: &[u8], ciphertext: &[u8], ad: &[u8], nonce: &Nonce, key: &Key) -> bool {
203 lazy_static::initialize(&super::SODIUM);
204 if tag.len() != TAG_BYTES {
205 false
206 } else {
207 unsafe {
208 crypto_aead_aes256gcm_decrypt_detached(
209 message.as_mut_ptr(),
210 std::ptr::null_mut(),
211 ciphertext.as_ptr(),
212 ciphertext.len() as c_ulonglong,
213 tag.as_ptr(),
214 ad.as_ptr(),
215 ad.len() as c_ulonglong,
216 nonce.0.as_ptr(),
217 key.0.as_ptr(),
218 ) == 0
219 }
220 }
221 }
222}
223
224pub mod scalarmult {
225 use super::*;
226 pub const BYTES: usize = 32;
227
228 #[derive(Debug)]
229 pub struct Scalar(pub [u8; BYTES]);
230 #[derive(Debug)]
231 pub struct GroupElement(pub [u8; BYTES]);
232
233 pub fn scalarmult_base(n: &Scalar) -> GroupElement {
234 lazy_static::initialize(&super::SODIUM);
235 let mut q = GroupElement([0; BYTES]);
236 unsafe {
237 crypto_scalarmult_curve25519_base(q.0.as_mut_ptr(), n.0.as_ptr());
238 }
239 q
240 }
241
242 pub fn scalarmult(n: &Scalar, p: &GroupElement) -> GroupElement {
243 lazy_static::initialize(&super::SODIUM);
244 let mut q = GroupElement([0; BYTES]);
245 unsafe {
246 crypto_scalarmult_curve25519(q.0.as_mut_ptr(), n.0.as_ptr(), p.0.as_ptr());
247 }
248 q
249 }
250}
251
252pub mod random {
253 use libc::c_void;
254 use libsodium_sys::randombytes_buf;
255
256 pub fn randombytes(buf: &mut [u8]) {
257 unsafe {
258 randombytes_buf(buf.as_mut_ptr() as *mut c_void, buf.len());
259 }
260 }
261}