@@ -36,6 +36,7 @@ use pkcs11::types::{
36
36
use pkcs11:: Ctx ;
37
37
use serde:: { Deserialize , Serialize } ;
38
38
use std:: collections:: HashSet ;
39
+ use std:: mem;
39
40
use std:: sync:: { Arc , Mutex , RwLock } ;
40
41
use uuid:: Uuid ;
41
42
@@ -490,9 +491,11 @@ impl Provide for Pkcs11Provider {
490
491
info ! ( "Pkcs11 Provider - Create Key" ) ;
491
492
492
493
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 ) )
494
496
{
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." ) ;
496
499
return Err ( ResponseStatus :: UnsupportedOperation ) ;
497
500
}
498
501
@@ -540,6 +543,8 @@ impl Provide for Pkcs11Provider {
540
543
pub_template. push (
541
544
CK_ATTRIBUTE :: new ( pkcs11:: types:: CKA_PRIVATE ) . with_bool ( & pkcs11:: types:: CK_FALSE ) ,
542
545
) ;
546
+ pub_template
547
+ . push ( CK_ATTRIBUTE :: new ( pkcs11:: types:: CKA_ENCRYPT ) . with_bool ( & pkcs11:: types:: CK_TRUE ) ) ;
543
548
544
549
let session = Session :: new ( self , ReadWriteSession :: ReadWrite ) . or_else ( |err| {
545
550
error ! ( "Error creating a new session: {}." , err) ;
@@ -581,9 +586,11 @@ impl Provide for Pkcs11Provider {
581
586
info ! ( "Pkcs11 Provider - Import Key" ) ;
582
587
583
588
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 ) )
585
591
{
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." ) ;
587
594
return Err ( ResponseStatus :: UnsupportedOperation ) ;
588
595
}
589
596
@@ -609,8 +616,8 @@ impl Provide for Pkcs11Provider {
609
616
return Err ( ResponseStatus :: PsaErrorInvalidArgument ) ;
610
617
}
611
618
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 ( ) ;
614
621
615
622
template. push (
616
623
CK_ATTRIBUTE :: new ( pkcs11:: types:: CKA_CLASS )
@@ -627,7 +634,24 @@ impl Provide for Pkcs11Provider {
627
634
) ;
628
635
template
629
636
. 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 ) ) ;
630
639
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) ;
631
655
632
656
let session = Session :: new ( self , ReadWriteSession :: ReadWrite ) . or_else ( |err| {
633
657
error ! ( "Error creating a new session: {}." , err) ;
@@ -731,20 +755,13 @@ impl Provide for Pkcs11Provider {
731
755
error ! ( "Error when extracting attribute: {}." , rv) ;
732
756
Err ( ResponseStatus :: PsaErrorCommunicationFailure )
733
757
} 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 ( ) ;
736
760
737
761
// To produce a valid ASN.1 RSAPublicKey structure, 0x00 is put in front of the positive
738
762
// 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) ;
748
765
749
766
let key = RsaPublicKey {
750
767
modulus,
@@ -828,7 +845,7 @@ impl Provide for Pkcs11Provider {
828
845
info ! ( "Pkcs11 Provider - Asym Sign" ) ;
829
846
830
847
let key_name = op. key_name ;
831
- let hash = op. hash ;
848
+ let mut hash = op. hash ;
832
849
let key_triple = KeyTriple :: new ( app_name, ProviderID :: Pkcs11Provider , key_name) ;
833
850
let store_handle = self . key_id_store . read ( ) . expect ( "Key store lock poisoned" ) ;
834
851
let key_id = get_key_id ( & key_triple, & * store_handle) ?;
@@ -839,6 +856,11 @@ impl Provide for Pkcs11Provider {
839
856
ulParameterLen : 0 ,
840
857
} ;
841
858
859
+ if hash. len ( ) != 32 {
860
+ error ! ( "The PKCS11 provider currently only supports 256 bits long digests." ) ;
861
+ return Err ( ResponseStatus :: UnsupportedOperation ) ;
862
+ }
863
+
842
864
let session = Session :: new ( self , ReadWriteSession :: ReadWrite ) ?;
843
865
info ! ( "Asymmetric sign in session {}" , session. session_handle( ) ) ;
844
866
@@ -848,7 +870,20 @@ impl Provide for Pkcs11Provider {
848
870
match self . backend . sign_init ( session. session_handle ( ) , & mech, key) {
849
871
Ok ( _) => {
850
872
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) {
852
887
Ok ( signature) => Ok ( ResultAsymSign { signature } ) ,
853
888
Err ( e) => {
854
889
error ! ( "Failed to execute signing operation. Error: {}" , e) ;
@@ -867,18 +902,24 @@ impl Provide for Pkcs11Provider {
867
902
info ! ( "Pkcs11 Provider - Asym Verify" ) ;
868
903
869
904
let key_name = op. key_name ;
870
- let hash = op. hash ;
905
+ let mut hash = op. hash ;
871
906
let signature = op. signature ;
872
907
let key_triple = KeyTriple :: new ( app_name, ProviderID :: Pkcs11Provider , key_name) ;
873
908
let store_handle = self . key_id_store . read ( ) . expect ( "Key store lock poisoned" ) ;
874
909
let key_id = get_key_id ( & key_triple, & * store_handle) ?;
875
910
876
911
let mech = CK_MECHANISM {
912
+ // Verify without hashing.
877
913
mechanism : pkcs11:: types:: CKM_RSA_PKCS ,
878
914
pParameter : std:: ptr:: null_mut ( ) ,
879
915
ulParameterLen : 0 ,
880
916
} ;
881
917
918
+ if hash. len ( ) != 32 {
919
+ error ! ( "The PKCS11 provider currently only supports 256 bits long digests." ) ;
920
+ return Err ( ResponseStatus :: UnsupportedOperation ) ;
921
+ }
922
+
882
923
let session = Session :: new ( self , ReadWriteSession :: ReadWrite ) ?;
883
924
info ! ( "Asymmetric verify in session {}" , session. session_handle( ) ) ;
884
925
@@ -891,9 +932,22 @@ impl Provide for Pkcs11Provider {
891
932
{
892
933
Ok ( _) => {
893
934
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
+
894
948
match self
895
949
. backend
896
- . verify ( session. session_handle ( ) , & hash , & signature)
950
+ . verify ( session. session_handle ( ) , & digest_info , & signature)
897
951
{
898
952
Ok ( _) => Ok ( ResultAsymVerify { } ) ,
899
953
Err ( e) => match e {
@@ -909,7 +963,7 @@ impl Provide for Pkcs11Provider {
909
963
}
910
964
}
911
965
Err ( e) => {
912
- error ! ( "Failed to initialize signing operation. Error: {}" , e) ;
966
+ error ! ( "Failed to initialize verifying operation. Error: {}" , e) ;
913
967
Err ( ResponseStatus :: PsaErrorGenericError )
914
968
}
915
969
}
0 commit comments