1extern crate libc;
2#[macro_use]
3extern crate lazy_static;
4use libc::c_ulonglong;
5use libsodium_sys::*;
6
7lazy_static! {
8 static ref SODIUM: i32 = unsafe { sodium_init() };
9}
10
11pub fn memcmp(a: &[u8], b: &[u8]) -> bool {
12 unsafe {
13 sodium_memcmp(
14 a.as_ptr() as *const libc::c_void,
15 b.as_ptr() as *const libc::c_void,
16 a.len().min(b.len()),
17 ) == 0
18 }
19}
20
21pub mod chacha20 {
22 use super::*;
23 pub const NONCE_BYTES: usize = 8;
24 pub const KEY_BYTES: usize = 32;
25 pub struct Nonce(pub [u8; NONCE_BYTES]);
26 pub struct Key(pub [u8; KEY_BYTES]);
27 pub fn chacha20_xor(c: &mut [u8], n: &Nonce, k: &Key) {
28 lazy_static::initialize(&super::SODIUM);
29 unsafe {
30 crypto_stream_chacha20_xor(
31 c.as_mut_ptr(),
32 c.as_ptr(),
33 c.len() as c_ulonglong,
34 n.0.as_ptr(),
35 k.0.as_ptr(),
36 );
37 }
38 }
39
40 pub fn chacha20_xor_ic(c: &mut [u8], n: &Nonce, ic: u64, k: &Key) {
41 lazy_static::initialize(&super::SODIUM);
42 unsafe {
43 crypto_stream_chacha20_xor_ic(
44 c.as_mut_ptr(),
45 c.as_ptr(),
46 c.len() as c_ulonglong,
47 n.0.as_ptr(),
48 ic,
49 k.0.as_ptr(),
50 );
51 }
52 }
53}
54
55pub mod hmac256 {
56 pub const KEY_BYTES: usize = libsodium_sys::crypto_auth_hmacsha256_KEYBYTES as usize;
57 pub const BYTES: usize = libsodium_sys::crypto_auth_hmacsha256_BYTES as usize;
58
59 pub fn init_state(key: &[u8; KEY_BYTES]) -> libsodium_sys::crypto_auth_hmacsha256_state {
60 unsafe {
61 let mut state = std::mem::zeroed();
62 libsodium_sys::crypto_auth_hmacsha256_init(&mut state, key.as_ptr(), KEY_BYTES);
63 state
64 }
65 }
66
67 pub fn update(s: &mut libsodium_sys::crypto_auth_hmacsha256_state, msg: &[u8]) {
68 unsafe {
69 libsodium_sys::crypto_auth_hmacsha256_update(s, msg.as_ptr(), msg.len() as u64);
70 }
71 }
72
73 pub fn finalize(s: &mut libsodium_sys::crypto_auth_hmacsha256_state, out: &mut [u8]) {
74 assert_eq!(out.len(), BYTES);
75 unsafe {
76 libsodium_sys::crypto_auth_hmacsha256_final(s, out.as_mut_ptr());
77 }
78 }
79}
80
81pub mod poly1305 {
82 use super::*;
83 pub const KEY_BYTES: usize = 32;
84 pub const TAG_BYTES: usize = 16;
85 pub struct Key(pub [u8; KEY_BYTES]);
86 pub struct Tag(pub [u8; TAG_BYTES]);
87 pub fn poly1305_auth(m: &[u8], key: &Key) -> Tag {
88 lazy_static::initialize(&super::SODIUM);
89 let mut tag = Tag([0; TAG_BYTES]);
90 unsafe {
91 crypto_onetimeauth(
92 tag.0.as_mut_ptr(),
93 m.as_ptr(),
94 m.len() as c_ulonglong,
95 key.0.as_ptr(),
96 );
97 }
98 tag
99 }
100 pub fn poly1305_verify(tag: &[u8], m: &[u8], key: &Key) -> bool {
101 lazy_static::initialize(&super::SODIUM);
102 if tag.len() != TAG_BYTES {
103 false
104 } else {
105 unsafe {
106 crypto_onetimeauth_verify(
107 tag.as_ptr(),
108 m.as_ptr(),
109 m.len() as c_ulonglong,
110 key.0.as_ptr(),
111 ) == 0
112 }
113 }
114 }
115}
116
117pub mod ed25519 {
118 use super::*;
119 pub const PUBLICKEY_BYTES: usize = 32;
120 pub const SECRETKEY_BYTES: usize = 64;
121 pub const SIGNATURE_BYTES: usize = 64;
122
123 #[derive(Debug, PartialEq, Eq)]
125 pub struct PublicKey {
126 pub key: [u8; PUBLICKEY_BYTES],
128 }
129
130 impl PublicKey {
131 pub fn new_zeroed() -> Self {
132 PublicKey {
133 key: [0; PUBLICKEY_BYTES],
134 }
135 }
136 }
137
138 #[derive(Clone)]
140 pub struct SecretKey {
141 pub key: [u8; SECRETKEY_BYTES],
143 }
144
145 impl SecretKey {
146 pub fn new_zeroed() -> Self {
147 SecretKey {
148 key: [0; SECRETKEY_BYTES],
149 }
150 }
151 }
152
153 pub struct Signature(pub [u8; SIGNATURE_BYTES]);
154
155 pub fn keypair() -> (PublicKey, SecretKey) {
157 unsafe {
158 lazy_static::initialize(&super::SODIUM);
159 let mut pk = PublicKey {
160 key: [0; PUBLICKEY_BYTES],
161 };
162 let mut sk = SecretKey {
163 key: [0; SECRETKEY_BYTES],
164 };
165 crypto_sign_keypair(pk.key.as_mut_ptr(), sk.key.as_mut_ptr());
166 (pk, sk)
167 }
168 }
169
170 pub fn verify_detached(sig: &[u8], m: &[u8], pk: &PublicKey) -> bool {
172 lazy_static::initialize(&super::SODIUM);
173 if sig.len() == SIGNATURE_BYTES {
174 unsafe {
175 crypto_sign_verify_detached(
176 sig.as_ptr(),
177 m.as_ptr(),
178 m.len() as c_ulonglong,
179 pk.key.as_ptr(),
180 ) == 0
181 }
182 } else {
183 false
184 }
185 }
186
187 pub fn sign_detached(m: &[u8], sk: &SecretKey) -> Signature {
189 lazy_static::initialize(&super::SODIUM);
190 let mut sig = Signature([0; SIGNATURE_BYTES]);
191 let mut sig_len = 0;
192 unsafe {
193 crypto_sign_detached(
194 sig.0.as_mut_ptr(),
195 &mut sig_len,
196 m.as_ptr(),
197 m.len() as c_ulonglong,
198 sk.key.as_ptr(),
199 );
200 }
201 sig
202 }
203}
204
205pub mod scalarmult {
206 use super::*;
207 pub const BYTES: usize = 32;
208
209 #[derive(Debug)]
210 pub struct Scalar(pub [u8; BYTES]);
211 #[derive(Debug)]
212 pub struct GroupElement(pub [u8; BYTES]);
213
214 pub fn scalarmult_base(n: &Scalar) -> GroupElement {
215 lazy_static::initialize(&super::SODIUM);
216 let mut q = GroupElement([0; BYTES]);
217 unsafe {
218 crypto_scalarmult_curve25519_base(q.0.as_mut_ptr(), n.0.as_ptr());
219 }
220 q
221 }
222
223 pub fn scalarmult(n: &Scalar, p: &GroupElement) -> GroupElement {
224 lazy_static::initialize(&super::SODIUM);
225 let mut q = GroupElement([0; BYTES]);
226 unsafe {
227 crypto_scalarmult_curve25519(q.0.as_mut_ptr(), n.0.as_ptr(), p.0.as_ptr());
228 }
229 q
230 }
231}