@@ -746,6 +746,7 @@ void SoftHSM::prepareSupportedMechanisms(std::map<std::string, CK_MECHANISM_TYPE
746746#endif
747747 t[" CKM_SHA1_RSA_PKCS" ] = CKM_SHA1_RSA_PKCS;
748748 t[" CKM_RSA_PKCS_OAEP" ] = CKM_RSA_PKCS_OAEP;
749+ t[" CKM_RSA_AES_KEY_WRAP" ] = CKM_RSA_AES_KEY_WRAP;
749750 t[" CKM_SHA224_RSA_PKCS" ] = CKM_SHA224_RSA_PKCS;
750751 t[" CKM_SHA256_RSA_PKCS" ] = CKM_SHA256_RSA_PKCS;
751752 t[" CKM_SHA384_RSA_PKCS" ] = CKM_SHA384_RSA_PKCS;
@@ -1181,6 +1182,12 @@ CK_RV SoftHSM::C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_
11811182 pInfo->flags = CKF_WRAP | CKF_UNWRAP;
11821183 break ;
11831184#endif
1185+ case CKM_RSA_AES_KEY_WRAP:
1186+ pInfo->ulMinKeySize = rsaMinSize;
1187+ pInfo->ulMaxKeySize = rsaMaxSize;
1188+ pInfo->flags = CKF_WRAP | CKF_UNWRAP;
1189+ break ;
1190+
11841191#ifndef WITH_FIPS
11851192 case CKM_DES_ECB_ENCRYPT_DATA:
11861193 case CKM_DES_CBC_ENCRYPT_DATA:
@@ -6498,6 +6505,11 @@ CK_RV SoftHSM::C_WrapKey
64986505 if (rv != CKR_OK)
64996506 return rv;
65006507 break ;
6508+ case CKM_RSA_AES_KEY_WRAP:
6509+ rv = MechParamCheckRSAAESKEYWRAP (pMechanism);
6510+ if (rv != CKR_OK)
6511+ return rv;
6512+ break ;
65016513 case CKM_AES_CBC:
65026514 case CKM_AES_CBC_PAD:
65036515 if (pMechanism->pParameter == NULL_PTR ||
@@ -6532,13 +6544,15 @@ CK_RV SoftHSM::C_WrapKey
65326544 // Check wrapping key class and type
65336545 if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && wrapKey->getUnsignedLongValue (CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
65346546 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6535- if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue (CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY)
6547+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP || pMechanism->mechanism == CKM_RSA_AES_KEY_WRAP) &&
6548+ wrapKey->getUnsignedLongValue (CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY)
65366549 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
65376550 if (pMechanism->mechanism == CKM_AES_KEY_WRAP && wrapKey->getUnsignedLongValue (CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
65386551 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
65396552 if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && wrapKey->getUnsignedLongValue (CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
65406553 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6541- if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue (CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6554+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP || pMechanism->mechanism == CKM_RSA_AES_KEY_WRAP) &&
6555+ wrapKey->getUnsignedLongValue (CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
65426556 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
65436557 if ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CBC_PAD) && wrapKey->getUnsignedLongValue (CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
65446558 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
@@ -6712,12 +6726,96 @@ CK_RV SoftHSM::C_WrapKey
67126726
67136727 keyClass = wrapKey->getUnsignedLongValue (CKA_CLASS, CKO_VENDOR_DEFINED);
67146728 ByteString wrapped;
6715- if (keyClass == CKO_SECRET_KEY)
6716- rv = SoftHSM::WrapKeySym (pMechanism, token, wrapKey, keydata, wrapped);
6729+
6730+ if (pMechanism->mechanism == CKM_RSA_AES_KEY_WRAP)
6731+ {
6732+ ByteString wrapped_1; // buffer for the wrapped AES key;
6733+ ByteString wrapped_2; // buffer for the wrapped target key;
6734+ CK_RSA_AES_KEY_WRAP_PARAMS_PTR params = (CK_RSA_AES_KEY_WRAP_PARAMS_PTR)pMechanism->pParameter ;
6735+ CK_ULONG emphKeyLen = params->aes_key_bits / 8 ;
6736+ CK_OBJECT_HANDLE hEmphKey = CK_INVALID_HANDLE;
6737+ CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
6738+ CK_KEY_TYPE keyType = CKK_AES;
6739+ CK_BBOOL isEmphOnToken = CK_FALSE;
6740+ CK_BBOOL isEmphPrivate = CK_TRUE;
6741+ CK_BBOOL bFalse = CK_FALSE;
6742+ CK_BBOOL bTrue = CK_TRUE;
6743+ CK_ATTRIBUTE emph_temp[] = {
6744+ {CKA_CLASS, &secretClass, sizeof (CK_OBJECT_CLASS)},
6745+ {CKA_KEY_TYPE, &keyType, sizeof (CK_KEY_TYPE)},
6746+ {CKA_TOKEN, &bFalse, sizeof (CK_BBOOL)},
6747+ {CKA_PRIVATE, &isEmphPrivate, sizeof (CK_BBOOL)},
6748+ {CKA_WRAP, &bTrue, sizeof (CK_BBOOL)},
6749+ {CKA_EXTRACTABLE, &bTrue, sizeof (CK_BBOOL)},
6750+ {CKA_VALUE_LEN, &emphKeyLen, sizeof (CK_ULONG)}
6751+ };
6752+ // Generates temporary random AES key of ulAESKeyBits length.
6753+ rv = this ->generateAES (hSession, emph_temp, sizeof (emph_temp)/sizeof (CK_ATTRIBUTE), &hEmphKey, isEmphOnToken, isEmphPrivate);
6754+ if (rv != CKR_OK)
6755+ {
6756+ // Remove secret that may have been created already when the function fails.
6757+ if (hEmphKey != CK_INVALID_HANDLE)
6758+ {
6759+ OSObject *emphKey = (OSObject *)handleManager->getObject (hEmphKey);
6760+ handleManager->destroyObject (hEmphKey);
6761+ if (emphKey) emphKey->destroyObject ();
6762+ hEmphKey = CK_INVALID_HANDLE;
6763+ }
6764+ return rv;
6765+ }
6766+
6767+ OSObject *emphKey = (OSObject *)handleManager->getObject (hEmphKey);
6768+ if (emphKey == NULL_PTR || !emphKey->isValid ())
6769+ {
6770+ return CKR_KEY_HANDLE_INVALID;
6771+ }
6772+
6773+ // Remove the emph key handle.
6774+ handleManager->destroyObject (hEmphKey);
6775+ hEmphKey = CK_INVALID_HANDLE;
6776+
6777+ CK_MECHANISM emphMech = {CKM_AES_KEY_WRAP_PAD, NULL_PTR, 0 };
6778+
6779+ // Wraps the target key with the temporary AES key using CKM_AES_KEY_WRAP_PAD (RFC5649).
6780+ rv = SoftHSM::WrapKeySym (&emphMech, token, emphKey, keydata, wrapped_2);
6781+ if (rv != CKR_OK)
6782+ {
6783+ emphKey->destroyObject ();
6784+ return rv;
6785+ }
6786+
6787+ // Get the AES emph key data
6788+ ByteString emphkeydata;
6789+ ByteString emphKeyValue = emphKey->getByteStringValue (CKA_VALUE);
6790+ token->decrypt (emphKeyValue, emphkeydata);
6791+ emphKey->destroyObject ();
6792+
6793+ CK_MECHANISM oaepMech = {CKM_RSA_PKCS_OAEP, params->oaep_params , sizeof (CK_RSA_AES_KEY_WRAP_PARAMS)};
6794+
6795+ // Wraps the AES emph key with the wrapping RSA key using CKM_RSA_PKCS_OAEP with parameters of OAEPParams.
6796+ rv = SoftHSM::WrapKeyAsym (&oaepMech, token, wrapKey, emphkeydata, wrapped_1);
6797+
6798+ // Zeroizes the temporary AES key
6799+ emphkeydata.wipe ();
6800+ emphKeyValue.wipe ();
6801+
6802+ if (rv != CKR_OK)
6803+ {
6804+ return rv;
6805+ }
6806+
6807+ // Concatenates two wrapped keys and outputs the concatenated blob.
6808+ wrapped = wrapped_1 + wrapped_2;
6809+ }
67176810 else
6718- rv = SoftHSM::WrapKeyAsym (pMechanism, token, wrapKey, keydata, wrapped);
6719- if (rv != CKR_OK)
6720- return rv;
6811+ {
6812+ if (keyClass == CKO_SECRET_KEY)
6813+ rv = SoftHSM::WrapKeySym (pMechanism, token, wrapKey, keydata, wrapped);
6814+ else
6815+ rv = SoftHSM::WrapKeyAsym (pMechanism, token, wrapKey, keydata, wrapped);
6816+ if (rv != CKR_OK)
6817+ return rv;
6818+ }
67216819
67226820 if (pWrappedKey != NULL ) {
67236821 if (*pulWrappedKeyLen >= wrapped.size ())
@@ -6957,6 +7055,11 @@ CK_RV SoftHSM::C_UnwrapKey
69577055 if (rv != CKR_OK)
69587056 return rv;
69597057 break ;
7058+ case CKM_RSA_AES_KEY_WRAP:
7059+ rv = MechParamCheckRSAAESKEYWRAP (pMechanism);
7060+ if (rv != CKR_OK)
7061+ return rv;
7062+ break ;
69607063
69617064 case CKM_AES_CBC_PAD:
69627065 // TODO check block length
@@ -7004,9 +7107,11 @@ CK_RV SoftHSM::C_UnwrapKey
70047107 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
70057108 if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && unwrapKey->getUnsignedLongValue (CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
70067109 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
7007- if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue (CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
7110+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP || pMechanism->mechanism == CKM_RSA_AES_KEY_WRAP) &&
7111+ unwrapKey->getUnsignedLongValue (CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
70087112 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
7009- if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue (CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
7113+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP || pMechanism->mechanism == CKM_RSA_AES_KEY_WRAP) &&
7114+ unwrapKey->getUnsignedLongValue (CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
70107115 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
70117116 if ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CBC_PAD) && unwrapKey->getUnsignedLongValue (CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
70127117 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
@@ -7128,14 +7233,130 @@ CK_RV SoftHSM::C_UnwrapKey
71287233 // Unwrap the key
71297234 ByteString wrapped (pWrappedKey, ulWrappedKeyLen);
71307235 ByteString keydata;
7131- if (unwrapKey->getUnsignedLongValue (CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
7132- rv = UnwrapKeySym (pMechanism, wrapped, token, unwrapKey, keydata);
7133- else if (unwrapKey->getUnsignedLongValue (CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_PRIVATE_KEY)
7134- rv = UnwrapKeyAsym (pMechanism, wrapped, token, unwrapKey, keydata);
7236+
7237+ if (pMechanism->mechanism == CKM_RSA_AES_KEY_WRAP)
7238+ {
7239+ CK_OBJECT_HANDLE hEmphKey = CK_INVALID_HANDLE;
7240+ CK_RSA_AES_KEY_WRAP_PARAMS_PTR params = (CK_RSA_AES_KEY_WRAP_PARAMS_PTR)pMechanism->pParameter ;
7241+ ByteString emphkeydata;
7242+ ByteString pubexp = unwrapKey->getByteStringValue (CKA_PUBLIC_EXPONENT);
7243+ ByteString modulus = unwrapKey->getByteStringValue (CKA_MODULUS);
7244+ CK_ULONG wrappedLen1 = modulus.size ();
7245+ if (isUnwrapKeyPrivate)
7246+ {
7247+ wrappedLen1 = modulus.size () - pubexp.size ();
7248+ }
7249+ CK_ULONG wrappedLen2 = ulWrappedKeyLen - wrappedLen1;
7250+
7251+ ByteString wrapped_1 (pWrappedKey, wrappedLen1); // the wrapped AES key
7252+ CK_MECHANISM oaepMech = {CKM_RSA_PKCS_OAEP, params->oaep_params , sizeof (CK_RSA_AES_KEY_WRAP_PARAMS)};
7253+
7254+ // Un-wraps the temporary AES key from the first part with the private RSA key using CKM_RSA_PKCS_OAEP.
7255+ rv = UnwrapKeyAsym (&oaepMech, wrapped_1, token, unwrapKey, emphkeydata);
7256+ if (rv != CKR_OK)
7257+ {
7258+ emphkeydata.wipe ();
7259+ return rv;
7260+ }
7261+
7262+ ByteString wrapped_2 (pWrappedKey + wrappedLen1, wrappedLen2); // the wrapped target key
7263+ CK_BBOOL isEmphPrivate = CK_TRUE;
7264+ CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
7265+ CK_KEY_TYPE keyType = CKK_AES;
7266+ CK_BBOOL bFalse = CK_FALSE;
7267+ CK_BBOOL bTrue = CK_TRUE;
7268+ CK_ATTRIBUTE emph_temp[] = {
7269+ {CKA_CLASS, &secretClass, sizeof (CK_OBJECT_CLASS)},
7270+ {CKA_KEY_TYPE, &keyType, sizeof (CK_KEY_TYPE)},
7271+ {CKA_TOKEN, &bFalse, sizeof (CK_BBOOL)},
7272+ {CKA_PRIVATE, &isEmphPrivate, sizeof (CK_BBOOL)},
7273+ {CKA_UNWRAP, &bTrue, sizeof (CK_BBOOL)}
7274+ };
7275+ // Create the temporary AES object using C_CreateObject
7276+ rv = this ->CreateObject (hSession, emph_temp, sizeof (emph_temp) / sizeof (CK_ATTRIBUTE), &hEmphKey, OBJECT_OP_UNWRAP);
7277+ if (rv != CKR_OK)
7278+ {
7279+ // Remove secret that may have been created already when the function fails.
7280+ if (hEmphKey != CK_INVALID_HANDLE)
7281+ {
7282+ OSObject *emphKey = (OSObject *)handleManager->getObject (hEmphKey);
7283+ handleManager->destroyObject (hEmphKey);
7284+ if (emphKey) emphKey->destroyObject ();
7285+ hEmphKey = CK_INVALID_HANDLE;
7286+ }
7287+ emphkeydata.wipe ();
7288+ return rv;
7289+ }
7290+
7291+ // Store the attributes that are being supplied
7292+ OSObject *emphKey = (OSObject *)handleManager->getObject (hEmphKey);
7293+ if (emphKey == NULL_PTR || !emphKey->isValid ())
7294+ {
7295+ emphkeydata.wipe ();
7296+ return CKR_FUNCTION_FAILED;
7297+ }
7298+ // remove the emphkey handle
7299+ handleManager->destroyObject (hEmphKey);
7300+ hEmphKey = CK_INVALID_HANDLE;
7301+
7302+ if (emphKey->startTransaction ())
7303+ {
7304+ bool bOK = true ;
7305+ // Common Attributes
7306+ bOK = bOK && emphKey->setAttribute (CKA_LOCAL, false );
7307+ // Common Secret Key Attributes
7308+ bOK = bOK && emphKey->setAttribute (CKA_ALWAYS_SENSITIVE, false );
7309+ bOK = bOK && emphKey->setAttribute (CKA_NEVER_EXTRACTABLE, false );
7310+ // Secret Attributes
7311+ ByteString emphKeyValue;
7312+ token->encrypt (emphkeydata, emphKeyValue);
7313+ bOK = bOK && emphKey->setAttribute (CKA_VALUE, emphKeyValue);
7314+
7315+ if (bOK)
7316+ {
7317+ bOK = emphKey->commitTransaction ();
7318+ }
7319+ else
7320+ {
7321+ emphKey->abortTransaction ();
7322+ }
7323+ // Zeroizes the temporary AES key.
7324+ emphkeydata.wipe ();
7325+ emphKeyValue.wipe ();
7326+
7327+ if (!bOK)
7328+ {
7329+ emphKey->destroyObject ();
7330+ return CKR_FUNCTION_FAILED;
7331+ }
7332+ }
7333+ else
7334+ {
7335+ emphkeydata.wipe ();
7336+ emphKey->destroyObject ();
7337+ return CKR_FUNCTION_FAILED;
7338+ }
7339+
7340+ CK_MECHANISM emphMech = {CKM_AES_KEY_WRAP_PAD, NULL_PTR, 0 };
7341+ // Un-wraps the target key from the second part with the temporary AES key using CKM_AES_KEY_WRAP_PAD (RFC5649)
7342+ rv = UnwrapKeySym (&emphMech, wrapped_2, token, emphKey, keydata);
7343+ emphKey->destroyObject ();
7344+ if (rv != CKR_OK)
7345+ {
7346+ return rv;
7347+ }
7348+ }
71357349 else
7136- rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
7137- if (rv != CKR_OK)
7138- return rv;
7350+ {
7351+ if (unwrapKey->getUnsignedLongValue (CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
7352+ rv = UnwrapKeySym (pMechanism, wrapped, token, unwrapKey, keydata);
7353+ else if (unwrapKey->getUnsignedLongValue (CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_PRIVATE_KEY)
7354+ rv = UnwrapKeyAsym (pMechanism, wrapped, token, unwrapKey, keydata);
7355+ else
7356+ rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
7357+ if (rv != CKR_OK)
7358+ return rv;
7359+ }
71397360
71407361 // Create the secret object using C_CreateObject
71417362 rv = this ->CreateObject (hSession, secretAttribs, secretAttribsCount, hKey, OBJECT_OP_UNWRAP);
@@ -12860,6 +13081,61 @@ CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism)
1286013081 return CKR_OK;
1286113082}
1286213083
13084+
13085+ CK_RV SoftHSM::MechParamCheckRSAAESKEYWRAP (CK_MECHANISM_PTR pMechanism)
13086+ {
13087+ // This is a programming error
13088+ if (pMechanism->mechanism != CKM_RSA_AES_KEY_WRAP) {
13089+ ERROR_MSG (" MechParamCheckRSAAESKEYWRAP called on wrong mechanism" );
13090+ return CKR_GENERAL_ERROR;
13091+ }
13092+ if (pMechanism->pParameter == NULL_PTR ||
13093+ pMechanism->ulParameterLen != sizeof (CK_RSA_AES_KEY_WRAP_PARAMS))
13094+ {
13095+ ERROR_MSG (" pParameter must be of type CK_RSA_AES_KEY_WRAP_PARAMS" );
13096+ return CKR_ARGUMENTS_BAD;
13097+ }
13098+
13099+ CK_RSA_AES_KEY_WRAP_PARAMS_PTR params = (CK_RSA_AES_KEY_WRAP_PARAMS_PTR)pMechanism->pParameter ;
13100+ if (params->aes_key_bits != 128 && params->aes_key_bits != 192 && params->aes_key_bits != 256 )
13101+ {
13102+ ERROR_MSG (" length of the temporary AES key in bits can be only 128, 192 or 256" );
13103+ return CKR_ARGUMENTS_BAD;
13104+ }
13105+ if (params->oaep_params == NULL_PTR)
13106+ {
13107+ ERROR_MSG (" oaep_params must be of type CK_RSA_PKCS_OAEP_PARAMS" );
13108+ return CKR_ARGUMENTS_BAD;
13109+ }
13110+ if (params->oaep_params ->hashAlg != CKM_SHA_1)
13111+ {
13112+ ERROR_MSG (" hashAlg must be CKM_SHA_1" );
13113+ return CKR_ARGUMENTS_BAD;
13114+ }
13115+ if (params->oaep_params ->mgf != CKG_MGF1_SHA1)
13116+ {
13117+ ERROR_MSG (" mgf must be CKG_MGF1_SHA1" );
13118+ return CKR_ARGUMENTS_BAD;
13119+ }
13120+ if (params->oaep_params ->source != CKZ_DATA_SPECIFIED)
13121+ {
13122+ ERROR_MSG (" source must be CKZ_DATA_SPECIFIED" );
13123+ return CKR_ARGUMENTS_BAD;
13124+ }
13125+ if (params->oaep_params ->pSourceData != NULL )
13126+ {
13127+ ERROR_MSG (" pSourceData must be NULL" );
13128+ return CKR_ARGUMENTS_BAD;
13129+ }
13130+ if (params->oaep_params ->ulSourceDataLen != 0 )
13131+ {
13132+ ERROR_MSG (" ulSourceDataLen must be 0" );
13133+ return CKR_ARGUMENTS_BAD;
13134+ }
13135+
13136+ return CKR_OK;
13137+ }
13138+
1286313139bool SoftHSM::isMechanismPermitted (OSObject* key, CK_MECHANISM_PTR pMechanism)
1286413140{
1286513141 std::list<CK_MECHANISM_TYPE> mechs = supportedMechanisms;
0 commit comments