1pub use bssl_sys::{
16 CBB_len, CBS_init, CBS_len, CRYPTO_memcmp, EC_GROUP_get_curve_name, ED25519_keypair,
17 ED25519_keypair_from_seed, ERR_print_errors_cb, HMAC_CTX_init, HMAC_size, RC4_set_key,
18 RSA_bits, RC4,
19};
20
21use std::convert::TryInto;
22use std::num::NonZeroUsize;
23use std::os::raw::{c_char, c_int, c_uint, c_void};
24use std::ptr::{self, NonNull};
25
26use bssl_sys::{
27 self as ffi, BIGNUM, BN_GENCB, CBB, CBS, EC_GROUP, EC_KEY, EVP_MD, EVP_PKEY, HMAC_CTX, RSA,
28 SHA512_CTX,
29};
30
31use boringssl::abort::UnwrapAbort;
32use boringssl::wrapper::CInit;
33use boringssl::BoringError;
34
35macro_rules! impl_hash_context {
36 ($ctx:ident, $update:ident, $final:ident) => {
37 #[allow(non_snake_case)]
38 pub unsafe fn $update(ctx: *mut ffi::$ctx, data: *const c_void, len: usize) {
39 assert_abort_eq!(ffi::$update(ctx, data, len), 1);
41 }
42 #[allow(non_snake_case)]
43 pub unsafe fn $final(md: *mut u8, ctx: *mut ffi::$ctx) -> Result<(), BoringError> {
44 one_or_err(stringify!($final), ffi::$final(md, ctx))
45 }
46 };
47}
48
49impl_traits!(BIGNUM, CInit => BN_init, CDestruct => BN_free);
55
56#[allow(non_snake_case)]
57#[must_use]
58pub unsafe fn BN_set_u64(bn: *mut BIGNUM, value: u64) -> Result<(), BoringError> {
59 one_or_err("BN_set_u64", ffi::BN_set_u64(bn, value))
60}
61
62impl_traits!(CBB, CDestruct => CBB_cleanup);
65impl_traits!(CBS, CDestruct => _);
66
67#[allow(non_snake_case)]
68#[must_use]
69pub unsafe fn CBB_init(cbb: *mut CBB, initial_capacity: usize) -> Result<(), BoringError> {
70 one_or_err("CBB_init", ffi::CBB_init(cbb, initial_capacity))
71}
72
73#[allow(non_snake_case)]
74#[must_use]
75pub unsafe fn CBB_data(cbb: *const CBB) -> Result<NonNull<u8>, BoringError> {
76 ptr_or_err("CBB_init", ffi::CBB_data(cbb) as *mut _)
77}
78
79#[allow(non_snake_case)]
82#[must_use]
83pub unsafe fn ED25519_sign(
84 out: *mut [u8; 64],
85 message: *const u8,
86 message_len: usize,
87 private_key: *const [u8; 64],
88) -> Result<(), BoringError> {
89 one_or_err(
90 "ED25519_sign",
91 ffi::ED25519_sign(out as *mut u8, message, message_len, private_key as *const u8),
92 )
93}
94
95#[allow(non_snake_case)]
96#[must_use]
97pub unsafe fn ED25519_verify(
98 message: *const u8,
99 message_len: usize,
100 signature: *const [u8; 64],
101 public_key: *const [u8; 32],
102) -> bool {
103 match ffi::ED25519_verify(message, message_len, signature as *const u8, public_key as *const u8)
104 {
105 0 => false,
106 1 => true,
107 _ => unreachable_abort!(),
109 }
110}
111
112macro_rules! evp_digest {
115 ($name:ident) => {
116 #[allow(non_snake_case)]
117 #[must_use]
118 pub unsafe fn $name() -> NonNull<EVP_MD> {
119 use boringssl::abort::UnwrapAbort;
122 ptr_or_err(stringify!($name), ffi::$name() as *mut _).unwrap_abort()
123 }
124 };
125}
126
127evp_digest!(EVP_md5);
128evp_digest!(EVP_sha1);
129evp_digest!(EVP_sha256);
130evp_digest!(EVP_sha384);
131evp_digest!(EVP_sha512);
132
133#[allow(non_snake_case)]
136#[must_use]
137pub unsafe fn EC_GROUP_new_by_curve_name(nid: c_int) -> Result<NonNull<EC_GROUP>, BoringError> {
138 ptr_or_err("EC_GROUP_new_by_curve_name", ffi::EC_GROUP_new_by_curve_name(nid))
139}
140
141impl_traits!(EC_KEY, CNew => EC_KEY_new, CUpRef => EC_KEY_up_ref, CFree => EC_KEY_free);
144impl_traits!(EVP_PKEY, CNew => EVP_PKEY_new, CUpRef => EVP_PKEY_up_ref, CFree => EVP_PKEY_free);
145
146#[allow(non_snake_case)]
147#[must_use]
148pub unsafe fn EC_curve_nid2nist(nid: c_int) -> Result<NonNull<c_char>, BoringError> {
149 ptr_or_err("EC_curve_nid2nist", ffi::EC_curve_nid2nist(nid) as *mut _)
150}
151
152#[allow(non_snake_case)]
153#[must_use]
154pub unsafe fn EC_KEY_generate_key(key: *mut EC_KEY) -> Result<(), BoringError> {
155 one_or_err("EC_KEY_generate_key", ffi::EC_KEY_generate_key(key))
156}
157
158#[allow(non_snake_case)]
159#[must_use]
160pub unsafe fn EC_KEY_get0_group(key: *const EC_KEY) -> Result<NonNull<EC_GROUP>, BoringError> {
161 ptr_or_err("EC_KEY_get0_group", ffi::EC_KEY_get0_group(key) as *mut _)
162}
163
164#[allow(non_snake_case)]
165#[must_use]
166pub unsafe fn EC_KEY_marshal_private_key(
167 cbb: *mut CBB,
168 key: *const EC_KEY,
169 enc_flags: c_uint,
170) -> Result<(), BoringError> {
171 one_or_err("EC_KEY_marshal_private_key", ffi::EC_KEY_marshal_private_key(cbb, key, enc_flags))
172}
173
174#[allow(non_snake_case)]
175#[must_use]
176pub unsafe fn EC_KEY_parse_private_key(
177 cbs: *mut CBS,
178 group: *const EC_GROUP,
179) -> Result<NonNull<EC_KEY>, BoringError> {
180 ptr_or_err("EC_KEY_parse_private_key", ffi::EC_KEY_parse_private_key(cbs, group))
181}
182
183#[allow(non_snake_case)]
184#[must_use]
185pub unsafe fn EC_KEY_set_group(
186 key: *mut EC_KEY,
187 group: *const EC_GROUP,
188) -> Result<(), BoringError> {
189 one_or_err("EC_KEY_set_group", ffi::EC_KEY_set_group(key, group))
190}
191
192#[allow(non_snake_case)]
195#[must_use]
196pub unsafe fn ECDSA_sign(
197 type_: c_int,
198 digest: *const u8,
199 digest_len: usize,
200 sig: *mut u8,
201 sig_len: *mut c_uint,
202 key: *const EC_KEY,
203) -> Result<(), BoringError> {
204 one_or_err("ECDSA_sign", ffi::ECDSA_sign(type_, digest, digest_len, sig, sig_len, key))
205}
206
207#[allow(non_snake_case)]
208#[must_use]
209pub unsafe fn ECDSA_size(key: *const EC_KEY) -> Result<NonZeroUsize, BoringError> {
210 NonZeroUsize::new(ffi::ECDSA_size(key)).ok_or_else(|| BoringError::consume_stack("ECDSA_size"))
211}
212
213#[allow(non_snake_case)]
214#[must_use]
215pub unsafe fn ECDSA_verify(
216 type_: c_int,
217 digest: *const u8,
218 digest_len: usize,
219 sig: *const u8,
220 sig_len: usize,
221 key: *const EC_KEY,
222) -> bool {
223 match ffi::ECDSA_verify(type_, digest, digest_len, sig, sig_len, key) {
224 1 => true,
225 0 => false,
226 _ => unreachable_abort!(),
228 }
229}
230
231#[allow(non_snake_case)]
234#[must_use]
235pub unsafe fn EVP_marshal_public_key(
236 cbb: *mut CBB,
237 key: *const EVP_PKEY,
238) -> Result<(), BoringError> {
239 one_or_err("EVP_marshal_public_key", ffi::EVP_marshal_public_key(cbb, key))
240}
241
242#[allow(non_snake_case)]
243#[must_use]
244pub unsafe fn EVP_parse_public_key(cbs: *mut CBS) -> Result<NonNull<EVP_PKEY>, BoringError> {
245 ptr_or_err("EVP_parse_public_key", ffi::EVP_parse_public_key(cbs))
246}
247
248#[allow(non_snake_case)]
249#[must_use]
250pub unsafe fn EVP_PKEY_assign_EC_KEY(
251 pkey: *mut EVP_PKEY,
252 key: *mut EC_KEY,
253) -> Result<(), BoringError> {
254 one_or_err("EVP_PKEY_assign_EC_KEY", ffi::EVP_PKEY_assign_EC_KEY(pkey, key))
255}
256
257#[allow(non_snake_case)]
258#[must_use]
259pub unsafe fn EVP_PKEY_assign_RSA(pkey: *mut EVP_PKEY, key: *mut RSA) -> Result<(), BoringError> {
260 one_or_err("EVP_PKEY_assign_RSA", ffi::EVP_PKEY_assign_RSA(pkey, key))
261}
262
263#[allow(non_snake_case)]
264#[must_use]
265pub unsafe fn EVP_PKEY_get1_EC_KEY(pkey: *mut EVP_PKEY) -> Result<NonNull<EC_KEY>, BoringError> {
266 ptr_or_err("EVP_PKEY_get1_EC_KEY", ffi::EVP_PKEY_get1_EC_KEY(pkey))
267}
268
269#[allow(non_snake_case)]
270#[must_use]
271pub unsafe fn EVP_PKEY_get1_RSA(pkey: *mut EVP_PKEY) -> Result<NonNull<RSA>, BoringError> {
272 ptr_or_err("EVP_PKEY_get1_RSA", ffi::EVP_PKEY_get1_RSA(pkey))
273}
274
275#[allow(non_snake_case)]
276#[allow(clippy::too_many_arguments)]
277#[must_use]
278pub unsafe fn EVP_PBE_scrypt(
279 password: *const c_char,
280 password_len: usize,
281 salt: *const u8,
282 salt_len: usize,
283 N: u64,
284 r: u64,
285 p: u64,
286 max_mem: usize,
287 out_key: *mut u8,
288 key_len: usize,
289) -> Result<(), BoringError> {
290 one_or_err(
291 "EVP_PBE_scrypt",
292 ffi::EVP_PBE_scrypt(
293 password,
294 password_len,
295 salt,
296 salt_len,
297 N,
298 r,
299 p,
300 max_mem,
301 out_key,
302 key_len,
303 ),
304 )
305}
306
307#[cfg(feature = "kdf")]
308#[allow(non_snake_case)]
309#[allow(clippy::too_many_arguments)]
310#[must_use]
311pub unsafe fn PKCS5_PBKDF2_HMAC(
312 password: *const c_char,
313 password_len: usize,
314 salt: *const u8,
315 salt_len: usize,
316 iterations: c_uint,
317 digest: *const EVP_MD,
318 key_len: usize,
319 out_key: *mut u8,
320) -> Result<(), BoringError> {
321 one_or_err(
322 "PKCS5_PBKDF2_HMAC",
323 ffi::PKCS5_PBKDF2_HMAC(
324 password,
325 password_len,
326 salt,
327 salt_len,
328 iterations,
329 digest,
330 key_len,
331 out_key,
332 ),
333 )
334}
335
336impl_traits!(HMAC_CTX, CDestruct => HMAC_CTX_cleanup);
345
346#[allow(non_snake_case)]
347#[must_use]
348pub unsafe fn HMAC_Init_ex(
349 ctx: *mut HMAC_CTX,
350 key: *const c_void,
351 key_len: usize,
352 md: *const EVP_MD,
353) -> Result<(), BoringError> {
354 one_or_err("HMAC_Init_ex", ffi::HMAC_Init_ex(ctx, key, key_len, md, ptr::null_mut()))
355}
356
357#[allow(non_snake_case)]
358pub unsafe fn HMAC_Update(ctx: *mut HMAC_CTX, data: *const u8, data_len: usize) {
359 assert_abort_eq!(ffi::HMAC_Update(ctx, data, data_len), 1);
361}
362
363#[allow(non_snake_case)]
364#[must_use]
365pub unsafe fn HMAC_Final(
366 ctx: *mut HMAC_CTX,
367 out: *mut u8,
368 out_len: *mut c_uint,
369) -> Result<(), BoringError> {
370 one_or_err("HMAC_Final", ffi::HMAC_Final(ctx, out, out_len))
371}
372
373#[allow(non_snake_case)]
374pub unsafe fn HMAC_CTX_copy(dest: *mut HMAC_CTX, src: *const HMAC_CTX) -> Result<(), BoringError> {
375 one_or_err("HMAC_CTX_copy", ffi::HMAC_CTX_copy(dest, src))
376}
377
378#[allow(non_snake_case)]
381pub unsafe fn RAND_bytes(buf: *mut u8, len: usize) {
382 assert_abort_eq!(ffi::RAND_bytes(buf, len), 1);
384}
385
386impl_traits!(RSA, CNew => RSA_new, CUpRef => RSA_up_ref, CFree => RSA_free);
389
390#[allow(non_snake_case)]
391#[must_use]
392pub unsafe fn RSA_generate_key_ex(
393 rsa: *mut RSA,
394 bits: c_int,
395 e: *const BIGNUM,
396 cb: *mut BN_GENCB,
397) -> Result<(), BoringError> {
398 one_or_err("RSA_generate_key_ex", ffi::RSA_generate_key_ex(rsa, bits, e, cb))
399}
400
401#[allow(non_snake_case)]
402#[must_use]
403pub unsafe fn RSA_marshal_private_key(cbb: *mut CBB, rsa: *const RSA) -> Result<(), BoringError> {
404 one_or_err("RSA_marshal_private_key", ffi::RSA_marshal_private_key(cbb, rsa))
405}
406
407#[allow(non_snake_case)]
408#[must_use]
409pub unsafe fn RSA_parse_private_key(cbs: *mut CBS) -> Result<NonNull<RSA>, BoringError> {
410 ptr_or_err("RSA_parse_private_key", ffi::RSA_parse_private_key(cbs))
411}
412
413#[cfg(feature = "rsa-pkcs1v15")]
414#[allow(non_snake_case)]
415#[must_use]
416pub unsafe fn RSA_sign(
417 hash_nid: c_int,
418 in_: *const u8,
419 in_len: usize,
420 out: *mut u8,
421 out_len: *mut c_uint,
422 key: *mut RSA,
423) -> Result<(), BoringError> {
424 one_or_err("RSA_sign", ffi::RSA_sign(hash_nid, in_, in_len, out, out_len, key))
425}
426
427#[allow(non_snake_case)]
428#[must_use]
429pub unsafe fn RSA_sign_pss_mgf1(
430 rsa: *mut RSA,
431 out_len: *mut usize,
432 out: *mut u8,
433 max_out: usize,
434 in_: *const u8,
435 in_len: usize,
436 md: *const EVP_MD,
437 mgf1_md: *const EVP_MD,
438 salt_len: c_int,
439) -> Result<(), BoringError> {
440 one_or_err(
441 "RSA_sign_pss_mgf1",
442 ffi::RSA_sign_pss_mgf1(rsa, out_len, out, max_out, in_, in_len, md, mgf1_md, salt_len),
443 )
444}
445
446#[allow(non_snake_case)]
447#[must_use]
448pub unsafe fn RSA_size(key: *const RSA) -> Result<NonZeroUsize, BoringError> {
449 NonZeroUsize::new(ffi::RSA_size(key).try_into().unwrap_abort())
450 .ok_or_else(|| BoringError::consume_stack("RSA_size"))
451}
452
453#[cfg(feature = "rsa-pkcs1v15")]
454#[allow(non_snake_case)]
455#[must_use]
456pub unsafe fn RSA_verify(
457 hash_nid: c_int,
458 msg: *const u8,
459 msg_len: usize,
460 sig: *const u8,
461 sig_len: usize,
462 rsa: *mut RSA,
463) -> bool {
464 match ffi::RSA_verify(hash_nid, msg, msg_len, sig, sig_len, rsa) {
465 0 => false,
466 1 => true,
467 _ => unreachable_abort!(),
469 }
470}
471
472#[allow(non_snake_case)]
473#[must_use]
474pub unsafe fn RSA_verify_pss_mgf1(
475 rsa: *mut RSA,
476 msg: *const u8,
477 msg_len: usize,
478 md: *const EVP_MD,
479 mgf1_md: *const EVP_MD,
480 salt_len: c_int,
481 sig: *const u8,
482 sig_len: usize,
483) -> bool {
484 match ffi::RSA_verify_pss_mgf1(rsa, msg, msg_len, md, mgf1_md, salt_len, sig, sig_len) {
485 0 => false,
486 1 => true,
487 _ => unreachable_abort!(),
489 }
490}
491
492impl_traits!(RC4_KEY, CDestruct => _);
495
496unsafe impl CInit for ffi::MD5_CTX {
499 unsafe fn init(ctx: *mut Self) {
500 assert_abort_eq!(ffi::MD5_Init(ctx), 1);
502 }
503}
504
505#[allow(non_snake_case)]
506pub unsafe fn SHA384_Init(ctx: *mut SHA512_CTX) {
507 assert_abort_eq!(ffi::SHA384_Init(ctx), 1);
509}
510
511unsafe impl CInit for ffi::SHA_CTX {
514 unsafe fn init(ctx: *mut Self) {
515 assert_abort_eq!(ffi::SHA1_Init(ctx), 1);
517 }
518}
519unsafe impl CInit for ffi::SHA256_CTX {
520 unsafe fn init(ctx: *mut Self) {
521 assert_abort_eq!(ffi::SHA256_Init(ctx), 1);
523 }
524}
525unsafe impl CInit for ffi::SHA512_CTX {
526 unsafe fn init(ctx: *mut Self) {
527 assert_abort_eq!(ffi::SHA512_Init(ctx), 1);
529 }
530}
531
532impl_traits!(MD5_CTX, CDestruct => _);
534impl_traits!(SHA_CTX, CDestruct => _);
535impl_traits!(SHA256_CTX, CDestruct => _);
536impl_traits!(SHA512_CTX, CDestruct => _);
537
538impl_hash_context!(MD5_CTX, MD5_Update, MD5_Final);
539impl_hash_context!(SHA_CTX, SHA1_Update, SHA1_Final);
540impl_hash_context!(SHA256_CTX, SHA256_Update, SHA256_Final);
541impl_hash_context!(SHA512_CTX, SHA384_Update, SHA384_Final);
542impl_hash_context!(SHA512_CTX, SHA512_Update, SHA512_Final);
543
544#[must_use]
549pub fn one_or_err<S: TryInto<usize>>(f: &str, code: S) -> Result<(), BoringError> {
550 if code.try_into().map(|code| code == 1).unwrap_or(false) {
554 Ok(())
555 } else {
556 Err(BoringError::consume_stack(f))
557 }
558}
559
560fn ptr_or_err<T>(f: &str, ptr: *mut T) -> Result<NonNull<T>, BoringError> {
563 NonNull::new(ptr).ok_or_else(|| BoringError::consume_stack(f))
564}