Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -7448,6 +7448,35 @@ CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession,
break;
}

if (rv == CKR_OK) {
int idx;

/* C_GenerateKey always yields a secret key of the mechanism-implied
* type. Reject a template that names a different class or key type
* rather than letting it override the generated object. Every
* occurrence is checked because a later duplicate would otherwise be
* applied by SetAttributeValue. The count is bounded to int as
* elsewhere so a caller-supplied length cannot drive an over-read. */
for (idx = 0; idx < (int)ulCount && rv == CKR_OK; idx++) {
CK_ATTRIBUTE* attr = &pTemplate[idx];

if (attr->type == CKA_CLASS) {
if (attr->pValue == NULL ||
attr->ulValueLen != sizeof(CK_OBJECT_CLASS))
rv = CKR_ATTRIBUTE_VALUE_INVALID;
else if (*(CK_OBJECT_CLASS*)attr->pValue != CKO_SECRET_KEY)
rv = CKR_TEMPLATE_INCONSISTENT;
}
else if (attr->type == CKA_KEY_TYPE) {
if (attr->pValue == NULL ||
attr->ulValueLen != sizeof(CK_KEY_TYPE))
rv = CKR_ATTRIBUTE_VALUE_INVALID;
else if (*(CK_KEY_TYPE*)attr->pValue != keyType)
rv = CKR_TEMPLATE_INCONSISTENT;
}
}
}

if (rv == CKR_OK) {
CK_ATTRIBUTE *lenAttr = NULL;

Expand Down Expand Up @@ -7805,6 +7834,38 @@ CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession,
* type of operation.
* CKR_OK on success.
*/
/* Reject a key-pair template whose CKA_CLASS or CKA_KEY_TYPE, in any position,
* disagrees with the class and type the mechanism implies. */
static CK_RV CheckGenPairAttrs(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
CK_OBJECT_CLASS expectClass,
CK_KEY_TYPE expectType)
{
int i;

/* Bound the count to int as elsewhere so a caller-supplied length cannot
* drive an over-read past the template array. */
for (i = 0; i < (int)ulCount; i++) {
CK_ATTRIBUTE* attr = &pTemplate[i];

if (attr->type == CKA_CLASS) {
if (attr->pValue == NULL ||
attr->ulValueLen != sizeof(CK_OBJECT_CLASS))
return CKR_ATTRIBUTE_VALUE_INVALID;
if (*(CK_OBJECT_CLASS*)attr->pValue != expectClass)
return CKR_TEMPLATE_INCONSISTENT;
}
else if (attr->type == CKA_KEY_TYPE) {
if (attr->pValue == NULL ||
attr->ulValueLen != sizeof(CK_KEY_TYPE))
return CKR_ATTRIBUTE_VALUE_INVALID;
if (*(CK_KEY_TYPE*)attr->pValue != expectType)
return CKR_TEMPLATE_INCONSISTENT;
}
}

return CKR_OK;
}

CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_ATTRIBUTE_PTR pPublicKeyTemplate,
Expand All @@ -7820,6 +7881,8 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession,
WP11_Object* pub = NULL;
WP11_Object* priv = NULL;
CK_ATTRIBUTE* reqAttr = NULL;
CK_KEY_TYPE pairType = 0;
int knownMech = 1;

WOLFPKCS11_ENTER("C_GenerateKeyPair");
#ifdef DEBUG_WOLFPKCS11
Expand Down Expand Up @@ -7888,6 +7951,52 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession,
return rv;
}

/* Reject a template whose class or key type contradicts the mechanism
* before any object is constructed. */
switch (pMechanism->mechanism) {
#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)
case CKM_RSA_PKCS_KEY_PAIR_GEN:
pairType = CKK_RSA;
break;
#endif
#ifdef HAVE_ECC
case CKM_EC_KEY_PAIR_GEN:
pairType = CKK_EC;
break;
#endif
#ifdef WOLFPKCS11_MLDSA
case CKM_ML_DSA_KEY_PAIR_GEN:
pairType = CKK_ML_DSA;
break;
#endif
#ifdef WOLFPKCS11_MLKEM
case CKM_ML_KEM_KEY_PAIR_GEN:
pairType = CKK_ML_KEM;
break;
#endif
#ifndef NO_DH
case CKM_DH_PKCS_KEY_PAIR_GEN:
pairType = CKK_DH;
break;
#endif
default:
knownMech = 0;
break;
}
if (knownMech) {
rv = CheckGenPairAttrs(pPublicKeyTemplate, ulPublicKeyAttributeCount,
CKO_PUBLIC_KEY, pairType);
if (rv == CKR_OK) {
rv = CheckGenPairAttrs(pPrivateKeyTemplate,
ulPrivateKeyAttributeCount, CKO_PRIVATE_KEY,
pairType);
}
if (rv != CKR_OK) {
WOLFPKCS11_LEAVE("C_GenerateKeyPair", rv);
return rv;
}
}

switch (pMechanism->mechanism) {
#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)
case CKM_RSA_PKCS_KEY_PAIR_GEN:
Expand Down
152 changes: 152 additions & 0 deletions tests/generate_key_class_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/* generate_key_class_test.c
*
* Copyright (C) 2006-2025 wolfSSL Inc.
*
* This file is part of wolfPKCS11.
*
* wolfPKCS11 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfPKCS11 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*
* C_GenerateKey must reject a template whose CKA_CLASS or CKA_KEY_TYPE is
* inconsistent with the generation mechanism.
*/

#ifdef HAVE_CONFIG_H
#include <wolfpkcs11/config.h>
#endif

#include <stdio.h>
#include <string.h>

#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/misc.h>

#ifndef WOLFPKCS11_USER_SETTINGS
#include <wolfpkcs11/options.h>
#endif
#include <wolfpkcs11/pkcs11.h>

#ifndef HAVE_PKCS11_STATIC
#include <dlfcn.h>
#endif

#include "testdata.h"
#include "pkcs11_test_util.h"

#define TEST_DIR "./store/generate_key_class_test"

#ifndef NO_AES
static int run_test(void)
{
CK_RV rv;
CK_SESSION_HANDLE session = 0;
CK_OBJECT_HANDLE key = CK_INVALID_HANDLE;
CK_MECHANISM mech = { CKM_AES_KEY_GEN, NULL, 0 };
CK_ULONG valueLen = 16;
CK_OBJECT_CLASS dataClass = CKO_DATA;
CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
CK_KEY_TYPE rsaType = CKK_RSA;
CK_KEY_TYPE aesType = CKK_AES;
CK_BBOOL ckFalse = CK_FALSE;
CK_ATTRIBUTE badClass[] = {
{ CKA_VALUE_LEN, &valueLen, sizeof(valueLen) },
{ CKA_PRIVATE, &ckFalse, sizeof(ckFalse) },
{ CKA_CLASS, &dataClass, sizeof(dataClass) },
};
CK_ATTRIBUTE badKeyType[] = {
{ CKA_VALUE_LEN, &valueLen, sizeof(valueLen) },
{ CKA_PRIVATE, &ckFalse, sizeof(ckFalse) },
{ CKA_KEY_TYPE, &rsaType, sizeof(rsaType) },
};
CK_ATTRIBUTE goodTmpl[] = {
{ CKA_VALUE_LEN, &valueLen, sizeof(valueLen) },
{ CKA_PRIVATE, &ckFalse, sizeof(ckFalse) },
{ CKA_CLASS, &secretClass, sizeof(secretClass) },
{ CKA_KEY_TYPE, &aesType, sizeof(aesType) },
};
CK_ATTRIBUTE minimalTmpl[] = {
{ CKA_VALUE_LEN, &valueLen, sizeof(valueLen) },
{ CKA_PRIVATE, &ckFalse, sizeof(ckFalse) },
};
CK_ATTRIBUTE dupClass[] = {
{ CKA_VALUE_LEN, &valueLen, sizeof(valueLen) },
{ CKA_PRIVATE, &ckFalse, sizeof(ckFalse) },
{ CKA_CLASS, &secretClass, sizeof(secretClass) },
{ CKA_CLASS, &dataClass, sizeof(dataClass) },
};

rv = pkcs11_load();
CHECK_RV(rv, "load library", CKR_OK);
if (rv != CKR_OK)
return -1;

rv = pkcs11_open_session(&session);
CHECK_RV(rv, "open session", CKR_OK);
if (rv != CKR_OK)
goto out;

rv = funcList->C_GenerateKey(session, &mech, badClass,
sizeof(badClass) / sizeof(*badClass), &key);
CHECK_RV(rv, "C_GenerateKey(inconsistent CKA_CLASS)",
CKR_TEMPLATE_INCONSISTENT);

rv = funcList->C_GenerateKey(session, &mech, badKeyType,
sizeof(badKeyType) / sizeof(*badKeyType),
&key);
CHECK_RV(rv, "C_GenerateKey(inconsistent CKA_KEY_TYPE)",
CKR_TEMPLATE_INCONSISTENT);

rv = funcList->C_GenerateKey(session, &mech, goodTmpl,
sizeof(goodTmpl) / sizeof(*goodTmpl), &key);
CHECK_RV(rv, "C_GenerateKey(consistent class and type)", CKR_OK);

rv = funcList->C_GenerateKey(session, &mech, minimalTmpl,
sizeof(minimalTmpl) / sizeof(*minimalTmpl),
&key);
CHECK_RV(rv, "C_GenerateKey(no class in template)", CKR_OK);

rv = funcList->C_GenerateKey(session, &mech, dupClass,
sizeof(dupClass) / sizeof(*dupClass), &key);
CHECK_RV(rv, "C_GenerateKey(duplicate inconsistent CKA_CLASS)",
CKR_TEMPLATE_INCONSISTENT);

out:
if (session != 0)
funcList->C_CloseSession(session);
funcList->C_Finalize(NULL);
pkcs11_unload();
return 0;
}
#endif /* !NO_AES */

int main(int argc, char* argv[])
{
(void)argc;
(void)argv;

#ifndef WOLFPKCS11_NO_ENV
XSETENV("WOLFPKCS11_TOKEN_PATH", TEST_DIR, 1);
#endif

printf("=== wolfPKCS11 C_GenerateKey class consistency test ===\n");
#ifndef NO_AES
run_test();
#else
printf("AES not compiled in!\n");
#endif
return pkcs11_test_summary();
}
Loading
Loading