Print this page
5031131 perf: pkcs11_kernel can benefit from a more efficient pkcs11_mech2str()
4947627 improve libcrypto string/mechanism conversion functions in edge cases
*** 21,36 ****
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
! #pragma ident "@(#)mechstr.c 1.6 08/01/07 SMI"
/*
* Convert Algorithm names as strings to PKCS#11 Mech numbers and vice versa.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <security/cryptoki.h>
#include <security/pkcs11t.h>
--- 21,37 ----
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
! #pragma ident "@(#)mechstr.c 1.7 08/06/30 SMI"
/*
* Convert Algorithm names as strings to PKCS#11 Mech numbers and vice versa.
*/
+ #include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <security/cryptoki.h>
#include <security/pkcs11t.h>
*** 39,52 ****
/*
* This table is a one-to-one mapping between mechanism names and numbers.
* As such, it should not contain deprecated mechanism names (aliases).
*/
! static const struct {
const char *str;
CK_MECHANISM_TYPE mech;
! } mapping[] = {
{ "CKM_RSA_PKCS_KEY_PAIR_GEN", CKM_RSA_PKCS_KEY_PAIR_GEN },
{ "CKM_RSA_PKCS", CKM_RSA_PKCS },
{ "CKM_RSA_9796", CKM_RSA_9796 },
{ "CKM_RSA_X_509", CKM_RSA_X_509 },
{ "CKM_MD2_RSA_PKCS", CKM_MD2_RSA_PKCS },
--- 40,59 ----
/*
* This table is a one-to-one mapping between mechanism names and numbers.
* As such, it should not contain deprecated mechanism names (aliases).
*/
! typedef struct {
const char *str;
CK_MECHANISM_TYPE mech;
! } pkcs11_mapping_t;
!
! /*
! * Note: elements in this table MUST be in numeric order,
! * since bsearch(3C) is used to search this table.
! */
! static const pkcs11_mapping_t mapping[] = {
{ "CKM_RSA_PKCS_KEY_PAIR_GEN", CKM_RSA_PKCS_KEY_PAIR_GEN },
{ "CKM_RSA_PKCS", CKM_RSA_PKCS },
{ "CKM_RSA_9796", CKM_RSA_9796 },
{ "CKM_RSA_X_509", CKM_RSA_X_509 },
{ "CKM_MD2_RSA_PKCS", CKM_MD2_RSA_PKCS },
*** 291,371 ****
{ "CKM_AES_ECB_ENCRYPT_DATA", CKM_AES_ECB_ENCRYPT_DATA },
{ "CKM_AES_CBC_ENCRYPT_DATA", CKM_AES_CBC_ENCRYPT_DATA },
{ "CKM_DSA_PARAMETER_GEN", CKM_DSA_PARAMETER_GEN },
{ "CKM_DH_PKCS_PARAMETER_GEN", CKM_DH_PKCS_PARAMETER_GEN },
{ "CKM_X9_42_DH_PARAMETER_GEN", CKM_X9_42_DH_PARAMETER_GEN },
! { "CKM_VENDOR_DEFINED", CKM_VENDOR_DEFINED },
{ NULL, 0 }
};
/*
* pkcs11_mech2str - convert PKCS#11 mech to a string
*
* Anything below CKM_VENDOR_DEFINED that wasn't in the mapping table
* at build time causes NULL to be returned. Anything above it also
! * returns NULL since we have no way to know what its real name is.
*/
! char
*pkcs11_mech2str(CK_MECHANISM_TYPE mech)
{
! int i;
! char buf[11]; /* Num chars for representing ulong in ASCII */
if (mech > CKM_VENDOR_DEFINED) {
! (void) snprintf(buf, sizeof (buf), "%#lx", mech);
! return (strdup(buf));
}
! for (i = 0; mapping[i].str; i++) {
! if (mapping[i].mech == mech)
! return (strdup(mapping[i].str));
}
return (NULL);
}
/*
* pkcs11_str2mech - convert a string into a PKCS#11 mech number.
*
! * Since there isn't reserved value for an invalid mech we return
* CKR_MECHANISM_INVALID for anything we don't recognise.
* The value in mech isn't meaningful in these cases.
*/
CK_RV
pkcs11_str2mech(char *mech_str, CK_MECHANISM_TYPE_PTR mech)
{
int i;
! char *tmech_str;
if (mech_str == NULL)
return (CKR_MECHANISM_INVALID);
! if (strncasecmp(mech_str, "0x8", 3) == 0) {
cryptodebug("pkcs11_str2mech: hex string passed in: %s",
mech_str);
! *mech = strtoll(mech_str, NULL, 16);
return (CKR_OK);
}
if (strncasecmp(mech_str, "CKM_", 4) != 0) {
- size_t tmech_strlen = strlen(mech_str) + 4 + 1;
cryptodebug("pkcs11_str2mech: no CKM_ prefix: %s", mech_str);
! tmech_str = malloc(tmech_strlen * sizeof (char));
! (void) snprintf(tmech_str, tmech_strlen, "CKM_%s", mech_str);
! cryptodebug("pkcs11_str2mech: with prefix: %s", tmech_str);
! } else {
! tmech_str = mech_str;
}
for (i = 0; mapping[i].str; i++) {
! if (strcasecmp(mapping[i].str, tmech_str) == 0) {
*mech = mapping[i].mech;
- if (tmech_str != mech_str)
- free(tmech_str);
return (CKR_OK);
}
}
- if (tmech_str != mech_str)
- free(tmech_str);
return (CKR_MECHANISM_INVALID);
}
--- 298,399 ----
{ "CKM_AES_ECB_ENCRYPT_DATA", CKM_AES_ECB_ENCRYPT_DATA },
{ "CKM_AES_CBC_ENCRYPT_DATA", CKM_AES_CBC_ENCRYPT_DATA },
{ "CKM_DSA_PARAMETER_GEN", CKM_DSA_PARAMETER_GEN },
{ "CKM_DH_PKCS_PARAMETER_GEN", CKM_DH_PKCS_PARAMETER_GEN },
{ "CKM_X9_42_DH_PARAMETER_GEN", CKM_X9_42_DH_PARAMETER_GEN },
! /*
! * Values above 0x8000000 (CKM_VENDOR_DEFINED) are represented
! * as strings with hexadecimal numbers (e.g., "0x8123456").
! */
{ NULL, 0 }
};
+
/*
+ * pkcs11_mech_comp - compare two pkcs11_mapping_t structures
+ *
+ * Return a strcmp-like result (positive, zero, or negative).
+ * For use with bsearch(3C) in pkcs11_mech2str().
+ */
+ static int
+ pkcs11_mech_comp(const void *mapping1, const void *mapping2) {
+ return (((pkcs11_mapping_t *)mapping1)->mech -
+ ((pkcs11_mapping_t *)mapping2)->mech);
+ }
+
+
+ /*
* pkcs11_mech2str - convert PKCS#11 mech to a string
*
* Anything below CKM_VENDOR_DEFINED that wasn't in the mapping table
* at build time causes NULL to be returned. Anything above it also
! * returns NULL since we have no way to know its real name.
*/
! const char
*pkcs11_mech2str(CK_MECHANISM_TYPE mech)
{
! pkcs11_mapping_t target;
! pkcs11_mapping_t *result = NULL;
if (mech > CKM_VENDOR_DEFINED) {
! return (NULL);
}
! /* Search for the mechanism number using bsearch(3C) */
! target.mech = mech;
! target.str = NULL;
! result = (pkcs11_mapping_t *)bsearch((void *)&target, (void *)mapping,
! (sizeof (mapping) / sizeof (pkcs11_mapping_t)) - 1,
! sizeof (pkcs11_mapping_t), pkcs11_mech_comp);
! if (result != NULL) {
! return (result->str);
}
return (NULL);
}
/*
* pkcs11_str2mech - convert a string into a PKCS#11 mech number.
*
! * Since there isn't a reserved value for an invalid mech we return
* CKR_MECHANISM_INVALID for anything we don't recognise.
* The value in mech isn't meaningful in these cases.
*/
CK_RV
pkcs11_str2mech(char *mech_str, CK_MECHANISM_TYPE_PTR mech)
{
int i;
! int compare_off = 0;
if (mech_str == NULL)
return (CKR_MECHANISM_INVALID);
! if (strncasecmp(mech_str, "0x", 2) == 0) {
! long long llnum;
cryptodebug("pkcs11_str2mech: hex string passed in: %s",
mech_str);
! llnum = strtoll(mech_str, NULL, 16);
! if ((llnum >= CKM_VENDOR_DEFINED) && (llnum <= UINT_MAX)) {
! *mech = llnum;
return (CKR_OK);
+ } else {
+ return (CKR_MECHANISM_INVALID);
}
+ }
+ /* If there's no CKM_ prefix, then ignore it in comparisons */
if (strncasecmp(mech_str, "CKM_", 4) != 0) {
cryptodebug("pkcs11_str2mech: no CKM_ prefix: %s", mech_str);
! cryptodebug("pkcs11_str2mech: with prefix: CKM_%s", mech_str);
! compare_off = 4;
}
+ /* Linear search for a matching string */
for (i = 0; mapping[i].str; i++) {
! if (strcasecmp(&mapping[i].str[compare_off], mech_str) == 0) {
*mech = mapping[i].mech;
return (CKR_OK);
}
}
return (CKR_MECHANISM_INVALID);
}