/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This file implements PKCS 11 on top of our existing security modules * * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. * This implementation has two slots: * slot 1 is our generic crypto support. It does not require login. * It supports Public Key ops, and all they bulk ciphers and hashes. * It can also support Private Key ops for imported Private keys. It does * not have any token storage. * slot 2 is our private key support. It requires a login before use. It * can store Private Keys and Certs as token objects. Currently only private * keys and their associated Certificates are saved on the token. * * In this implementation, session objects are only visible to the session * that created or generated them.
*/ #include"seccomon.h" #include"secitem.h" #include"secport.h" #include"blapi.h" #include"pkcs11.h" #include"pkcs11i.h" #include"pkcs1sig.h" #include"lowkeyi.h" #include"secder.h" #include"secdig.h" #include"lowpbe.h"/* We do PBE below */ #include"pkcs11t.h" #include"secoid.h" #include"alghmac.h" #include"softoken.h" #include"secasn1.h" #include"secerr.h"
#include"prprf.h" #include"prenv.h"
/* * A common prfContext to handle both hmac and aes xcbc * hash contexts have non-null hashObj and hmac, aes
* contexts have non-null aes */ typedefstruct prfContextStr {
HASH_HashType hashType; const SECHashObject *hashObj;
HMACContext *hmac;
AESContext *aes; unsignedint nextChar; unsignedchar padBuf[AES_BLOCK_SIZE]; unsignedchar macBuf[AES_BLOCK_SIZE]; unsignedchar k1[AES_BLOCK_SIZE]; unsignedchar k2[AES_BLOCK_SIZE]; unsignedchar k3[AES_BLOCK_SIZE];
} prfContext;
/* iv full of zeros used in several places in aes xcbc */ staticconstunsignedchar iv_zero[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* * Generate AES XCBC keys from the AES MAC key. * k1 is used in the actual mac. * k2 and k3 are used in the final pad step.
*/ static CK_RV
sftk_aes_xcbc_get_keys(constunsignedchar *keyValue, unsignedint keyLen, unsignedchar *k1, unsignedchar *k2, unsignedchar *k3)
{
SECStatus rv;
CK_RV crv; unsignedint tmpLen;
AESContext *aes_context = NULL; unsignedchar newKey[AES_BLOCK_SIZE];
/* first make sure out input key is the correct length * rfc 4434. If key is shorter, pad with zeros to the * the right. If key is longer newKey = aes_xcbc(0, key, keyLen).
*/ if (keyLen < AES_BLOCK_SIZE) {
PORT_Memcpy(newKey, keyValue, keyLen);
PORT_Memset(&newKey[keyLen], 0, AES_BLOCK_SIZE - keyLen);
keyValue = newKey;
} elseif (keyLen > AES_BLOCK_SIZE) { /* calculate our new key = aes_xcbc(0, key, keyLen). Because the * key above is fixed (0), we can precalculate k1, k2, and k3. * if this code ever needs to be more generic (support any xcbc * function rather than just aes, we would probably want to just * recurse here using our prf functions. This would be safe because * the recurse case would have keyLen == blocksize and thus skip * this conditional.
*/
aes_context = AES_CreateContext(k1_0, iv_zero, NSS_AES_CBC,
PR_TRUE, AES_BLOCK_SIZE, AES_BLOCK_SIZE); /* we know the following loop will execute at least once */ while (keyLen > AES_BLOCK_SIZE) {
rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE,
keyValue, AES_BLOCK_SIZE); if (rv != SECSuccess) { goto fail;
}
keyValue += AES_BLOCK_SIZE;
keyLen -= AES_BLOCK_SIZE;
}
PORT_Memcpy(newKey, keyValue, keyLen);
sftk_xcbc_mac_pad(newKey, keyLen, AES_BLOCK_SIZE, k2_0, k3_0);
rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE,
newKey, AES_BLOCK_SIZE); if (rv != SECSuccess) { goto fail;
}
keyValue = newKey;
AES_DestroyContext(aes_context, PR_TRUE);
} /* the length of the key in keyValue is known to be AES_BLOCK_SIZE, * either because it was on input, or it was shorter and extended, or * because it was mac'd down using aes_xcbc_prf.
*/
aes_context = AES_CreateContext(keyValue, iv_zero,
NSS_AES, PR_TRUE, AES_BLOCK_SIZE, AES_BLOCK_SIZE); if (aes_context == NULL) { goto fail;
}
rv = AES_Encrypt(aes_context, k1, &tmpLen, AES_BLOCK_SIZE,
k1data, sizeof(k1data)); if (rv != SECSuccess) { goto fail;
}
rv = AES_Encrypt(aes_context, k2, &tmpLen, AES_BLOCK_SIZE,
k2data, sizeof(k2data)); if (rv != SECSuccess) { goto fail;
}
rv = AES_Encrypt(aes_context, k3, &tmpLen, AES_BLOCK_SIZE,
k3data, sizeof(k3data)); if (rv != SECSuccess) { goto fail;
}
AES_DestroyContext(aes_context, PR_TRUE);
PORT_Memset(newKey, 0, AES_BLOCK_SIZE); return CKR_OK;
fail:
crv = sftk_MapCryptError(PORT_GetError()); if (aes_context) {
AES_DestroyContext(aes_context, PR_TRUE);
}
PORT_Memset(k1, 0, AES_BLOCK_SIZE);
PORT_Memset(k2, 0, AES_BLOCK_SIZE);
PORT_Memset(k3, 0, AES_BLOCK_SIZE);
PORT_Memset(newKey, 0, AES_BLOCK_SIZE); return crv;
}
/* encode the final pad block of aes xcbc, padBuf is modified */
CK_RV
sftk_xcbc_mac_pad(unsignedchar *padBuf, unsignedint bufLen, unsignedint blockSize, constunsignedchar *k2, constunsignedchar *k3)
{ unsignedint i; if (bufLen == blockSize) { for (i = 0; i < blockSize; i++) {
padBuf[i] ^= k2[i];
}
} else {
padBuf[bufLen++] = 0x80; for (i = bufLen; i < blockSize; i++) {
padBuf[i] = 0x00;
} for (i = 0; i < blockSize; i++) {
padBuf[i] ^= k3[i];
}
} return CKR_OK;
}
/* Map the mechanism to the underlying hash. If the type is not a hash * or HMAC, return HASH_AlgNULL. This can happen legitimately if
* we are doing AES XCBC */ static HASH_HashType
sftk_map_hmac_to_hash(CK_MECHANISM_TYPE type)
{ switch (type) { case CKM_SHA_1_HMAC: case CKM_SHA_1: return HASH_AlgSHA1; case CKM_MD5_HMAC: case CKM_MD5: return HASH_AlgMD5; case CKM_MD2_HMAC: case CKM_MD2: return HASH_AlgMD2; case CKM_SHA224_HMAC: case CKM_SHA224: return HASH_AlgSHA224; case CKM_SHA256_HMAC: case CKM_SHA256: return HASH_AlgSHA256; case CKM_SHA384_HMAC: case CKM_SHA384: return HASH_AlgSHA384; case CKM_SHA512_HMAC: case CKM_SHA512: return HASH_AlgSHA512;
} return HASH_AlgNULL;
}
/* * Generally setup the context based on the mechanism. * If the mech is HMAC, context->hashObj should be set * Otherwise it is assumed to be AES XCBC. prf_setup * checks these assumptions and will return an error * if they are not met. NOTE: this function does not allocate * anything, so there is no requirement to free context after * prf_setup like there is if you call prf_init.
*/ static CK_RV
prf_setup(prfContext *context, CK_MECHANISM_TYPE mech)
{
context->hashType = sftk_map_hmac_to_hash(mech);
context->hashObj = NULL;
context->hmac = NULL;
context->aes = NULL; if (context->hashType != HASH_AlgNULL) {
context->hashObj = HASH_GetRawHashObject(context->hashType); if (context->hashObj == NULL) { return CKR_GENERAL_ERROR;
} return CKR_OK;
} elseif (mech == CKM_AES_XCBC_MAC) { return CKR_OK;
} return CKR_MECHANISM_PARAM_INVALID;
}
/* return the underlying prf length for this context. This will
* function once the context is setup */ static CK_RV
prf_length(prfContext *context)
{ if (context->hashObj) { return context->hashObj->length;
} return AES_BLOCK_SIZE; /* AES */
}
/* set up the key for the prf. prf_update or prf_final should not be called if * prf_init has not been called first. Once prf_init returns hmac and * aes contexts should set and valid.
*/ static CK_RV
prf_init(prfContext *context, constunsignedchar *keyValue, unsignedint keyLen)
{
CK_RV crv;
/* * process input to the prf
*/ static CK_RV
prf_update(prfContext *context, constunsignedchar *buf, unsignedint len)
{ unsignedint tmpLen;
SECStatus rv;
if (context->hmac) {
HMAC_Update(context->hmac, buf, len);
} else { /* AES MAC XCBC*/ /* We must keep the last block back so that it can be processed in * final. This is why we only check that nextChar + len > blocksize,
* rather than checking that nextChar + len >= blocksize */ while (context->nextChar + len > AES_BLOCK_SIZE) { if (context->nextChar != 0) { /* first handle fill in any partial blocks in the buffer */ unsignedint left = AES_BLOCK_SIZE - context->nextChar; /* note: left can be zero */
PORT_Memcpy(context->padBuf + context->nextChar, buf, left); /* NOTE: AES MAC XCBC xors the data with the previous block * We don't do that step here because our AES_Encrypt mode
* is CBC, which does the xor automatically */
rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen, sizeof(context->macBuf), context->padBuf, sizeof(context->padBuf)); if (rv != SECSuccess) { return sftk_MapCryptError(PORT_GetError());
}
context->nextChar = 0;
len -= left;
buf += left;
} else { /* optimization. if we have complete blocks to write out * (and will still have leftover blocks for padbuf in the end). * we can mac directly out of our buffer without first copying
* them to padBuf */
rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen, sizeof(context->macBuf), buf, AES_BLOCK_SIZE); if (rv != SECSuccess) { return sftk_MapCryptError(PORT_GetError());
}
len -= AES_BLOCK_SIZE;
buf += AES_BLOCK_SIZE;
}
}
PORT_Memcpy(context->padBuf + context->nextChar, buf, len);
context->nextChar += len;
} return CKR_OK;
}
/* * free the data associated with the prf. Clear any possible CSPs * This can safely be called on any context after prf_setup. It can * also be called an an already freed context. * A free context can be reused by calling prf_init again without * the need to call prf_setup.
*/ staticvoid
prf_free(prfContext *context)
{ if (context->hmac) {
HMAC_Destroy(context->hmac, PR_TRUE);
context->hmac = NULL;
} if (context->aes) {
PORT_Memset(context->k1, 0, sizeof(context->k1));
PORT_Memset(context->k2, 0, sizeof(context->k2));
PORT_Memset(context->k3, 0, sizeof(context->k2));
PORT_Memset(context->padBuf, 0, sizeof(context->padBuf));
PORT_Memset(context->macBuf, 0, sizeof(context->macBuf));
AES_DestroyContext(context->aes, PR_TRUE);
context->aes = NULL;
}
}
/* * extract the final prf value. On success, this has the side effect of * also freeing the context data and clearing the keys
*/ static CK_RV
prf_final(prfContext *context, unsignedchar *buf, unsignedint len)
{ unsignedint tmpLen;
SECStatus rv;
if (context->hmac) { unsignedint outLen;
HMAC_Finish(context->hmac, buf, &outLen, len); if (outLen != len) { return CKR_GENERAL_ERROR;
}
} else { /* prf_update had guarrenteed that the last full block is still in * the padBuf if the input data is a multiple of the blocksize. This
* allows sftk_xcbc_mac_pad to process that pad buf accordingly */
CK_RV crv = sftk_xcbc_mac_pad(context->padBuf, context->nextChar,
AES_BLOCK_SIZE, context->k2, context->k3); if (crv != CKR_OK) { return crv;
}
rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen, sizeof(context->macBuf), context->padBuf, AES_BLOCK_SIZE); if (rv != SECSuccess) { return sftk_MapCryptError(PORT_GetError());
}
PORT_Memcpy(buf, context->macBuf, len);
}
prf_free(context); return CKR_OK;
}
/* * There are four flavors of ike prf functions here. * ike_prf is used in both ikeV1 and ikeV2 to generate * an initial key that all the other keys are generated with. * * These functions are called from NSC_DeriveKey with the inKey value * already looked up, and it expects the CKA_VALUE for outKey to be set. * * Depending on usage it returns either: * 1. prf(Ni|Nr, inKey); (bDataAsKey=TRUE, bRekey=FALSE) * 2. prf(inKey, Ni|Nr); (bDataAsKkey=FALSE, bRekey=FALSE) * 3. prf(inKey, newKey | Ni | Nr); (bDataAsKey=FALSE, bRekey=TRUE) * The resulting output key is always the length of the underlying prf * (as returned by prf_length()). * The combination of bDataAsKey=TRUE and bRekey=TRUE is not allowed * * Case 1 is used in * a. ikev2 (rfc5996) inKey is called g^ir, the output is called SKEYSEED * b. ikev1 (rfc2409) inKey is called g^ir, the output is called SKEYID * Case 2 is used in ikev1 (rfc2409) inkey is called pre-shared-key, output * is called SKEYID * Case 3 is used in ikev2 (rfc5996) rekey case, inKey is SK_d, newKey is * g^ir (new), the output is called SKEYSEED
*/
CK_RV
sftk_ike_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey, const CK_NSS_IKE_PRF_DERIVE_PARAMS *params, SFTKObject *outKey)
{
SFTKAttribute *newKeyValue = NULL;
SFTKObject *newKeyObj = NULL; unsignedchar outKeyData[HASH_LENGTH_MAX]; unsignedchar *newInKey = NULL; unsignedint newInKeySize = 0; unsignedint macSize;
CK_RV crv = CKR_OK;
prfContext context;
crv = prf_setup(&context, params->prfMechanism); if (crv != CKR_OK) { return crv;
}
macSize = prf_length(&context); if ((params->bDataAsKey) && (params->bRekey)) { return CKR_ARGUMENTS_BAD;
} if (params->bRekey) { /* lookup the value of new key from the session and key handle */
SFTKSession *session = sftk_SessionFromHandle(hSession); if (session == NULL) { return CKR_SESSION_HANDLE_INVALID;
}
newKeyObj = sftk_ObjectFromHandle(params->hNewKey, session);
sftk_FreeSession(session); if (newKeyObj == NULL) { return CKR_KEY_HANDLE_INVALID;
}
newKeyValue = sftk_FindAttribute(newKeyObj, CKA_VALUE); if (newKeyValue == NULL) {
crv = CKR_KEY_HANDLE_INVALID; goto fail;
}
} if (params->bDataAsKey) { /* The key is Ni || Np, so we need to concatenate them together first */
newInKeySize = params->ulNiLen + params->ulNrLen;
newInKey = PORT_Alloc(newInKeySize); if (newInKey == NULL) {
crv = CKR_HOST_MEMORY; goto fail;
}
PORT_Memcpy(newInKey, params->pNi, params->ulNiLen);
PORT_Memcpy(newInKey + params->ulNiLen, params->pNr, params->ulNrLen);
crv = prf_init(&context, newInKey, newInKeySize); if (crv != CKR_OK) { goto fail;
} /* key as the data */
crv = prf_update(&context, inKey->attrib.pValue,
inKey->attrib.ulValueLen); if (crv != CKR_OK) { goto fail;
}
} else {
crv = prf_init(&context, inKey->attrib.pValue,
inKey->attrib.ulValueLen); if (crv != CKR_OK) { goto fail;
} if (newKeyValue) {
crv = prf_update(&context, newKeyValue->attrib.pValue,
newKeyValue->attrib.ulValueLen); if (crv != CKR_OK) { goto fail;
}
}
crv = prf_update(&context, params->pNi, params->ulNiLen); if (crv != CKR_OK) { goto fail;
}
crv = prf_update(&context, params->pNr, params->ulNrLen); if (crv != CKR_OK) { goto fail;
}
}
crv = prf_final(&context, outKeyData, macSize); if (crv != CKR_OK) { goto fail;
}
crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, macSize);
fail: if (newInKey) {
PORT_ZFree(newInKey, newInKeySize);
} if (newKeyValue) {
sftk_FreeAttribute(newKeyValue);
} if (newKeyObj) {
sftk_FreeObject(newKeyObj);
}
PORT_Memset(outKeyData, 0, macSize);
prf_free(&context); return crv;
}
/* * The second flavor of ike prf is ike1_prf. * * It is used by ikeV1 to generate the various session keys used in the * connection. It uses the initial key, an optional previous key, and a one byte * key number to generate a unique key for each of the various session * functions (encryption, decryption, mac). These keys expect a key size * (as they may vary in length based on usage). If no length is provided, * it will default to the length of the prf. * * This function returns either: * prf(inKey, gxyKey || CKYi || CKYr || key_number) * or * prf(inKey, prevkey || gxyKey || CKYi || CKYr || key_number) * depending on the stats of bHasPrevKey * * This is defined in rfc2409. For each of the following keys. * inKey is SKEYID, gxyKey is g^xy * for outKey = SKEYID_d, bHasPrevKey = false, key_number = 0 * for outKey = SKEYID_a, prevKey= SKEYID_d, key_number = 1 * for outKey = SKEYID_e, prevKey= SKEYID_a, key_number = 2
*/
CK_RV
sftk_ike1_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey, const CK_NSS_IKE1_PRF_DERIVE_PARAMS *params, SFTKObject *outKey, unsignedint keySize)
{
SFTKAttribute *gxyKeyValue = NULL;
SFTKObject *gxyKeyObj = NULL;
SFTKAttribute *prevKeyValue = NULL;
SFTKObject *prevKeyObj = NULL;
SFTKSession *session; unsignedchar outKeyData[HASH_LENGTH_MAX]; unsignedint macSize;
CK_RV crv;
prfContext context;
if (params->ulExtraDataLen != 0) {
quickMode = PR_TRUE;
}
macSize = prf_length(&context);
if (keySize == 0) {
keySize = macSize;
}
/* In appendix B, we are just expanding or contracting a single key. * If the input key is less than or equal to the the key size we want, * just subset the original key. In quick mode we are actually getting * new keys (salted with our seed data and our gxy key), so we want to
* run through our algorithm */ if ((!quickMode) && (keySize <= inKey->attrib.ulValueLen)) { return sftk_forceAttribute(outKey, CKA_VALUE,
inKey->attrib.pValue, keySize);
}
/* * this loop generates on block of the prf, basically * kn = prf(key, Kn-1 | [Keygxy] | [ExtraData]) * Kn is thisKey, Kn-1 is lastKey * key is inKey
*/
thisKey = outKeyData; for (genKeySize = 0; genKeySize < keySize; genKeySize += macSize) {
PRBool hashedData = PR_FALSE;
crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen); if (crv != CKR_OK) { goto fail;
} if (lastKey != NULL) {
crv = prf_update(&context, lastKey, macSize); if (crv != CKR_OK) { goto fail;
}
hashedData = PR_TRUE;
} if (gxyKeyValue != NULL) {
crv = prf_update(&context, gxyKeyValue->attrib.pValue,
gxyKeyValue->attrib.ulValueLen); if (crv != CKR_OK) { goto fail;
}
hashedData = PR_TRUE;
} if (params->ulExtraDataLen != 0) {
crv = prf_update(&context, params->pExtraData, params->ulExtraDataLen); if (crv != CKR_OK) { goto fail;
}
hashedData = PR_TRUE;
} /* if we haven't hashed anything yet, hash a zero */ if (hashedData == PR_FALSE) { constunsignedchar zero = 0;
crv = prf_update(&context, &zero, 1); if (crv != CKR_OK) { goto fail;
}
}
crv = prf_final(&context, thisKey, macSize); if (crv != CKR_OK) { goto fail;
}
lastKey = thisKey;
thisKey += macSize;
}
crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
fail: if (gxyKeyValue) {
sftk_FreeAttribute(gxyKeyValue);
} if (gxyKeyObj) {
sftk_FreeObject(gxyKeyObj);
} if (outKeyData) {
PORT_ZFree(outKeyData, outKeySize);
}
prf_free(&context); return crv;
}
/* * The final flavor of ike prf is ike_prf_plus * * It is used by ikeV2 to generate the various session keys used in the * connection. It uses the initial key and a feedback version of the prf * to generate sufficient bytes to cover all the session keys. The application * will then use CK_EXTRACT_KEY_FROM_KEY to pull out the various subkeys. * This function expects a key size to be set by the application to cover * all the keys. Unlike ike1_prf, if no length is provided, this function * will generate a KEY_RANGE_ERROR * * This function returns (from rfc5996): * prfplus = T1 | T2 | T3 | T4 |... Tn * where: * T1 = prf(K, S | 0x01) * T2 = prf(K, T1 | S | 0x02) * T3 = prf(K, T3 | S | 0x03) * T4 = prf(K, T4 | S | 0x04) * . * Tn = prf(K, T(n-1) | n) * K = inKey, S = seedKey | seedData
*/
/* * this loop generates on block of the prf, basically * Tn = prf(key, Tn-1 | S | n) * Tn is thisKey, Tn-2 is lastKey, S is seedKey || seedData, * key is inKey. currentByte = n-1 on entry.
*/
thisKey = outKeyData; for (getKeySize = 0; getKeySize < keySize; getKeySize += macSize) { /* if currentByte is 255, we'll overflow when we increment it below. * This can only happen if keysize > 255*macSize. In that case * the application has asked for too much key material, so return
* an error */ if (currentByte == 255) {
crv = CKR_KEY_SIZE_RANGE; goto fail;
}
crv = prf_init(&context, inKeyData, inKeyLen); if (crv != CKR_OK) { goto fail;
}
if (lastKey) {
crv = prf_update(&context, lastKey, macSize); if (crv != CKR_OK) { goto fail;
}
} /* prf the key first */ if (seedValue) {
crv = prf_update(&context, seedValue->attrib.pValue,
seedValue->attrib.ulValueLen); if (crv != CKR_OK) { goto fail;
}
} /* then prf the data */ if (params->ulSeedDataLen != 0) {
crv = prf_update(&context, params->pSeedData,
params->ulSeedDataLen); if (crv != CKR_OK) { goto fail;
}
}
currentByte++;
crv = prf_update(&context, ¤tByte, 1); if (crv != CKR_OK) { goto fail;
}
crv = prf_final(&context, thisKey, macSize); if (crv != CKR_OK) { goto fail;
}
lastKey = thisKey;
thisKey += macSize;
}
*outKeyDataPtr = outKeyData;
*outKeySizePtr = outKeySize;
outKeyData = NULL; /* don't free it here, our caller will free it */
fail: if (outKeyData) {
PORT_ZFree(outKeyData, outKeySize);
} if (seedValue) {
sftk_FreeAttribute(seedValue);
} if (seedKeyObj) {
sftk_FreeObject(seedKeyObj);
}
prf_free(&context); return crv;
}
/* sftk_aes_xcbc_new_keys: * * aes xcbc creates 3 new keys from the input key. The first key will be the * base key of the underlying cbc. The sign code hooks directly into encrypt * so we'll have to create a full PKCS #11 key with handle for that key. The * caller needs to delete the key when it's through setting up the context. * * The other two keys will be stored in the sign context until we need them * at the end.
*/
CK_RV
sftk_aes_xcbc_new_keys(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE_PTR phKey, unsignedchar *k2, unsignedchar *k3)
{
SFTKObject *key = NULL;
SFTKSession *session = NULL;
SFTKObject *inKeyObj = NULL;
SFTKAttribute *inKeyValue = NULL;
CK_KEY_TYPE key_type = CKK_AES;
CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
CK_BBOOL ck_true = CK_TRUE;
CK_RV crv = CKR_OK;
SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); unsignedchar buf[AES_BLOCK_SIZE];
if (!slot) { return CKR_SESSION_HANDLE_INVALID;
}
/* get the session */
session = sftk_SessionFromHandle(hSession); if (session == NULL) {
crv = CKR_SESSION_HANDLE_INVALID; goto fail;
}
/* * now lets create an object to hang the attributes off of
*/
key = sftk_NewObject(slot); /* fill in the handle later */ if (key == NULL) {
crv = CKR_HOST_MEMORY; goto fail;
}
/* make sure we don't have any class, key_type, or value fields */
sftk_DeleteAttributeType(key, CKA_CLASS);
sftk_DeleteAttributeType(key, CKA_KEY_TYPE);
sftk_DeleteAttributeType(key, CKA_VALUE);
sftk_DeleteAttributeType(key, CKA_SIGN);
/* Add the class, key_type, and value */
crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS)); if (crv != CKR_OK) { goto fail;
}
crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)); if (crv != CKR_OK) { goto fail;
}
crv = sftk_AddAttributeType(key, CKA_SIGN, &ck_true, sizeof(CK_BBOOL)); if (crv != CKR_OK) { goto fail;
}
crv = sftk_AddAttributeType(key, CKA_VALUE, buf, AES_BLOCK_SIZE); if (crv != CKR_OK) { goto fail;
}
/* * finish filling in the key and link it with our global system.
*/
crv = sftk_handleObject(key, session); if (crv != CKR_OK) { goto fail;
}
*phKey = key->handle;
fail: if (session) {
sftk_FreeSession(session);
}
if (inKeyValue) {
sftk_FreeAttribute(inKeyValue);
} if (inKeyObj) {
sftk_FreeObject(inKeyObj);
} if (key) {
sftk_FreeObject(key);
} /* clear our CSPs */
PORT_Memset(buf, 0, sizeof(buf)); if (crv != CKR_OK) {
PORT_Memset(k2, 0, AES_BLOCK_SIZE);
PORT_Memset(k3, 0, AES_BLOCK_SIZE);
} return crv;
}
/* * Helper function that tests a single prf test vector
*/ static SECStatus
prf_test(CK_MECHANISM_TYPE mech, constunsignedchar *inKey, unsignedint inKeyLen, constunsignedchar *plainText, unsignedint plainTextLen, constunsignedchar *expectedResult, unsignedint expectedResultLen)
{
PRUint8 ike_computed_mac[HASH_LENGTH_MAX];
prfContext context; unsignedint macSize;
CK_RV crv;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.21Bemerkung:
(vorverarbeitet am 2026-06-05)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.