Skip to content

Commit f918a2d

Browse files
authored
Merge pull request #88 from hug-dev/verify-tests
Add a verify-only integration test
2 parents 29dded3 + c7f1001 commit f918a2d

File tree

19 files changed

+1106
-997
lines changed

19 files changed

+1106
-997
lines changed

Cargo.lock

Lines changed: 456 additions & 420 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ serde = { version = "1.0", features = ["derive"] }
2424
env_logger = "0.7.1"
2525
log = { version = "0.4.8", features = ["serde"] }
2626
pkcs11 = { version = "0.4.0", optional = true }
27-
picky-asn1-der = { version = "0.2.0", optional = true }
28-
picky-asn1 = { version = "0.1.0", optional = true }
29-
tss-esapi = { git = "https://github.com/parallaxsecond/rust-tss-esapi", tag = "0.5.0", optional = true }
27+
picky-asn1-der = { version = "0.2.2", optional = true }
28+
picky-asn1 = { version = "0.2.1", optional = true }
29+
tss-esapi = { version = "1.0.1", optional = true }
3030
bincode = "1.1.4"
3131
structopt = "0.3.5"
3232
derivative = "1.0.3"
3333

3434
[dev-dependencies]
35-
parsec-client-test = { git = "https://github.com/parallaxsecond/parsec-client-test", tag = "0.1.8" }
35+
parsec-client-test = { git = "https://github.com/parallaxsecond/parsec-client-test", tag = "0.1.10" }
3636
num_cpus = "1.10.1"
3737

3838
[build-dependencies]

src/key_id_managers/on_disk_manager/mod.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ mod test {
379379
let key_triple = new_key_triple("insert_remove_key".to_string());
380380
let key_id = vec![0x11, 0x22, 0x33];
381381

382-
let _ = manager.insert(key_triple.clone(), key_id.clone()).unwrap();
382+
let _ = manager.insert(key_triple.clone(), key_id).unwrap();
383383

384384
assert!(manager.remove(&key_triple).unwrap().is_some());
385385
fs::remove_dir_all(path).unwrap();
@@ -405,7 +405,7 @@ mod test {
405405

406406
assert!(!manager.exists(&key_triple).unwrap());
407407

408-
let _ = manager.insert(key_triple.clone(), key_id.clone()).unwrap();
408+
let _ = manager.insert(key_triple.clone(), key_id).unwrap();
409409
assert!(manager.exists(&key_triple).unwrap());
410410

411411
let _ = manager.remove(&key_triple).unwrap();
@@ -422,9 +422,7 @@ mod test {
422422
let key_id_1 = vec![0x11, 0x22, 0x33];
423423
let key_id_2 = vec![0xaa, 0xbb, 0xcc];
424424

425-
let _ = manager
426-
.insert(key_triple.clone(), key_id_1.clone())
427-
.unwrap();
425+
let _ = manager.insert(key_triple.clone(), key_id_1).unwrap();
428426
let _ = manager
429427
.insert(key_triple.clone(), key_id_2.clone())
430428
.unwrap();

src/providers/pkcs11_provider/mod.rs

Lines changed: 76 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use pkcs11::types::{
3636
use pkcs11::Ctx;
3737
use serde::{Deserialize, Serialize};
3838
use std::collections::HashSet;
39+
use std::mem;
3940
use std::sync::{Arc, Mutex, RwLock};
4041
use uuid::Uuid;
4142

@@ -490,9 +491,11 @@ impl Provide for Pkcs11Provider {
490491
info!("Pkcs11 Provider - Create Key");
491492

492493
if op.key_attributes.key_type != KeyType::RsaKeypair
493-
|| op.key_attributes.algorithm != Algorithm::sign(SignAlgorithm::RsaPkcs1v15Sign, None)
494+
|| op.key_attributes.algorithm
495+
!= Algorithm::sign(SignAlgorithm::RsaPkcs1v15Sign, Some(HashAlgorithm::Sha256))
494496
{
495-
error!("The PKCS 11 provider currently only supports creating RSA key pairs for signing and verifying.");
497+
error!(
498+
"The PKCS11 provider currently only supports creating RSA key pairs for signing and verifying. The signature algorithm needs to be RSA PKCS#1 v1.5 and the text hashed with SHA-256.");
496499
return Err(ResponseStatus::UnsupportedOperation);
497500
}
498501

@@ -540,6 +543,8 @@ impl Provide for Pkcs11Provider {
540543
pub_template.push(
541544
CK_ATTRIBUTE::new(pkcs11::types::CKA_PRIVATE).with_bool(&pkcs11::types::CK_FALSE),
542545
);
546+
pub_template
547+
.push(CK_ATTRIBUTE::new(pkcs11::types::CKA_ENCRYPT).with_bool(&pkcs11::types::CK_TRUE));
543548

544549
let session = Session::new(self, ReadWriteSession::ReadWrite).or_else(|err| {
545550
error!("Error creating a new session: {}.", err);
@@ -581,9 +586,11 @@ impl Provide for Pkcs11Provider {
581586
info!("Pkcs11 Provider - Import Key");
582587

583588
if op.key_attributes.key_type != KeyType::RsaPublicKey
584-
|| op.key_attributes.algorithm != Algorithm::sign(SignAlgorithm::RsaPkcs1v15Sign, None)
589+
|| op.key_attributes.algorithm
590+
!= Algorithm::sign(SignAlgorithm::RsaPkcs1v15Sign, Some(HashAlgorithm::Sha256))
585591
{
586-
error!("The PKCS 11 provider currently only supports importing RSA public key for verifying.");
592+
error!(
593+
"The PKCS 11 provider currently only supports importing RSA public key for verifying. The signature algorithm needs to be RSA PKCS#1 v1.5 and the text hashed with SHA-256.");
587594
return Err(ResponseStatus::UnsupportedOperation);
588595
}
589596

@@ -609,8 +616,8 @@ impl Provide for Pkcs11Provider {
609616
return Err(ResponseStatus::PsaErrorInvalidArgument);
610617
}
611618

612-
let modulus_object = &public_key.modulus.as_bytes_be();
613-
let exponent_object = &public_key.public_exponent.as_bytes_be();
619+
let modulus_object = &public_key.modulus.as_unsigned_bytes_be();
620+
let exponent_object = &public_key.public_exponent.as_unsigned_bytes_be();
614621

615622
template.push(
616623
CK_ATTRIBUTE::new(pkcs11::types::CKA_CLASS)
@@ -627,7 +634,24 @@ impl Provide for Pkcs11Provider {
627634
);
628635
template
629636
.push(CK_ATTRIBUTE::new(pkcs11::types::CKA_VERIFY).with_bool(&pkcs11::types::CK_TRUE));
637+
template
638+
.push(CK_ATTRIBUTE::new(pkcs11::types::CKA_ENCRYPT).with_bool(&pkcs11::types::CK_TRUE));
630639
template.push(CK_ATTRIBUTE::new(pkcs11::types::CKA_ID).with_bytes(&key_id));
640+
template.push(
641+
CK_ATTRIBUTE::new(pkcs11::types::CKA_PRIVATE).with_bool(&pkcs11::types::CK_FALSE),
642+
);
643+
644+
// Restrict to RSA.
645+
let allowed_mechanisms = [pkcs11::types::CKM_RSA_PKCS];
646+
// The attribute contains a pointer to the allowed_mechanism array and its size as
647+
// ulValueLen.
648+
let mut allowed_mechanisms_attribute =
649+
CK_ATTRIBUTE::new(pkcs11::types::CKA_ALLOWED_MECHANISMS);
650+
allowed_mechanisms_attribute.ulValueLen = mem::size_of_val(&allowed_mechanisms);
651+
allowed_mechanisms_attribute.pValue = &allowed_mechanisms
652+
as *const pkcs11::types::CK_MECHANISM_TYPE
653+
as pkcs11::types::CK_VOID_PTR;
654+
template.push(allowed_mechanisms_attribute);
631655

632656
let session = Session::new(self, ReadWriteSession::ReadWrite).or_else(|err| {
633657
error!("Error creating a new session: {}.", err);
@@ -731,20 +755,13 @@ impl Provide for Pkcs11Provider {
731755
error!("Error when extracting attribute: {}.", rv);
732756
Err(ResponseStatus::PsaErrorCommunicationFailure)
733757
} else {
734-
let mut modulus = attrs[0].get_bytes();
735-
let mut public_exponent = attrs[1].get_bytes();
758+
let modulus = attrs[0].get_bytes();
759+
let public_exponent = attrs[1].get_bytes();
736760

737761
// To produce a valid ASN.1 RSAPublicKey structure, 0x00 is put in front of the positive
738762
// integer if highest significant bit is one, to differentiate it from a negative number.
739-
if modulus[0] & 0x80 == 0x80 {
740-
modulus.insert(0, 0x00);
741-
}
742-
if public_exponent[0] & 0x80 == 0x80 {
743-
public_exponent.insert(0, 0x00);
744-
}
745-
746-
let modulus = IntegerAsn1::from_signed_bytes_be(modulus);
747-
let public_exponent = IntegerAsn1::from_signed_bytes_be(public_exponent);
763+
let modulus = IntegerAsn1::from_unsigned_bytes_be(modulus);
764+
let public_exponent = IntegerAsn1::from_unsigned_bytes_be(public_exponent);
748765

749766
let key = RsaPublicKey {
750767
modulus,
@@ -828,7 +845,7 @@ impl Provide for Pkcs11Provider {
828845
info!("Pkcs11 Provider - Asym Sign");
829846

830847
let key_name = op.key_name;
831-
let hash = op.hash;
848+
let mut hash = op.hash;
832849
let key_triple = KeyTriple::new(app_name, ProviderID::Pkcs11Provider, key_name);
833850
let store_handle = self.key_id_store.read().expect("Key store lock poisoned");
834851
let key_id = get_key_id(&key_triple, &*store_handle)?;
@@ -839,6 +856,11 @@ impl Provide for Pkcs11Provider {
839856
ulParameterLen: 0,
840857
};
841858

859+
if hash.len() != 32 {
860+
error!("The PKCS11 provider currently only supports 256 bits long digests.");
861+
return Err(ResponseStatus::UnsupportedOperation);
862+
}
863+
842864
let session = Session::new(self, ReadWriteSession::ReadWrite)?;
843865
info!("Asymmetric sign in session {}", session.session_handle());
844866

@@ -848,7 +870,20 @@ impl Provide for Pkcs11Provider {
848870
match self.backend.sign_init(session.session_handle(), &mech, key) {
849871
Ok(_) => {
850872
info!("Signing operation initialized.");
851-
match self.backend.sign(session.session_handle(), &hash) {
873+
874+
// Build a valid ASN.1 DigestInfo DER-encoded structure by appending the hash to a
875+
// DigestAlgorithmIdentifier value representing the SHA256 OID with no parameters.
876+
// The OID used is: "2.16.840.1.101.3.4.2.1".
877+
// It would be better to use the DigestInfo structure defined in this file but the
878+
// AlgorithmIdentifier structure does not currently support the simple SHA256 OID.
879+
// See Devolutions/picky-rs#19
880+
let mut digest_info = vec![
881+
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
882+
0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
883+
];
884+
digest_info.append(&mut hash);
885+
886+
match self.backend.sign(session.session_handle(), &digest_info) {
852887
Ok(signature) => Ok(ResultAsymSign { signature }),
853888
Err(e) => {
854889
error!("Failed to execute signing operation. Error: {}", e);
@@ -867,18 +902,24 @@ impl Provide for Pkcs11Provider {
867902
info!("Pkcs11 Provider - Asym Verify");
868903

869904
let key_name = op.key_name;
870-
let hash = op.hash;
905+
let mut hash = op.hash;
871906
let signature = op.signature;
872907
let key_triple = KeyTriple::new(app_name, ProviderID::Pkcs11Provider, key_name);
873908
let store_handle = self.key_id_store.read().expect("Key store lock poisoned");
874909
let key_id = get_key_id(&key_triple, &*store_handle)?;
875910

876911
let mech = CK_MECHANISM {
912+
// Verify without hashing.
877913
mechanism: pkcs11::types::CKM_RSA_PKCS,
878914
pParameter: std::ptr::null_mut(),
879915
ulParameterLen: 0,
880916
};
881917

918+
if hash.len() != 32 {
919+
error!("The PKCS11 provider currently only supports 256 bits long digests.");
920+
return Err(ResponseStatus::UnsupportedOperation);
921+
}
922+
882923
let session = Session::new(self, ReadWriteSession::ReadWrite)?;
883924
info!("Asymmetric verify in session {}", session.session_handle());
884925

@@ -891,9 +932,22 @@ impl Provide for Pkcs11Provider {
891932
{
892933
Ok(_) => {
893934
info!("Verify operation initialized.");
935+
936+
// Build a valid ASN.1 DigestInfo DER-encoded structure by appending the hash to a
937+
// DigestAlgorithmIdentifier value representing the SHA256 OID with no parameters.
938+
// The OID used is: "2.16.840.1.101.3.4.2.1".
939+
// It would be better to use the DigestInfo structure defined in this file but the
940+
// AlgorithmIdentifier structure does not currently support the simple SHA256 OID.
941+
// See Devolutions/picky-rs#19
942+
let mut digest_info = vec![
943+
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
944+
0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
945+
];
946+
digest_info.append(&mut hash);
947+
894948
match self
895949
.backend
896-
.verify(session.session_handle(), &hash, &signature)
950+
.verify(session.session_handle(), &digest_info, &signature)
897951
{
898952
Ok(_) => Ok(ResultAsymVerify {}),
899953
Err(e) => match e {
@@ -909,7 +963,7 @@ impl Provide for Pkcs11Provider {
909963
}
910964
}
911965
Err(e) => {
912-
error!("Failed to initialize signing operation. Error: {}", e);
966+
error!("Failed to initialize verifying operation. Error: {}", e);
913967
Err(ResponseStatus::PsaErrorGenericError)
914968
}
915969
}

src/providers/tpm_provider/mod.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,11 @@ impl Provide for TpmProvider {
174174

175175
fn create_key(&self, app_name: ApplicationName, op: OpCreateKey) -> Result<ResultCreateKey> {
176176
if op.key_attributes.key_type != KeyType::RsaKeypair
177-
|| op.key_attributes.algorithm != Algorithm::sign(SignAlgorithm::RsaPkcs1v15Sign, None)
177+
|| op.key_attributes.algorithm
178+
!= Algorithm::sign(SignAlgorithm::RsaPkcs1v15Sign, Some(HashAlgorithm::Sha256))
178179
{
179-
error!("The TPM provider currently only supports creating RSA key pairs for signing and verifying.");
180+
error!(
181+
"The TPM provider currently only supports creating RSA key pairs for signing and verifying. The signature algorithm needs to be RSA PKCS#1 v1.5 and the text hashed with SHA-256.");
180182
return Err(ResponseStatus::UnsupportedOperation);
181183
}
182184

@@ -213,11 +215,11 @@ impl Provide for TpmProvider {
213215

214216
fn import_key(&self, app_name: ApplicationName, op: OpImportKey) -> Result<ResultImportKey> {
215217
if op.key_attributes.key_type != KeyType::RsaPublicKey
216-
|| op.key_attributes.algorithm != Algorithm::sign(SignAlgorithm::RsaPkcs1v15Sign, None)
218+
|| op.key_attributes.algorithm
219+
!= Algorithm::sign(SignAlgorithm::RsaPkcs1v15Sign, Some(HashAlgorithm::Sha256))
217220
{
218221
error!(
219-
"The TPM provider currently only supports importing RSA public key for verifying."
220-
);
222+
"The TPM provider currently only supports importing RSA public key for verifying. The signature algorithm needs to be RSA PKCS#1 v1.5 and the text hashed with SHA-256.");
221223
return Err(ResponseStatus::UnsupportedOperation);
222224
}
223225

@@ -241,11 +243,11 @@ impl Provide for TpmProvider {
241243
return Err(ResponseStatus::PsaErrorInvalidArgument);
242244
}
243245

244-
if public_key.public_exponent.as_bytes_be() != PUBLIC_EXPONENT {
245-
error!("The TPM Provider only supports 0x101 as public exponent for RSA public keys, {:?} given.", public_key.public_exponent.as_bytes_be());
246+
if public_key.public_exponent.as_unsigned_bytes_be() != PUBLIC_EXPONENT {
247+
error!("The TPM Provider only supports 0x101 as public exponent for RSA public keys, {:?} given.", public_key.public_exponent.as_unsigned_bytes_be());
246248
return Err(ResponseStatus::UnsupportedOperation);
247249
}
248-
let key_data = public_key.modulus.as_bytes_be();
250+
let key_data = public_key.modulus.as_unsigned_bytes_be();
249251

250252
let len = key_data.len();
251253
if len != 128 && len != 256 {
@@ -291,21 +293,17 @@ impl Provide for TpmProvider {
291293

292294
let password_context = get_password_context(&*store_handle, key_triple)?;
293295

294-
let mut pub_key_data = esapi_context
296+
let pub_key_data = esapi_context
295297
.read_public_key(password_context.context)
296298
.or_else(|e| {
297299
error!("Error reading a public key: {}.", e);
298300
Err(ResponseStatus::PsaErrorHardwareFailure)
299301
})?;
300302

301-
// To produce a valid ASN.1 RSAPublicKey structure, 0x00 is put in front of the positive
302-
// modulus if highest significant bit is one, to differentiate it from a negative number.
303-
if pub_key_data[0] & 0x80 == 0x80 {
304-
pub_key_data.insert(0, 0x00);
305-
}
306-
307303
let key = RsaPublicKey {
308-
modulus: IntegerAsn1::from_signed_bytes_be(pub_key_data),
304+
// To produce a valid ASN.1 RSAPublicKey structure, 0x00 is put in front of the positive
305+
// modulus if highest significant bit is one, to differentiate it from a negative number.
306+
modulus: IntegerAsn1::from_unsigned_bytes_be(pub_key_data),
309307
public_exponent: IntegerAsn1::from_signed_bytes_be(PUBLIC_EXPONENT.to_vec()),
310308
};
311309
let key_data = picky_asn1_der::to_vec(&key).or_else(|err| {
@@ -466,7 +464,13 @@ impl TpmProviderBuilder {
466464
self
467465
}
468466

469-
pub fn build(self) -> TpmProvider {
467+
/// Create an instance of TpmProvider
468+
///
469+
/// # Safety
470+
///
471+
/// Undefined behaviour might appear if two instances of TransientObjectContext are created
472+
/// using a same TCTI that does not handle multiple applications concurrently.
473+
pub unsafe fn build(self) -> TpmProvider {
470474
TpmProvider::new(
471475
self.key_id_store.expect("Missing key ID store."),
472476
tss_esapi::TransientObjectContext::new(

0 commit comments

Comments
 (0)