| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| //! Cryptography in Rust. |
| //! |
| //! Mundane is a Rust cryptography library backed by BoringSSL that is difficult |
| //! to misuse, ergonomic, and performant (in that order). |
| //! |
| //! # Features |
| //! |
| //! By default, Mundane provides only high-level cryptographic primitives. |
| //! Unless you are implementing cryptographic protocols, these high-level |
| //! primitives should be all you need. However, if you are sure that you need |
| //! something lower level, Mundane provides features to enable a number of |
| //! different low level primitives. |
| //! |
| //! WARNING: Being low level, these primitives provide the programmer with more |
| //! degrees of freedom. There are more conditions that the programmer must meet |
| //! in order to guarantee security, and thus more ways for the programmer to |
| //! shoot themself in the foot. Please only use these primitives if you're aware |
| //! of the risks and are comfortable with the responsibility of using them |
| //! correctly! |
| //! |
| //! **Features** |
| //! |
| //! | Name | Description | |
| //! | -------------- | ------------------------------------| |
| //! | `kdf` | Key derivation functions | |
| //! | `bytes` | Low-level operations on byte slices | |
| //! | `rsa-pkcs1v15` | RSA-PKCS1v1.5 signatures | |
| //! |
| //! # Insecure Operations |
| //! |
| //! Mundane supports one additional feature not listed in the previous section: |
| //! `insecure`. This enables some cryptographic primitives which are today |
| //! considered insecure. These should only be used for compatibility with legacy |
| //! systems - never in new systems! When the `insecure` feature is used, an |
| //! `insecure` module is added to the crate root. All insecure primitives are |
| //! exposed through this module. |
| |
| #![deny(missing_docs)] |
| #![deny(warnings)] |
| // just in case we forget to add #[forbid(unsafe_code)] on new module |
| // definitions |
| #![deny(unsafe_code)] |
| |
| #[macro_use] |
| mod macros; |
| |
| extern crate boringssl_sys; |
| |
| // Forbid unsafe code except in the boringssl module. |
| #[allow(unsafe_code)] |
| mod boringssl; |
| #[cfg(any(doc, feature = "bytes"))] |
| #[forbid(unsafe_code)] |
| pub mod bytes; |
| #[forbid(unsafe_code)] |
| pub mod hash; |
| #[forbid(unsafe_code)] |
| pub mod hmac; |
| #[cfg(any(doc, feature = "insecure"))] |
| #[forbid(unsafe_code)] |
| pub mod insecure; |
| #[cfg(any(doc, feature = "insecure"))] |
| #[forbid(unsafe_code)] |
| mod insecure_rc4; |
| #[cfg(any(doc, feature = "kdf"))] |
| #[forbid(unsafe_code)] |
| pub mod kdf; |
| #[forbid(unsafe_code)] |
| pub mod password; |
| #[forbid(unsafe_code)] |
| pub mod public; |
| #[forbid(unsafe_code)] |
| mod util; |
| |
| use std::fmt::{self, Debug, Display, Formatter}; |
| |
| use boringssl::BoringError; |
| |
| /// Errors generated by this crate. |
| /// |
| /// `Error` represents two types of errors: errors generated by BoringSSL, and |
| /// errors generated by the Rust code in this crate. When printed (using either |
| /// `Display` or `Debug`), BoringSSL errors are of the form `boringssl: |
| /// <error>`, while errors generated by Rust code are of the form `<error>`. |
| pub struct Error(ErrorInner); |
| |
| impl Error { |
| fn new(s: String) -> Error { |
| Error(ErrorInner::Mundane(s)) |
| } |
| } |
| |
| #[doc(hidden)] |
| impl From<BoringError> for Error { |
| fn from(err: BoringError) -> Error { |
| Error(ErrorInner::Boring(err)) |
| } |
| } |
| |
| impl Display for Error { |
| fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { |
| match &self.0 { |
| ErrorInner::Mundane(err) => write!(f, "{}", err), |
| ErrorInner::Boring(err) => write!(f, "boringssl: {}", err), |
| } |
| } |
| } |
| |
| impl Debug for Error { |
| fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { |
| match &self.0 { |
| ErrorInner::Mundane(err) => write!(f, "{}", err), |
| |
| ErrorInner::Boring(err) => { |
| if err.stack_depth() == 1 { |
| // Either there was no stack trace, or the stack trace only |
| // contained a single frame. In either case, don't bother |
| // printing a preceding newline. |
| write!(f, "boringssl: {:?}", err) |
| } else { |
| // There's a multi-line stack trace, so print a preceding |
| // newline. |
| write!(f, "boringssl:\n{:?}", err) |
| } |
| } |
| } |
| } |
| } |
| |
| impl std::error::Error for Error {} |
| |
| enum ErrorInner { |
| Mundane(String), |
| Boring(BoringError), |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::Error; |
| |
| #[test] |
| fn test_send() { |
| fn assert_send<T: Send>() {} |
| assert_send::<Error>(); |
| } |
| |
| #[test] |
| fn test_sync() { |
| fn assert_sync<T: Sync>() {} |
| assert_sync::<Error>(); |
| } |
| } |