diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000..050dec5 --- /dev/null +++ b/clippy.toml @@ -0,0 +1 @@ +allowed-duplicate-crates = ["base64", "syn"] diff --git a/src/subcommands/create_csr.rs b/src/subcommands/create_csr.rs index 6b6c39a..6af10a2 100644 --- a/src/subcommands/create_csr.rs +++ b/src/subcommands/create_csr.rs @@ -182,10 +182,17 @@ impl CreateCsr { error!("Signing key specifies raw signing only, which is not supported for certificate requests."); Err(ToolErrorKind::NotSupported.into()) } - AsymmetricSignature::RsaPss { .. } => { - error!("Signing key specifies RSA PSS scheme, which is not supported for certificate requests."); - Err(ToolErrorKind::NotSupported.into()) - } + AsymmetricSignature::RsaPss { hash_alg } => match hash_alg { + SignHash::Specific(Hash::Sha256) => Ok(&PKCS_RSA_SHA256), + SignHash::Specific(Hash::Sha384) => Ok(&PKCS_RSA_SHA384), + SignHash::Specific(Hash::Sha512) => Ok(&PKCS_RSA_SHA512), + SignHash::Any => Ok(&PKCS_RSA_SHA256), // Default hash algorithm for the tool. + _ => { + // The algorithm is specific, but not one that RCGEN can use, so fail the operation. + error!("Signing key requires use of hashing algorithm ({:?}), which is not supported for certificate requests.", alg); + Err(ToolErrorKind::NotSupported.into()) + } + }, AsymmetricSignature::Ecdsa { hash_alg } => { if !matches!( attributes.key_type, diff --git a/src/subcommands/create_rsa_key.rs b/src/subcommands/create_rsa_key.rs index 2ffdfec..060cff2 100644 --- a/src/subcommands/create_rsa_key.rs +++ b/src/subcommands/create_rsa_key.rs @@ -24,9 +24,14 @@ pub struct CreateRsaKey { /// This command creates RSA encryption keys by default. Supply this flag to create a signing key instead. /// Signing keys, by default, will specify the SHA-256 hash algorithm and use PKCS#1 v1.5. + /// This has priority over ("r", "for-signing-pss") option. #[structopt(short = 's', long = "for-signing")] is_for_signing: bool, + /// Supply this flag to create a signing key with PSS scheme and SHA-256 hash algorithm. + #[structopt(short = 'r', long = "for-signing-pss")] + is_for_signing_pss: bool, + /// Specifies the size (strength) of the key in bits. The default size for RSA keys is 2048 bits. #[structopt(short = 'b', long = "bits")] bits: Option, @@ -41,7 +46,8 @@ impl CreateRsaKey { /// Exports a key. pub fn run(&self, basic_client: BasicClient) -> Result<()> { let policy = if self.is_for_signing { - info!("Creating RSA signing key..."); + // If both "-s" and "-r" flags are set, then "-s" takes precedence + info!("Creating RSA signing key with PKCS1 v1.5 scheme..."); Policy { usage_flags: { let mut usage_flags = UsageFlags::default(); @@ -57,6 +63,23 @@ impl CreateRsaKey { } .into(), } + } else if self.is_for_signing_pss { + info!("Creating RSA signing key with PSS scheme..."); + Policy { + usage_flags: { + let mut usage_flags = UsageFlags::default(); + let _ = usage_flags + .set_sign_hash() + .set_verify_hash() + .set_sign_message() + .set_verify_message(); + usage_flags + }, + permitted_algorithms: AsymmetricSignature::RsaPss { + hash_alg: SignHash::Specific(Hash::Sha256), + } + .into(), + } } else { info!("Creating RSA encryption key..."); Policy { diff --git a/tests/parsec-cli-tests.sh b/tests/parsec-cli-tests.sh index 3fbb961..b9959e7 100755 --- a/tests/parsec-cli-tests.sh +++ b/tests/parsec-cli-tests.sh @@ -45,11 +45,13 @@ delete_key() { create_key() { # $1 - key type ("RSA" or "ECC") # $2 - key name -# $3 - key usage ("SIGN" or "OAEP"), only consulted if $1 == "RSA" +# $3 - key usage ("SIGN_PKCS1_V15", "SIGN_PSS" or "OAEP"), only consulted if $1 == "RSA" KEY="$2" - if [ "$3" = "SIGN" -a "$1" = "RSA" ]; then + if [ "$3" = "SIGN_PKCS1_V15" -a "$1" = "RSA" ]; then EXTRA_CREATE_KEY_ARGS="--for-signing" + elif [ "$3" = "SIGN_PSS" -a "$1" = "RSA" ]; then + EXTRA_CREATE_KEY_ARGS="--for-signing-pss" elif [ "$3" = "OAEP" -a "$1" = "RSA" ]; then EXTRA_CREATE_KEY_ARGS="--oaep" else @@ -96,9 +98,10 @@ test_crypto_provider() { test_encryption "OAEP" test_decryption "OAEP" fi - test_signing "RSA" + test_signing "ECC" - test_csr "RSA" + test_csr "RSA" "SIGN_PKCS1_V15" + test_csr "RSA" "SIGN_PSS" test_csr "ECC" test_rsa_key_bits test_rsa_key_bits 1024 @@ -180,10 +183,16 @@ test_decryption() { test_signing() { # $1 - key type ("RSA" or "ECC") +# $2 - RSA scheme ("SIGN_PKCS1_V15" or "SIGN_PSS") KEY="anta-key-sign" TEST_STR="$(date) Parsec signature test" - create_key $1 $KEY "SIGN" + create_key $1 $KEY $2 + + EXTRA_VERIFY_ARGS= + if [ "$2" = "SIGN_PSS" -a "$1" = "RSA" ]; then + EXTRA_VERIFY_ARGS="-sigopt rsa_padding_mode:pss" + fi # If the key was successfully created and exported if [ -s ${MY_TMP}/${KEY}.pem ]; then @@ -200,7 +209,7 @@ test_signing() { run_cmd $OPENSSL base64 -d -a -A -in ${MY_TMP}/${KEY}.sign -out ${MY_TMP}/${KEY}.bin printf "$TEST_STR" >${MY_TMP}/${KEY}.test_str - run_cmd $OPENSSL dgst -sha256 -verify ${MY_TMP}/${KEY}.pem \ + run_cmd $OPENSSL dgst -sha256 -verify ${MY_TMP}/${KEY}.pem ${EXTRA_VERIFY_ARGS} \ -signature ${MY_TMP}/${KEY}.bin ${MY_TMP}/${KEY}.test_str fi @@ -209,13 +218,14 @@ test_signing() { test_csr() { # $1 - key type ("RSA" or "ECC") +# $2 - RSA scheme ("SIGN_PKCS1_V15" or "SIGN_PSS") KEY="anta-key-csr" TEST_CN="parallaxsecond.com" TEST_SAN="localhost" TEST_SERIAL="EZ4U2CIXL" # CSR creation needs a signing key. - create_key $1 $KEY "SIGN" + create_key $1 $KEY $2 # If the key was successfully created and exported if [ -s ${MY_TMP}/${KEY}.pem ]; then @@ -287,6 +297,9 @@ while [ "$#" -gt 0 ]; do --no-v1.5 ) NO_PKCS1_V15="true" ;; + --no-pss ) + NO_PSS="true" + ;; --rsa-key-size ) shift; RSA_KEY_SIZE=$1 ;;