Skip to content

Commit

Permalink
Add support for RSA-PSS signature verification
Browse files Browse the repository at this point in the history
  • Loading branch information
nthuemmel-scontain authored and chifflier committed Apr 4, 2024
1 parent e77fbc8 commit a1ce88a
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 3 deletions.
7 changes: 7 additions & 0 deletions assets/rsa-pss/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Generating Test Certificates

```shell
openssl req -new -x509 -newkey rsa:2048 -keyout /dev/null -nodes -sigopt rsa_padding_mode:pss -sha256 -sigopt rsa_pss_saltlen:-1 -outform der -out self_signed_sha256.der -batch
openssl req -new -x509 -newkey rsa:2048 -keyout /dev/null -nodes -sigopt rsa_padding_mode:pss -sha384 -sigopt rsa_pss_saltlen:-1 -outform der -out self_signed_sha384.der -batch
openssl req -new -x509 -newkey rsa:2048 -keyout /dev/null -nodes -sigopt rsa_padding_mode:pss -sha512 -sigopt rsa_pss_saltlen:-1 -outform der -out self_signed_sha512.der -batch
```
Binary file added assets/rsa-pss/self_signed_sha256.der
Binary file not shown.
Binary file added assets/rsa-pss/self_signed_sha384.der
Binary file not shown.
Binary file added assets/rsa-pss/self_signed_sha512.der
Binary file not shown.
41 changes: 38 additions & 3 deletions src/verify.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use crate::prelude::*;
use asn1_rs::BitString;
use crate::signature_algorithm::RsaSsaPssParams;
use asn1_rs::{Any, BitString};
use oid_registry::{
OID_EC_P256, OID_NIST_EC_P384, OID_PKCS1_SHA1WITHRSA, OID_PKCS1_SHA256WITHRSA,
OID_EC_P256, OID_NIST_EC_P384, OID_NIST_HASH_SHA256, OID_NIST_HASH_SHA384,
OID_NIST_HASH_SHA512, OID_PKCS1_RSASSAPSS, OID_PKCS1_SHA1WITHRSA, OID_PKCS1_SHA256WITHRSA,
OID_PKCS1_SHA384WITHRSA, OID_PKCS1_SHA512WITHRSA, OID_SHA1_WITH_RSA, OID_SIG_ECDSA_WITH_SHA256,
OID_SIG_ECDSA_WITH_SHA384, OID_SIG_ED25519,
};
use std::convert::TryFrom;

/// Verify the cryptographic signature of the raw data (can be a certificate, a CRL or a CSR).
///
Expand All @@ -18,7 +21,12 @@ pub fn verify_signature(
raw_data: &[u8],
) -> Result<(), X509Error> {
use ring::signature;
let signature_algorithm = &signature_algorithm.algorithm;

let AlgorithmIdentifier {
algorithm: signature_algorithm,
parameters: signature_algorithm_parameters,
} = &signature_algorithm;

// identify verification algorithm
let verification_alg: &dyn signature::VerificationAlgorithm = if *signature_algorithm
== OID_PKCS1_SHA1WITHRSA
Expand All @@ -31,6 +39,9 @@ pub fn verify_signature(
&signature::RSA_PKCS1_2048_8192_SHA384
} else if *signature_algorithm == OID_PKCS1_SHA512WITHRSA {
&signature::RSA_PKCS1_2048_8192_SHA512
} else if *signature_algorithm == OID_PKCS1_RSASSAPSS {
get_rsa_pss_verification_algo(signature_algorithm_parameters)
.ok_or(X509Error::SignatureUnsupportedAlgorithm)?
} else if *signature_algorithm == OID_SIG_ECDSA_WITH_SHA256 {
get_ec_curve_sha(&public_key.algorithm, 256)
.ok_or(X509Error::SignatureUnsupportedAlgorithm)?
Expand Down Expand Up @@ -76,3 +87,27 @@ fn get_ec_curve_sha(
None
}
}

/// Find the verification algorithm for the given RSA-PSS parameters
///
/// Not all algorithms are supported, we are limited to what `ring` supports.
/// Notably, the SHA-1 hash algorithm is not supported.
fn get_rsa_pss_verification_algo(
params: &Option<Any>,
) -> Option<&'static dyn ring::signature::VerificationAlgorithm> {
use ring::signature;

let params = params.as_ref()?;
let params = RsaSsaPssParams::try_from(params).ok()?;
let hash_algo = params.hash_algorithm_oid();

if *hash_algo == OID_NIST_HASH_SHA256 {
Some(&signature::RSA_PSS_2048_8192_SHA256)
} else if *hash_algo == OID_NIST_HASH_SHA384 {
Some(&signature::RSA_PSS_2048_8192_SHA384)
} else if *hash_algo == OID_NIST_HASH_SHA512 {
Some(&signature::RSA_PSS_2048_8192_SHA512)
} else {
None
}
}
34 changes: 34 additions & 0 deletions tests/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,37 @@ fn test_signature_verification_ed25519() {
eprintln!("Verification: {:?}", res);
assert!(res.is_ok());
}

static RSA_PSS_SELF_SIGNED_SHA256: &[u8] =
include_bytes!("../assets/rsa-pss/self_signed_sha256.der");
static RSA_PSS_SELF_SIGNED_SHA384: &[u8] =
include_bytes!("../assets/rsa-pss/self_signed_sha384.der");
static RSA_PSS_SELF_SIGNED_SHA512: &[u8] =
include_bytes!("../assets/rsa-pss/self_signed_sha512.der");

#[test]
fn test_signature_verification_rsa_pss_sha256() {
let (_, x509) =
parse_x509_certificate(RSA_PSS_SELF_SIGNED_SHA256).expect("could not parse certificate");
let res = x509.verify_signature(None);
eprintln!("Verification: {:?}", res);
assert!(res.is_ok());
}

#[test]
fn test_signature_verification_rsa_pss_sha384() {
let (_, x509) =
parse_x509_certificate(RSA_PSS_SELF_SIGNED_SHA384).expect("could not parse certificate");
let res = x509.verify_signature(None);
eprintln!("Verification: {:?}", res);
assert!(res.is_ok());
}

#[test]
fn test_signature_verification_rsa_pss_sha512() {
let (_, x509) =
parse_x509_certificate(RSA_PSS_SELF_SIGNED_SHA512).expect("could not parse certificate");
let res = x509.verify_signature(None);
eprintln!("Verification: {:?}", res);
assert!(res.is_ok());
}

0 comments on commit a1ce88a

Please sign in to comment.