From 58c4a4b18cd9ad5521707efcd47654c27892e782 Mon Sep 17 00:00:00 2001 From: Dana Keeler Date: Fri, 30 Oct 2020 13:09:50 -0700 Subject: [PATCH] fixes #138: adds and implements a CryptographyProvider trait --- .gitignore | 1 + Cargo.toml | 3 ++- src/crypto.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/errors.rs | 16 ++++++++++++ src/lib.rs | 4 +++ 5 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/crypto.rs diff --git a/.gitignore b/.gitignore index 148e97ce..ee645285 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # will have compiled files and executables /target/ **/*.rs.bk +**/.*.swp # Fuzzing corpuses should be explicitly updated fuzz/corpus/ diff --git a/Cargo.toml b/Cargo.toml index f6527951..3ce334e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "authenticator" version = "0.3.1" -authors = ["J.C. Jones ", "Tim Taubert ", "Kyle Machulis "] +authors = ["J.C. Jones ", "Tim Taubert ", "Kyle Machulis ", "Dana Keeler "] keywords = ["ctap2", "u2f", "fido", "webauthn"] categories = ["cryptography", "hardware-support", "os"] repository = "https://github.com/mozilla/authenticator-rs/" @@ -51,6 +51,7 @@ serde = { version = "1.0", optional = true, features = ["derive"] } serde_json = { version = "1.0", optional = true } bytes = { version = "0.5", optional = true, features = ["serde"] } base64 = { version = "^0.10", optional = true } +ring = "0.16" [dev-dependencies] sha2 = "^0.8.2" diff --git a/src/crypto.rs b/src/crypto.rs new file mode 100644 index 00000000..b45920d6 --- /dev/null +++ b/src/crypto.rs @@ -0,0 +1,67 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use crate::ring::rand::SecureRandom; +use crate::ring::signature::KeyPair; +use crate::Result; + +pub trait CryptoProvider { + fn new_key(&self) -> Result>; + fn random_bytes(&self, destination: &mut [u8]) -> Result<()>; +} + +pub trait Key { + fn sign(&self, data: &[u8]) -> Result>; + fn public(&self) -> Vec; +} + +pub struct RingCryptoProvider { + rng: ring::rand::SystemRandom, +} + +impl RingCryptoProvider { + pub fn new() -> RingCryptoProvider { + RingCryptoProvider { + rng: ring::rand::SystemRandom::new(), + } + } +} + +impl CryptoProvider for RingCryptoProvider { + fn new_key(&self) -> Result> { + let pkcs8 = ring::signature::EcdsaKeyPair::generate_pkcs8( + &ring::signature::ECDSA_P256_SHA256_ASN1_SIGNING, + &self.rng, + )?; + let handle = ring::signature::EcdsaKeyPair::from_pkcs8( + &ring::signature::ECDSA_P256_SHA256_ASN1_SIGNING, + pkcs8.as_ref(), + )?; + Ok(Box::new(RingKey { + handle, + rng: self.rng.clone(), + })) + } + + fn random_bytes(&self, destination: &mut [u8]) -> Result<()> { + self.rng.fill(destination)?; + Ok(()) + } +} + +pub struct RingKey { + handle: ring::signature::EcdsaKeyPair, + rng: ring::rand::SystemRandom, +} + +impl Key for RingKey { + fn sign(&self, data: &[u8]) -> Result> { + let signature = self.handle.sign(&self.rng, data)?; + Ok(signature.as_ref().to_vec()) + } + + fn public(&self) -> Vec { + self.handle.public_key().as_ref().to_vec() + } +} diff --git a/src/errors.rs b/src/errors.rs index ee63cfac..46f38efc 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -20,6 +20,7 @@ pub enum AuthenticatorError { InternalError(String), U2FToken(U2FTokenError), Custom(String), + CryptoError, } impl AuthenticatorError { @@ -50,6 +51,9 @@ impl fmt::Display for AuthenticatorError { write!(f, "A u2f token error occurred {:?}", err) } AuthenticatorError::Custom(ref err) => write!(f, "A custom error occurred {:?}", err), + AuthenticatorError::CryptoError => { + write!(f, "The cryptography implementation encountered an error") + } } } } @@ -66,6 +70,18 @@ impl From> for AuthenticatorError { } } +impl From for AuthenticatorError { + fn from(_: ring::error::Unspecified) -> Self { + AuthenticatorError::CryptoError + } +} + +impl From for AuthenticatorError { + fn from(_: ring::error::KeyRejected) -> Self { + AuthenticatorError::CryptoError + } +} + #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum U2FTokenError { Unknown = 1, diff --git a/src/lib.rs b/src/lib.rs index cfe82deb..6a62e624 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,6 +61,8 @@ extern crate runloop; #[macro_use] extern crate bitflags; +extern crate ring; + pub mod authenticatorservice; mod consts; mod statemachine; @@ -77,6 +79,8 @@ pub mod errors; pub mod statecallback; mod virtualdevices; +mod crypto; + // Keep this in sync with the constants in u2fhid-capi.h. bitflags! { pub struct RegisterFlags: u64 {