Skip to content

Commit 6126206

Browse files
author
Kiril Nikolov
committed
Add feature based on aws-lc-rs cryptographic library instead of ring
1 parent 193eb8d commit 6126206

File tree

8 files changed

+72
-10
lines changed

8 files changed

+72
-10
lines changed

.github/workflows/ci.yml

+3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ jobs:
6060
- name: Run tests no features
6161
run: cargo test --no-default-features
6262

63+
- name: Run tests no features
64+
run: cargo test --features fips
65+
6366
wasm:
6467
name: Run tests in wasm
6568
runs-on: ubuntu-latest

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ base64 = "0.21.0"
2626
# For PEM decoding
2727
pem = { version = "3", optional = true }
2828
simple_asn1 = { version = "0.6", optional = true }
29+
aws-lc-rs = { version = "1.6.2", optional = true }
2930

3031
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
3132
ring = { version = "0.17.4", features = ["std"] }
@@ -50,6 +51,7 @@ criterion = { version = "0.4", default-features = false }
5051
[features]
5152
default = ["use_pem"]
5253
use_pem = ["pem", "simple_asn1"]
54+
fips = ["aws-lc-rs"]
5355

5456
[[bench]]
5557
name = "jwt"

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,7 @@ you can add some leeway to the `iat`, `exp`, and `nbf` validation by setting the
166166
Last but not least, you will need to set the algorithm(s) allowed for this token if you are not using `HS256`.
167167

168168
Look at `examples/validation.rs` for a full working example.
169+
170+
## FIPS compliance
171+
172+
This library exports a feature that replaces `ring` with `aws_lc_rs` to achieve FIPS compliance. The name of the feature is `fips`.

src/crypto/ecdsa.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#[cfg(feature = "fips")]
2+
use aws_lc_rs as ring;
3+
4+
#[cfg(not(feature = "fips"))]
5+
use ring;
6+
17
use ring::{rand, signature};
28

39
use crate::algorithms::Algorithm;
@@ -26,6 +32,7 @@ pub(crate) fn alg_to_ec_signing(alg: Algorithm) -> &'static signature::EcdsaSign
2632

2733
/// The actual ECDSA signing + encoding
2834
/// The key needs to be in PKCS8 format
35+
#[cfg(not(feature = "fips"))]
2936
pub fn sign(
3037
alg: &'static signature::EcdsaSigningAlgorithm,
3138
key: &[u8],
@@ -36,3 +43,17 @@ pub fn sign(
3643
let out = signing_key.sign(&rng, message)?;
3744
Ok(b64_encode(out))
3845
}
46+
47+
/// The actual ECDSA signing + encoding
48+
/// The key needs to be in PKCS8 format
49+
#[cfg(feature = "fips")]
50+
pub fn sign(
51+
alg: &'static signature::EcdsaSigningAlgorithm,
52+
key: &[u8],
53+
message: &[u8],
54+
) -> Result<String> {
55+
let rng = rand::SystemRandom::new();
56+
let signing_key = signature::EcdsaKeyPair::from_pkcs8(alg, key)?;
57+
let out = signing_key.sign(&rng, message)?;
58+
Ok(b64_encode(out))
59+
}

src/crypto/eddsa.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
1-
use ring::signature;
1+
#[cfg(feature = "fips")]
2+
use aws_lc_rs as ring;
3+
4+
#[cfg(not(feature = "fips"))]
5+
use ring;
26

37
use crate::algorithms::Algorithm;
48
use crate::errors::Result;
59
use crate::serialization::b64_encode;
610

711
/// Only used internally when signing or validating EdDSA, to map from our enum to the Ring EdDSAParameters structs.
8-
pub(crate) fn alg_to_ec_verification(alg: Algorithm) -> &'static signature::EdDSAParameters {
12+
pub(crate) fn alg_to_ec_verification(alg: Algorithm) -> &'static ring::signature::EdDSAParameters {
913
// To support additional key subtypes, like Ed448, we would need to match on the JWK's ("crv")
1014
// parameter.
1115
match alg {
12-
Algorithm::EdDSA => &signature::ED25519,
16+
Algorithm::EdDSA => &ring::signature::ED25519,
1317
_ => unreachable!("Tried to get EdDSA alg for a non-EdDSA algorithm"),
1418
}
1519
}
1620

1721
/// The actual EdDSA signing + encoding
1822
/// The key needs to be in PKCS8 format
1923
pub fn sign(key: &[u8], message: &[u8]) -> Result<String> {
20-
let signing_key = signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(key)?;
24+
let signing_key = ring::signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(key)?;
2125
let out = signing_key.sign(message);
2226
Ok(b64_encode(out))
2327
}

src/crypto/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#[cfg(feature = "fips")]
2+
use aws_lc_rs as ring;
3+
4+
#[cfg(not(feature = "fips"))]
5+
use ring;
6+
17
use ring::constant_time::verify_slices_are_equal;
28
use ring::{hmac, signature};
39

src/crypto/rsa.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#[cfg(feature = "fips")]
2+
use aws_lc_rs as ring;
3+
4+
#[cfg(not(feature = "fips"))]
5+
use ring;
6+
17
use ring::{rand, signature};
28

39
use crate::algorithms::Algorithm;
@@ -41,7 +47,8 @@ pub(crate) fn sign(
4147
let key_pair = signature::RsaKeyPair::from_der(key)
4248
.map_err(|e| ErrorKind::InvalidRsaKey(e.to_string()))?;
4349

44-
let mut signature = vec![0; key_pair.public().modulus_len()];
50+
let mut signature = get_signature(&key_pair);
51+
4552
let rng = rand::SystemRandom::new();
4653
key_pair.sign(alg, &rng, message, &mut signature).map_err(|_| ErrorKind::RsaFailedSigning)?;
4754

@@ -60,3 +67,13 @@ pub(crate) fn verify_from_components(
6067
let res = pubkey.verify(alg, message, &signature_bytes);
6168
Ok(res.is_ok())
6269
}
70+
71+
#[cfg(feature = "fips")]
72+
fn get_signature(key_pair: &signature::RsaKeyPair) -> Vec<u8> {
73+
vec![0; key_pair.public_modulus_len()]
74+
}
75+
76+
#[cfg(not(feature = "fips"))]
77+
fn get_signature(key_pair: &signature::RsaKeyPair) -> Vec<u8> {
78+
vec![0; key_pair.public().modulus_len()]
79+
}

src/errors.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
#[cfg(feature = "fips")]
2+
use aws_lc_rs as ring;
3+
4+
#[cfg(not(feature = "fips"))]
5+
use ring;
16
use std::error::Error as StdError;
27
use std::fmt;
38
use std::result;
@@ -77,7 +82,7 @@ pub enum ErrorKind {
7782
/// Some of the text was invalid UTF-8
7883
Utf8(::std::string::FromUtf8Error),
7984
/// Something unspecified went wrong with crypto
80-
Crypto(::ring::error::Unspecified),
85+
Crypto(ring::error::Unspecified),
8186
}
8287

8388
impl StdError for Error {
@@ -159,14 +164,14 @@ impl From<::std::string::FromUtf8Error> for Error {
159164
}
160165
}
161166

162-
impl From<::ring::error::Unspecified> for Error {
163-
fn from(err: ::ring::error::Unspecified) -> Error {
167+
impl From<ring::error::Unspecified> for Error {
168+
fn from(err: ring::error::Unspecified) -> Error {
164169
new_error(ErrorKind::Crypto(err))
165170
}
166171
}
167172

168-
impl From<::ring::error::KeyRejected> for Error {
169-
fn from(_err: ::ring::error::KeyRejected) -> Error {
173+
impl From<ring::error::KeyRejected> for Error {
174+
fn from(_err: ring::error::KeyRejected) -> Error {
170175
new_error(ErrorKind::InvalidEcdsaKey)
171176
}
172177
}

0 commit comments

Comments
 (0)