mundane/
lib.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Cryptography in Rust.
6//!
7//! Mundane is a Rust cryptography library backed by BoringSSL that is difficult
8//! to misuse, ergonomic, and performant (in that order).
9//!
10//! # Features
11//!
12//! By default, Mundane provides only high-level cryptographic primitives.
13//! Unless you are implementing cryptographic protocols, these high-level
14//! primitives should be all you need. However, if you are sure that you need
15//! something lower level, Mundane provides features to enable a number of
16//! different low level primitives.
17//!
18//! WARNING: Being low level, these primitives provide the programmer with more
19//! degrees of freedom. There are more conditions that the programmer must meet
20//! in order to guarantee security, and thus more ways for the programmer to
21//! shoot themself in the foot. Please only use these primitives if you're aware
22//! of the risks and are comfortable with the responsibility of using them
23//! correctly!
24//!
25//! **Features**
26//!
27//! | Name           | Description                         |
28//! | -------------- | ------------------------------------|
29//! | `kdf`          | Key derivation functions            |
30//! | `bytes`        | Low-level operations on byte slices |
31//! | `rsa-pkcs1v15` | RSA-PKCS1v1.5 signatures            |
32//!
33//! # Insecure Operations
34//!
35//! Mundane supports one additional feature not listed in the previous section:
36//! `insecure`. This enables some cryptographic primitives which are today
37//! considered insecure. These should only be used for compatibility with legacy
38//! systems - never in new systems! When the `insecure` feature is used, an
39//! `insecure` module is added to the crate root. All insecure primitives are
40//! exposed through this module.
41
42#![deny(missing_docs)]
43// just in case we forget to add #[forbid(unsafe_code)] on new module
44// definitions
45#![deny(unsafe_code)]
46
47#[macro_use]
48mod macros;
49
50extern crate bssl_sys;
51
52// Forbid unsafe code except in the boringssl module.
53#[allow(unsafe_code)]
54mod boringssl;
55#[cfg(any(doc, feature = "bytes"))]
56#[forbid(unsafe_code)]
57pub mod bytes;
58#[forbid(unsafe_code)]
59pub mod hash;
60#[forbid(unsafe_code)]
61pub mod hmac;
62#[cfg(any(doc, feature = "insecure"))]
63#[forbid(unsafe_code)]
64pub mod insecure;
65#[cfg(any(doc, feature = "insecure"))]
66#[forbid(unsafe_code)]
67mod insecure_rc4;
68#[cfg(any(doc, feature = "kdf"))]
69#[forbid(unsafe_code)]
70pub mod kdf;
71#[forbid(unsafe_code)]
72pub mod password;
73#[forbid(unsafe_code)]
74pub mod public;
75#[forbid(unsafe_code)]
76mod util;
77
78use std::fmt::{self, Debug, Display, Formatter};
79
80use boringssl::BoringError;
81
82/// Errors generated by this crate.
83///
84/// `Error` represents two types of errors: errors generated by BoringSSL, and
85/// errors generated by the Rust code in this crate. When printed (using either
86/// `Display` or `Debug`), BoringSSL errors are of the form `boringssl:
87/// <error>`, while errors generated by Rust code are of the form `<error>`.
88pub struct Error(ErrorInner);
89
90impl Error {
91    fn new(s: String) -> Error {
92        Error(ErrorInner::Mundane(s))
93    }
94}
95
96#[doc(hidden)]
97impl From<BoringError> for Error {
98    fn from(err: BoringError) -> Error {
99        Error(ErrorInner::Boring(err))
100    }
101}
102
103impl Display for Error {
104    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
105        match &self.0 {
106            ErrorInner::Mundane(err) => write!(f, "{}", err),
107            ErrorInner::Boring(err) => write!(f, "boringssl: {}", err),
108        }
109    }
110}
111
112impl Debug for Error {
113    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
114        match &self.0 {
115            ErrorInner::Mundane(err) => write!(f, "{}", err),
116
117            ErrorInner::Boring(err) => {
118                if err.stack_depth() == 1 {
119                    // Either there was no stack trace, or the stack trace only
120                    // contained a single frame. In either case, don't bother
121                    // printing a preceding newline.
122                    write!(f, "boringssl: {:?}", err)
123                } else {
124                    // There's a multi-line stack trace, so print a preceding
125                    // newline.
126                    write!(f, "boringssl:\n{:?}", err)
127                }
128            }
129        }
130    }
131}
132
133impl std::error::Error for Error {}
134
135enum ErrorInner {
136    Mundane(String),
137    Boring(BoringError),
138}
139
140#[cfg(test)]
141mod tests {
142    use super::Error;
143
144    #[test]
145    fn test_send() {
146        fn assert_send<T: Send>() {}
147        assert_send::<Error>();
148    }
149
150    #[test]
151    fn test_sync() {
152        fn assert_sync<T: Sync>() {}
153        assert_sync::<Error>();
154    }
155}