Skip to content

Commit 54cc197

Browse files
authored
Merge pull request parallaxsecond#241 from ionut-arm/soft-pkcs11
Allow software operations in PKCS11 provider
2 parents 40bf768 + 61d207b commit 54cc197

File tree

14 files changed

+244
-15
lines changed

14 files changed

+244
-15
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ features = ["docs"]
6666
default = []
6767
no-parsec-user-and-clients-group = []
6868
mbed-crypto-provider = ["psa-crypto"]
69-
pkcs11-provider = ["pkcs11", "picky-asn1-der", "picky-asn1", "picky-asn1-x509"]
69+
pkcs11-provider = ["pkcs11", "picky-asn1-der", "picky-asn1", "picky-asn1-x509", "psa-crypto"]
7070
tpm-provider = ["tss-esapi", "picky-asn1-der", "picky-asn1", "picky-asn1-x509"]
7171
all-providers = ["tpm-provider", "pkcs11-provider", "mbed-crypto-provider"]
7272
docs = ["pkcs11-provider", "tpm-provider", "tss-esapi/docs", "mbed-crypto-provider"]

ci.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ pgrep -f target/debug/parsec >/dev/null
137137
if [ "$PROVIDER_NAME" = "all" ]; then
138138
echo "Execute all-providers tests"
139139
RUST_BACKTRACE=1 cargo test $TEST_FEATURES --manifest-path ./e2e_tests/Cargo.toml all_providers
140-
RUST_BACKTRACE=1 cargo test $TEST_FEATURES --manifest-path ./e2e_tests/Cargo.toml config
140+
RUST_BACKTRACE=1 cargo test $TEST_FEATURES --manifest-path ./e2e_tests/Cargo.toml config -- --test-threads=1
141141
else
142142
# Per provider tests
143143
echo "Execute normal tests"

config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ key_info_manager = "on-disk-manager"
8080
# (Optional) User pin for authentication with the specific slot. If not set, no authentication will
8181
# be used.
8282
#user_pin = "123456"
83+
# (Optional) Control whether missing public key operation (such as verifying signatures or asymmetric
84+
# encryption) are fully performed in software.
85+
#software_public_operations = false
8386

8487
# Example of a TPM provider configuration
8588
#[[provider]]

e2e_tests/provider_cfg/pkcs11/Dockerfile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ FROM ubuntu:18.04
22

33
RUN apt-get update && \
44
apt-get install -y wget automake autoconf libtool pkg-config && \
5-
apt-get install -y curl libssl-dev libgcc1
5+
apt-get install -y curl libssl-dev libgcc1 && \
6+
apt-get install -y git make gcc python3 python curl wget libgcc1 cmake && \
7+
# These libraries are needed for bindgen as it uses libclang.so
8+
apt-get install -y clang libclang-dev && \
9+
# Needed for Open SSL
10+
apt-get install -y pkg-config libssl-dev
611

712
WORKDIR /tmp
813
RUN wget https://github.com/opendnssec/SoftHSMv2/archive/2.5.0.tar.gz

e2e_tests/provider_cfg/pkcs11/config.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ provider_type = "Pkcs11"
2222
key_info_manager = "on-disk-manager"
2323
library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
2424
user_pin = "123456"
25+
software_public_operations = false
2526
# The slot_number mandatory field is going to replace the following line with a valid number
2627
# slot_number

e2e_tests/tests/config/mod.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,56 @@ fn list_providers() {
7474
]
7575
);
7676
}
77+
78+
#[cfg(feature = "pkcs11-provider")]
79+
#[test]
80+
fn pkcs11_verify_software() {
81+
use sha2::{Digest, Sha256};
82+
set_config("pkcs11_software.toml");
83+
reload_service();
84+
85+
let mut client = TestClient::new();
86+
let key_name = String::from("pkcs11_verify_software");
87+
88+
let mut hasher = Sha256::new();
89+
hasher.update(b"Bob wrote this message.");
90+
let hash = hasher.finalize().to_vec();
91+
92+
client.generate_rsa_sign_key(key_name.clone()).unwrap();
93+
94+
let signature = client
95+
.sign_with_rsa_sha256(key_name.clone(), hash.clone())
96+
.unwrap();
97+
client
98+
.verify_with_rsa_sha256(key_name, hash, signature)
99+
.unwrap();
100+
}
101+
102+
#[cfg(feature = "pkcs11-provider")]
103+
#[test]
104+
fn pkcs11_encrypt_software() {
105+
set_config("pkcs11_software.toml");
106+
reload_service();
107+
108+
let mut client = TestClient::new();
109+
let key_name = String::from("pkcs11_verify_software");
110+
let plaintext_msg = [
111+
0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84,
112+
0xA2, 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81,
113+
0x37, 0x78,
114+
];
115+
client
116+
.generate_rsa_encryption_keys_rsaoaep_sha1(key_name.clone())
117+
.unwrap();
118+
let ciphertext = client
119+
.asymmetric_encrypt_message_with_rsaoaep_sha1(
120+
key_name.clone(),
121+
plaintext_msg.to_vec(),
122+
vec![],
123+
)
124+
.unwrap();
125+
let plaintext = client
126+
.asymmetric_decrypt_message_with_rsaoaep_sha1(key_name, ciphertext, vec![])
127+
.unwrap();
128+
assert_eq!(&plaintext_msg[..], &plaintext[..]);
129+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[core_settings]
2+
# The CI already timestamps the logs
3+
log_timestamp = false
4+
log_error_details = true
5+
6+
# The container runs the Parsec service as root, so make sure we disable root
7+
# checks.
8+
allow_root = true
9+
10+
[listener]
11+
listener_type = "DomainSocket"
12+
# The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13+
# that the service does not hang for very big values of body or authentication length.
14+
timeout = 3000 # in milliseconds
15+
16+
[[key_manager]]
17+
name = "on-disk-manager"
18+
manager_type = "OnDisk"
19+
20+
[[provider]]
21+
provider_type = "Pkcs11"
22+
key_info_manager = "on-disk-manager"
23+
library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
24+
user_pin = "123456"
25+
software_public_operations = true
26+
# The slot_number mandatory field is going to replace the following line with a valid number
27+
# slot_number

e2e_tests/tests/per_provider/normal_tests/asym_encryption.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,6 @@ fn simple_asym_encrypt_rsa_oaep_pkcs11() {
8585
let key_name = String::from("simple_asym_encrypt_rsa_oaep_pkcs11");
8686
let mut client = TestClient::new();
8787

88-
if !client.is_operation_supported(Opcode::PsaAsymmetricEncrypt) {
89-
return;
90-
}
91-
9288
client
9389
.generate_rsa_encryption_keys_rsaoaep_sha1(key_name.clone())
9490
.unwrap();

src/providers/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ pub enum ProviderConfig {
4747
slot_number: usize,
4848
/// User Pin
4949
user_pin: Option<String>,
50+
/// Control whether public key operations are performed in software
51+
software_public_operations: Option<bool>,
5052
},
5153
/// TPM provider configuration
5254
Tpm {

src/providers/pkcs11_provider/asym_encryption.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::key_info_managers::KeyTriple;
77
use log::{info, trace};
88
use parsec_interface::operations::psa_algorithm::Algorithm;
99
use parsec_interface::operations::{psa_asymmetric_decrypt, psa_asymmetric_encrypt};
10-
use parsec_interface::requests::{ProviderID, Result};
10+
use parsec_interface::requests::{ProviderID, ResponseStatus, Result};
1111
use std::convert::TryFrom;
1212
use utils::CkMechanism;
1313

@@ -108,4 +108,45 @@ impl Pkcs11Provider {
108108
}
109109
}
110110
}
111+
112+
pub(super) fn software_psa_asymmetric_encrypt_internal(
113+
&self,
114+
app_name: ApplicationName,
115+
op: psa_asymmetric_encrypt::Operation,
116+
) -> Result<psa_asymmetric_encrypt::Result> {
117+
let key_triple = KeyTriple::new(app_name, ProviderID::Pkcs11, op.key_name.clone());
118+
let (_, key_attributes) = self.get_key_info(&key_triple)?;
119+
120+
op.validate(key_attributes)?;
121+
122+
let alg = op.alg;
123+
let salt_buff = op.salt.as_ref().map(|salt| salt.as_slice());
124+
let buffer_size = key_attributes.asymmetric_encrypt_output_size(alg)?;
125+
let mut ciphertext = vec![0u8; buffer_size];
126+
let pub_key_id = self.move_pub_key_to_psa_crypto(&key_triple)?;
127+
128+
info!("Encrypting plaintext with PSA Crypto");
129+
let res = match psa_crypto::operations::asym_encryption::encrypt(
130+
pub_key_id,
131+
alg,
132+
&op.plaintext,
133+
salt_buff,
134+
&mut ciphertext,
135+
) {
136+
Ok(output_size) => {
137+
ciphertext.resize(output_size, 0);
138+
Ok(psa_asymmetric_encrypt::Result {
139+
ciphertext: ciphertext.into(),
140+
})
141+
}
142+
Err(error) => {
143+
let error = ResponseStatus::from(error);
144+
format_error!("Asymmetric encryption failed", error);
145+
Err(error)
146+
}
147+
};
148+
149+
let _ = self.remove_psa_crypto_pub_key(pub_key_id);
150+
res
151+
}
111152
}

0 commit comments

Comments
 (0)