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

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libcryptoutil/common/mechstr.c
          +++ new/usr/src/lib/libcryptoutil/common/mechstr.c
↓ open down ↓ 15 lines elided ↑ open up ↑
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26      -#pragma ident   "@(#)mechstr.c  1.6     08/01/07 SMI"
       26 +#pragma ident   "@(#)mechstr.c  1.7     08/06/30 SMI"
  27   27  
  28   28  /*
  29   29   * Convert Algorithm names as strings to PKCS#11 Mech numbers and vice versa.
  30   30   */
  31   31  
       32 +#include <limits.h>
  32   33  #include <string.h>
  33   34  #include <stdlib.h>
  34   35  #include <stdio.h>
  35   36  #include <security/cryptoki.h>
  36   37  #include <security/pkcs11t.h>
  37   38  
  38   39  #include <cryptoutil.h>
  39   40  
  40   41  /*
  41   42   * This table is a one-to-one mapping between mechanism names and numbers.
  42   43   * As such, it should not contain deprecated mechanism names (aliases).
  43   44   */
  44      -static const struct {
  45      -        const char *str;
  46      -        CK_MECHANISM_TYPE mech;
  47      -} mapping[] = {
       45 +typedef struct {
       46 +        const char              *str;
       47 +        CK_MECHANISM_TYPE       mech;
       48 +} pkcs11_mapping_t;
       49 +
       50 +/*
       51 + * Note: elements in this table MUST be in numeric order,
       52 + * since bsearch(3C) is used to search this table.
       53 + */
       54 +static const pkcs11_mapping_t mapping[] = {
  48   55          { "CKM_RSA_PKCS_KEY_PAIR_GEN", CKM_RSA_PKCS_KEY_PAIR_GEN },
  49   56          { "CKM_RSA_PKCS", CKM_RSA_PKCS },
  50   57          { "CKM_RSA_9796", CKM_RSA_9796 },
  51   58          { "CKM_RSA_X_509", CKM_RSA_X_509 },
  52   59          { "CKM_MD2_RSA_PKCS", CKM_MD2_RSA_PKCS },
  53   60          { "CKM_MD5_RSA_PKCS", CKM_MD5_RSA_PKCS },
  54   61          { "CKM_SHA1_RSA_PKCS", CKM_SHA1_RSA_PKCS },
  55   62          { "CKM_RIPEMD128_RSA_PKCS", CKM_RIPEMD128_RSA_PKCS },
  56   63          { "CKM_RIPEMD160_RSA_PKCS", CKM_RIPEMD160_RSA_PKCS },
  57   64          { "CKM_RSA_PKCS_OAEP", CKM_RSA_PKCS_OAEP },
↓ open down ↓ 228 lines elided ↑ open up ↑
 286  293          { "CKM_TWOFISH_CBC", CKM_TWOFISH_CBC },
 287  294          { "CKM_DES_ECB_ENCRYPT_DATA", CKM_DES_ECB_ENCRYPT_DATA },
 288  295          { "CKM_DES_CBC_ENCRYPT_DATA", CKM_DES_CBC_ENCRYPT_DATA },
 289  296          { "CKM_DES3_ECB_ENCRYPT_DATA", CKM_DES3_ECB_ENCRYPT_DATA },
 290  297          { "CKM_DES3_CBC_ENCRYPT_DATA", CKM_DES3_CBC_ENCRYPT_DATA },
 291  298          { "CKM_AES_ECB_ENCRYPT_DATA", CKM_AES_ECB_ENCRYPT_DATA },
 292  299          { "CKM_AES_CBC_ENCRYPT_DATA", CKM_AES_CBC_ENCRYPT_DATA },
 293  300          { "CKM_DSA_PARAMETER_GEN", CKM_DSA_PARAMETER_GEN },
 294  301          { "CKM_DH_PKCS_PARAMETER_GEN", CKM_DH_PKCS_PARAMETER_GEN },
 295  302          { "CKM_X9_42_DH_PARAMETER_GEN", CKM_X9_42_DH_PARAMETER_GEN },
 296      -        { "CKM_VENDOR_DEFINED", CKM_VENDOR_DEFINED },
      303 +        /*
      304 +         * Values above 0x8000000 (CKM_VENDOR_DEFINED) are represented
      305 +         * as strings with hexadecimal numbers (e.g., "0x8123456").
      306 +         */
 297  307          { NULL, 0 }
 298  308  };
 299  309  
      310 +
 300  311  /*
      312 + * pkcs11_mech_comp - compare two pkcs11_mapping_t structures
      313 + *
      314 + * Return a strcmp-like result (positive, zero, or negative).
      315 + * For use with bsearch(3C) in pkcs11_mech2str().
      316 + */
      317 +static int
      318 +pkcs11_mech_comp(const void *mapping1, const void *mapping2) {
      319 +        return (((pkcs11_mapping_t *)mapping1)->mech -
      320 +                ((pkcs11_mapping_t *)mapping2)->mech);
      321 +}
      322 +
      323 +
      324 +/*
 301  325   * pkcs11_mech2str - convert PKCS#11 mech to a string
 302  326   *
 303  327   * Anything below CKM_VENDOR_DEFINED that wasn't in the mapping table
 304  328   * at build time causes NULL to be returned.  Anything above it also
 305      - * returns NULL since we have no way to know what its real name is.
      329 + * returns NULL since we have no way to know its real name.
 306  330   */
 307      -char
      331 +const char
 308  332  *pkcs11_mech2str(CK_MECHANISM_TYPE mech)
 309  333  {
 310      -        int i;
 311      -        char buf[11];   /* Num chars for representing ulong in ASCII */
      334 +        pkcs11_mapping_t        target;
      335 +        pkcs11_mapping_t        *result = NULL;
 312  336  
 313  337          if (mech > CKM_VENDOR_DEFINED) {
 314      -                (void) snprintf(buf, sizeof (buf), "%#lx", mech);
 315      -                return (strdup(buf));
      338 +                return (NULL);
 316  339          }
 317  340  
 318      -        for (i = 0; mapping[i].str; i++) {
 319      -                if (mapping[i].mech == mech)
 320      -                        return (strdup(mapping[i].str));
      341 +        /* Search for the mechanism number using bsearch(3C) */
      342 +        target.mech = mech;
      343 +        target.str = NULL;
      344 +        result = (pkcs11_mapping_t *)bsearch((void *)&target, (void *)mapping,
      345 +            (sizeof (mapping) / sizeof (pkcs11_mapping_t)) - 1,
      346 +            sizeof (pkcs11_mapping_t), pkcs11_mech_comp);
      347 +        if (result != NULL) {
      348 +                return (result->str);
 321  349          }
 322  350  
 323  351          return (NULL);
 324  352  }
 325  353  
 326  354  /*
 327  355   * pkcs11_str2mech - convert a string into a PKCS#11 mech number.
 328  356   *
 329      - * Since there isn't reserved value for an invalid mech we return
      357 + * Since there isn't a reserved value for an invalid mech we return
 330  358   * CKR_MECHANISM_INVALID for anything we don't recognise.
 331  359   * The value in mech isn't meaningful in these cases.
 332  360   */
 333  361  CK_RV
 334  362  pkcs11_str2mech(char *mech_str, CK_MECHANISM_TYPE_PTR mech)
 335  363  {
 336      -        int i;
 337      -        char *tmech_str;
      364 +        int     i;
      365 +        int     compare_off = 0;
 338  366  
 339  367          if (mech_str == NULL)
 340  368                  return (CKR_MECHANISM_INVALID);
 341  369  
 342      -        if (strncasecmp(mech_str, "0x8", 3) == 0) {
      370 +        if (strncasecmp(mech_str, "0x", 2) == 0) {
      371 +                long long llnum;
 343  372                  cryptodebug("pkcs11_str2mech: hex string passed in: %s",
 344  373                      mech_str);
 345      -                *mech = strtoll(mech_str, NULL, 16);
 346      -                return (CKR_OK);
      374 +                llnum = strtoll(mech_str, NULL, 16);
      375 +                if ((llnum >= CKM_VENDOR_DEFINED) && (llnum <= UINT_MAX)) {
      376 +                        *mech = llnum;
      377 +                        return (CKR_OK);
      378 +                } else {
      379 +                        return (CKR_MECHANISM_INVALID);
      380 +                }
 347  381          }
 348  382  
      383 +        /* If there's no CKM_ prefix, then ignore it in comparisons */
 349  384          if (strncasecmp(mech_str, "CKM_", 4) != 0) {
 350      -                size_t tmech_strlen = strlen(mech_str) + 4 + 1;
 351  385                  cryptodebug("pkcs11_str2mech: no CKM_ prefix: %s", mech_str);
 352      -                tmech_str = malloc(tmech_strlen * sizeof (char));
 353      -                (void) snprintf(tmech_str, tmech_strlen, "CKM_%s", mech_str);
 354      -                cryptodebug("pkcs11_str2mech: with prefix: %s", tmech_str);
 355      -        } else {
 356      -                tmech_str = mech_str;
      386 +                cryptodebug("pkcs11_str2mech: with prefix: CKM_%s", mech_str);
      387 +                compare_off = 4;
 357  388          }
 358  389  
      390 +        /* Linear search for a matching string */
 359  391          for (i = 0; mapping[i].str; i++) {
 360      -                if (strcasecmp(mapping[i].str, tmech_str) == 0) {
      392 +                if (strcasecmp(&mapping[i].str[compare_off], mech_str) == 0) {
 361  393                          *mech = mapping[i].mech;
 362      -                        if (tmech_str != mech_str)
 363      -                                free(tmech_str);
 364  394                          return (CKR_OK);
 365  395                  }
 366  396          }
 367      -        if (tmech_str != mech_str)
 368      -                free(tmech_str);
 369  397  
 370  398          return (CKR_MECHANISM_INVALID);
 371  399  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX