@@ -15,6 +15,7 @@ use serial_test::serial;
1515use std:: collections:: HashMap ;
1616use std:: thread;
1717
18+ use cryptoki:: mechanism:: ekdf:: AesCbcDeriveParams ;
1819use testresult:: TestResult ;
1920
2021#[ test]
@@ -1105,3 +1106,84 @@ fn wait_for_slot_event() {
11051106 res
11061107 ) ;
11071108}
1109+
1110+ #[ test]
1111+ #[ serial]
1112+ fn generate_generic_secret_key ( ) -> TestResult {
1113+ let ( pkcs11, slot) = init_pins ( ) ;
1114+ let session = pkcs11. open_rw_session ( slot) ?;
1115+ session. login ( UserType :: User , Some ( & AuthPin :: new ( USER_PIN . into ( ) ) ) ) ?;
1116+
1117+ let key_label = Attribute :: Label ( b"test_generic_secret_key_gen" . to_vec ( ) ) ;
1118+ let key_template = vec ! [
1119+ Attribute :: Class ( ObjectClass :: SECRET_KEY ) ,
1120+ Attribute :: KeyType ( KeyType :: GENERIC_SECRET ) ,
1121+ Attribute :: Token ( true ) ,
1122+ Attribute :: Sensitive ( true ) ,
1123+ Attribute :: Private ( true ) ,
1124+ Attribute :: ValueLen ( 512 . into( ) ) ,
1125+ key_label. clone( ) ,
1126+ ] ;
1127+
1128+ let key = session. generate_key ( & Mechanism :: GenericSecretKeyGen , & key_template) ?;
1129+ let attributes_result = session. find_objects ( & [ key_label] ) ?. remove ( 0 ) ;
1130+ assert_eq ! ( key, attributes_result) ;
1131+
1132+ Ok ( ( ) )
1133+ }
1134+
1135+ #[ test]
1136+ #[ serial]
1137+ fn ekdf_aes_cbc_encrypt_data ( ) -> TestResult {
1138+ let ( pkcs11, slot) = init_pins ( ) ;
1139+ let session = pkcs11. open_rw_session ( slot) ?;
1140+ session. login ( UserType :: User , Some ( & AuthPin :: new ( USER_PIN . into ( ) ) ) ) ?;
1141+
1142+ // key template
1143+ let key_template = vec ! [
1144+ Attribute :: Class ( ObjectClass :: SECRET_KEY ) ,
1145+ Attribute :: KeyType ( KeyType :: AES ) ,
1146+ Attribute :: Token ( true ) ,
1147+ Attribute :: Sensitive ( true ) ,
1148+ Attribute :: Private ( true ) ,
1149+ Attribute :: ValueLen ( 32 . into( ) ) ,
1150+ Attribute :: Derive ( true ) ,
1151+ ] ;
1152+
1153+ // generate master key
1154+ let master_key_label = Attribute :: Label ( b"test_aes_cbc_encrypt_data_master_key" . to_vec ( ) ) ;
1155+ let mut master_key_template = key_template. clone ( ) ;
1156+ master_key_template. insert ( 0 , master_key_label. clone ( ) ) ;
1157+
1158+ let master_key = session. generate_key ( & Mechanism :: AesKeyGen , & master_key_template) ?;
1159+ assert_eq ! (
1160+ master_key,
1161+ session. find_objects( & [ master_key_label] ) ?. remove( 0 )
1162+ ) ;
1163+
1164+ // generate a derived pair
1165+ let derived_key_label = Attribute :: Label ( b"test_aes_cbc_encrypt_data_child_key" . to_vec ( ) ) ;
1166+ let mut derived_key_template = key_template. clone ( ) ;
1167+ derived_key_template. insert ( 0 , derived_key_label. clone ( ) ) ;
1168+
1169+ // ============================================== IMPORTANT ==============================================
1170+ // When using this derivation method in production, be aware that it's better to keep first bytes of data
1171+ // filled with actual data (e.g., derivation path) - this shall cause CBC mode to propagate randomness to
1172+ // remaining 128 bit-wide AES blocks.
1173+ // Otherwise, if filling only last bytes, you are risking to keep first N of 128 bit-wide chunks of your
1174+ // derived private key the same for all child keys. If deriving a key for 256-bit AES, this means half of
1175+ // the key to be static.
1176+ // =======================================================================================================
1177+ let aes_cbc_derive_params = AesCbcDeriveParams :: new ( [ 0u8 ; 16 ] , [ 1u8 ; 32 ] . as_slice ( ) ) ;
1178+ let derived_key = session. derive_key (
1179+ & Mechanism :: AesCbcEncryptData ( aes_cbc_derive_params) ,
1180+ master_key,
1181+ & derived_key_template,
1182+ ) ?;
1183+ assert_eq ! (
1184+ derived_key,
1185+ session. find_objects( & [ derived_key_label] ) ?. remove( 0 )
1186+ ) ;
1187+
1188+ Ok ( ( ) )
1189+ }
0 commit comments