Print this page
    
(void) an sk_set via a macro which upsets lint.  If the macro is
complicated, this might need to be /* LINTED */ instead
remove lint supression made unnecessary by the openssl upgrade
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c
          +++ new/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c
   1    1  /*
   2    2   * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
   3    3   *
   4    4   * Use is subject to license terms.
   5    5   */
   6    6  /*
   7    7   * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
   8    8   */
   9    9  /*
  10   10   * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
  11   11   * project 2000.
  12   12   */
  13   13  /*
  14   14   * ====================================================================
  15   15   * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
  16   16   *
  17   17   * Redistribution and use in source and binary forms, with or without
  18   18   * modification, are permitted provided that the following conditions
  19   19   * are met:
  20   20   *
  21   21   * 1. Redistributions of source code must retain the above copyright
  22   22   *    notice, this list of conditions and the following disclaimer.
  23   23   *
  24   24   * 2. Redistributions in binary form must reproduce the above copyright
  25   25   *    notice, this list of conditions and the following disclaimer in
  26   26   *    the documentation and/or other materials provided with the
  27   27   *    distribution.
  28   28   *
  29   29   * 3. All advertising materials mentioning features or use of this
  30   30   *    software must display the following acknowledgment:
  31   31   *    "This product includes software developed by the OpenSSL Project
  32   32   *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  33   33   *
  34   34   * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  35   35   *    endorse or promote products derived from this software without
  36   36   *    prior written permission. For written permission, please contact
  37   37   *    licensing@OpenSSL.org.
  38   38   *
  39   39   * 5. Products derived from this software may not be called "OpenSSL"
  40   40   *    nor may "OpenSSL" appear in their names without prior written
  41   41   *    permission of the OpenSSL Project.
  42   42   *
  43   43   * 6. Redistributions of any form whatsoever must retain the following
  44   44   *    acknowledgment:
  45   45   *    "This product includes software developed by the OpenSSL Project
  46   46   *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  47   47   *
  48   48   * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  49   49   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  50   50   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  51   51   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  52   52   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  53   53   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  54   54   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  55   55   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  56   56   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  57   57   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  58   58   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  59   59   * OF THE POSSIBILITY OF SUCH DAMAGE.
  60   60   * ====================================================================
  61   61   *
  62   62   * This product includes cryptographic software written by Eric Young
  63   63   * (eay@cryptsoft.com).  This product includes software written by Tim
  64   64   * Hudson (tjh@cryptsoft.com).
  65   65   *
  66   66   */
  67   67  
  68   68  #include <stdlib.h>
  69   69  #include <kmfapiP.h>
  70   70  #include <ber_der.h>
  71   71  #include <fcntl.h>
  72   72  #include <sys/stat.h>
  73   73  #include <dirent.h>
  74   74  #include <cryptoutil.h>
  75   75  #include <synch.h>
  76   76  #include <thread.h>
  77   77  
  78   78  /* OPENSSL related headers */
  79   79  #include <openssl/bio.h>
  80   80  #include <openssl/bn.h>
  81   81  #include <openssl/asn1.h>
  82   82  #include <openssl/err.h>
  83   83  #include <openssl/bn.h>
  84   84  #include <openssl/x509.h>
  85   85  #include <openssl/rsa.h>
  86   86  #include <openssl/dsa.h>
  87   87  #include <openssl/x509v3.h>
  88   88  #include <openssl/objects.h>
  89   89  #include <openssl/pem.h>
  90   90  #include <openssl/pkcs12.h>
  91   91  #include <openssl/ocsp.h>
  92   92  #include <openssl/des.h>
  93   93  #include <openssl/rand.h>
  94   94  
  95   95  #define PRINT_ANY_EXTENSION (\
  96   96          KMF_X509_EXT_KEY_USAGE |\
  97   97          KMF_X509_EXT_CERT_POLICIES |\
  98   98          KMF_X509_EXT_SUBJALTNAME |\
  99   99          KMF_X509_EXT_BASIC_CONSTRAINTS |\
 100  100          KMF_X509_EXT_NAME_CONSTRAINTS |\
 101  101          KMF_X509_EXT_POLICY_CONSTRAINTS |\
 102  102          KMF_X509_EXT_EXT_KEY_USAGE |\
 103  103          KMF_X509_EXT_INHIBIT_ANY_POLICY |\
 104  104          KMF_X509_EXT_AUTH_KEY_ID |\
 105  105          KMF_X509_EXT_SUBJ_KEY_ID |\
 106  106          KMF_X509_EXT_POLICY_MAPPING)
 107  107  
 108  108  static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
 109  109          0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
 110  110          0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
 111  111          0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
 112  112          0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
 113  113          0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
 114  114          0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
 115  115          0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
 116  116          0x91 };
 117  117  
 118  118  static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
 119  119          0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
 120  120          0x8e, 0xda, 0xce, 0x91, 0x5f };
 121  121  
 122  122  static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
 123  123          0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
 124  124          0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
 125  125          0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
 126  126          0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
 127  127          0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
 128  128          0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
 129  129          0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
 130  130          0x02 };
 131  131  
 132  132  #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
 133  133          h->lasterr.errcode = c;
 134  134  
 135  135  #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
 136  136  
 137  137  /*
 138  138   * Declare some new macros for managing stacks of EVP_PKEYS, similar to
 139  139   * what wanboot did.
 140  140   */
 141  141  DECLARE_STACK_OF(EVP_PKEY)
 142  142  
 143  143  #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
 144  144  #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
 145  145  #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
 146  146  #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
 147  147  #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
 148  148  #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
 149  149          (free_func))
 150  150  
 151  151  mutex_t init_lock = DEFAULTMUTEX;
 152  152  static int ssl_initialized = 0;
 153  153  static BIO *bio_err = NULL;
 154  154  
 155  155  static int
 156  156  test_for_file(char *, mode_t);
 157  157  static KMF_RETURN
 158  158  openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
 159  159      STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
 160  160  
 161  161  static KMF_RETURN
 162  162  local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
 163  163      int, KMF_KEY_HANDLE *, char *);
 164  164  
 165  165  static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
 166  166  
 167  167  static KMF_RETURN
 168  168  extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
 169  169      CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
 170  170  
 171  171  static KMF_RETURN
 172  172  kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
 173  173      char *, KMF_DATA *);
 174  174  
 175  175  static KMF_RETURN
 176  176  load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
 177  177      char *, KMF_DATA **, uint32_t *);
 178  178  
 179  179  static KMF_RETURN
 180  180  sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
 181  181  
 182  182  static EVP_PKEY *
 183  183  ImportRawRSAKey(KMF_RAW_RSA_KEY *);
 184  184  
 185  185  static KMF_RETURN
 186  186  convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
 187  187  
 188  188  KMF_RETURN
 189  189  OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 190  190  
 191  191  void
 192  192  OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
 193  193  
 194  194  KMF_RETURN
 195  195  OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
 196  196  
 197  197  KMF_RETURN
 198  198  OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
 199  199  
 200  200  KMF_RETURN
 201  201  OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 202  202  
 203  203  KMF_RETURN
 204  204  OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 205  205  
 206  206  KMF_RETURN
 207  207  OpenSSL_EncodePubKeyData(KMF_HANDLE_T,  KMF_KEY_HANDLE *, KMF_DATA *);
 208  208  
 209  209  KMF_RETURN
 210  210  OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
 211  211          KMF_DATA *, KMF_DATA *);
 212  212  
 213  213  KMF_RETURN
 214  214  OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 215  215  
 216  216  KMF_RETURN
 217  217  OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 218  218  
 219  219  KMF_RETURN
 220  220  OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 221  221  
 222  222  KMF_RETURN
 223  223  OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 224  224  
 225  225  KMF_RETURN
 226  226  OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 227  227  
 228  228  KMF_RETURN
 229  229  OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
 230  230          KMF_PRINTABLE_ITEM, char *);
 231  231  
 232  232  KMF_RETURN
 233  233  OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
 234  234  
 235  235  KMF_RETURN
 236  236  OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 237  237  
 238  238  KMF_RETURN
 239  239  OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
 240  240          KMF_DATA *, KMF_DATA *);
 241  241  
 242  242  KMF_RETURN
 243  243  OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 244  244  
 245  245  KMF_RETURN
 246  246  OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 247  247  
 248  248  KMF_RETURN
 249  249  OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 250  250  
 251  251  KMF_RETURN
 252  252  OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 253  253  
 254  254  KMF_RETURN
 255  255  OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
 256  256  
 257  257  KMF_RETURN
 258  258  OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
 259  259  
 260  260  KMF_RETURN
 261  261  OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
 262  262  
 263  263  KMF_RETURN
 264  264  OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
 265  265  
 266  266  static
 267  267  KMF_PLUGIN_FUNCLIST openssl_plugin_table =
 268  268  {
 269  269          1,                              /* Version */
 270  270          NULL, /* ConfigureKeystore */
 271  271          OpenSSL_FindCert,
 272  272          OpenSSL_FreeKMFCert,
 273  273          OpenSSL_StoreCert,
 274  274          NULL, /* ImportCert */
 275  275          OpenSSL_ImportCRL,
 276  276          OpenSSL_DeleteCert,
 277  277          OpenSSL_DeleteCRL,
 278  278          OpenSSL_CreateKeypair,
 279  279          OpenSSL_FindKey,
 280  280          OpenSSL_EncodePubKeyData,
 281  281          OpenSSL_SignData,
 282  282          OpenSSL_DeleteKey,
 283  283          OpenSSL_ListCRL,
 284  284          NULL,   /* FindCRL */
 285  285          OpenSSL_FindCertInCRL,
 286  286          OpenSSL_GetErrorString,
 287  287          OpenSSL_FindPrikeyByCert,
 288  288          OpenSSL_DecryptData,
 289  289          OpenSSL_ExportPK12,
 290  290          OpenSSL_CreateSymKey,
 291  291          OpenSSL_GetSymKeyValue,
 292  292          NULL,   /* SetTokenPin */
 293  293          OpenSSL_StoreKey,
 294  294          NULL    /* Finalize */
 295  295  };
 296  296  
 297  297  static mutex_t *lock_cs;
 298  298  static long *lock_count;
 299  299  
 300  300  static void
 301  301  /* ARGSUSED1 */
 302  302  locking_cb(int mode, int type, char *file, int line)
 303  303  {
 304  304          if (mode & CRYPTO_LOCK) {
 305  305                  (void) mutex_lock(&(lock_cs[type]));
 306  306                  lock_count[type]++;
 307  307          } else {
 308  308                  (void) mutex_unlock(&(lock_cs[type]));
 309  309          }
 310  310  }
 311  311  
 312  312  static unsigned long
 313  313  thread_id()
 314  314  {
 315  315          return ((unsigned long)thr_self());
 316  316  }
 317  317  
 318  318  KMF_PLUGIN_FUNCLIST *
 319  319  KMF_Plugin_Initialize()
 320  320  {
 321  321          int i;
 322  322  
 323  323          (void) mutex_lock(&init_lock);
 324  324          if (!ssl_initialized) {
 325  325                  /*
 326  326                   * Add support for extension OIDs that are not yet in the
 327  327                   * openssl default set.
 328  328                   */
 329  329                  (void) OBJ_create("2.5.29.30", "nameConstraints",
 330  330                      "X509v3 Name Constraints");
 331  331                  (void) OBJ_create("2.5.29.33", "policyMappings",
 332  332                      "X509v3 Policy Mappings");
 333  333                  (void) OBJ_create("2.5.29.36", "policyConstraints",
 334  334                      "X509v3 Policy Constraints");
 335  335                  (void) OBJ_create("2.5.29.46", "freshestCRL",
 336  336                      "X509v3 Freshest CRL");
 337  337                  (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
 338  338                      "X509v3 Inhibit Any-Policy");
 339  339                  /*
 340  340                   * Set up for thread-safe operation.
 341  341                   */
 342  342                  lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
 343  343                  if (lock_cs == NULL) {
 344  344                          (void) mutex_unlock(&init_lock);
 345  345                          return (NULL);
 346  346                  }
 347  347  
 348  348                  lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
 349  349                  if (lock_count == NULL) {
 350  350                          OPENSSL_free(lock_cs);
 351  351                          (void) mutex_unlock(&init_lock);
 352  352                          return (NULL);
 353  353                  }
 354  354  
 355  355                  for (i = 0; i < CRYPTO_num_locks(); i++) {
 356  356                          lock_count[i] = 0;
 357  357                          (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
 358  358                  }
 359  359  
 360  360                  CRYPTO_set_id_callback((unsigned long (*)())thread_id);
 361  361                  if (CRYPTO_get_locking_callback() == NULL)
 362  362                          CRYPTO_set_locking_callback((void (*)())locking_cb);
 363  363  
 364  364                  OpenSSL_add_all_algorithms();
 365  365  
 366  366                  /* Enable error strings for reporting */
 367  367                  ERR_load_crypto_strings();
 368  368  
 369  369                  ssl_initialized = 1;
 370  370          }
 371  371          (void) mutex_unlock(&init_lock);
 372  372  
 373  373          return (&openssl_plugin_table);
 374  374  }
 375  375  /*
 376  376   * Convert an SSL DN to a KMF DN.
 377  377   */
 378  378  static KMF_RETURN
 379  379  get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
 380  380  {
 381  381          KMF_DATA derdata;
 382  382          KMF_RETURN rv = KMF_OK;
 383  383          uchar_t *tmp;
 384  384  
 385  385          /* Convert to raw DER format */
 386  386          derdata.Length = i2d_X509_NAME(sslDN, NULL);
 387  387          if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
 388  388              == NULL) {
 389  389                  return (KMF_ERR_MEMORY);
 390  390          }
 391  391          (void) i2d_X509_NAME(sslDN, &tmp);
 392  392  
 393  393          /* Decode to KMF format */
 394  394          rv = DerDecodeName(&derdata, kmfDN);
 395  395          if (rv != KMF_OK) {
 396  396                  rv = KMF_ERR_BAD_CERT_FORMAT;
 397  397          }
 398  398          OPENSSL_free(derdata.Data);
 399  399  
 400  400          return (rv);
 401  401  }
 402  402  
 403  403  int
 404  404  isdir(char *path)
 405  405  {
 406  406          struct stat s;
 407  407  
 408  408          if (stat(path, &s) == -1)
 409  409                  return (0);
 410  410  
 411  411          return ((s.st_mode & S_IFMT) == S_IFDIR);
 412  412  }
 413  413  
 414  414  static KMF_RETURN
 415  415  ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
 416  416  {
 417  417          KMF_RETURN rv = KMF_OK;
 418  418          unsigned char *buf = NULL, *p;
 419  419          int len;
 420  420  
 421  421          /*
 422  422           * Convert the X509 internal struct to DER encoded data
 423  423           */
 424  424          if ((len = i2d_X509(x509cert, NULL)) < 0) {
 425  425                  SET_ERROR(kmfh, ERR_get_error());
 426  426                  rv = KMF_ERR_BAD_CERT_FORMAT;
 427  427                  goto cleanup;
 428  428          }
 429  429          if ((buf = malloc(len)) == NULL) {
 430  430                  SET_SYS_ERROR(kmfh, errno);
 431  431                  rv = KMF_ERR_MEMORY;
 432  432                  goto cleanup;
 433  433          }
 434  434  
 435  435          /*
 436  436           * i2d_X509 will increment the buf pointer so that we need to
 437  437           * save it.
 438  438           */
 439  439          p = buf;
 440  440          if ((len = i2d_X509(x509cert, &p)) < 0) {
 441  441                  SET_ERROR(kmfh, ERR_get_error());
 442  442                  free(buf);
 443  443                  rv = KMF_ERR_BAD_CERT_FORMAT;
 444  444                  goto cleanup;
 445  445          }
 446  446  
 447  447          /* caller's responsibility to free it */
 448  448          cert->Data = buf;
 449  449          cert->Length = len;
 450  450  
 451  451  cleanup:
 452  452          if (rv != KMF_OK) {
 453  453                  if (buf)
 454  454                          free(buf);
 455  455                  cert->Data = NULL;
 456  456                  cert->Length = 0;
 457  457          }
 458  458  
 459  459          return (rv);
 460  460  }
 461  461  
 462  462  
 463  463  static KMF_RETURN
 464  464  check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
 465  465      boolean_t *match)
 466  466  {
 467  467          KMF_RETURN rv = KMF_OK;
 468  468          boolean_t findIssuer = FALSE;
 469  469          boolean_t findSubject = FALSE;
 470  470          boolean_t findSerial = FALSE;
 471  471          KMF_X509_NAME issuerDN, subjectDN;
 472  472          KMF_X509_NAME certIssuerDN, certSubjectDN;
 473  473  
 474  474          *match = FALSE;
 475  475          if (xcert == NULL) {
 476  476                  return (KMF_ERR_BAD_PARAMETER);
 477  477          }
 478  478  
 479  479          (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
 480  480          (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
 481  481          (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
 482  482          (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
 483  483  
 484  484          if (issuer != NULL && strlen(issuer)) {
 485  485                  rv = kmf_dn_parser(issuer, &issuerDN);
 486  486                  if (rv != KMF_OK)
 487  487                          return (KMF_ERR_BAD_PARAMETER);
 488  488  
 489  489                  rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
 490  490                  if (rv != KMF_OK) {
 491  491                          kmf_free_dn(&issuerDN);
 492  492                          return (KMF_ERR_BAD_PARAMETER);
 493  493                  }
 494  494  
 495  495                  findIssuer = TRUE;
 496  496          }
 497  497          if (subject != NULL && strlen(subject)) {
 498  498                  rv = kmf_dn_parser(subject, &subjectDN);
 499  499                  if (rv != KMF_OK) {
 500  500                          rv = KMF_ERR_BAD_PARAMETER;
 501  501                          goto cleanup;
 502  502                  }
 503  503  
 504  504                  rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
 505  505                  if (rv != KMF_OK) {
 506  506                          rv = KMF_ERR_BAD_PARAMETER;
 507  507                          goto cleanup;
 508  508                  }
 509  509                  findSubject = TRUE;
 510  510          }
 511  511          if (serial != NULL && serial->val != NULL)
 512  512                  findSerial = TRUE;
 513  513  
 514  514          if (findSerial) {
 515  515                  BIGNUM *bn;
 516  516  
 517  517                  /* Comparing BIGNUMs is a pain! */
 518  518                  bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
 519  519                  if (bn != NULL) {
 520  520                          int bnlen = BN_num_bytes(bn);
 521  521  
 522  522                          if (bnlen == serial->len) {
 523  523                                  uchar_t *a = malloc(bnlen);
 524  524                                  if (a == NULL) {
 525  525                                          rv = KMF_ERR_MEMORY;
 526  526                                          BN_free(bn);
 527  527                                          goto cleanup;
 528  528                                  }
 529  529                                  bnlen = BN_bn2bin(bn, a);
 530  530                                  *match = (memcmp(a, serial->val, serial->len) ==
 531  531                                      0);
 532  532                                  rv = KMF_OK;
 533  533                                  free(a);
 534  534                          }
 535  535                          BN_free(bn);
 536  536                          if (!(*match))
 537  537                                  goto cleanup;
 538  538                  } else {
 539  539                          rv = KMF_OK;
 540  540                          goto cleanup;
 541  541                  }
 542  542          }
 543  543          if (findIssuer) {
 544  544                  *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
 545  545                  if ((*match) == B_FALSE) {
 546  546                          /* stop checking and bail */
 547  547                          rv = KMF_OK;
 548  548                          goto cleanup;
 549  549                  }
 550  550          }
 551  551          if (findSubject) {
 552  552                  *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
 553  553                  if ((*match) == B_FALSE) {
 554  554                          /* stop checking and bail */
 555  555                          rv = KMF_OK;
 556  556                          goto cleanup;
 557  557                  }
 558  558          }
 559  559  
 560  560          *match = TRUE;
 561  561  cleanup:
 562  562          if (findIssuer) {
 563  563                  kmf_free_dn(&issuerDN);
 564  564                  kmf_free_dn(&certIssuerDN);
 565  565          }
 566  566          if (findSubject) {
 567  567                  kmf_free_dn(&subjectDN);
 568  568                  kmf_free_dn(&certSubjectDN);
 569  569          }
 570  570  
 571  571          return (rv);
 572  572  }
 573  573  
 574  574  
 575  575  /*
 576  576   * This function loads a certificate file into an X509 data structure, and
 577  577   * checks if its issuer, subject or the serial number matches with those
 578  578   * values.  If it matches, then return the X509 data structure.
 579  579   */
 580  580  static KMF_RETURN
 581  581  load_X509cert(KMF_HANDLE *kmfh,
 582  582      char *issuer, char *subject, KMF_BIGINT *serial,
 583  583      char *pathname, X509 **outcert)
 584  584  {
 585  585          KMF_RETURN rv = KMF_OK;
 586  586          X509 *xcert = NULL;
 587  587          BIO *bcert = NULL;
 588  588          boolean_t  match = FALSE;
 589  589          KMF_ENCODE_FORMAT format;
 590  590  
 591  591          /*
 592  592           * auto-detect the file format, regardless of what
 593  593           * the 'format' parameters in the params say.
 594  594           */
 595  595          rv = kmf_get_file_format(pathname, &format);
 596  596          if (rv != KMF_OK) {
 597  597                  if (rv == KMF_ERR_OPEN_FILE)
 598  598                          rv = KMF_ERR_CERT_NOT_FOUND;
 599  599                  return (rv);
 600  600          }
 601  601  
 602  602          /* Not ASN1(DER) format */
 603  603          if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
 604  604                  SET_ERROR(kmfh, ERR_get_error());
 605  605                  rv = KMF_ERR_OPEN_FILE;
 606  606                  goto cleanup;
 607  607          }
 608  608  
 609  609          if (format == KMF_FORMAT_PEM)
 610  610                  xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
 611  611          else if (format == KMF_FORMAT_ASN1)
 612  612                  xcert = d2i_X509_bio(bcert, NULL);
 613  613          else if (format == KMF_FORMAT_PKCS12) {
 614  614                  PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
 615  615                  if (p12 != NULL) {
 616  616                          (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
 617  617                          PKCS12_free(p12);
 618  618                          p12 = NULL;
 619  619                  } else {
 620  620                          SET_ERROR(kmfh, ERR_get_error());
 621  621                          rv = KMF_ERR_BAD_CERT_FORMAT;
 622  622                  }
 623  623          } else {
 624  624                  rv = KMF_ERR_BAD_PARAMETER;
 625  625                  goto cleanup;
 626  626          }
 627  627  
 628  628          if (xcert == NULL) {
 629  629                  SET_ERROR(kmfh, ERR_get_error());
 630  630                  rv = KMF_ERR_BAD_CERT_FORMAT;
 631  631                  goto cleanup;
 632  632          }
 633  633  
 634  634          if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
 635  635              match == FALSE) {
 636  636                  rv = KMF_ERR_CERT_NOT_FOUND;
 637  637                  goto cleanup;
 638  638          }
 639  639  
 640  640          if (outcert != NULL) {
 641  641                  *outcert = xcert;
 642  642          }
 643  643  
 644  644  cleanup:
 645  645          if (bcert != NULL) (void) BIO_free(bcert);
 646  646          if (rv != KMF_OK && xcert != NULL)
 647  647                  X509_free(xcert);
 648  648  
 649  649          return (rv);
 650  650  }
 651  651  
 652  652  static int
 653  653  datacmp(const void *a, const void *b)
 654  654  {
 655  655          KMF_DATA *adata = (KMF_DATA *)a;
 656  656          KMF_DATA *bdata = (KMF_DATA *)b;
 657  657          if (adata->Length > bdata->Length)
 658  658                  return (-1);
 659  659          if (adata->Length < bdata->Length)
 660  660                  return (1);
 661  661          return (0);
 662  662  }
 663  663  
 664  664  static KMF_RETURN
 665  665  load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
 666  666      KMF_CERT_VALIDITY validity, char *pathname,
 667  667      KMF_DATA **certlist, uint32_t *numcerts)
 668  668  {
 669  669          KMF_RETURN rv = KMF_OK;
 670  670          int i;
 671  671          KMF_DATA *certs = NULL;
 672  672          int nc = 0;
 673  673          int hits = 0;
 674  674          KMF_ENCODE_FORMAT format;
 675  675  
 676  676          rv = kmf_get_file_format(pathname, &format);
 677  677          if (rv != KMF_OK) {
 678  678                  if (rv == KMF_ERR_OPEN_FILE)
 679  679                          rv = KMF_ERR_CERT_NOT_FOUND;
 680  680                  return (rv);
 681  681          }
 682  682          if (format == KMF_FORMAT_ASN1) {
 683  683                  /* load a single certificate */
 684  684                  certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
 685  685                  if (certs == NULL)
 686  686                          return (KMF_ERR_MEMORY);
 687  687                  certs->Data = NULL;
 688  688                  certs->Length = 0;
 689  689                  rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
 690  690                      pathname, certs);
 691  691                  if (rv == KMF_OK) {
 692  692                          *certlist = certs;
 693  693                          *numcerts = 1;
 694  694                  } else {
 695  695                          kmf_free_data(certs);
 696  696                          free(certs);
 697  697                          certs = NULL;
 698  698                  }
 699  699                  return (rv);
 700  700          } else if (format == KMF_FORMAT_PKCS12) {
 701  701                  /* We need a credential to access a PKCS#12 file */
 702  702                  rv = KMF_ERR_BAD_CERT_FORMAT;
 703  703          } else if (format == KMF_FORMAT_PEM ||
 704  704              format != KMF_FORMAT_PEM_KEYPAIR) {
 705  705  
 706  706                  /* This function only works on PEM files */
 707  707                  rv = extract_pem(kmfh, issuer, subject, serial, pathname,
 708  708                      (uchar_t *)NULL, 0, NULL, &certs, &nc);
 709  709          } else {
 710  710                  return (KMF_ERR_ENCODING);
 711  711          }
 712  712  
 713  713          if (rv != KMF_OK)
 714  714                  return (rv);
 715  715  
 716  716          for (i = 0; i < nc; i++) {
 717  717                  if (validity == KMF_NONEXPIRED_CERTS) {
 718  718                          rv = kmf_check_cert_date(kmfh, &certs[i]);
 719  719                  } else if (validity == KMF_EXPIRED_CERTS) {
 720  720                          rv = kmf_check_cert_date(kmfh, &certs[i]);
 721  721                          if (rv == KMF_OK)
 722  722                                  rv = KMF_ERR_CERT_NOT_FOUND;
 723  723                          if (rv == KMF_ERR_VALIDITY_PERIOD)
 724  724                                  rv = KMF_OK;
 725  725                  }
 726  726                  if (rv != KMF_OK) {
 727  727                          /* Remove this cert from the list by clearing it. */
 728  728                          kmf_free_data(&certs[i]);
 729  729                  } else {
 730  730                          hits++; /* count valid certs found */
 731  731                  }
 732  732                  rv = KMF_OK;
 733  733          }
 734  734          if (rv == KMF_OK && hits > 0) {
 735  735                  /*
 736  736                   * Sort the list of certs by length to put the cleared ones
 737  737                   * at the end so they don't get accessed by the caller.
 738  738                   */
 739  739                  qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
 740  740                  *certlist = certs;
 741  741  
 742  742                  /* since we sorted the list, just return the number of hits */
 743  743                  *numcerts = hits;
 744  744          } else {
 745  745                  if (rv == KMF_OK && hits == 0)
 746  746                          rv = KMF_ERR_CERT_NOT_FOUND;
 747  747                  if (certs != NULL) {
 748  748                          free(certs);
 749  749                          certs = NULL;
 750  750                  }
 751  751          }
 752  752          return (rv);
 753  753  }
 754  754  
 755  755  static KMF_RETURN
 756  756  kmf_load_cert(KMF_HANDLE *kmfh,
 757  757      char *issuer, char *subject, KMF_BIGINT *serial,
 758  758      KMF_CERT_VALIDITY validity,
 759  759      char *pathname,
 760  760      KMF_DATA *cert)
 761  761  {
 762  762          KMF_RETURN rv = KMF_OK;
 763  763          X509 *x509cert = NULL;
 764  764  
 765  765          rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
 766  766          if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
 767  767                  rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
 768  768                  if (rv != KMF_OK) {
 769  769                          goto cleanup;
 770  770                  }
 771  771                  if (validity == KMF_NONEXPIRED_CERTS) {
 772  772                          rv = kmf_check_cert_date(kmfh, cert);
 773  773                  } else if (validity == KMF_EXPIRED_CERTS) {
 774  774                          rv = kmf_check_cert_date(kmfh, cert);
 775  775                          if (rv == KMF_OK)  {
 776  776                                  /*
 777  777                                   * This is a valid cert so skip it.
 778  778                                   */
 779  779                                  rv = KMF_ERR_CERT_NOT_FOUND;
 780  780                          }
 781  781                          if (rv == KMF_ERR_VALIDITY_PERIOD) {
 782  782                                  /*
 783  783                                   * We want to return success when we
 784  784                                   * find an invalid cert.
 785  785                                   */
 786  786                                  rv = KMF_OK;
 787  787                                  goto cleanup;
 788  788                          }
 789  789                  }
 790  790          }
 791  791  cleanup:
 792  792          if (x509cert != NULL)
 793  793                  X509_free(x509cert);
 794  794  
 795  795          return (rv);
 796  796  }
 797  797  
 798  798  static KMF_RETURN
 799  799  readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
 800  800  {
 801  801          KMF_RETURN ret = KMF_OK;
 802  802          KMF_RAW_RSA_KEY rsa;
 803  803          BerElement *asn1 = NULL;
 804  804          BerValue filebuf;
 805  805          BerValue OID = { NULL, 0 };
 806  806          BerValue *Mod = NULL, *PubExp = NULL;
 807  807          BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
 808  808          BerValue *Coef = NULL;
 809  809          BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
 810  810          BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
 811  811          BIGNUM *qminus1 = NULL;
 812  812          BN_CTX *ctx = NULL;
 813  813  
 814  814          *pkey = NULL;
 815  815  
 816  816          filebuf.bv_val = (char *)filedata->Data;
 817  817          filebuf.bv_len = filedata->Length;
 818  818  
 819  819          asn1 = kmfder_init(&filebuf);
 820  820          if (asn1 == NULL) {
 821  821                  ret = KMF_ERR_MEMORY;
 822  822                  goto out;
 823  823          }
 824  824  
 825  825          if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
 826  826              &OID, &Mod, &PubExp, &PriExp, &Prime1,
 827  827              &Prime2, &Coef) == -1)  {
 828  828                  ret = KMF_ERR_ENCODING;
 829  829                  goto out;
 830  830          }
 831  831  
 832  832          /*
 833  833           * We have to derive the 2 Exponents using Bignumber math.
 834  834           * Exp1 = PriExp mod (Prime1 - 1)
 835  835           * Exp2 = PriExp mod (Prime2 - 1)
 836  836           */
 837  837  
 838  838          /* D = PrivateExponent */
 839  839          D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
 840  840          if (D == NULL) {
 841  841                  ret = KMF_ERR_MEMORY;
 842  842                  goto out;
 843  843          }
 844  844  
 845  845          /* P = Prime1 (first prime factor of Modulus) */
 846  846          P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
 847  847          if (D == NULL) {
 848  848                  ret = KMF_ERR_MEMORY;
 849  849                  goto out;
 850  850          }
 851  851  
 852  852          /* Q = Prime2 (second prime factor of Modulus) */
 853  853          Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
 854  854  
 855  855          if ((ctx = BN_CTX_new()) == NULL) {
 856  856                  ret = KMF_ERR_MEMORY;
 857  857                  goto out;
 858  858          }
 859  859  
 860  860          /* Compute (P - 1) */
 861  861          pminus1 = BN_new();
 862  862          (void) BN_sub(pminus1, P, BN_value_one());
 863  863  
 864  864          /* Exponent1 = D mod (P - 1) */
 865  865          Exp1 = BN_new();
 866  866          (void) BN_mod(Exp1, D, pminus1, ctx);
 867  867  
 868  868          /* Compute (Q - 1) */
 869  869          qminus1 = BN_new();
 870  870          (void) BN_sub(qminus1, Q, BN_value_one());
 871  871  
 872  872          /* Exponent2 = D mod (Q - 1) */
 873  873          Exp2 = BN_new();
 874  874          (void) BN_mod(Exp2, D, qminus1, ctx);
 875  875  
 876  876          /* Coef = (Inverse Q) mod P */
 877  877          COEF = BN_new();
 878  878          (void) BN_mod_inverse(COEF, Q, P, ctx);
 879  879  
 880  880          /* Convert back to KMF format */
 881  881          (void) memset(&rsa, 0, sizeof (rsa));
 882  882  
 883  883          if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
 884  884                  goto out;
 885  885          if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
 886  886                  goto out;
 887  887          if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
 888  888                  goto out;
 889  889  
 890  890          rsa.mod.val = (uchar_t *)Mod->bv_val;
 891  891          rsa.mod.len = Mod->bv_len;
 892  892  
 893  893          rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
 894  894          rsa.pubexp.len = PubExp->bv_len;
 895  895  
 896  896          rsa.priexp.val = (uchar_t *)PriExp->bv_val;
 897  897          rsa.priexp.len = PriExp->bv_len;
 898  898  
 899  899          rsa.prime1.val = (uchar_t *)Prime1->bv_val;
 900  900          rsa.prime1.len = Prime1->bv_len;
 901  901  
 902  902          rsa.prime2.val = (uchar_t *)Prime2->bv_val;
 903  903          rsa.prime2.len = Prime2->bv_len;
 904  904  
 905  905          *pkey = ImportRawRSAKey(&rsa);
 906  906  out:
 907  907          if (asn1 != NULL)
 908  908                  kmfber_free(asn1, 1);
 909  909  
 910  910          if (OID.bv_val) {
 911  911                  free(OID.bv_val);
 912  912          }
 913  913          if (PriExp)
 914  914                  free(PriExp);
 915  915  
 916  916          if (Mod)
 917  917                  free(Mod);
 918  918  
 919  919          if (PubExp)
 920  920                  free(PubExp);
 921  921  
 922  922          if (Coef) {
 923  923                  (void) memset(Coef->bv_val, 0, Coef->bv_len);
 924  924                  free(Coef->bv_val);
 925  925                  free(Coef);
 926  926          }
 927  927          if (Prime1)
 928  928                  free(Prime1);
 929  929          if (Prime2)
 930  930                  free(Prime2);
 931  931  
 932  932          if (ctx != NULL)
 933  933                  BN_CTX_free(ctx);
 934  934  
 935  935          if (D)
 936  936                  BN_clear_free(D);
 937  937          if (P)
 938  938                  BN_clear_free(P);
 939  939          if (Q)
 940  940                  BN_clear_free(Q);
 941  941          if (pminus1)
 942  942                  BN_clear_free(pminus1);
 943  943          if (qminus1)
 944  944                  BN_clear_free(qminus1);
 945  945          if (Exp1)
 946  946                  BN_clear_free(Exp1);
 947  947          if (Exp2)
 948  948                  BN_clear_free(Exp2);
 949  949  
 950  950          return (ret);
 951  951  
 952  952  }
 953  953  
 954  954  static EVP_PKEY *
 955  955  openssl_load_key(KMF_HANDLE_T handle, const char *file)
 956  956  {
 957  957          BIO *keyfile = NULL;
 958  958          EVP_PKEY *pkey = NULL;
 959  959          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
 960  960          KMF_ENCODE_FORMAT format;
 961  961          KMF_RETURN rv;
 962  962          KMF_DATA filedata;
 963  963  
 964  964          if (file == NULL) {
 965  965                  return (NULL);
 966  966          }
 967  967  
 968  968          if (kmf_get_file_format((char *)file, &format) != KMF_OK)
 969  969                  return (NULL);
 970  970  
 971  971          keyfile = BIO_new_file(file, "rb");
 972  972          if (keyfile == NULL) {
 973  973                  goto end;
 974  974          }
 975  975  
 976  976          if (format == KMF_FORMAT_ASN1) {
 977  977                  pkey = d2i_PrivateKey_bio(keyfile, NULL);
 978  978                  if (pkey == NULL) {
 979  979  
 980  980                          (void) BIO_free(keyfile);
 981  981                          keyfile = NULL;
 982  982                          /* Try odd ASN.1 variations */
 983  983                          rv = kmf_read_input_file(kmfh, (char *)file,
 984  984                              &filedata);
 985  985                          if (rv == KMF_OK) {
 986  986                                  (void) readAltFormatPrivateKey(&filedata,
 987  987                                      &pkey);
 988  988                                  kmf_free_data(&filedata);
 989  989                          }
 990  990                  }
 991  991          } else if (format == KMF_FORMAT_PEM ||
 992  992              format == KMF_FORMAT_PEM_KEYPAIR) {
 993  993                  pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
 994  994                  if (pkey == NULL) {
 995  995                          KMF_DATA derdata;
 996  996                          /*
 997  997                           * Check if this is the alt. format
 998  998                           * RSA private key file.
 999  999                           */
1000 1000                          rv = kmf_read_input_file(kmfh, (char *)file,
1001 1001                              &filedata);
1002 1002                          if (rv == KMF_OK) {
1003 1003                                  uchar_t *d = NULL;
1004 1004                                  int len;
1005 1005                                  rv = kmf_pem_to_der(filedata.Data,
1006 1006                                      filedata.Length, &d, &len);
1007 1007                                  if (rv == KMF_OK && d != NULL) {
1008 1008                                          derdata.Data = d;
1009 1009                                          derdata.Length = (size_t)len;
1010 1010                                          (void) readAltFormatPrivateKey(
1011 1011                                              &derdata, &pkey);
1012 1012                                          free(d);
1013 1013                                  }
1014 1014                                  kmf_free_data(&filedata);
1015 1015                          }
1016 1016                  }
1017 1017          }
1018 1018  
1019 1019  end:
1020 1020          if (pkey == NULL)
1021 1021                  SET_ERROR(kmfh, ERR_get_error());
1022 1022  
1023 1023          if (keyfile != NULL)
1024 1024                  (void) BIO_free(keyfile);
1025 1025  
1026 1026          return (pkey);
1027 1027  }
1028 1028  
1029 1029  KMF_RETURN
1030 1030  OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1031 1031  {
1032 1032          KMF_RETURN rv = KMF_OK;
1033 1033          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1034 1034          int i, n;
1035 1035          uint32_t maxcerts = 0;
1036 1036          uint32_t *num_certs;
1037 1037          KMF_X509_DER_CERT *kmf_cert = NULL;
1038 1038          char *dirpath = NULL;
1039 1039          char *filename = NULL;
1040 1040          char *fullpath = NULL;
1041 1041          char *issuer = NULL;
1042 1042          char *subject = NULL;
1043 1043          KMF_BIGINT *serial = NULL;
1044 1044          KMF_CERT_VALIDITY validity;
1045 1045  
1046 1046          num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1047 1047          if (num_certs == NULL)
1048 1048                  return (KMF_ERR_BAD_PARAMETER);
1049 1049  
1050 1050          /* num_certs should reference the size of kmf_cert */
1051 1051          maxcerts = *num_certs;
1052 1052          if (maxcerts == 0)
1053 1053                  maxcerts = 0xFFFFFFFF;
1054 1054          *num_certs = 0;
1055 1055  
1056 1056          /* Get the optional returned certificate list  */
1057 1057          kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
1058 1058              numattr);
1059 1059  
1060 1060          /*
1061 1061           * The dirpath attribute and the filename attribute can not be NULL
1062 1062           * at the same time.
1063 1063           */
1064 1064          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1065 1065          filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1066 1066              numattr);
1067 1067  
1068 1068          fullpath = get_fullpath(dirpath, filename);
1069 1069          if (fullpath == NULL)
1070 1070                  return (KMF_ERR_BAD_PARAMETER);
1071 1071  
1072 1072          /* Get optional search criteria attributes */
1073 1073          issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1074 1074          subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1075 1075          serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1076 1076          rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1077 1077              &validity, NULL);
1078 1078          if (rv != KMF_OK) {
1079 1079                  validity = KMF_ALL_CERTS;
1080 1080                  rv = KMF_OK;
1081 1081          }
1082 1082  
1083 1083          if (isdir(fullpath)) {
1084 1084                  DIR *dirp;
1085 1085                  struct dirent *dp;
1086 1086  
1087 1087                  n = 0;
1088 1088                  /* open all files in the directory and attempt to read them */
1089 1089                  if ((dirp = opendir(fullpath)) == NULL) {
1090 1090                          return (KMF_ERR_BAD_PARAMETER);
1091 1091                  }
1092 1092                  while ((dp = readdir(dirp)) != NULL) {
1093 1093                          char *fname;
1094 1094                          KMF_DATA *certlist = NULL;
1095 1095                          uint32_t loaded_certs = 0;
1096 1096  
1097 1097                          if (strcmp(dp->d_name, ".") == 0 ||
1098 1098                              strcmp(dp->d_name, "..") == 0)
1099 1099                                  continue;
1100 1100  
1101 1101                          fname = get_fullpath(fullpath, (char *)&dp->d_name);
1102 1102  
1103 1103                          rv = load_certs(kmfh, issuer, subject, serial,
1104 1104                              validity, fname, &certlist, &loaded_certs);
1105 1105  
1106 1106                          if (rv != KMF_OK) {
1107 1107                                  free(fname);
1108 1108                                  if (certlist != NULL) {
1109 1109                                          for (i = 0; i < loaded_certs; i++)
1110 1110                                                  kmf_free_data(&certlist[i]);
1111 1111                                          free(certlist);
1112 1112                                  }
1113 1113                                  continue;
1114 1114                          }
1115 1115  
1116 1116                          /* If load succeeds, add certdata to the list */
1117 1117                          if (kmf_cert != NULL) {
1118 1118                                  for (i = 0; i < loaded_certs &&
1119 1119                                      n < maxcerts; i++) {
1120 1120                                          kmf_cert[n].certificate.Data =
1121 1121                                              certlist[i].Data;
1122 1122                                          kmf_cert[n].certificate.Length =
1123 1123                                              certlist[i].Length;
1124 1124  
1125 1125                                          kmf_cert[n].kmf_private.keystore_type =
1126 1126                                              KMF_KEYSTORE_OPENSSL;
1127 1127                                          kmf_cert[n].kmf_private.flags =
1128 1128                                              KMF_FLAG_CERT_VALID;
1129 1129                                          kmf_cert[n].kmf_private.label =
1130 1130                                              strdup(fname);
1131 1131                                          n++;
1132 1132                                  }
1133 1133                                  /*
1134 1134                                   * If maxcerts < loaded_certs, clean up the
1135 1135                                   * certs that were not used.
1136 1136                                   */
1137 1137                                  for (; i < loaded_certs; i++)
1138 1138                                          kmf_free_data(&certlist[i]);
1139 1139                          } else {
1140 1140                                  for (i = 0; i < loaded_certs; i++)
1141 1141                                          kmf_free_data(&certlist[i]);
1142 1142                                  n += loaded_certs;
1143 1143                          }
1144 1144                          free(certlist);
1145 1145                          free(fname);
1146 1146                  }
1147 1147                  (*num_certs) = n;
1148 1148                  if (*num_certs == 0)
1149 1149                          rv = KMF_ERR_CERT_NOT_FOUND;
1150 1150                  if (*num_certs > 0)
1151 1151                          rv = KMF_OK;
1152 1152  exit:
1153 1153                  (void) closedir(dirp);
1154 1154          } else {
1155 1155                  KMF_DATA *certlist = NULL;
1156 1156                  uint32_t loaded_certs = 0;
1157 1157  
1158 1158                  rv = load_certs(kmfh, issuer, subject, serial, validity,
1159 1159                      fullpath, &certlist, &loaded_certs);
1160 1160                  if (rv != KMF_OK) {
1161 1161                          free(fullpath);
1162 1162                          return (rv);
1163 1163                  }
1164 1164  
1165 1165                  n = 0;
1166 1166                  if (kmf_cert != NULL && certlist != NULL) {
1167 1167                          for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1168 1168                                  kmf_cert[n].certificate.Data =
1169 1169                                      certlist[i].Data;
1170 1170                                  kmf_cert[n].certificate.Length =
1171 1171                                      certlist[i].Length;
1172 1172                                  kmf_cert[n].kmf_private.keystore_type =
1173 1173                                      KMF_KEYSTORE_OPENSSL;
1174 1174                                  kmf_cert[n].kmf_private.flags =
1175 1175                                      KMF_FLAG_CERT_VALID;
1176 1176                                  kmf_cert[n].kmf_private.label =
1177 1177                                      strdup(fullpath);
1178 1178                                  n++;
1179 1179                          }
1180 1180                          /* If maxcerts < loaded_certs, clean up */
1181 1181                          for (; i < loaded_certs; i++)
1182 1182                                  kmf_free_data(&certlist[i]);
1183 1183                  } else if (certlist != NULL) {
1184 1184                          for (i = 0; i < loaded_certs; i++)
1185 1185                                  kmf_free_data(&certlist[i]);
1186 1186                          n = loaded_certs;
1187 1187                  }
1188 1188                  if (certlist != NULL)
1189 1189                          free(certlist);
1190 1190                  *num_certs = n;
1191 1191          }
1192 1192  
1193 1193          free(fullpath);
1194 1194  
1195 1195          return (rv);
1196 1196  }
1197 1197  
1198 1198  void
1199 1199  /*ARGSUSED*/
1200 1200  OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
1201 1201          KMF_X509_DER_CERT *kmf_cert)
1202 1202  {
1203 1203          if (kmf_cert != NULL) {
1204 1204                  if (kmf_cert->certificate.Data != NULL) {
1205 1205                          kmf_free_data(&kmf_cert->certificate);
1206 1206                  }
1207 1207                  if (kmf_cert->kmf_private.label)
1208 1208                          free(kmf_cert->kmf_private.label);
1209 1209          }
1210 1210  }
1211 1211  
1212 1212  /*ARGSUSED*/
1213 1213  KMF_RETURN
1214 1214  OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1215 1215  {
1216 1216          KMF_RETURN ret = KMF_OK;
1217 1217          KMF_DATA *cert = NULL;
1218 1218          char *outfilename = NULL;
1219 1219          char *dirpath = NULL;
1220 1220          char *fullpath = NULL;
1221 1221          KMF_ENCODE_FORMAT format;
1222 1222  
1223 1223          /* Get the cert data */
1224 1224          cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1225 1225          if (cert == NULL || cert->Data == NULL)
1226 1226                  return (KMF_ERR_BAD_PARAMETER);
1227 1227  
1228 1228          /* Check the output filename and directory attributes. */
1229 1229          outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1230 1230              numattr);
1231 1231          if (outfilename == NULL)
1232 1232                  return (KMF_ERR_BAD_PARAMETER);
1233 1233  
1234 1234          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1235 1235          fullpath = get_fullpath(dirpath, outfilename);
1236 1236          if (fullpath == NULL)
1237 1237                  return (KMF_ERR_BAD_CERTFILE);
1238 1238  
1239 1239          /* Check the optional format attribute */
1240 1240          ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1241 1241              &format, NULL);
1242 1242          if (ret != KMF_OK) {
1243 1243                  /* If there is no format attribute, then default to PEM */
1244 1244                  format = KMF_FORMAT_PEM;
1245 1245                  ret = KMF_OK;
1246 1246          } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
1247 1247                  ret = KMF_ERR_BAD_CERT_FORMAT;
1248 1248                  goto out;
1249 1249          }
1250 1250  
1251 1251          /* Store the certificate in the file with the specified format */
1252 1252          ret = kmf_create_cert_file(cert, format, fullpath);
1253 1253  
1254 1254  out:
1255 1255          if (fullpath != NULL)
1256 1256                  free(fullpath);
1257 1257  
1258 1258          return (ret);
1259 1259  }
1260 1260  
1261 1261  
1262 1262  KMF_RETURN
1263 1263  OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1264 1264  {
1265 1265          KMF_RETURN rv;
1266 1266          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1267 1267          KMF_DATA certdata = {NULL, 0};
1268 1268          char *dirpath = NULL;
1269 1269          char *filename = NULL;
1270 1270          char *fullpath = NULL;
1271 1271          char *issuer = NULL;
1272 1272          char *subject = NULL;
1273 1273          KMF_BIGINT *serial = NULL;
1274 1274          KMF_CERT_VALIDITY validity;
1275 1275  
1276 1276          /*
1277 1277           * Get the DIRPATH and CERT_FILENAME attributes.  They can not be
1278 1278           * NULL at the same time.
1279 1279           */
1280 1280          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1281 1281          filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1282 1282              numattr);
1283 1283          fullpath = get_fullpath(dirpath, filename);
1284 1284          if (fullpath == NULL)
1285 1285                  return (KMF_ERR_BAD_PARAMETER);
1286 1286  
1287 1287          /* Get optional search criteria attributes */
1288 1288          issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1289 1289          subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1290 1290          serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1291 1291          rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1292 1292              &validity, NULL);
1293 1293          if (rv != KMF_OK) {
1294 1294                  validity = KMF_ALL_CERTS;
1295 1295                  rv = KMF_OK;
1296 1296          }
1297 1297  
1298 1298          if (isdir(fullpath)) {
1299 1299                  DIR *dirp;
1300 1300                  struct dirent *dp;
1301 1301  
1302 1302                  /* open all files in the directory and attempt to read them */
1303 1303                  if ((dirp = opendir(fullpath)) == NULL) {
1304 1304                          return (KMF_ERR_BAD_PARAMETER);
1305 1305                  }
1306 1306  
1307 1307                  while ((dp = readdir(dirp)) != NULL) {
1308 1308                          if (strcmp(dp->d_name, ".") != 0 &&
1309 1309                              strcmp(dp->d_name, "..") != 0) {
1310 1310                                  char *fname;
1311 1311  
1312 1312                                  fname = get_fullpath(fullpath,
1313 1313                                      (char *)&dp->d_name);
1314 1314  
1315 1315                                  if (fname == NULL) {
1316 1316                                          rv = KMF_ERR_MEMORY;
1317 1317                                          break;
1318 1318                                  }
1319 1319  
1320 1320                                  rv = kmf_load_cert(kmfh, issuer, subject,
1321 1321                                      serial, validity, fname, &certdata);
1322 1322  
1323 1323                                  if (rv == KMF_ERR_CERT_NOT_FOUND) {
1324 1324                                          free(fname);
1325 1325                                          kmf_free_data(&certdata);
1326 1326                                          rv = KMF_OK;
1327 1327                                          continue;
1328 1328                                  } else if (rv != KMF_OK) {
1329 1329                                          free(fname);
1330 1330                                          break;
1331 1331                                  }
1332 1332  
1333 1333                                  if (unlink(fname) != 0) {
1334 1334                                          SET_SYS_ERROR(kmfh, errno);
1335 1335                                          rv = KMF_ERR_INTERNAL;
1336 1336                                          free(fname);
1337 1337                                          break;
1338 1338                                  }
1339 1339                                  free(fname);
1340 1340                                  kmf_free_data(&certdata);
1341 1341                          }
1342 1342                  }
1343 1343                  (void) closedir(dirp);
1344 1344          } else {
1345 1345                  /* Just try to load a single certificate */
1346 1346                  rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
1347 1347                      fullpath, &certdata);
1348 1348                  if (rv == KMF_OK) {
1349 1349                          if (unlink(fullpath) != 0) {
1350 1350                                  SET_SYS_ERROR(kmfh, errno);
1351 1351                                  rv = KMF_ERR_INTERNAL;
1352 1352                          }
1353 1353                  }
1354 1354          }
1355 1355  
1356 1356  out:
1357 1357          if (fullpath != NULL)
1358 1358                  free(fullpath);
1359 1359  
1360 1360          kmf_free_data(&certdata);
1361 1361  
1362 1362          return (rv);
1363 1363  }
1364 1364  
1365 1365  KMF_RETURN
1366 1366  OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1367 1367          KMF_DATA *keydata)
1368 1368  {
1369 1369          KMF_RETURN rv = KMF_OK;
1370 1370          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1371 1371          int n;
1372 1372  
1373 1373          if (key == NULL || keydata == NULL ||
1374 1374              key->keyp == NULL)
1375 1375                  return (KMF_ERR_BAD_PARAMETER);
1376 1376  
1377 1377          if (key->keyalg == KMF_RSA) {
1378 1378                  RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
1379 1379  
1380 1380                  if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
1381 1381                          SET_ERROR(kmfh, ERR_get_error());
1382 1382                          return (KMF_ERR_ENCODING);
1383 1383                  }
1384 1384                  RSA_free(pubkey);
1385 1385          } else if (key->keyalg == KMF_DSA) {
1386 1386                  DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
1387 1387  
1388 1388                  if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
1389 1389                          SET_ERROR(kmfh, ERR_get_error());
1390 1390                          return (KMF_ERR_ENCODING);
1391 1391                  }
1392 1392                  DSA_free(pubkey);
1393 1393          } else {
1394 1394                  return (KMF_ERR_BAD_PARAMETER);
1395 1395          }
1396 1396          keydata->Length = n;
1397 1397  
1398 1398  cleanup:
1399 1399          if (rv != KMF_OK) {
1400 1400                  if (keydata->Data)
1401 1401                          free(keydata->Data);
1402 1402                  keydata->Data = NULL;
1403 1403                  keydata->Length = 0;
1404 1404          }
1405 1405  
1406 1406          return (rv);
1407 1407  }
1408 1408  
1409 1409  static KMF_RETURN
1410 1410  ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
1411 1411          KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
1412 1412  {
1413 1413          int rv = 0;
1414 1414          RSA *rsa;
1415 1415          DSA *dsa;
1416 1416  
1417 1417          if (pkey == NULL || out == NULL)
1418 1418                  return (KMF_ERR_BAD_PARAMETER);
1419 1419  
1420 1420          switch (format) {
1421 1421                  case KMF_FORMAT_RAWKEY:
1422 1422                          /* same as ASN.1 */
1423 1423                  case KMF_FORMAT_ASN1:
1424 1424                          if (pkey->type == EVP_PKEY_RSA) {
1425 1425                                  rsa = EVP_PKEY_get1_RSA(pkey);
1426 1426                                  if (private)
1427 1427                                          rv = i2d_RSAPrivateKey_bio(out, rsa);
1428 1428                                  else
1429 1429                                          rv = i2d_RSAPublicKey_bio(out, rsa);
1430 1430                                  RSA_free(rsa);
1431 1431                          } else if (pkey->type == EVP_PKEY_DSA) {
1432 1432                                  dsa = EVP_PKEY_get1_DSA(pkey);
1433 1433                                  rv = i2d_DSAPrivateKey_bio(out, dsa);
1434 1434                                  DSA_free(dsa);
1435 1435                          }
1436 1436                          if (rv == 1) {
1437 1437                                  rv = KMF_OK;
1438 1438                          } else {
1439 1439                                  SET_ERROR(kmfh, rv);
1440 1440                          }
1441 1441                          break;
1442 1442                  case KMF_FORMAT_PEM:
1443 1443                          if (pkey->type == EVP_PKEY_RSA) {
1444 1444                                  rsa = EVP_PKEY_get1_RSA(pkey);
1445 1445                                  if (private)
1446 1446                                          rv = PEM_write_bio_RSAPrivateKey(out,
1447 1447                                              rsa, NULL, NULL, 0, NULL,
1448 1448                                              (cred != NULL ? cred->cred : NULL));
1449 1449                                  else
1450 1450                                          rv = PEM_write_bio_RSAPublicKey(out,
1451 1451                                              rsa);
1452 1452                                  RSA_free(rsa);
1453 1453                          } else if (pkey->type == EVP_PKEY_DSA) {
1454 1454                                  dsa = EVP_PKEY_get1_DSA(pkey);
1455 1455                                  rv = PEM_write_bio_DSAPrivateKey(out,
1456 1456                                      dsa, NULL, NULL, 0, NULL,
1457 1457                                      (cred != NULL ? cred->cred : NULL));
1458 1458                                  DSA_free(dsa);
1459 1459                          }
1460 1460  
1461 1461                          if (rv == 1) {
1462 1462                                  rv = KMF_OK;
1463 1463                          } else {
1464 1464                                  SET_ERROR(kmfh, rv);
1465 1465                          }
1466 1466                          break;
1467 1467  
1468 1468                  default:
1469 1469                          rv = KMF_ERR_BAD_PARAMETER;
1470 1470          }
1471 1471  
1472 1472          return (rv);
1473 1473  }
1474 1474  
1475 1475  KMF_RETURN
1476 1476  OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
1477 1477          KMF_ATTRIBUTE *attrlist)
1478 1478  {
1479 1479          KMF_RETURN rv = KMF_OK;
1480 1480          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1481 1481          uint32_t eValue = 0x010001;
1482 1482          RSA *sslPrivKey = NULL;
1483 1483          DSA *sslDSAKey = NULL;
1484 1484          EVP_PKEY *eprikey = NULL;
1485 1485          EVP_PKEY *epubkey = NULL;
1486 1486          BIO *out = NULL;
1487 1487          KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
1488 1488          uint32_t keylen = 1024;
1489 1489          uint32_t keylen_size = sizeof (uint32_t);
1490 1490          boolean_t storekey = TRUE;
1491 1491          KMF_KEY_ALG keytype = KMF_RSA;
1492 1492  
1493 1493          rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
1494 1494              &storekey, NULL);
1495 1495          if (rv != KMF_OK) {
1496 1496                  /* "storekey" is optional. Default is TRUE */
1497 1497                  rv = KMF_OK;
1498 1498          }
1499 1499  
1500 1500          rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1501 1501              (void *)&keytype, NULL);
1502 1502          if (rv != KMF_OK)
1503 1503                  /* keytype is optional.  KMF_RSA is default */
1504 1504                  rv = KMF_OK;
1505 1505  
1506 1506          pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1507 1507          if (pubkey == NULL)
1508 1508                  return (KMF_ERR_BAD_PARAMETER);
1509 1509  
1510 1510          privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1511 1511          if (privkey == NULL)
1512 1512                  return (KMF_ERR_BAD_PARAMETER);
1513 1513  
1514 1514          (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
1515 1515          (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
1516 1516  
1517 1517          eprikey = EVP_PKEY_new();
1518 1518          if (eprikey == NULL) {
1519 1519                  SET_ERROR(kmfh, ERR_get_error());
1520 1520                  rv = KMF_ERR_KEYGEN_FAILED;
1521 1521                  goto cleanup;
1522 1522          }
1523 1523          epubkey = EVP_PKEY_new();
1524 1524          if (epubkey == NULL) {
1525 1525                  SET_ERROR(kmfh, ERR_get_error());
1526 1526                  rv = KMF_ERR_KEYGEN_FAILED;
1527 1527                  goto cleanup;
1528 1528          }
1529 1529          if (keytype == KMF_RSA) {
1530 1530                  KMF_BIGINT *rsaexp = NULL;
1531 1531  
1532 1532                  rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
1533 1533                  if (rsaexp != NULL) {
1534 1534                          if (rsaexp->len > 0 &&
1535 1535                              rsaexp->len <= sizeof (eValue) &&
1536 1536                              rsaexp->val != NULL) {
1537 1537                                  /* LINTED E_BAD_PTR_CAST_ALIGN */
1538 1538                                  eValue = *(uint32_t *)rsaexp->val;
1539 1539                          } else {
1540 1540                                  rv = KMF_ERR_BAD_PARAMETER;
1541 1541                                  goto cleanup;
1542 1542                          }
1543 1543                  } else {
1544 1544                          /* RSA Exponent is optional. Default is 0x10001 */
1545 1545                          rv = KMF_OK;
1546 1546                  }
1547 1547  
1548 1548                  rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
1549 1549                      &keylen, &keylen_size);
1550 1550                  if (rv == KMF_ERR_ATTR_NOT_FOUND)
1551 1551                          /* keylen is optional, default is 1024 */
1552 1552                          rv = KMF_OK;
1553 1553                  if (rv != KMF_OK) {
1554 1554                          rv = KMF_ERR_BAD_PARAMETER;
1555 1555                          goto cleanup;
1556 1556                  }
1557 1557  
1558 1558                  sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
1559 1559                  if (sslPrivKey == NULL) {
1560 1560                          SET_ERROR(kmfh, ERR_get_error());
1561 1561                          rv = KMF_ERR_KEYGEN_FAILED;
1562 1562                  } else {
1563 1563                          (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
1564 1564                          privkey->kstype = KMF_KEYSTORE_OPENSSL;
1565 1565                          privkey->keyalg = KMF_RSA;
1566 1566                          privkey->keyclass = KMF_ASYM_PRI;
1567 1567                          privkey->israw = FALSE;
1568 1568                          privkey->keyp = (void *)eprikey;
1569 1569  
1570 1570                          /* OpenSSL derives the public key from the private */
1571 1571                          (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
1572 1572                          pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1573 1573                          pubkey->keyalg = KMF_RSA;
1574 1574                          pubkey->israw = FALSE;
1575 1575                          pubkey->keyclass = KMF_ASYM_PUB;
1576 1576                          pubkey->keyp = (void *)epubkey;
1577 1577                  }
1578 1578          } else if (keytype == KMF_DSA) {
1579 1579                  DSA *dp;
1580 1580                  sslDSAKey = DSA_new();
1581 1581                  if (sslDSAKey == NULL) {
1582 1582                          SET_ERROR(kmfh, ERR_get_error());
1583 1583                          return (KMF_ERR_MEMORY);
1584 1584                  }
1585 1585  
1586 1586                  if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
1587 1587                      NULL) {
1588 1588                          SET_ERROR(kmfh, ERR_get_error());
1589 1589                          rv = KMF_ERR_KEYGEN_FAILED;
1590 1590                          goto cleanup;
1591 1591                  }
1592 1592                  if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
1593 1593                      NULL) {
1594 1594                          SET_ERROR(kmfh, ERR_get_error());
1595 1595                          rv = KMF_ERR_KEYGEN_FAILED;
1596 1596                          goto cleanup;
1597 1597                  }
1598 1598                  if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
1599 1599                      NULL) {
1600 1600                          SET_ERROR(kmfh, ERR_get_error());
1601 1601                          rv = KMF_ERR_KEYGEN_FAILED;
1602 1602                          goto cleanup;
1603 1603                  }
1604 1604  
1605 1605                  if (!DSA_generate_key(sslDSAKey)) {
1606 1606                          SET_ERROR(kmfh, ERR_get_error());
1607 1607                          rv = KMF_ERR_KEYGEN_FAILED;
1608 1608                          goto cleanup;
1609 1609                  }
1610 1610  
1611 1611                  privkey->kstype = KMF_KEYSTORE_OPENSSL;
1612 1612                  privkey->keyalg = KMF_DSA;
1613 1613                  privkey->keyclass = KMF_ASYM_PRI;
1614 1614                  privkey->israw = FALSE;
1615 1615                  if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
1616 1616                          privkey->keyp = (void *)eprikey;
1617 1617                  } else {
1618 1618                          SET_ERROR(kmfh, ERR_get_error());
1619 1619                          rv = KMF_ERR_KEYGEN_FAILED;
1620 1620                          goto cleanup;
1621 1621                  }
1622 1622                  dp = DSA_new();
1623 1623                  /* Make a copy for the public key */
1624 1624                  if (dp != NULL) {
1625 1625                          if ((dp->p = BN_new()) == NULL) {
1626 1626                                  SET_ERROR(kmfh, ERR_get_error());
1627 1627                                  rv = KMF_ERR_MEMORY;
1628 1628                                  DSA_free(dp);
1629 1629                                  goto cleanup;
1630 1630                          }
1631 1631                          if ((dp->q = BN_new()) == NULL) {
1632 1632                                  SET_ERROR(kmfh, ERR_get_error());
1633 1633                                  rv = KMF_ERR_MEMORY;
1634 1634                                  BN_free(dp->p);
1635 1635                                  DSA_free(dp);
1636 1636                                  goto cleanup;
1637 1637                          }
1638 1638                          if ((dp->g = BN_new()) == NULL) {
1639 1639                                  SET_ERROR(kmfh, ERR_get_error());
1640 1640                                  rv = KMF_ERR_MEMORY;
1641 1641                                  BN_free(dp->q);
1642 1642                                  BN_free(dp->p);
1643 1643                                  DSA_free(dp);
1644 1644                                  goto cleanup;
1645 1645                          }
1646 1646                          if ((dp->pub_key = BN_new()) == NULL) {
1647 1647                                  SET_ERROR(kmfh, ERR_get_error());
1648 1648                                  rv = KMF_ERR_MEMORY;
1649 1649                                  BN_free(dp->q);
1650 1650                                  BN_free(dp->p);
1651 1651                                  BN_free(dp->g);
1652 1652                                  DSA_free(dp);
1653 1653                                  goto cleanup;
1654 1654                          }
1655 1655                          (void) BN_copy(dp->p, sslDSAKey->p);
1656 1656                          (void) BN_copy(dp->q, sslDSAKey->q);
1657 1657                          (void) BN_copy(dp->g, sslDSAKey->g);
1658 1658                          (void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
1659 1659  
1660 1660                          pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1661 1661                          pubkey->keyalg = KMF_DSA;
1662 1662                          pubkey->keyclass = KMF_ASYM_PUB;
1663 1663                          pubkey->israw = FALSE;
1664 1664  
1665 1665                          if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
1666 1666                                  pubkey->keyp = (void *)epubkey;
1667 1667                          } else {
1668 1668                                  SET_ERROR(kmfh, ERR_get_error());
1669 1669                                  rv = KMF_ERR_KEYGEN_FAILED;
1670 1670                                  goto cleanup;
1671 1671                          }
1672 1672                  }
1673 1673          }
1674 1674  
1675 1675          if (rv != KMF_OK) {
1676 1676                  goto cleanup;
1677 1677          }
1678 1678  
1679 1679          if (storekey) {
1680 1680                  KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
1681 1681                  int i = 0;
1682 1682                  char *keyfile = NULL, *dirpath = NULL;
1683 1683                  KMF_ENCODE_FORMAT format;
1684 1684                  /*
1685 1685                   * Construct a new attribute arrray and call openssl_store_key
1686 1686                   */
1687 1687                  kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
1688 1688                      privkey, sizeof (privkey));
1689 1689                  i++;
1690 1690  
1691 1691                  dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1692 1692                  if (dirpath != NULL) {
1693 1693                          storeattrs[i].type = KMF_DIRPATH_ATTR;
1694 1694                          storeattrs[i].pValue = dirpath;
1695 1695                          storeattrs[i].valueLen = strlen(dirpath);
1696 1696                          i++;
1697 1697                  } else {
1698 1698                          rv = KMF_OK; /* DIRPATH is optional */
1699 1699                  }
1700 1700                  keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
1701 1701                      attrlist, numattr);
1702 1702                  if (keyfile != NULL) {
1703 1703                          storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
1704 1704                          storeattrs[i].pValue = keyfile;
1705 1705                          storeattrs[i].valueLen = strlen(keyfile);
1706 1706                          i++;
1707 1707                  } else {
1708 1708                          goto cleanup; /* KEYFILE is required */
1709 1709                  }
1710 1710                  rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1711 1711                      (void *)&format, NULL);
1712 1712                  if (rv == KMF_OK) {
1713 1713                          storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
1714 1714                          storeattrs[i].pValue = &format;
1715 1715                          storeattrs[i].valueLen = sizeof (format);
1716 1716                          i++;
1717 1717                  }
1718 1718  
1719 1719                  rv = OpenSSL_StoreKey(handle, i, storeattrs);
1720 1720          }
1721 1721  
1722 1722  cleanup:
1723 1723          if (rv != KMF_OK) {
1724 1724                  if (eprikey != NULL)
1725 1725                          EVP_PKEY_free(eprikey);
1726 1726  
1727 1727                  if (epubkey != NULL)
1728 1728                          EVP_PKEY_free(epubkey);
1729 1729  
1730 1730                  if (pubkey->keylabel) {
1731 1731                          free(pubkey->keylabel);
1732 1732                          pubkey->keylabel = NULL;
1733 1733                  }
1734 1734  
1735 1735                  if (privkey->keylabel) {
1736 1736                          free(privkey->keylabel);
1737 1737                          privkey->keylabel = NULL;
1738 1738                  }
1739 1739  
1740 1740                  pubkey->keyp = NULL;
1741 1741                  privkey->keyp = NULL;
1742 1742          }
1743 1743  
1744 1744          if (sslPrivKey)
1745 1745                  RSA_free(sslPrivKey);
1746 1746  
1747 1747          if (sslDSAKey)
1748 1748                  DSA_free(sslDSAKey);
1749 1749  
1750 1750          if (out != NULL)
1751 1751                  (void) BIO_free(out);
1752 1752  
1753 1753          return (rv);
1754 1754  }
1755 1755  
1756 1756  /*
1757 1757   * Make sure the BN conversion is properly padded with 0x00
1758 1758   * bytes.  If not, signature verification for DSA signatures
1759 1759   * may fail in the case where the bignum value does not use
1760 1760   * all of the bits.
1761 1761   */
1762 1762  static int
1763 1763  fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
1764 1764          int bytes = len - BN_num_bytes(bn);
1765 1765  
1766 1766          /* prepend with leading 0x00 if necessary */
1767 1767          while (bytes-- > 0)
1768 1768                  *buf++ = 0;
1769 1769  
1770 1770          (void) BN_bn2bin(bn, buf);
1771 1771          /*
1772 1772           * Return the desired length since we prepended it
1773 1773           * with the necessary 0x00 padding.
1774 1774           */
1775 1775          return (len);
1776 1776  }
1777 1777  
1778 1778  KMF_RETURN
1779 1779  OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1780 1780          KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
1781 1781  {
1782 1782          KMF_RETURN ret = KMF_OK;
1783 1783          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1784 1784          KMF_ALGORITHM_INDEX             AlgId;
1785 1785          EVP_MD_CTX ctx;
1786 1786          const EVP_MD *md;
1787 1787  
1788 1788          if (key == NULL || AlgOID == NULL ||
1789 1789              tobesigned == NULL || output == NULL ||
1790 1790              tobesigned->Data == NULL ||
1791 1791              output->Data == NULL)
1792 1792                  return (KMF_ERR_BAD_PARAMETER);
1793 1793  
1794 1794          /* Map the OID to an OpenSSL algorithm */
1795 1795          AlgId = x509_algoid_to_algid(AlgOID);
1796 1796          if (AlgId == KMF_ALGID_NONE)
1797 1797                  return (KMF_ERR_BAD_ALGORITHM);
1798 1798  
1799 1799          if (key->keyalg == KMF_RSA) {
1800 1800                  EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
1801 1801                  uchar_t *p;
1802 1802                  int len;
1803 1803                  if (AlgId == KMF_ALGID_MD5WithRSA)
1804 1804                          md = EVP_md5();
1805 1805                  else if (AlgId == KMF_ALGID_MD2WithRSA)
1806 1806                          md = EVP_md2();
1807 1807                  else if (AlgId == KMF_ALGID_SHA1WithRSA)
1808 1808                          md = EVP_sha1();
1809 1809                  else if (AlgId == KMF_ALGID_SHA256WithRSA)
1810 1810                          md = EVP_sha256();
1811 1811                  else if (AlgId == KMF_ALGID_SHA384WithRSA)
1812 1812                          md = EVP_sha384();
1813 1813                  else if (AlgId == KMF_ALGID_SHA512WithRSA)
1814 1814                          md = EVP_sha512();
1815 1815                  else if (AlgId == KMF_ALGID_RSA)
1816 1816                          md = NULL;
1817 1817                  else
1818 1818                          return (KMF_ERR_BAD_ALGORITHM);
1819 1819  
1820 1820                  if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
1821 1821                          RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
1822 1822  
1823 1823                          p = output->Data;
1824 1824                          if ((len = RSA_private_encrypt(tobesigned->Length,
1825 1825                              tobesigned->Data, p, rsa,
1826 1826                              RSA_PKCS1_PADDING)) <= 0) {
1827 1827                                  SET_ERROR(kmfh, ERR_get_error());
1828 1828                                  ret = KMF_ERR_INTERNAL;
1829 1829                          }
1830 1830                          output->Length = len;
1831 1831                  } else {
1832 1832                          (void) EVP_MD_CTX_init(&ctx);
1833 1833                          (void) EVP_SignInit_ex(&ctx, md, NULL);
1834 1834                          (void) EVP_SignUpdate(&ctx, tobesigned->Data,
1835 1835                              (uint32_t)tobesigned->Length);
1836 1836                          len = (uint32_t)output->Length;
1837 1837                          p = output->Data;
1838 1838                          if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
1839 1839                                  SET_ERROR(kmfh, ERR_get_error());
1840 1840                                  len = 0;
1841 1841                                  ret = KMF_ERR_INTERNAL;
1842 1842                          }
1843 1843                          output->Length = len;
1844 1844                          (void) EVP_MD_CTX_cleanup(&ctx);
1845 1845                  }
1846 1846          } else if (key->keyalg == KMF_DSA) {
1847 1847                  DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
1848 1848  
1849 1849                  uchar_t hash[EVP_MAX_MD_SIZE];
1850 1850                  uint32_t hashlen;
1851 1851                  DSA_SIG *dsasig;
1852 1852  
1853 1853                  if (AlgId == KMF_ALGID_DSA ||
1854 1854                      AlgId == KMF_ALGID_SHA1WithDSA)
1855 1855                          md = EVP_sha1();
1856 1856                  else if (AlgId == KMF_ALGID_SHA256WithDSA)
1857 1857                          md = EVP_sha256();
1858 1858                  else /* Bad algorithm */
1859 1859                          return (KMF_ERR_BAD_ALGORITHM);
1860 1860  
1861 1861                  /*
1862 1862                   * OpenSSL EVP_Sign operation automatically converts to
1863 1863                   * ASN.1 output so we do the operations separately so we
1864 1864                   * are assured of NOT getting ASN.1 output returned.
1865 1865                   * KMF does not want ASN.1 encoded results because
1866 1866                   * not all mechanisms return ASN.1 encodings (PKCS#11
1867 1867                   * and NSS return raw signature data).
1868 1868                   */
1869 1869                  EVP_MD_CTX_init(&ctx);
1870 1870                  (void) EVP_DigestInit_ex(&ctx, md, NULL);
1871 1871                  (void) EVP_DigestUpdate(&ctx, tobesigned->Data,
1872 1872                      tobesigned->Length);
1873 1873                  (void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
1874 1874  
1875 1875                  /* Only sign first 20 bytes for SHA2 */
1876 1876                  if (AlgId == KMF_ALGID_SHA256WithDSA)
1877 1877                          hashlen = 20;
1878 1878                  dsasig = DSA_do_sign(hash, hashlen, dsa);
1879 1879                  if (dsasig != NULL) {
1880 1880                          int i;
1881 1881                          output->Length = i = fixbnlen(dsasig->r, output->Data,
1882 1882                              hashlen);
1883 1883  
1884 1884                          output->Length += fixbnlen(dsasig->s, &output->Data[i],
1885 1885                              hashlen);
1886 1886  
1887 1887                          DSA_SIG_free(dsasig);
1888 1888                  } else {
1889 1889                          SET_ERROR(kmfh, ERR_get_error());
1890 1890                  }
1891 1891                  (void) EVP_MD_CTX_cleanup(&ctx);
1892 1892          } else {
1893 1893                  return (KMF_ERR_BAD_PARAMETER);
1894 1894          }
1895 1895  cleanup:
1896 1896          return (ret);
1897 1897  }
1898 1898  
1899 1899  KMF_RETURN
1900 1900  /*ARGSUSED*/
1901 1901  OpenSSL_DeleteKey(KMF_HANDLE_T handle,
1902 1902          int numattr, KMF_ATTRIBUTE *attrlist)
1903 1903  {
1904 1904          KMF_RETURN rv = KMF_OK;
1905 1905          KMF_KEY_HANDLE *key;
1906 1906          boolean_t destroy = B_TRUE;
1907 1907  
1908 1908          key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1909 1909          if (key == NULL || key->keyp == NULL)
1910 1910                  return (KMF_ERR_BAD_PARAMETER);
1911 1911  
1912 1912          rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1913 1913              (void *)&destroy, NULL);
1914 1914          if (rv != KMF_OK) {
1915 1915                  /* "destroy" is optional. Default is TRUE */
1916 1916                  rv = KMF_OK;
1917 1917          }
1918 1918  
1919 1919          if (key->keyclass != KMF_ASYM_PUB &&
1920 1920              key->keyclass != KMF_ASYM_PRI &&
1921 1921              key->keyclass != KMF_SYMMETRIC)
1922 1922                  return (KMF_ERR_BAD_KEY_CLASS);
1923 1923  
1924 1924          if (key->keyclass == KMF_SYMMETRIC) {
1925 1925                  kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
1926 1926                  key->keyp = NULL;
1927 1927          } else {
1928 1928                  if (key->keyp != NULL) {
1929 1929                          EVP_PKEY_free(key->keyp);
1930 1930                          key->keyp = NULL;
1931 1931                  }
1932 1932          }
1933 1933  
1934 1934          if (key->keylabel != NULL) {
1935 1935                  EVP_PKEY *pkey = NULL;
1936 1936                  /* If the file exists, make sure it is a proper key. */
1937 1937                  pkey = openssl_load_key(handle, key->keylabel);
1938 1938                  if (pkey == NULL) {
1939 1939                          if (key->keylabel != NULL) {
1940 1940                                  free(key->keylabel);
1941 1941                                  key->keylabel = NULL;
1942 1942                          }
1943 1943                          return (KMF_ERR_KEY_NOT_FOUND);
1944 1944                  }
1945 1945                  EVP_PKEY_free(pkey);
1946 1946  
1947 1947                  if (destroy) {
1948 1948                          if (unlink(key->keylabel) != 0) {
1949 1949                                  KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1950 1950                                  SET_SYS_ERROR(kmfh, errno);
1951 1951                                  rv = KMF_ERR_INTERNAL;
1952 1952                          }
1953 1953                  }
1954 1954                  if (key->keylabel != NULL) {
1955 1955                          free(key->keylabel);
1956 1956                          key->keylabel = NULL;
1957 1957                  }
1958 1958          }
1959 1959          return (rv);
1960 1960  }
1961 1961  
1962 1962  KMF_RETURN
1963 1963  OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1964 1964  {
1965 1965          KMF_RETURN ret = KMF_OK;
1966 1966          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1967 1967          char str[256];  /* OpenSSL needs at least 120 byte buffer */
1968 1968  
1969 1969          ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
1970 1970          if (strlen(str)) {
1971 1971                  *msgstr = (char *)strdup(str);
1972 1972                  if ((*msgstr) == NULL)
1973 1973                          ret = KMF_ERR_MEMORY;
1974 1974          } else {
1975 1975                  *msgstr = NULL;
1976 1976          }
1977 1977  
1978 1978          return (ret);
1979 1979  }
1980 1980  
1981 1981  static int
1982 1982  ext2NID(int kmfext)
1983 1983  {
1984 1984          switch (kmfext) {
1985 1985                  case KMF_X509_EXT_KEY_USAGE:
1986 1986                          return (NID_key_usage);
1987 1987                  case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
1988 1988                          return (NID_private_key_usage_period);
1989 1989                  case KMF_X509_EXT_CERT_POLICIES:
1990 1990                          return (NID_certificate_policies);
1991 1991                  case KMF_X509_EXT_SUBJ_ALTNAME:
1992 1992                          return (NID_subject_alt_name);
1993 1993                  case KMF_X509_EXT_ISSUER_ALTNAME:
1994 1994                          return (NID_issuer_alt_name);
1995 1995                  case KMF_X509_EXT_BASIC_CONSTRAINTS:
1996 1996                          return (NID_basic_constraints);
1997 1997                  case KMF_X509_EXT_EXT_KEY_USAGE:
1998 1998                          return (NID_ext_key_usage);
1999 1999                  case KMF_X509_EXT_AUTH_KEY_ID:
2000 2000                          return (NID_authority_key_identifier);
2001 2001                  case KMF_X509_EXT_CRL_DIST_POINTS:
2002 2002                          return (NID_crl_distribution_points);
2003 2003                  case KMF_X509_EXT_SUBJ_KEY_ID:
2004 2004                          return (NID_subject_key_identifier);
2005 2005                  case KMF_X509_EXT_POLICY_MAPPINGS:
2006 2006                          return (OBJ_sn2nid("policyMappings"));
2007 2007                  case KMF_X509_EXT_NAME_CONSTRAINTS:
2008 2008                          return (OBJ_sn2nid("nameConstraints"));
2009 2009                  case KMF_X509_EXT_POLICY_CONSTRAINTS:
2010 2010                          return (OBJ_sn2nid("policyConstraints"));
2011 2011                  case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2012 2012                          return (OBJ_sn2nid("inhibitAnyPolicy"));
2013 2013                  case KMF_X509_EXT_FRESHEST_CRL:
2014 2014                          return (OBJ_sn2nid("freshestCRL"));
2015 2015                  default:
2016 2016                          return (NID_undef);
2017 2017          }
2018 2018  }
2019 2019  
2020 2020  KMF_RETURN
2021 2021  OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
2022 2022          KMF_PRINTABLE_ITEM flag, char *resultStr)
2023 2023  {
2024 2024          KMF_RETURN ret = KMF_OK;
2025 2025          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
  
    | ↓ open down ↓ | 2025 lines elided | ↑ open up ↑ | 
2026 2026          X509 *xcert = NULL;
2027 2027          unsigned char *outbuf = NULL;
2028 2028          unsigned char *outbuf_p;
2029 2029          char *tmpstr = NULL;
2030 2030          int j;
2031 2031          int ext_index, nid, len;
2032 2032          BIO *mem = NULL;
2033 2033  #if OPENSSL_VERSION_NUMBER < 0x10000000L
2034 2034          STACK *emlst = NULL;
2035 2035  #else
2036      -        STACK_OF(OPENSSL_STRING) *emlst = NULL;
     2036 +        STACK_OF(OPENSSL_STRING) *emlst = NULL;
2037 2037  #endif
2038 2038          X509_EXTENSION *ex;
2039 2039          X509_CINF *ci;
2040 2040  
2041 2041          if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
2042 2042                  return (KMF_ERR_BAD_PARAMETER);
2043 2043          }
2044 2044  
2045 2045          /* copy cert data to outbuf */
2046 2046          outbuf = malloc(pcert->Length);
2047 2047          if (outbuf == NULL) {
2048 2048                  return (KMF_ERR_MEMORY);
2049 2049          }
2050 2050          (void) memcpy(outbuf, pcert->Data, pcert->Length);
2051 2051  
2052 2052          outbuf_p = outbuf; /* use a temp pointer; required by openssl */
2053 2053          xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
2054 2054          if (xcert == NULL) {
2055 2055                  SET_ERROR(kmfh, ERR_get_error());
2056 2056                  ret = KMF_ERR_ENCODING;
2057 2057                  goto out;
2058 2058          }
2059 2059  
2060 2060          mem = BIO_new(BIO_s_mem());
2061 2061          if (mem == NULL) {
2062 2062                  SET_ERROR(kmfh, ERR_get_error());
2063 2063                  ret = KMF_ERR_MEMORY;
2064 2064                  goto out;
2065 2065          }
2066 2066  
2067 2067          switch (flag) {
2068 2068          case KMF_CERT_ISSUER:
2069 2069                  (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
2070 2070                      XN_FLAG_SEP_CPLUS_SPC);
2071 2071                  len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2072 2072                  break;
2073 2073  
2074 2074          case KMF_CERT_SUBJECT:
2075 2075                  (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
2076 2076                      XN_FLAG_SEP_CPLUS_SPC);
2077 2077                  len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2078 2078                  break;
2079 2079  
2080 2080          case KMF_CERT_VERSION:
2081 2081                  tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
2082 2082                  (void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
2083 2083                  OPENSSL_free(tmpstr);
2084 2084                  len = strlen(resultStr);
2085 2085                  break;
2086 2086  
2087 2087          case KMF_CERT_SERIALNUM:
2088 2088                  if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
2089 2089                          (void) strcpy(resultStr, "0x");
2090 2090                          len = BIO_gets(mem, &resultStr[2],
2091 2091                              KMF_CERT_PRINTABLE_LEN - 2);
2092 2092                  }
2093 2093                  break;
2094 2094  
2095 2095          case KMF_CERT_NOTBEFORE:
2096 2096                  (void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
2097 2097                  len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2098 2098                  break;
2099 2099  
2100 2100          case KMF_CERT_NOTAFTER:
2101 2101                  (void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
2102 2102                  len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2103 2103                  break;
2104 2104  
2105 2105          case KMF_CERT_PUBKEY_DATA:
2106 2106                  {
2107 2107                          EVP_PKEY *pkey = X509_get_pubkey(xcert);
2108 2108                          if (pkey == NULL) {
2109 2109                                  SET_ERROR(kmfh, ERR_get_error());
2110 2110                                  ret = KMF_ERR_ENCODING;
2111 2111                                  goto out;
2112 2112                          }
2113 2113  
2114 2114                          if (pkey->type == EVP_PKEY_RSA) {
2115 2115                                  (void) BIO_printf(mem,
2116 2116                                      "RSA Public Key: (%d bit)\n",
2117 2117                                      BN_num_bits(pkey->pkey.rsa->n));
2118 2118                                  (void) RSA_print(mem, pkey->pkey.rsa, 0);
2119 2119                          } else if (pkey->type == EVP_PKEY_DSA) {
2120 2120                                  (void) BIO_printf(mem,
2121 2121                                      "%12sDSA Public Key:\n", "");
2122 2122                                  (void) DSA_print(mem, pkey->pkey.dsa, 0);
2123 2123                          } else {
2124 2124                                  (void) BIO_printf(mem,
2125 2125                                      "%12sUnknown Public Key:\n", "");
2126 2126                          }
2127 2127                          (void) BIO_printf(mem, "\n");
2128 2128                          EVP_PKEY_free(pkey);
2129 2129                  }
2130 2130                  len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2131 2131                  break;
2132 2132          case KMF_CERT_SIGNATURE_ALG:
2133 2133          case KMF_CERT_PUBKEY_ALG:
2134 2134                  if (flag == KMF_CERT_SIGNATURE_ALG) {
2135 2135                          len = i2a_ASN1_OBJECT(mem,
2136 2136                              xcert->sig_alg->algorithm);
2137 2137                  } else {
2138 2138                          len = i2a_ASN1_OBJECT(mem,
2139 2139                              xcert->cert_info->key->algor->algorithm);
2140 2140                  }
2141 2141  
2142 2142                  if (len > 0) {
2143 2143                          len = BIO_read(mem, resultStr,
2144 2144                              KMF_CERT_PRINTABLE_LEN);
2145 2145                  }
  
    | ↓ open down ↓ | 99 lines elided | ↑ open up ↑ | 
2146 2146                  break;
2147 2147  
2148 2148          case KMF_CERT_EMAIL:
2149 2149                  emlst = X509_get1_email(xcert);
2150 2150  #if OPENSSL_VERSION_NUMBER < 0x10000000L
2151 2151                  for (j = 0; j < sk_num(emlst); j++)
2152 2152                          (void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
2153 2153  #else
2154 2154                  for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
2155 2155                          (void) BIO_printf(mem, "%s\n",
2156      -                            sk_OPENSSL_STRING_value(emlst, j));
     2156 +                            sk_OPENSSL_STRING_value(emlst, j));
2157 2157  #endif
2158 2158  
2159 2159                  len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2160 2160                  X509_email_free(emlst);
2161 2161                  break;
2162 2162          case KMF_X509_EXT_ISSUER_ALTNAME:
2163 2163          case KMF_X509_EXT_SUBJ_ALTNAME:
2164 2164          case KMF_X509_EXT_KEY_USAGE:
2165 2165          case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
2166 2166          case KMF_X509_EXT_CERT_POLICIES:
2167 2167          case KMF_X509_EXT_BASIC_CONSTRAINTS:
2168 2168          case KMF_X509_EXT_NAME_CONSTRAINTS:
2169 2169          case KMF_X509_EXT_POLICY_CONSTRAINTS:
2170 2170          case KMF_X509_EXT_EXT_KEY_USAGE:
2171 2171          case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2172 2172          case KMF_X509_EXT_AUTH_KEY_ID:
2173 2173          case KMF_X509_EXT_SUBJ_KEY_ID:
2174 2174          case KMF_X509_EXT_POLICY_MAPPINGS:
2175 2175          case KMF_X509_EXT_CRL_DIST_POINTS:
2176 2176          case KMF_X509_EXT_FRESHEST_CRL:
2177 2177                  nid = ext2NID(flag);
2178 2178                  if (nid == NID_undef) {
2179 2179                          ret = KMF_ERR_EXTENSION_NOT_FOUND;
2180 2180                          goto out;
2181 2181                  }
2182 2182                  ci = xcert->cert_info;
2183 2183  
2184 2184                  ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
2185 2185                  if (ext_index == -1) {
2186 2186                          SET_ERROR(kmfh, ERR_get_error());
2187 2187  
2188 2188                          ret = KMF_ERR_EXTENSION_NOT_FOUND;
2189 2189                          goto out;
2190 2190                  }
2191 2191                  ex = X509v3_get_ext(ci->extensions, ext_index);
2192 2192  
2193 2193                  (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
2194 2194  
2195 2195                  if (BIO_printf(mem, ": %s\n",
2196 2196                      X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
2197 2197                          SET_ERROR(kmfh, ERR_get_error());
2198 2198                          ret = KMF_ERR_ENCODING;
2199 2199                          goto out;
2200 2200                  }
2201 2201                  if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
2202 2202                          (void) BIO_printf(mem, "%*s", 4, "");
2203 2203                          (void) M_ASN1_OCTET_STRING_print(mem, ex->value);
2204 2204                  }
2205 2205                  if (BIO_write(mem, "\n", 1) <= 0) {
2206 2206                          SET_ERROR(kmfh, ERR_get_error());
2207 2207                          ret = KMF_ERR_ENCODING;
2208 2208                          goto out;
2209 2209                  }
2210 2210                  len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2211 2211          }
2212 2212          if (len <= 0) {
2213 2213                  SET_ERROR(kmfh, ERR_get_error());
2214 2214                  ret = KMF_ERR_ENCODING;
2215 2215          }
2216 2216  
2217 2217  out:
2218 2218          if (outbuf != NULL) {
2219 2219                  free(outbuf);
2220 2220          }
2221 2221  
2222 2222          if (xcert != NULL) {
2223 2223                  X509_free(xcert);
2224 2224          }
2225 2225  
2226 2226          if (mem != NULL) {
2227 2227                  (void) BIO_free(mem);
2228 2228          }
2229 2229  
2230 2230          return (ret);
2231 2231  }
2232 2232  
2233 2233  KMF_RETURN
2234 2234  /*ARGSUSED*/
2235 2235  OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
2236 2236      KMF_ATTRIBUTE *attrlist)
2237 2237  {
2238 2238          KMF_RETURN rv = KMF_OK;
2239 2239          KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2240 2240          KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
2241 2241          KMF_KEY_HANDLE *key = NULL;
2242 2242          uint32_t numkeys = 1; /* 1 key only */
2243 2243          char *dirpath = NULL;
2244 2244          char *keyfile = NULL;
2245 2245          KMF_ATTRIBUTE new_attrlist[16];
2246 2246          int i = 0;
2247 2247  
2248 2248          /*
2249 2249           * This is really just a FindKey operation, reuse the
2250 2250           * FindKey function.
2251 2251           */
2252 2252          kmf_set_attr_at_index(new_attrlist, i,
2253 2253              KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2254 2254          i++;
2255 2255  
2256 2256          kmf_set_attr_at_index(new_attrlist, i,
2257 2257              KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
2258 2258          i++;
2259 2259  
2260 2260          kmf_set_attr_at_index(new_attrlist, i,
2261 2261              KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
2262 2262          i++;
2263 2263  
2264 2264          key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2265 2265          if (key == NULL) {
2266 2266                  return (KMF_ERR_BAD_PARAMETER);
2267 2267          } else {
2268 2268                  kmf_set_attr_at_index(new_attrlist, i,
2269 2269                      KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
2270 2270                  i++;
2271 2271          }
2272 2272  
2273 2273          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2274 2274          if (dirpath != NULL) {
2275 2275                  kmf_set_attr_at_index(new_attrlist, i,
2276 2276                      KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2277 2277                  i++;
2278 2278          }
2279 2279  
2280 2280          keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2281 2281          if (keyfile == NULL)
2282 2282                  return (KMF_ERR_BAD_PARAMETER);
2283 2283          else {
2284 2284                  kmf_set_attr_at_index(new_attrlist, i,
2285 2285                      KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
2286 2286                  i++;
2287 2287          }
2288 2288  
2289 2289          rv = OpenSSL_FindKey(handle, i, new_attrlist);
2290 2290          return (rv);
2291 2291  }
2292 2292  
2293 2293  KMF_RETURN
2294 2294  /*ARGSUSED*/
2295 2295  OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2296 2296          KMF_OID *AlgOID, KMF_DATA *ciphertext,
2297 2297          KMF_DATA *output)
2298 2298  {
2299 2299          KMF_RETURN              ret = KMF_OK;
2300 2300          RSA *rsa = NULL;
2301 2301          unsigned int in_len = 0, out_len = 0;
2302 2302          unsigned int total_decrypted = 0, modulus_len = 0;
2303 2303          uint8_t *in_data, *out_data;
2304 2304          int i, blocks;
2305 2305  
2306 2306          if (key == NULL || AlgOID == NULL ||
2307 2307              ciphertext == NULL || output == NULL ||
2308 2308              ciphertext->Data == NULL ||
2309 2309              output->Data == NULL)
2310 2310                  return (KMF_ERR_BAD_PARAMETER);
2311 2311  
2312 2312          if (key->keyalg == KMF_RSA) {
2313 2313                  rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
2314 2314                  modulus_len = RSA_size(rsa);
2315 2315          } else {
2316 2316                  return (KMF_ERR_BAD_PARAMETER);
2317 2317          }
2318 2318  
2319 2319          blocks = ciphertext->Length/modulus_len;
2320 2320          out_data = output->Data;
2321 2321          in_data = ciphertext->Data;
2322 2322          out_len = modulus_len - 11;
2323 2323          in_len = modulus_len;
2324 2324  
2325 2325          for (i = 0; i < blocks; i++) {
2326 2326                  out_len  = RSA_private_decrypt(in_len,
2327 2327                      in_data, out_data, rsa, RSA_PKCS1_PADDING);
2328 2328  
2329 2329                  if (out_len == 0) {
2330 2330                          ret = KMF_ERR_INTERNAL;
2331 2331                          goto cleanup;
2332 2332                  }
2333 2333  
2334 2334                  out_data += out_len;
2335 2335                  total_decrypted += out_len;
2336 2336                  in_data += in_len;
2337 2337          }
2338 2338  
2339 2339          output->Length = total_decrypted;
2340 2340  
2341 2341  cleanup:
2342 2342          RSA_free(rsa);
2343 2343          if (ret != KMF_OK)
2344 2344                  output->Length = 0;
2345 2345  
2346 2346          return (ret);
2347 2347  
2348 2348  }
2349 2349  
2350 2350  /*
2351 2351   *  This function will create a certid from issuer_cert and user_cert.
2352 2352   *  The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
2353 2353   *  certid memory after use.
2354 2354   */
2355 2355  static KMF_RETURN
2356 2356  create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
2357 2357      const KMF_DATA *user_cert, OCSP_CERTID **certid)
2358 2358  {
2359 2359          KMF_RETURN ret = KMF_OK;
2360 2360          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2361 2361          X509   *issuer = NULL;
2362 2362          X509   *cert = NULL;
2363 2363          unsigned char *ptmp;
2364 2364  
2365 2365          if (issuer_cert == NULL || user_cert == NULL) {
2366 2366                  return (KMF_ERR_BAD_PARAMETER);
2367 2367          }
2368 2368  
2369 2369          /* convert the DER-encoded issuer cert to an internal X509 */
2370 2370          ptmp = issuer_cert->Data;
2371 2371          issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2372 2372              issuer_cert->Length);
2373 2373          if (issuer == NULL) {
2374 2374                  SET_ERROR(kmfh, ERR_get_error());
2375 2375                  ret = KMF_ERR_OCSP_BAD_ISSUER;
2376 2376                  goto end;
2377 2377          }
2378 2378  
2379 2379          /* convert the DER-encoded user cert to an internal X509 */
2380 2380          ptmp = user_cert->Data;
2381 2381          cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
2382 2382              user_cert->Length);
2383 2383          if (cert == NULL) {
2384 2384                  SET_ERROR(kmfh, ERR_get_error());
2385 2385  
2386 2386                  ret = KMF_ERR_OCSP_BAD_CERT;
2387 2387                  goto end;
2388 2388          }
2389 2389  
2390 2390          /* create a CERTID */
2391 2391          *certid = OCSP_cert_to_id(NULL, cert, issuer);
2392 2392          if (*certid == NULL) {
2393 2393                  SET_ERROR(kmfh, ERR_get_error());
2394 2394                  ret = KMF_ERR_OCSP_CERTID;
2395 2395                  goto end;
2396 2396          }
2397 2397  
2398 2398  end:
2399 2399          if (issuer != NULL) {
2400 2400                  X509_free(issuer);
2401 2401          }
2402 2402  
2403 2403          if (cert != NULL) {
2404 2404                  X509_free(cert);
2405 2405          }
2406 2406  
2407 2407          return (ret);
2408 2408  }
2409 2409  
2410 2410  KMF_RETURN
2411 2411  OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
2412 2412          int numattr, KMF_ATTRIBUTE *attrlist)
2413 2413  {
2414 2414          KMF_RETURN ret = KMF_OK;
2415 2415          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2416 2416          OCSP_CERTID *id = NULL;
2417 2417          OCSP_REQUEST *req = NULL;
2418 2418          BIO *derbio = NULL;
2419 2419          char *reqfile;
2420 2420          KMF_DATA *issuer_cert;
2421 2421          KMF_DATA *user_cert;
2422 2422  
2423 2423          user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2424 2424              attrlist, numattr);
2425 2425          if (user_cert == NULL)
2426 2426                  return (KMF_ERR_BAD_PARAMETER);
2427 2427  
2428 2428          issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2429 2429              attrlist, numattr);
2430 2430          if (issuer_cert == NULL)
2431 2431                  return (KMF_ERR_BAD_PARAMETER);
2432 2432  
2433 2433          reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
2434 2434              attrlist, numattr);
2435 2435          if (reqfile == NULL)
2436 2436                  return (KMF_ERR_BAD_PARAMETER);
2437 2437  
2438 2438          ret = create_certid(handle, issuer_cert, user_cert, &id);
2439 2439          if (ret != KMF_OK) {
2440 2440                  return (ret);
2441 2441          }
2442 2442  
2443 2443          /* Create an OCSP request */
2444 2444          req = OCSP_REQUEST_new();
2445 2445          if (req == NULL) {
2446 2446                  SET_ERROR(kmfh, ERR_get_error());
2447 2447                  ret = KMF_ERR_OCSP_CREATE_REQUEST;
2448 2448                  goto end;
2449 2449          }
2450 2450  
2451 2451          if (!OCSP_request_add0_id(req, id)) {
2452 2452                  ret = KMF_ERR_OCSP_CREATE_REQUEST;
2453 2453                  goto end;
2454 2454          }
2455 2455  
2456 2456          /* Write the request to the output file with DER encoding */
2457 2457          derbio = BIO_new_file(reqfile, "wb");
2458 2458          if (!derbio) {
2459 2459                  SET_ERROR(kmfh, ERR_get_error());
2460 2460                  ret = KMF_ERR_OPEN_FILE;
2461 2461                  goto end;
2462 2462          }
2463 2463          if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
2464 2464                  ret = KMF_ERR_ENCODING;
2465 2465          }
2466 2466  
2467 2467  end:
2468 2468          /*
2469 2469           * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2470 2470           * will also deallocate certid's space.
2471 2471           */
2472 2472          if (req != NULL) {
2473 2473                  OCSP_REQUEST_free(req);
2474 2474          }
2475 2475  
2476 2476          if (derbio != NULL) {
2477 2477                  (void) BIO_free(derbio);
2478 2478          }
2479 2479  
2480 2480          return (ret);
2481 2481  }
2482 2482  
2483 2483  /* ocsp_find_signer_sk() is copied from openssl source */
2484 2484  static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
2485 2485  {
2486 2486          int i;
2487 2487          unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2488 2488  
2489 2489          /* Easy if lookup by name */
2490 2490          if (id->type == V_OCSP_RESPID_NAME)
2491 2491                  return (X509_find_by_subject(certs, id->value.byName));
  
    | ↓ open down ↓ | 325 lines elided | ↑ open up ↑ | 
2492 2492  
2493 2493          /* Lookup by key hash */
2494 2494  
2495 2495          /* If key hash isn't SHA1 length then forget it */
2496 2496          if (id->value.byKey->length != SHA_DIGEST_LENGTH)
2497 2497                  return (NULL);
2498 2498  
2499 2499          keyhash = id->value.byKey->data;
2500 2500          /* Calculate hash of each key and compare */
2501 2501          for (i = 0; i < sk_X509_num(certs); i++) {
2502      -                /* LINTED E_BAD_PTR_CAST_ALIGN */
2503 2502                  X509 *x = sk_X509_value(certs, i);
2504 2503                  /* Use pubkey_digest to get the key ID value */
2505 2504                  (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
2506 2505                  if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
2507 2506                          return (x);
2508 2507          }
2509 2508          return (NULL);
2510 2509  }
2511 2510  
2512 2511  /* ocsp_find_signer() is copied from openssl source */
2513 2512  /* ARGSUSED2 */
2514 2513  static int
2515 2514  ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
2516 2515      X509_STORE *st, unsigned long flags)
2517 2516  {
2518 2517          X509 *signer;
2519 2518          OCSP_RESPID *rid = bs->tbsResponseData->responderId;
2520 2519          if ((signer = ocsp_find_signer_sk(certs, rid))) {
2521 2520                  *psigner = signer;
2522 2521                  return (2);
2523 2522          }
2524 2523          if (!(flags & OCSP_NOINTERN) &&
2525 2524              (signer = ocsp_find_signer_sk(bs->certs, rid))) {
2526 2525                  *psigner = signer;
2527 2526                  return (1);
2528 2527          }
2529 2528          /* Maybe lookup from store if by subject name */
2530 2529  
2531 2530          *psigner = NULL;
2532 2531          return (0);
2533 2532  }
2534 2533  
2535 2534  /*
2536 2535   * This function will verify the signature of a basic response, using
2537 2536   * the public key from the OCSP responder certificate.
2538 2537   */
2539 2538  static KMF_RETURN
2540 2539  check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
2541 2540      KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
2542 2541  {
2543 2542          KMF_RETURN ret = KMF_OK;
2544 2543          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2545 2544          STACK_OF(X509) *cert_stack = NULL;
2546 2545          X509 *signer = NULL;
2547 2546          X509 *issuer = NULL;
2548 2547          EVP_PKEY *skey = NULL;
2549 2548          unsigned char *ptmp;
2550 2549  
2551 2550  
2552 2551          if (bs == NULL || issuer_cert == NULL)
2553 2552                  return (KMF_ERR_BAD_PARAMETER);
2554 2553  
2555 2554          /*
2556 2555           * Find the certificate that signed the basic response.
2557 2556           *
2558 2557           * If signer_cert is not NULL, we will use that as the signer cert.
2559 2558           * Otherwise, we will check if the issuer cert is actually the signer.
2560 2559           * If we still do not find a signer, we will look for it from the
2561 2560           * certificate list came with the response file.
2562 2561           */
2563 2562          if (signer_cert != NULL) {
2564 2563                  ptmp = signer_cert->Data;
2565 2564                  signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2566 2565                      signer_cert->Length);
2567 2566                  if (signer == NULL) {
2568 2567                          SET_ERROR(kmfh, ERR_get_error());
2569 2568                          ret = KMF_ERR_OCSP_BAD_SIGNER;
2570 2569                          goto end;
2571 2570                  }
2572 2571          } else {
2573 2572                  /*
2574 2573                   * Convert the issuer cert into X509 and push it into a
2575 2574                   * stack to be used by ocsp_find_signer().
2576 2575                   */
2577 2576                  ptmp = issuer_cert->Data;
2578 2577                  issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2579 2578                      issuer_cert->Length);
2580 2579                  if (issuer == NULL) {
2581 2580                          SET_ERROR(kmfh, ERR_get_error());
2582 2581                          ret = KMF_ERR_OCSP_BAD_ISSUER;
2583 2582                          goto end;
2584 2583                  }
2585 2584  
2586 2585                  if ((cert_stack = sk_X509_new_null()) == NULL) {
2587 2586                          ret = KMF_ERR_INTERNAL;
2588 2587                          goto end;
2589 2588                  }
2590 2589  
2591 2590                  if (sk_X509_push(cert_stack, issuer) == NULL) {
2592 2591                          ret = KMF_ERR_INTERNAL;
2593 2592                          goto end;
2594 2593                  }
2595 2594  
2596 2595                  ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
2597 2596                  if (!ret) {
2598 2597                          /* can not find the signer */
2599 2598                          ret = KMF_ERR_OCSP_BAD_SIGNER;
2600 2599                          goto end;
2601 2600                  }
2602 2601          }
2603 2602  
2604 2603          /* Verify the signature of the response */
2605 2604          skey = X509_get_pubkey(signer);
2606 2605          if (skey == NULL) {
2607 2606                  ret = KMF_ERR_OCSP_BAD_SIGNER;
2608 2607                  goto end;
2609 2608          }
2610 2609  
2611 2610          ret = OCSP_BASICRESP_verify(bs, skey, 0);
2612 2611          if (ret == 0) {
2613 2612                  ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
2614 2613                  goto end;
2615 2614          }
2616 2615  
2617 2616  end:
2618 2617          if (issuer != NULL) {
2619 2618                  X509_free(issuer);
2620 2619          }
2621 2620  
2622 2621          if (signer != NULL) {
2623 2622                  X509_free(signer);
2624 2623          }
2625 2624  
2626 2625          if (skey != NULL) {
2627 2626                  EVP_PKEY_free(skey);
2628 2627          }
2629 2628  
2630 2629          if (cert_stack != NULL) {
2631 2630                  sk_X509_free(cert_stack);
2632 2631          }
2633 2632  
2634 2633          return (ret);
2635 2634  }
2636 2635  
2637 2636  
2638 2637  
2639 2638  KMF_RETURN
2640 2639  OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
2641 2640          int numattr, KMF_ATTRIBUTE *attrlist)
2642 2641  {
2643 2642          KMF_RETURN ret = KMF_OK;
2644 2643          BIO *derbio = NULL;
2645 2644          OCSP_RESPONSE *resp = NULL;
2646 2645          OCSP_BASICRESP *bs = NULL;
2647 2646          OCSP_CERTID *id = NULL;
2648 2647          OCSP_SINGLERESP *single = NULL;
2649 2648          ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
2650 2649          int index, status, reason;
2651 2650          KMF_DATA *issuer_cert;
2652 2651          KMF_DATA *user_cert;
2653 2652          KMF_DATA *signer_cert;
2654 2653          KMF_DATA *response;
2655 2654          int *response_reason, *response_status, *cert_status;
2656 2655          boolean_t ignore_response_sign = B_FALSE;       /* default is FALSE */
2657 2656          uint32_t response_lifetime;
2658 2657  
2659 2658          issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2660 2659              attrlist, numattr);
2661 2660          if (issuer_cert == NULL)
2662 2661                  return (KMF_ERR_BAD_PARAMETER);
2663 2662  
2664 2663          user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2665 2664              attrlist, numattr);
2666 2665          if (user_cert == NULL)
2667 2666                  return (KMF_ERR_BAD_PARAMETER);
2668 2667  
2669 2668          response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
2670 2669              attrlist, numattr);
2671 2670          if (response == NULL)
2672 2671                  return (KMF_ERR_BAD_PARAMETER);
2673 2672  
2674 2673          response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
2675 2674              attrlist, numattr);
2676 2675          if (response_status == NULL)
2677 2676                  return (KMF_ERR_BAD_PARAMETER);
2678 2677  
2679 2678          response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
2680 2679              attrlist, numattr);
2681 2680          if (response_reason == NULL)
2682 2681                  return (KMF_ERR_BAD_PARAMETER);
2683 2682  
2684 2683          cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
2685 2684              attrlist, numattr);
2686 2685          if (cert_status == NULL)
2687 2686                  return (KMF_ERR_BAD_PARAMETER);
2688 2687  
2689 2688          /* Read in the response */
2690 2689          derbio = BIO_new_mem_buf(response->Data, response->Length);
2691 2690          if (!derbio) {
2692 2691                  ret = KMF_ERR_MEMORY;
2693 2692                  return (ret);
2694 2693          }
2695 2694  
2696 2695          resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
2697 2696          if (resp == NULL) {
2698 2697                  ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
2699 2698                  goto end;
2700 2699          }
2701 2700  
2702 2701          /* Check the response status */
2703 2702          status = OCSP_response_status(resp);
2704 2703          *response_status = status;
2705 2704          if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2706 2705                  ret = KMF_ERR_OCSP_RESPONSE_STATUS;
2707 2706                  goto end;
2708 2707          }
2709 2708  
2710 2709  #ifdef DEBUG
2711 2710          printf("Successfully checked the response file status.\n");
2712 2711  #endif /* DEBUG */
2713 2712  
2714 2713          /* Extract basic response */
2715 2714          bs = OCSP_response_get1_basic(resp);
2716 2715          if (bs == NULL) {
2717 2716                  ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
2718 2717                  goto end;
2719 2718          }
2720 2719  
2721 2720  #ifdef DEBUG
2722 2721          printf("Successfully retrieved the basic response.\n");
2723 2722  #endif /* DEBUG */
2724 2723  
2725 2724          /* Check the basic response signature if required */
2726 2725          ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
2727 2726              (void *)&ignore_response_sign, NULL);
2728 2727          if (ret != KMF_OK)
2729 2728                  ret = KMF_OK;
2730 2729  
2731 2730          signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
2732 2731              attrlist, numattr);
2733 2732  
2734 2733          if (ignore_response_sign == B_FALSE) {
2735 2734                  ret = check_response_signature(handle, bs,
2736 2735                      signer_cert, issuer_cert);
2737 2736                  if (ret != KMF_OK)
2738 2737                          goto end;
2739 2738          }
2740 2739  
2741 2740  #ifdef DEBUG
2742 2741          printf("Successfully verified the response signature.\n");
2743 2742  #endif /* DEBUG */
2744 2743  
2745 2744          /* Create a certid for the certificate in question */
2746 2745          ret = create_certid(handle, issuer_cert, user_cert, &id);
2747 2746          if (ret != KMF_OK) {
2748 2747                  ret = KMF_ERR_OCSP_CERTID;
2749 2748                  goto end;
2750 2749          }
2751 2750  
2752 2751  #ifdef DEBUG
2753 2752          printf("successfully created a certid for the cert.\n");
2754 2753  #endif /* DEBUG */
2755 2754  
2756 2755          /* Find the index of the single response for the certid */
2757 2756          index = OCSP_resp_find(bs, id, -1);
2758 2757          if (index < 0) {
2759 2758                  /* cound not find this certificate in the response */
2760 2759                  ret = KMF_ERR_OCSP_UNKNOWN_CERT;
2761 2760                  goto end;
2762 2761          }
2763 2762  
2764 2763  #ifdef DEBUG
2765 2764          printf("Successfully found the single response index for the cert.\n");
2766 2765  #endif /* DEBUG */
2767 2766  
2768 2767          /* Retrieve the single response and get the cert status */
2769 2768          single = OCSP_resp_get0(bs, index);
2770 2769          status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
2771 2770              &nextupd);
2772 2771          if (status == V_OCSP_CERTSTATUS_GOOD) {
2773 2772                  *cert_status = OCSP_GOOD;
2774 2773          } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
2775 2774                  *cert_status = OCSP_UNKNOWN;
2776 2775          } else { /* revoked */
2777 2776                  *cert_status = OCSP_REVOKED;
2778 2777                  *response_reason = reason;
2779 2778          }
2780 2779          ret = KMF_OK;
2781 2780  
2782 2781          /* resp. time is optional, so we don't care about the return code. */
2783 2782          (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
2784 2783              (void *)&response_lifetime, NULL);
2785 2784  
2786 2785          if (!OCSP_check_validity(thisupd, nextupd, 300,
2787 2786              response_lifetime)) {
2788 2787                  ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
2789 2788                  goto end;
2790 2789          }
2791 2790  
2792 2791  #ifdef DEBUG
2793 2792          printf("Successfully verify the time.\n");
2794 2793  #endif /* DEBUG */
2795 2794  
2796 2795  end:
2797 2796          if (derbio != NULL)
2798 2797                  (void) BIO_free(derbio);
2799 2798  
2800 2799          if (resp != NULL)
2801 2800                  OCSP_RESPONSE_free(resp);
2802 2801  
2803 2802          if (bs != NULL)
2804 2803                  OCSP_BASICRESP_free(bs);
2805 2804  
2806 2805          if (id != NULL)
2807 2806                  OCSP_CERTID_free(id);
2808 2807  
2809 2808          return (ret);
2810 2809  }
2811 2810  
2812 2811  static KMF_RETURN
2813 2812  fetch_key(KMF_HANDLE_T handle, char *path,
2814 2813          KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
2815 2814  {
2816 2815          KMF_RETURN rv = KMF_OK;
2817 2816          EVP_PKEY *pkey = NULL;
2818 2817          KMF_RAW_SYM_KEY *rkey = NULL;
2819 2818  
2820 2819          if (keyclass == KMF_ASYM_PRI ||
2821 2820              keyclass == KMF_ASYM_PUB) {
2822 2821                  pkey = openssl_load_key(handle, path);
2823 2822                  if (pkey == NULL) {
2824 2823                          return (KMF_ERR_KEY_NOT_FOUND);
2825 2824                  }
2826 2825                  if (key != NULL) {
2827 2826                          if (pkey->type == EVP_PKEY_RSA)
2828 2827                                  key->keyalg = KMF_RSA;
2829 2828                          else if (pkey->type == EVP_PKEY_DSA)
2830 2829                                  key->keyalg = KMF_DSA;
2831 2830  
2832 2831                          key->kstype = KMF_KEYSTORE_OPENSSL;
2833 2832                          key->keyclass = keyclass;
2834 2833                          key->keyp = (void *)pkey;
2835 2834                          key->israw = FALSE;
2836 2835                          if (path != NULL &&
2837 2836                              ((key->keylabel = strdup(path)) == NULL)) {
2838 2837                                  EVP_PKEY_free(pkey);
2839 2838                                  return (KMF_ERR_MEMORY);
2840 2839                          }
2841 2840                  } else {
2842 2841                          EVP_PKEY_free(pkey);
2843 2842                          pkey = NULL;
2844 2843                  }
2845 2844          } else if (keyclass == KMF_SYMMETRIC) {
2846 2845                  KMF_ENCODE_FORMAT fmt;
2847 2846                  /*
2848 2847                   * If the file is a recognized format,
2849 2848                   * then it is NOT a symmetric key.
2850 2849                   */
2851 2850                  rv = kmf_get_file_format(path, &fmt);
2852 2851                  if (rv == KMF_OK || fmt != 0) {
2853 2852                          return (KMF_ERR_KEY_NOT_FOUND);
2854 2853                  } else if (rv == KMF_ERR_ENCODING) {
2855 2854                          /*
2856 2855                           * If we don't know the encoding,
2857 2856                           * it is probably  a symmetric key.
2858 2857                           */
2859 2858                          rv = KMF_OK;
2860 2859                  } else if (rv == KMF_ERR_OPEN_FILE) {
2861 2860                          return (KMF_ERR_KEY_NOT_FOUND);
2862 2861                  }
2863 2862  
2864 2863                  if (key != NULL) {
2865 2864                          KMF_DATA keyvalue;
2866 2865                          rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
2867 2866                          if (rkey == NULL) {
2868 2867                                  rv = KMF_ERR_MEMORY;
2869 2868                                  goto out;
2870 2869                          }
2871 2870  
2872 2871                          (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
2873 2872                          rv = kmf_read_input_file(handle, path, &keyvalue);
2874 2873                          if (rv != KMF_OK)
2875 2874                                  goto out;
2876 2875  
2877 2876                          rkey->keydata.len = keyvalue.Length;
2878 2877                          rkey->keydata.val = keyvalue.Data;
2879 2878  
2880 2879                          key->kstype = KMF_KEYSTORE_OPENSSL;
2881 2880                          key->keyclass = keyclass;
2882 2881                          key->israw = TRUE;
2883 2882                          key->keyp = (void *)rkey;
2884 2883                          if (path != NULL &&
2885 2884                              ((key->keylabel = strdup(path)) == NULL)) {
2886 2885                                  rv = KMF_ERR_MEMORY;
2887 2886                          }
2888 2887                  }
2889 2888          }
2890 2889  out:
2891 2890          if (rv != KMF_OK) {
2892 2891                  if (rkey != NULL) {
2893 2892                          kmf_free_raw_sym_key(rkey);
2894 2893                  }
2895 2894                  if (pkey != NULL)
2896 2895                          EVP_PKEY_free(pkey);
2897 2896  
2898 2897                  if (key != NULL) {
2899 2898                          key->keyalg = KMF_KEYALG_NONE;
2900 2899                          key->keyclass = KMF_KEYCLASS_NONE;
2901 2900                          key->keyp = NULL;
2902 2901                  }
2903 2902          }
2904 2903  
2905 2904          return (rv);
2906 2905  }
2907 2906  
2908 2907  KMF_RETURN
2909 2908  OpenSSL_FindKey(KMF_HANDLE_T handle,
2910 2909          int numattr, KMF_ATTRIBUTE *attrlist)
2911 2910  {
2912 2911          KMF_RETURN rv = KMF_OK;
2913 2912          char *fullpath = NULL;
2914 2913          uint32_t maxkeys;
2915 2914          KMF_KEY_HANDLE *key;
2916 2915          uint32_t *numkeys;
2917 2916          KMF_KEY_CLASS keyclass;
2918 2917          KMF_RAW_KEY_DATA *rawkey;
2919 2918          char *dirpath;
2920 2919          char *keyfile;
2921 2920  
2922 2921          if (handle == NULL)
2923 2922                  return (KMF_ERR_BAD_PARAMETER);
2924 2923  
2925 2924          numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2926 2925          if (numkeys == NULL)
2927 2926                  return (KMF_ERR_BAD_PARAMETER);
2928 2927  
2929 2928          rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2930 2929              (void *)&keyclass, NULL);
2931 2930          if (rv != KMF_OK)
2932 2931                  return (KMF_ERR_BAD_PARAMETER);
2933 2932  
2934 2933          if (keyclass != KMF_ASYM_PUB &&
2935 2934              keyclass != KMF_ASYM_PRI &&
2936 2935              keyclass != KMF_SYMMETRIC)
2937 2936                  return (KMF_ERR_BAD_KEY_CLASS);
2938 2937  
2939 2938          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2940 2939          keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2941 2940  
2942 2941          fullpath = get_fullpath(dirpath, keyfile);
2943 2942  
2944 2943          if (fullpath == NULL)
2945 2944                  return (KMF_ERR_BAD_PARAMETER);
2946 2945  
2947 2946          maxkeys = *numkeys;
2948 2947          if (maxkeys == 0)
2949 2948                  maxkeys = 0xFFFFFFFF;
2950 2949          *numkeys = 0;
2951 2950  
2952 2951          key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2953 2952          /* it is okay to have "keys" contains NULL */
2954 2953  
2955 2954          /*
2956 2955           * The caller may want a list of the raw key data as well.
2957 2956           * Useful for importing keys from a file into other keystores.
2958 2957           */
2959 2958          rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
2960 2959  
2961 2960          if (isdir(fullpath)) {
2962 2961                  DIR *dirp;
2963 2962                  struct dirent *dp;
2964 2963                  int n = 0;
2965 2964  
2966 2965                  /* open all files in the directory and attempt to read them */
2967 2966                  if ((dirp = opendir(fullpath)) == NULL) {
2968 2967                          return (KMF_ERR_BAD_PARAMETER);
2969 2968                  }
2970 2969                  rewinddir(dirp);
2971 2970                  while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
2972 2971                          if (strcmp(dp->d_name, ".") &&
2973 2972                              strcmp(dp->d_name, "..")) {
2974 2973                                  char *fname;
2975 2974  
2976 2975                                  fname = get_fullpath(fullpath,
2977 2976                                      (char *)&dp->d_name);
2978 2977  
2979 2978                                  rv = fetch_key(handle, fname,
2980 2979                                      keyclass, key ? &key[n] : NULL);
2981 2980  
2982 2981                                  if (rv == KMF_OK) {
2983 2982                                          if (key != NULL && rawkey != NULL)
2984 2983                                                  rv = convertToRawKey(
2985 2984                                                      key[n].keyp, &rawkey[n]);
2986 2985                                          n++;
2987 2986                                  }
2988 2987  
2989 2988                                  if (rv != KMF_OK || key == NULL)
2990 2989                                          free(fname);
2991 2990                          }
2992 2991                  }
2993 2992                  (void) closedir(dirp);
2994 2993                  free(fullpath);
2995 2994                  (*numkeys) = n;
2996 2995          } else {
2997 2996                  rv = fetch_key(handle, fullpath, keyclass, key);
2998 2997                  if (rv == KMF_OK)
2999 2998                          (*numkeys) = 1;
3000 2999  
3001 3000                  if (rv != KMF_OK || key == NULL)
3002 3001                          free(fullpath);
3003 3002  
3004 3003                  if (rv == KMF_OK && key != NULL && rawkey != NULL) {
3005 3004                          rv = convertToRawKey(key->keyp, rawkey);
3006 3005                  }
3007 3006          }
3008 3007  
3009 3008          if (rv == KMF_OK && (*numkeys) == 0)
3010 3009                  rv = KMF_ERR_KEY_NOT_FOUND;
3011 3010          else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
3012 3011                  rv = KMF_OK;
3013 3012  
3014 3013          return (rv);
3015 3014  }
3016 3015  
3017 3016  #define HANDLE_PK12_ERROR { \
3018 3017          SET_ERROR(kmfh, ERR_get_error()); \
3019 3018          rv = KMF_ERR_ENCODING; \
3020 3019          goto out; \
3021 3020  }
3022 3021  
3023 3022  static int
3024 3023  add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
3025 3024  {
3026 3025          if (xcert != NULL && xcert->aux != NULL &&
3027 3026              xcert->aux->alias != NULL) {
3028 3027                  if (PKCS12_add_friendlyname_asc(bag,
3029 3028                      (const char *)xcert->aux->alias->data,
3030 3029                      xcert->aux->alias->length) == 0)
3031 3030                          return (0);
3032 3031          }
3033 3032          return (1);
3034 3033  }
3035 3034  
3036 3035  static PKCS7 *
3037 3036  add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
3038 3037          uchar_t *keyid, unsigned int keyidlen)
3039 3038  {
3040 3039          PKCS12_SAFEBAG *bag = NULL;
3041 3040          PKCS7 *cert_authsafe = NULL;
3042 3041          STACK_OF(PKCS12_SAFEBAG) *bag_stack;
3043 3042  
3044 3043          bag_stack = sk_PKCS12_SAFEBAG_new_null();
3045 3044          if (bag_stack == NULL)
3046 3045                  return (NULL);
3047 3046  
3048 3047          /* Convert cert from X509 struct to PKCS#12 bag */
3049 3048          bag = PKCS12_x5092certbag(sslcert);
3050 3049          if (bag == NULL) {
3051 3050                  goto out;
3052 3051          }
3053 3052  
3054 3053          /* Add the key id to the certificate bag. */
3055 3054          if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
3056 3055                  goto out;
3057 3056          }
3058 3057  
3059 3058          if (!add_alias_to_bag(bag, sslcert))
3060 3059                  goto out;
3061 3060  
3062 3061          /* Pile it on the bag_stack. */
3063 3062          if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
3064 3063                  goto out;
3065 3064          }
3066 3065          /* Turn bag_stack of certs into encrypted authsafe. */
3067 3066          cert_authsafe = PKCS12_pack_p7encdata(
3068 3067              NID_pbe_WithSHA1And40BitRC2_CBC,
3069 3068              cred->cred, cred->credlen, NULL, 0,
3070 3069              PKCS12_DEFAULT_ITER, bag_stack);
3071 3070  
3072 3071  out:
3073 3072          if (bag_stack != NULL)
3074 3073                  sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3075 3074  
3076 3075          return (cert_authsafe);
3077 3076  }
3078 3077  
3079 3078  static PKCS7 *
3080 3079  add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
3081 3080          uchar_t *keyid,  unsigned int keyidlen,
3082 3081          char *label, int label_len)
3083 3082  {
3084 3083          PKCS8_PRIV_KEY_INFO *p8 = NULL;
3085 3084          STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
3086 3085          PKCS12_SAFEBAG *bag = NULL;
3087 3086          PKCS7 *key_authsafe = NULL;
3088 3087  
3089 3088          p8 = EVP_PKEY2PKCS8(pkey);
3090 3089          if (p8 == NULL) {
3091 3090                  return (NULL);
3092 3091          }
3093 3092          /* Put the shrouded key into a PKCS#12 bag. */
3094 3093          bag = PKCS12_MAKE_SHKEYBAG(
3095 3094              NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
3096 3095              cred->cred, cred->credlen,
3097 3096              NULL, 0, PKCS12_DEFAULT_ITER, p8);
3098 3097  
3099 3098          /* Clean up the PKCS#8 shrouded key, don't need it now. */
3100 3099          PKCS8_PRIV_KEY_INFO_free(p8);
3101 3100          p8 = NULL;
3102 3101  
3103 3102          if (bag == NULL) {
3104 3103                  return (NULL);
3105 3104          }
3106 3105          if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
3107 3106                  goto out;
3108 3107          if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
3109 3108                  goto out;
3110 3109  
3111 3110          /* Start a PKCS#12 safebag container for the private key. */
3112 3111          bag_stack = sk_PKCS12_SAFEBAG_new_null();
3113 3112          if (bag_stack == NULL)
3114 3113                  goto out;
3115 3114  
3116 3115          /* Pile on the private key on the bag_stack. */
3117 3116          if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
3118 3117                  goto out;
3119 3118  
3120 3119          key_authsafe = PKCS12_pack_p7data(bag_stack);
3121 3120  
3122 3121  out:
3123 3122          if (bag_stack != NULL)
3124 3123                  sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3125 3124          bag_stack = NULL;
3126 3125          return (key_authsafe);
3127 3126  }
3128 3127  
3129 3128  static EVP_PKEY *
3130 3129  ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
3131 3130  {
3132 3131          RSA             *rsa = NULL;
3133 3132          EVP_PKEY        *newkey = NULL;
3134 3133  
3135 3134          if ((rsa = RSA_new()) == NULL)
3136 3135                  return (NULL);
3137 3136  
3138 3137          if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
3139 3138                  return (NULL);
3140 3139  
3141 3140          if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
3142 3141              NULL)
3143 3142                  return (NULL);
3144 3143  
3145 3144          if (key->priexp.val != NULL)
3146 3145                  if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
3147 3146                      rsa->d)) == NULL)
3148 3147                          return (NULL);
3149 3148  
3150 3149          if (key->prime1.val != NULL)
3151 3150                  if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
3152 3151                      rsa->p)) == NULL)
3153 3152                          return (NULL);
3154 3153  
3155 3154          if (key->prime2.val != NULL)
3156 3155                  if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
3157 3156                      rsa->q)) == NULL)
3158 3157                          return (NULL);
3159 3158  
3160 3159          if (key->exp1.val != NULL)
3161 3160                  if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
3162 3161                      rsa->dmp1)) == NULL)
3163 3162                          return (NULL);
3164 3163  
3165 3164          if (key->exp2.val != NULL)
3166 3165                  if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
3167 3166                      rsa->dmq1)) == NULL)
3168 3167                          return (NULL);
3169 3168  
3170 3169          if (key->coef.val != NULL)
3171 3170                  if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
3172 3171                      rsa->iqmp)) == NULL)
3173 3172                          return (NULL);
3174 3173  
3175 3174          if ((newkey = EVP_PKEY_new()) == NULL)
3176 3175                  return (NULL);
3177 3176  
3178 3177          (void) EVP_PKEY_set1_RSA(newkey, rsa);
3179 3178  
3180 3179          /* The original key must be freed once here or it leaks memory */
3181 3180          RSA_free(rsa);
3182 3181  
3183 3182          return (newkey);
3184 3183  }
3185 3184  
3186 3185  static EVP_PKEY *
3187 3186  ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
3188 3187  {
3189 3188          DSA             *dsa = NULL;
3190 3189          EVP_PKEY        *newkey = NULL;
3191 3190  
3192 3191          if ((dsa = DSA_new()) == NULL)
3193 3192                  return (NULL);
3194 3193  
3195 3194          if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
3196 3195              dsa->p)) == NULL)
3197 3196                  return (NULL);
3198 3197  
3199 3198          if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
3200 3199              dsa->q)) == NULL)
3201 3200                  return (NULL);
3202 3201  
3203 3202          if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
3204 3203              dsa->g)) == NULL)
3205 3204                  return (NULL);
3206 3205  
3207 3206          if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
3208 3207              dsa->priv_key)) == NULL)
3209 3208                  return (NULL);
3210 3209  
3211 3210          if (key->pubvalue.val != NULL) {
3212 3211                  if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
3213 3212                      key->pubvalue.len, dsa->pub_key)) == NULL)
3214 3213                          return (NULL);
3215 3214          }
3216 3215  
3217 3216          if ((newkey = EVP_PKEY_new()) == NULL)
3218 3217                  return (NULL);
3219 3218  
3220 3219          (void) EVP_PKEY_set1_DSA(newkey, dsa);
3221 3220  
3222 3221          /* The original key must be freed once here or it leaks memory */
3223 3222          DSA_free(dsa);
3224 3223          return (newkey);
3225 3224  }
3226 3225  
3227 3226  static EVP_PKEY *
3228 3227  raw_key_to_pkey(KMF_KEY_HANDLE *key)
3229 3228  {
3230 3229          EVP_PKEY *pkey = NULL;
3231 3230          KMF_RAW_KEY_DATA *rawkey;
3232 3231          ASN1_TYPE *attr = NULL;
3233 3232          KMF_RETURN ret;
3234 3233  
3235 3234          if (key == NULL || !key->israw)
3236 3235                  return (NULL);
3237 3236  
3238 3237          rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
3239 3238          if (rawkey->keytype == KMF_RSA) {
3240 3239                  pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
3241 3240          } else if (rawkey->keytype == KMF_DSA) {
3242 3241                  pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3243 3242          } else if (rawkey->keytype == KMF_ECDSA) {
3244 3243                  /*
3245 3244                   * OpenSSL in Solaris does not support EC for
3246 3245                   * legal reasons
3247 3246                   */
3248 3247                  return (NULL);
3249 3248          } else {
3250 3249                  /* wrong kind of key */
3251 3250                  return (NULL);
3252 3251          }
3253 3252  
3254 3253          if (rawkey->label != NULL) {
3255 3254                  if ((attr = ASN1_TYPE_new()) == NULL) {
3256 3255                          EVP_PKEY_free(pkey);
3257 3256                          return (NULL);
3258 3257                  }
3259 3258                  attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
3260 3259                  (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
3261 3260                      strlen(rawkey->label));
3262 3261                  attr->type = V_ASN1_BMPSTRING;
3263 3262                  attr->value.ptr = (char *)attr->value.bmpstring;
3264 3263                  ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3265 3264                  if (ret != KMF_OK) {
3266 3265                          EVP_PKEY_free(pkey);
3267 3266                          ASN1_TYPE_free(attr);
3268 3267                          return (NULL);
3269 3268                  }
3270 3269          }
3271 3270          if (rawkey->id.Data != NULL) {
3272 3271                  if ((attr = ASN1_TYPE_new()) == NULL) {
3273 3272                          EVP_PKEY_free(pkey);
3274 3273                          return (NULL);
3275 3274                  }
3276 3275                  attr->value.octet_string =
3277 3276                      ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
3278 3277                  attr->type = V_ASN1_OCTET_STRING;
3279 3278                  (void) ASN1_STRING_set(attr->value.octet_string,
3280 3279                      rawkey->id.Data, rawkey->id.Length);
3281 3280                  attr->value.ptr = (char *)attr->value.octet_string;
3282 3281                  ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3283 3282                  if (ret != KMF_OK) {
3284 3283                          EVP_PKEY_free(pkey);
3285 3284                          ASN1_TYPE_free(attr);
3286 3285                          return (NULL);
3287 3286                  }
3288 3287          }
3289 3288          return (pkey);
3290 3289  }
3291 3290  
3292 3291  /*
3293 3292   * Search a list of private keys to find one that goes with the certificate.
3294 3293   */
3295 3294  static EVP_PKEY *
3296 3295  find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
3297 3296  {
3298 3297          int i;
3299 3298          EVP_PKEY *pkey = NULL;
3300 3299  
3301 3300          if (numkeys == 0 || keylist == NULL || xcert == NULL)
3302 3301                  return (NULL);
3303 3302          for (i = 0; i < numkeys; i++) {
3304 3303                  if (keylist[i].israw)
3305 3304                          pkey = raw_key_to_pkey(&keylist[i]);
3306 3305                  else
3307 3306                          pkey = (EVP_PKEY *)keylist[i].keyp;
3308 3307                  if (pkey != NULL) {
3309 3308                          if (X509_check_private_key(xcert, pkey)) {
3310 3309                                  return (pkey);
3311 3310                          } else {
3312 3311                                  EVP_PKEY_free(pkey);
3313 3312                                  pkey = NULL;
3314 3313                          }
3315 3314                  }
3316 3315          }
3317 3316          return (pkey);
3318 3317  }
3319 3318  
3320 3319  static KMF_RETURN
3321 3320  local_export_pk12(KMF_HANDLE_T handle,
3322 3321          KMF_CREDENTIAL *cred,
3323 3322          int numcerts, KMF_X509_DER_CERT *certlist,
3324 3323          int numkeys, KMF_KEY_HANDLE *keylist,
3325 3324          char *filename)
3326 3325  {
3327 3326          KMF_RETURN rv = KMF_OK;
3328 3327          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3329 3328          BIO *bio = NULL;
3330 3329          PKCS7 *cert_authsafe = NULL;
3331 3330          PKCS7 *key_authsafe = NULL;
3332 3331          STACK_OF(PKCS7) *authsafe_stack = NULL;
3333 3332          PKCS12 *p12_elem = NULL;
3334 3333          int i;
3335 3334  
3336 3335          if (numcerts == 0 && numkeys == 0)
3337 3336                  return (KMF_ERR_BAD_PARAMETER);
3338 3337  
3339 3338          /*
3340 3339           * Open the output file.
3341 3340           */
3342 3341          if ((bio = BIO_new_file(filename, "wb")) == NULL) {
3343 3342                  SET_ERROR(kmfh, ERR_get_error());
3344 3343                  rv = KMF_ERR_OPEN_FILE;
3345 3344                  goto cleanup;
3346 3345          }
3347 3346  
3348 3347          /* Start a PKCS#7 stack. */
3349 3348          authsafe_stack = sk_PKCS7_new_null();
3350 3349          if (authsafe_stack == NULL) {
3351 3350                  rv = KMF_ERR_MEMORY;
3352 3351                  goto cleanup;
3353 3352          }
3354 3353          if (numcerts > 0) {
3355 3354                  for (i = 0; rv == KMF_OK && i < numcerts; i++) {
3356 3355                          const uchar_t *p = certlist[i].certificate.Data;
3357 3356                          long len = certlist[i].certificate.Length;
3358 3357                          X509 *xcert = NULL;
3359 3358                          EVP_PKEY *pkey = NULL;
3360 3359                          unsigned char keyid[EVP_MAX_MD_SIZE];
3361 3360                          unsigned int keyidlen = 0;
3362 3361  
3363 3362                          xcert = d2i_X509(NULL, &p, len);
3364 3363                          if (xcert == NULL) {
3365 3364                                  SET_ERROR(kmfh, ERR_get_error());
3366 3365                                  rv = KMF_ERR_ENCODING;
3367 3366                          }
3368 3367                          if (certlist[i].kmf_private.label != NULL) {
3369 3368                                  /* Set alias attribute */
3370 3369                                  (void) X509_alias_set1(xcert,
3371 3370                                      (uchar_t *)certlist[i].kmf_private.label,
3372 3371                                      strlen(certlist[i].kmf_private.label));
3373 3372                          }
3374 3373                          /* Check if there is a key corresponding to this cert */
3375 3374                          pkey = find_matching_key(xcert, numkeys, keylist);
3376 3375  
3377 3376                          /*
3378 3377                           * If key is found, get fingerprint and create a
3379 3378                           * safebag.
3380 3379                           */
3381 3380                          if (pkey != NULL) {
3382 3381                                  (void) X509_digest(xcert, EVP_sha1(),
3383 3382                                      keyid, &keyidlen);
3384 3383                                  key_authsafe = add_key_to_safe(pkey, cred,
3385 3384                                      keyid, keyidlen,
3386 3385                                      certlist[i].kmf_private.label,
3387 3386                                      (certlist[i].kmf_private.label ?
3388 3387                                      strlen(certlist[i].kmf_private.label) : 0));
3389 3388  
3390 3389                                  if (key_authsafe == NULL) {
3391 3390                                          X509_free(xcert);
3392 3391                                          EVP_PKEY_free(pkey);
3393 3392                                          goto cleanup;
3394 3393                                  }
3395 3394                                  /* Put the key safe into the Auth Safe */
3396 3395                                  if (!sk_PKCS7_push(authsafe_stack,
3397 3396                                      key_authsafe)) {
3398 3397                                          X509_free(xcert);
3399 3398                                          EVP_PKEY_free(pkey);
3400 3399                                          goto cleanup;
3401 3400                                  }
3402 3401                          }
3403 3402  
3404 3403                          /* create a certificate safebag */
3405 3404                          cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
3406 3405                              keyidlen);
3407 3406                          if (cert_authsafe == NULL) {
3408 3407                                  X509_free(xcert);
3409 3408                                  EVP_PKEY_free(pkey);
3410 3409                                  goto cleanup;
3411 3410                          }
3412 3411                          if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
3413 3412                                  X509_free(xcert);
3414 3413                                  EVP_PKEY_free(pkey);
3415 3414                                  goto cleanup;
3416 3415                          }
3417 3416  
3418 3417                          X509_free(xcert);
3419 3418                          if (pkey)
3420 3419                                  EVP_PKEY_free(pkey);
3421 3420                  }
3422 3421          } else if (numcerts == 0 && numkeys > 0) {
3423 3422                  /*
3424 3423                   * If only adding keys to the file.
3425 3424                   */
3426 3425                  for (i = 0; i < numkeys; i++) {
3427 3426                          EVP_PKEY *pkey = NULL;
3428 3427  
3429 3428                          if (keylist[i].israw)
3430 3429                                  pkey = raw_key_to_pkey(&keylist[i]);
3431 3430                          else
3432 3431                                  pkey = (EVP_PKEY *)keylist[i].keyp;
3433 3432  
3434 3433                          if (pkey == NULL)
3435 3434                                  continue;
3436 3435  
3437 3436                          key_authsafe = add_key_to_safe(pkey, cred,
3438 3437                              NULL, 0, NULL, 0);
3439 3438  
3440 3439                          if (key_authsafe == NULL) {
3441 3440                                  EVP_PKEY_free(pkey);
3442 3441                                  goto cleanup;
3443 3442                          }
3444 3443                          if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
3445 3444                                  EVP_PKEY_free(pkey);
3446 3445                                  goto cleanup;
3447 3446                          }
3448 3447                  }
3449 3448          }
3450 3449          p12_elem = PKCS12_init(NID_pkcs7_data);
3451 3450          if (p12_elem == NULL) {
3452 3451                  goto cleanup;
3453 3452          }
3454 3453  
3455 3454          /* Put the PKCS#7 stack into the PKCS#12 element. */
3456 3455          if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
3457 3456                  goto cleanup;
3458 3457          }
3459 3458  
3460 3459          /* Set the integrity MAC on the PKCS#12 element. */
3461 3460          if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
3462 3461              NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
3463 3462                  goto cleanup;
3464 3463          }
3465 3464  
3466 3465          /* Write the PKCS#12 element to the export file. */
3467 3466          if (!i2d_PKCS12_bio(bio, p12_elem)) {
3468 3467                  goto cleanup;
3469 3468          }
3470 3469          PKCS12_free(p12_elem);
3471 3470  
3472 3471  cleanup:
3473 3472          /* Clear away the PKCS#7 stack, we're done with it. */
3474 3473          if (authsafe_stack)
3475 3474                  sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
3476 3475  
3477 3476          if (bio != NULL)
3478 3477                  (void) BIO_free_all(bio);
3479 3478  
3480 3479          return (rv);
3481 3480  }
3482 3481  
3483 3482  KMF_RETURN
3484 3483  openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
3485 3484      KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
3486 3485      KMF_CREDENTIAL *p12cred, char *filename)
3487 3486  {
3488 3487          KMF_RETURN rv;
3489 3488  
3490 3489          if (certlist == NULL && keylist == NULL)
3491 3490                  return (KMF_ERR_BAD_PARAMETER);
3492 3491  
3493 3492          rv = local_export_pk12(handle, p12cred, numcerts, certlist,
3494 3493              numkeys, keylist, filename);
3495 3494  
3496 3495          return (rv);
3497 3496  }
3498 3497  
3499 3498  KMF_RETURN
3500 3499  OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
3501 3500  {
3502 3501          KMF_RETURN rv;
3503 3502          KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
3504 3503          char *fullpath = NULL;
3505 3504          char *dirpath = NULL;
3506 3505          char *certfile = NULL;
3507 3506          char *keyfile = NULL;
3508 3507          char *filename = NULL;
3509 3508          KMF_CREDENTIAL *p12cred = NULL;
3510 3509          KMF_X509_DER_CERT certdata;
3511 3510          KMF_KEY_HANDLE key;
3512 3511          int gotkey = 0;
3513 3512          int gotcert = 0;
3514 3513  
3515 3514          if (handle == NULL)
3516 3515                  return (KMF_ERR_BAD_PARAMETER);
3517 3516  
3518 3517          /*
3519 3518           *  First, find the certificate.
3520 3519           */
3521 3520          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
3522 3521          certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
3523 3522          if (certfile != NULL) {
3524 3523                  fullpath = get_fullpath(dirpath, certfile);
3525 3524                  if (fullpath == NULL)
3526 3525                          return (KMF_ERR_BAD_PARAMETER);
3527 3526  
3528 3527                  if (isdir(fullpath)) {
3529 3528                          free(fullpath);
3530 3529                          return (KMF_ERR_AMBIGUOUS_PATHNAME);
3531 3530                  }
3532 3531  
3533 3532                  (void) memset(&certdata, 0, sizeof (certdata));
3534 3533                  rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
3535 3534                      fullpath, &certdata.certificate);
3536 3535                  if (rv != KMF_OK)
3537 3536                          goto end;
3538 3537  
3539 3538                  gotcert++;
3540 3539                  certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
3541 3540                  free(fullpath);
3542 3541          }
3543 3542  
3544 3543          /*
3545 3544           * Now find the private key.
3546 3545           */
3547 3546          keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
3548 3547          if (keyfile != NULL) {
3549 3548                  fullpath = get_fullpath(dirpath, keyfile);
3550 3549                  if (fullpath == NULL)
3551 3550                          return (KMF_ERR_BAD_PARAMETER);
3552 3551  
3553 3552                  if (isdir(fullpath)) {
3554 3553                          free(fullpath);
3555 3554                          return (KMF_ERR_AMBIGUOUS_PATHNAME);
3556 3555                  }
3557 3556  
3558 3557                  (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
3559 3558                  rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
3560 3559                  if (rv != KMF_OK)
3561 3560                          goto end;
3562 3561                  gotkey++;
3563 3562          }
3564 3563  
3565 3564          /*
3566 3565           * Open the output file.
3567 3566           */
3568 3567          filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
3569 3568              numattr);
3570 3569          if (filename == NULL) {
3571 3570                  rv = KMF_ERR_BAD_PARAMETER;
3572 3571                  goto end;
3573 3572          }
3574 3573  
3575 3574          /* Stick the key and the cert into a PKCS#12 file */
3576 3575          p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
3577 3576          if (p12cred == NULL) {
3578 3577                  rv = KMF_ERR_BAD_PARAMETER;
3579 3578                  goto end;
3580 3579          }
3581 3580  
3582 3581          rv = local_export_pk12(handle, p12cred, 1, &certdata,
3583 3582              1, &key, filename);
3584 3583  
3585 3584  end:
3586 3585          if (fullpath)
3587 3586                  free(fullpath);
3588 3587  
3589 3588          if (gotcert)
3590 3589                  kmf_free_kmf_cert(handle, &certdata);
3591 3590          if (gotkey)
3592 3591                  kmf_free_kmf_key(handle, &key);
3593 3592          return (rv);
3594 3593  }
3595 3594  
3596 3595  /*
3597 3596   * Helper function to extract keys and certificates from
3598 3597   * a single PEM file.  Typically the file should contain a
3599 3598   * private key and an associated public key wrapped in an x509 cert.
3600 3599   * However, the file may be just a list of X509 certs with no keys.
3601 3600   */
3602 3601  static KMF_RETURN
3603 3602  extract_pem(KMF_HANDLE *kmfh,
3604 3603          char *issuer, char *subject, KMF_BIGINT *serial,
3605 3604          char *filename, CK_UTF8CHAR *pin,
3606 3605          CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
3607 3606          int *numcerts)
3608 3607  /* ARGSUSED6 */
3609 3608  {
3610 3609          KMF_RETURN rv = KMF_OK;
3611 3610          FILE *fp;
3612 3611          STACK_OF(X509_INFO) *x509_info_stack = NULL;
3613 3612          int i, ncerts = 0, matchcerts = 0;
3614 3613          EVP_PKEY *pkey = NULL;
3615 3614          X509_INFO *info;
3616 3615          X509 *x;
3617 3616          X509_INFO **cert_infos = NULL;
3618 3617          KMF_DATA *certlist = NULL;
3619 3618  
3620 3619          if (priv_key)
3621 3620                  *priv_key = NULL;
3622 3621          if (certs)
3623 3622                  *certs = NULL;
3624 3623          fp = fopen(filename, "r");
3625 3624          if (fp == NULL)
3626 3625                  return (KMF_ERR_OPEN_FILE);
3627 3626  
3628 3627          x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
3629 3628          if (x509_info_stack == NULL) {
3630 3629                  (void) fclose(fp);
3631 3630                  return (KMF_ERR_ENCODING);
  
    | ↓ open down ↓ | 1119 lines elided | ↑ open up ↑ | 
3632 3631          }
3633 3632          cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
3634 3633              sizeof (X509_INFO *));
3635 3634          if (cert_infos == NULL) {
3636 3635                  (void) fclose(fp);
3637 3636                  rv = KMF_ERR_MEMORY;
3638 3637                  goto err;
3639 3638          }
3640 3639  
3641 3640          for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3642      -                /* LINTED E_BAD_PTR_CAST_ALIGN */
3643 3641                  cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
3644 3642                  ncerts++;
3645 3643          }
3646 3644  
3647 3645          if (ncerts == 0) {
3648 3646                  (void) fclose(fp);
3649 3647                  rv = KMF_ERR_CERT_NOT_FOUND;
3650 3648                  goto err;
3651 3649          }
3652 3650  
3653 3651          if (priv_key != NULL) {
3654 3652                  rewind(fp);
3655 3653                  pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
3656 3654          }
3657 3655          (void) fclose(fp);
3658 3656  
3659 3657          x = cert_infos[ncerts - 1]->x509;
3660 3658          /*
3661 3659           * Make sure the private key matchs the last cert in the file.
3662 3660           */
3663 3661          if (pkey != NULL && !X509_check_private_key(x, pkey)) {
3664 3662                  EVP_PKEY_free(pkey);
3665 3663                  rv = KMF_ERR_KEY_MISMATCH;
3666 3664                  goto err;
3667 3665          }
3668 3666  
3669 3667          certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
3670 3668          if (certlist == NULL) {
3671 3669                  if (pkey != NULL)
3672 3670                          EVP_PKEY_free(pkey);
3673 3671                  rv = KMF_ERR_MEMORY;
3674 3672                  goto err;
3675 3673          }
3676 3674  
3677 3675          /*
3678 3676           * Convert all of the certs to DER format.
3679 3677           */
3680 3678          matchcerts = 0;
3681 3679          for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
3682 3680                  boolean_t match = FALSE;
3683 3681                  info =  cert_infos[ncerts - 1 - i];
3684 3682  
3685 3683                  rv = check_cert(info->x509, issuer, subject, serial, &match);
3686 3684                  if (rv != KMF_OK || match != TRUE) {
3687 3685                          rv = KMF_OK;
3688 3686                          continue;
3689 3687                  }
3690 3688  
3691 3689                  rv = ssl_cert2KMFDATA(kmfh, info->x509,
3692 3690                          &certlist[matchcerts++]);
3693 3691  
3694 3692                  if (rv != KMF_OK) {
3695 3693                          int j;
3696 3694                          for (j = 0; j < matchcerts; j++)
3697 3695                                  kmf_free_data(&certlist[j]);
3698 3696                          free(certlist);
3699 3697                          certlist = NULL;
3700 3698                          ncerts = matchcerts = 0;
3701 3699                  }
3702 3700          }
3703 3701  
3704 3702          if (numcerts != NULL)
3705 3703                  *numcerts = matchcerts;
3706 3704  
3707 3705          if (certs != NULL)
3708 3706                  *certs = certlist;
3709 3707          else if (certlist != NULL) {
3710 3708                  for (i = 0; i < ncerts; i++)
3711 3709                          kmf_free_data(&certlist[i]);
3712 3710                  free(certlist);
3713 3711                  certlist = NULL;
  
    | ↓ open down ↓ | 61 lines elided | ↑ open up ↑ | 
3714 3712          }
3715 3713  
3716 3714          if (priv_key == NULL && pkey != NULL)
3717 3715                  EVP_PKEY_free(pkey);
3718 3716          else if (priv_key != NULL && pkey != NULL)
3719 3717                  *priv_key = pkey;
3720 3718  
3721 3719  err:
3722 3720          /* Cleanup the stack of X509 info records */
3723 3721          for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3724      -                /* LINTED E_BAD_PTR_CAST_ALIGN */
3725 3722                  info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
3726 3723                  X509_INFO_free(info);
3727 3724          }
3728 3725          if (x509_info_stack)
3729 3726                  sk_X509_INFO_free(x509_info_stack);
3730 3727  
3731 3728          if (cert_infos != NULL)
3732 3729                  free(cert_infos);
3733 3730  
3734 3731          return (rv);
3735 3732  }
3736 3733  
3737 3734  static KMF_RETURN
3738 3735  openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
3739 3736          STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
3740 3737  {
3741 3738          KMF_RETURN ret;
3742 3739          int i;
3743 3740  
3744 3741          for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3745      -                /* LINTED E_BAD_PTR_CAST_ALIGN */
3746 3742                  PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
3747 3743                  ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
3748 3744                      keys, certs);
3749 3745  
3750 3746                  if (ret != KMF_OK)
3751 3747                          return (ret);
3752 3748          }
3753 3749  
3754 3750          return (ret);
3755 3751  }
3756 3752  
3757 3753  static KMF_RETURN
3758 3754  set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
3759 3755  {
3760 3756          X509_ATTRIBUTE *attr = NULL;
3761 3757  
3762 3758          if (pkey == NULL || attrib == NULL)
3763 3759                  return (KMF_ERR_BAD_PARAMETER);
3764 3760  
3765 3761          if (pkey->attributes == NULL) {
  
    | ↓ open down ↓ | 10 lines elided | ↑ open up ↑ | 
3766 3762                  pkey->attributes = sk_X509_ATTRIBUTE_new_null();
3767 3763                  if (pkey->attributes == NULL)
3768 3764                          return (KMF_ERR_MEMORY);
3769 3765          }
3770 3766          attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
3771 3767          if (attr != NULL) {
3772 3768                  int i;
3773 3769                  X509_ATTRIBUTE *a;
3774 3770                  for (i = 0;
3775 3771                      i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3776      -                        /* LINTED E_BAD_PTR_CASE_ALIGN */
3777 3772                          a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
3778 3773                          if (OBJ_obj2nid(a->object) == nid) {
3779 3774                                  X509_ATTRIBUTE_free(a);
3780      -                                /* LINTED E_BAD_PTR_CAST_ALIGN */
3781      -                                sk_X509_ATTRIBUTE_set(pkey->attributes,
     3775 +                                (void) sk_X509_ATTRIBUTE_set(pkey->attributes,
3782 3776                                      i, attr);
3783 3777                                  return (KMF_OK);
3784 3778                          }
3785 3779                  }
3786 3780                  if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
3787 3781                          X509_ATTRIBUTE_free(attr);
3788 3782                          return (KMF_ERR_MEMORY);
3789 3783                  }
3790 3784          } else {
3791 3785                  return (KMF_ERR_MEMORY);
3792 3786          }
3793 3787  
3794 3788          return (KMF_OK);
3795 3789  }
3796 3790  
3797 3791  static KMF_RETURN
3798 3792  openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
3799 3793          STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
3800 3794  {
3801 3795          KMF_RETURN ret = KMF_OK;
3802 3796          PKCS8_PRIV_KEY_INFO *p8 = NULL;
3803 3797          EVP_PKEY *pkey = NULL;
3804 3798          X509 *xcert = NULL;
3805 3799          ASN1_TYPE *keyid = NULL;
3806 3800          ASN1_TYPE *fname = NULL;
3807 3801          uchar_t *data = NULL;
3808 3802  
3809 3803          keyid = PKCS12_get_attr(bag, NID_localKeyID);
3810 3804          fname = PKCS12_get_attr(bag, NID_friendlyName);
3811 3805  
3812 3806          switch (M_PKCS12_bag_type(bag)) {
3813 3807                  case NID_keyBag:
3814 3808                          if (keylist == NULL)
3815 3809                                  goto end;
3816 3810                          pkey = EVP_PKCS82PKEY(bag->value.keybag);
3817 3811                          if (pkey == NULL)
3818 3812                                  ret = KMF_ERR_PKCS12_FORMAT;
3819 3813  
3820 3814                          break;
3821 3815                  case NID_pkcs8ShroudedKeyBag:
3822 3816                          if (keylist == NULL)
3823 3817                                  goto end;
3824 3818                          p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
3825 3819                          if (p8 == NULL)
3826 3820                                  return (KMF_ERR_AUTH_FAILED);
3827 3821                          pkey = EVP_PKCS82PKEY(p8);
3828 3822                          PKCS8_PRIV_KEY_INFO_free(p8);
3829 3823                          if (pkey == NULL)
3830 3824                                  ret = KMF_ERR_PKCS12_FORMAT;
3831 3825                          break;
3832 3826                  case NID_certBag:
3833 3827                          if (certlist == NULL)
3834 3828                                  goto end;
3835 3829                          if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
3836 3830                                  return (KMF_ERR_PKCS12_FORMAT);
3837 3831                          xcert = M_PKCS12_certbag2x509(bag);
3838 3832                          if (xcert == NULL) {
3839 3833                                  ret = KMF_ERR_PKCS12_FORMAT;
3840 3834                                  goto end;
3841 3835                          }
3842 3836                          if (keyid != NULL) {
3843 3837                                  if (X509_keyid_set1(xcert,
3844 3838                                      keyid->value.octet_string->data,
3845 3839                                      keyid->value.octet_string->length) == 0) {
3846 3840                                          ret = KMF_ERR_PKCS12_FORMAT;
3847 3841                                          goto end;
3848 3842                                  }
3849 3843                          }
3850 3844                          if (fname != NULL) {
3851 3845                                  int len, r;
3852 3846                                  len = ASN1_STRING_to_UTF8(&data,
3853 3847                                      fname->value.asn1_string);
3854 3848                                  if (len > 0 && data != NULL) {
3855 3849                                          r = X509_alias_set1(xcert, data, len);
3856 3850                                          if (r == NULL) {
3857 3851                                                  ret = KMF_ERR_PKCS12_FORMAT;
3858 3852                                                  goto end;
3859 3853                                          }
3860 3854                                  } else {
3861 3855                                          ret = KMF_ERR_PKCS12_FORMAT;
3862 3856                                          goto end;
3863 3857                                  }
3864 3858                          }
3865 3859                          if (sk_X509_push(certlist, xcert) == 0)
3866 3860                                  ret = KMF_ERR_MEMORY;
3867 3861                          else
3868 3862                                  xcert = NULL;
3869 3863                          break;
3870 3864                  case NID_safeContentsBag:
3871 3865                          return (openssl_parse_bags(bag->value.safes, pass,
3872 3866                              keylist, certlist));
3873 3867                  default:
3874 3868                          ret = KMF_ERR_PKCS12_FORMAT;
3875 3869                          break;
3876 3870          }
3877 3871  
3878 3872          /*
3879 3873           * Set the ID and/or FriendlyName attributes on the key.
3880 3874           * If converting to PKCS11 objects, these can translate to CKA_ID
3881 3875           * and CKA_LABEL values.
3882 3876           */
3883 3877          if (pkey != NULL && ret == KMF_OK) {
3884 3878                  ASN1_TYPE *attr = NULL;
3885 3879                  if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
3886 3880                          if ((attr = ASN1_TYPE_new()) == NULL)
3887 3881                                  return (KMF_ERR_MEMORY);
3888 3882                          attr->value.octet_string =
3889 3883                              ASN1_STRING_dup(keyid->value.octet_string);
3890 3884                          attr->type = V_ASN1_OCTET_STRING;
3891 3885                          attr->value.ptr = (char *)attr->value.octet_string;
3892 3886                          ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3893 3887                          OPENSSL_free(attr);
3894 3888                  }
3895 3889  
3896 3890                  if (ret == KMF_OK && fname != NULL &&
3897 3891                      fname->type == V_ASN1_BMPSTRING) {
3898 3892                          if ((attr = ASN1_TYPE_new()) == NULL)
3899 3893                                  return (KMF_ERR_MEMORY);
3900 3894                          attr->value.bmpstring =
3901 3895                              ASN1_STRING_dup(fname->value.bmpstring);
3902 3896                          attr->type = V_ASN1_BMPSTRING;
3903 3897                          attr->value.ptr = (char *)attr->value.bmpstring;
3904 3898                          ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3905 3899                          OPENSSL_free(attr);
3906 3900                  }
3907 3901  
3908 3902                  if (ret == KMF_OK && keylist != NULL &&
3909 3903                      sk_EVP_PKEY_push(keylist, pkey) == 0)
3910 3904                          ret = KMF_ERR_MEMORY;
3911 3905          }
3912 3906          if (ret == KMF_OK && keylist != NULL)
3913 3907                  pkey = NULL;
3914 3908  end:
3915 3909          if (pkey != NULL)
3916 3910                  EVP_PKEY_free(pkey);
3917 3911          if (xcert != NULL)
3918 3912                  X509_free(xcert);
3919 3913          if (data != NULL)
3920 3914                  OPENSSL_free(data);
3921 3915  
3922 3916          return (ret);
3923 3917  }
3924 3918  
3925 3919  static KMF_RETURN
3926 3920  openssl_pkcs12_parse(PKCS12 *p12, char *pin,
3927 3921          STACK_OF(EVP_PKEY) *keys,
3928 3922          STACK_OF(X509) *certs,
3929 3923          STACK_OF(X509) *ca)
3930 3924  /* ARGSUSED3 */
3931 3925  {
3932 3926          KMF_RETURN ret = KMF_OK;
3933 3927          STACK_OF(PKCS7) *asafes = NULL;
3934 3928          STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
3935 3929          int i, bagnid;
3936 3930          PKCS7 *p7;
3937 3931  
3938 3932          if (p12 == NULL || (keys == NULL && certs == NULL))
3939 3933                  return (KMF_ERR_BAD_PARAMETER);
3940 3934  
3941 3935          if (pin == NULL || *pin == NULL) {
3942 3936                  if (PKCS12_verify_mac(p12, NULL, 0)) {
3943 3937                          pin = NULL;
3944 3938                  } else if (PKCS12_verify_mac(p12, "", 0)) {
3945 3939                          pin = "";
3946 3940                  } else {
3947 3941                          return (KMF_ERR_AUTH_FAILED);
  
    | ↓ open down ↓ | 156 lines elided | ↑ open up ↑ | 
3948 3942                  }
3949 3943          } else if (!PKCS12_verify_mac(p12, pin, -1)) {
3950 3944                  return (KMF_ERR_AUTH_FAILED);
3951 3945          }
3952 3946  
3953 3947          if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
3954 3948                  return (KMF_ERR_PKCS12_FORMAT);
3955 3949  
3956 3950          for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
3957 3951                  bags = NULL;
3958      -                /* LINTED E_BAD_PTR_CAST_ALIGN */
3959 3952                  p7 = sk_PKCS7_value(asafes, i);
3960 3953                  bagnid = OBJ_obj2nid(p7->type);
3961 3954  
3962 3955                  if (bagnid == NID_pkcs7_data) {
3963 3956                          bags = PKCS12_unpack_p7data(p7);
3964 3957                  } else if (bagnid == NID_pkcs7_encrypted) {
3965 3958                          bags = PKCS12_unpack_p7encdata(p7, pin,
3966 3959                              (pin ? strlen(pin) : 0));
3967 3960                  } else {
3968 3961                          continue;
3969 3962                  }
3970 3963                  if (bags == NULL) {
3971 3964                          ret = KMF_ERR_PKCS12_FORMAT;
3972 3965                          goto out;
3973 3966                  }
3974 3967  
3975 3968                  if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
3976 3969                          ret = KMF_ERR_PKCS12_FORMAT;
3977 3970  
3978 3971                  sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
3979 3972          }
3980 3973  out:
3981 3974          if (asafes != NULL)
3982 3975                  sk_PKCS7_pop_free(asafes, PKCS7_free);
3983 3976  
3984 3977          return (ret);
3985 3978  }
3986 3979  
3987 3980  /*
3988 3981   * Helper function to decrypt and parse PKCS#12 import file.
3989 3982   */
3990 3983  static KMF_RETURN
3991 3984  extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
3992 3985          STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
3993 3986          STACK_OF(X509) **ca)
3994 3987  /* ARGSUSED2 */
3995 3988  {
3996 3989          PKCS12                  *pk12, *pk12_tmp;
3997 3990          STACK_OF(EVP_PKEY)      *pkeylist = NULL;
3998 3991          STACK_OF(X509)          *xcertlist = NULL;
3999 3992          STACK_OF(X509)          *cacertlist = NULL;
4000 3993  
4001 3994          if ((pk12 = PKCS12_new()) == NULL) {
4002 3995                  return (KMF_ERR_MEMORY);
4003 3996          }
4004 3997  
4005 3998          if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
4006 3999                  /* This is ok; it seems to mean there is no more to read. */
4007 4000                  if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
4008 4001                      ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
4009 4002                          goto end_extract_pkcs12;
4010 4003  
4011 4004                  PKCS12_free(pk12);
4012 4005                  return (KMF_ERR_PKCS12_FORMAT);
4013 4006          }
4014 4007          pk12 = pk12_tmp;
4015 4008  
4016 4009          xcertlist = sk_X509_new_null();
4017 4010          if (xcertlist == NULL) {
4018 4011                  PKCS12_free(pk12);
4019 4012                  return (KMF_ERR_MEMORY);
4020 4013          }
4021 4014          pkeylist = sk_EVP_PKEY_new_null();
4022 4015          if (pkeylist == NULL) {
4023 4016                  sk_X509_pop_free(xcertlist, X509_free);
4024 4017                  PKCS12_free(pk12);
4025 4018                  return (KMF_ERR_MEMORY);
4026 4019          }
4027 4020  
4028 4021          if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
4029 4022              cacertlist) != KMF_OK) {
4030 4023                  sk_X509_pop_free(xcertlist, X509_free);
4031 4024                  sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4032 4025                  PKCS12_free(pk12);
4033 4026                  return (KMF_ERR_PKCS12_FORMAT);
4034 4027          }
4035 4028  
4036 4029          if (priv_key && pkeylist)
4037 4030                  *priv_key = pkeylist;
4038 4031          else if (pkeylist)
4039 4032                  sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4040 4033          if (certs && xcertlist)
4041 4034                  *certs = xcertlist;
4042 4035          else if (xcertlist)
4043 4036                  sk_X509_pop_free(xcertlist, X509_free);
4044 4037          if (ca && cacertlist)
4045 4038                  *ca = cacertlist;
4046 4039          else if (cacertlist)
4047 4040                  sk_X509_pop_free(cacertlist, X509_free);
4048 4041  
4049 4042  end_extract_pkcs12:
4050 4043  
4051 4044          PKCS12_free(pk12);
4052 4045          return (KMF_OK);
4053 4046  }
4054 4047  
4055 4048  static KMF_RETURN
4056 4049  sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
4057 4050  {
4058 4051          KMF_RETURN rv = KMF_OK;
4059 4052          uint32_t sz;
4060 4053  
4061 4054          sz = BN_num_bytes(from);
4062 4055          to->val = (uchar_t *)malloc(sz);
4063 4056          if (to->val == NULL)
4064 4057                  return (KMF_ERR_MEMORY);
4065 4058  
4066 4059          if ((to->len = BN_bn2bin(from, to->val)) != sz) {
4067 4060                  free(to->val);
4068 4061                  to->val = NULL;
4069 4062                  to->len = 0;
4070 4063                  rv = KMF_ERR_MEMORY;
4071 4064          }
4072 4065  
4073 4066          return (rv);
4074 4067  }
4075 4068  
4076 4069  static KMF_RETURN
4077 4070  exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
4078 4071  {
4079 4072          KMF_RETURN rv;
4080 4073          KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
4081 4074  
4082 4075          (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4083 4076          if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
4084 4077                  goto cleanup;
4085 4078  
4086 4079          if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
4087 4080                  goto cleanup;
4088 4081  
4089 4082          if (rsa->d != NULL)
4090 4083                  if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
4091 4084                          goto cleanup;
4092 4085  
4093 4086          if (rsa->p != NULL)
4094 4087                  if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
4095 4088                          goto cleanup;
4096 4089  
4097 4090          if (rsa->q != NULL)
4098 4091                  if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
4099 4092                          goto cleanup;
4100 4093  
4101 4094          if (rsa->dmp1 != NULL)
4102 4095                  if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
4103 4096                          goto cleanup;
4104 4097  
4105 4098          if (rsa->dmq1 != NULL)
4106 4099                  if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
4107 4100                          goto cleanup;
4108 4101  
4109 4102          if (rsa->iqmp != NULL)
4110 4103                  if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
4111 4104                          goto cleanup;
4112 4105  cleanup:
4113 4106          if (rv != KMF_OK)
4114 4107                  kmf_free_raw_key(key);
4115 4108          else
4116 4109                  key->keytype = KMF_RSA;
4117 4110  
4118 4111          /*
4119 4112           * Free the reference to this key, SSL will not actually free
4120 4113           * the memory until the refcount == 0, so this is safe.
4121 4114           */
4122 4115          RSA_free(rsa);
4123 4116  
4124 4117          return (rv);
4125 4118  }
4126 4119  
4127 4120  static KMF_RETURN
4128 4121  exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
4129 4122  {
4130 4123          KMF_RETURN rv;
4131 4124          KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4132 4125  
4133 4126          (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4134 4127          if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
4135 4128                  goto cleanup;
4136 4129  
4137 4130          if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
4138 4131                  goto cleanup;
4139 4132  
4140 4133          if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
4141 4134                  goto cleanup;
4142 4135  
4143 4136          if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
4144 4137                  goto cleanup;
4145 4138  
4146 4139  cleanup:
4147 4140          if (rv != KMF_OK)
4148 4141                  kmf_free_raw_key(key);
4149 4142          else
4150 4143                  key->keytype = KMF_DSA;
4151 4144  
4152 4145          /*
4153 4146           * Free the reference to this key, SSL will not actually free
4154 4147           * the memory until the refcount == 0, so this is safe.
4155 4148           */
4156 4149          DSA_free(dsa);
4157 4150  
4158 4151          return (rv);
4159 4152  }
4160 4153  
4161 4154  static KMF_RETURN
4162 4155  add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
4163 4156          KMF_X509_DER_CERT **certlist, int *ncerts)
4164 4157  {
4165 4158          KMF_RETURN rv = KMF_OK;
4166 4159          KMF_X509_DER_CERT *list = (*certlist);
4167 4160          KMF_X509_DER_CERT cert;
4168 4161          int n = (*ncerts);
4169 4162  
4170 4163          if (list == NULL) {
4171 4164                  list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
4172 4165          } else {
4173 4166                  list = (KMF_X509_DER_CERT *)realloc(list,
4174 4167                      sizeof (KMF_X509_DER_CERT) * (n + 1));
4175 4168          }
4176 4169  
4177 4170          if (list == NULL)
4178 4171                  return (KMF_ERR_MEMORY);
4179 4172  
4180 4173          (void) memset(&cert, 0, sizeof (cert));
4181 4174          rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
4182 4175          if (rv == KMF_OK) {
4183 4176                  int len = 0;
4184 4177                  /* Get the alias name for the cert if there is one */
4185 4178                  char *a = (char *)X509_alias_get0(sslcert, &len);
4186 4179                  if (a != NULL)
4187 4180                          cert.kmf_private.label = strdup(a);
4188 4181                  cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
4189 4182  
4190 4183                  list[n] = cert;
4191 4184                  (*ncerts) = n + 1;
4192 4185  
4193 4186                  *certlist = list;
4194 4187          } else {
4195 4188                  free(list);
4196 4189          }
4197 4190  
4198 4191          return (rv);
4199 4192  }
4200 4193  
4201 4194  static KMF_RETURN
4202 4195  add_key_to_list(KMF_RAW_KEY_DATA **keylist,
4203 4196          KMF_RAW_KEY_DATA *newkey, int *nkeys)
4204 4197  {
4205 4198          KMF_RAW_KEY_DATA *list = (*keylist);
4206 4199          int n = (*nkeys);
4207 4200  
4208 4201          if (list == NULL) {
4209 4202                  list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
4210 4203          } else {
4211 4204                  list = (KMF_RAW_KEY_DATA *)realloc(list,
4212 4205                      sizeof (KMF_RAW_KEY_DATA) * (n + 1));
4213 4206          }
4214 4207  
4215 4208          if (list == NULL)
4216 4209                  return (KMF_ERR_MEMORY);
4217 4210  
4218 4211          list[n] = *newkey;
4219 4212          (*nkeys) = n + 1;
4220 4213  
4221 4214          *keylist = list;
4222 4215  
4223 4216          return (KMF_OK);
4224 4217  }
4225 4218  
  
    | ↓ open down ↓ | 257 lines elided | ↑ open up ↑ | 
4226 4219  static X509_ATTRIBUTE *
4227 4220  find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
4228 4221  {
4229 4222          X509_ATTRIBUTE *a;
4230 4223          int i;
4231 4224  
4232 4225          if (attrs == NULL)
4233 4226                  return (NULL);
4234 4227  
4235 4228          for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4236      -                /* LINTED E_BAD_PTR_CAST_ALIGN */
4237 4229                  a = sk_X509_ATTRIBUTE_value(attrs, i);
4238 4230                  if (OBJ_obj2nid(a->object) == nid)
4239 4231                          return (a);
4240 4232          }
4241 4233          return (NULL);
4242 4234  }
4243 4235  
4244 4236  static KMF_RETURN
4245 4237  convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
4246 4238  {
4247 4239          KMF_RETURN rv = KMF_OK;
4248 4240          X509_ATTRIBUTE *attr;
4249 4241  
4250 4242          if (pkey == NULL || key == NULL)
4251 4243                  return (KMF_ERR_BAD_PARAMETER);
4252 4244          /* Convert SSL key to raw key */
4253 4245          switch (pkey->type) {
4254 4246                  case EVP_PKEY_RSA:
4255 4247                          rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
4256 4248                              key);
4257 4249                          if (rv != KMF_OK)
4258 4250                                  return (rv);
4259 4251                          break;
4260 4252                  case EVP_PKEY_DSA:
4261 4253                          rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
4262 4254                              key);
4263 4255                          if (rv != KMF_OK)
4264 4256                                  return (rv);
4265 4257                          break;
4266 4258                  default:
  
    | ↓ open down ↓ | 20 lines elided | ↑ open up ↑ | 
4267 4259                          return (KMF_ERR_BAD_PARAMETER);
4268 4260          }
4269 4261          /*
4270 4262           * If friendlyName, add it to record.
4271 4263           */
4272 4264          attr = find_attr(pkey->attributes, NID_friendlyName);
4273 4265          if (attr != NULL) {
4274 4266                  ASN1_TYPE *ty = NULL;
4275 4267                  int numattr = sk_ASN1_TYPE_num(attr->value.set);
4276 4268                  if (attr->single == 0 && numattr > 0) {
4277      -                        /* LINTED E_BAD_PTR_CAST_ALIGN */
4278 4269                          ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4279 4270                  }
4280 4271                  if (ty != NULL) {
4281 4272  #if OPENSSL_VERSION_NUMBER < 0x10000000L
4282 4273                          key->label = uni2asc(ty->value.bmpstring->data,
4283 4274                              ty->value.bmpstring->length);
4284 4275  #else
4285 4276                          key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
4286 4277                              ty->value.bmpstring->length);
4287 4278  #endif
4288 4279                  }
4289 4280          } else {
4290 4281                  key->label = NULL;
  
    | ↓ open down ↓ | 3 lines elided | ↑ open up ↑ | 
4291 4282          }
4292 4283  
4293 4284          /*
4294 4285           * If KeyID, add it to record as a KMF_DATA object.
4295 4286           */
4296 4287          attr = find_attr(pkey->attributes, NID_localKeyID);
4297 4288          if (attr != NULL) {
4298 4289                  ASN1_TYPE *ty = NULL;
4299 4290                  int numattr = sk_ASN1_TYPE_num(attr->value.set);
4300 4291                  if (attr->single == 0 && numattr > 0) {
4301      -                        /* LINTED E_BAD_PTR_CAST_ALIGN */
4302 4292                          ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4303 4293                  }
4304 4294                  key->id.Data = (uchar_t *)malloc(
4305 4295                      ty->value.octet_string->length);
4306 4296                  if (key->id.Data == NULL)
4307 4297                          return (KMF_ERR_MEMORY);
4308 4298                  (void) memcpy(key->id.Data, ty->value.octet_string->data,
4309 4299                      ty->value.octet_string->length);
4310 4300                  key->id.Length = ty->value.octet_string->length;
4311 4301          } else {
4312 4302                  (void) memset(&key->id, 0, sizeof (KMF_DATA));
4313 4303          }
4314 4304  
4315 4305          return (rv);
4316 4306  }
4317 4307  
4318 4308  static KMF_RETURN
4319 4309  convertPK12Objects(
4320 4310          KMF_HANDLE *kmfh,
4321 4311          STACK_OF(EVP_PKEY) *sslkeys,
  
    | ↓ open down ↓ | 10 lines elided | ↑ open up ↑ | 
4322 4312          STACK_OF(X509) *sslcert,
4323 4313          STACK_OF(X509) *sslcacerts,
4324 4314          KMF_RAW_KEY_DATA **keylist, int *nkeys,
4325 4315          KMF_X509_DER_CERT **certlist, int *ncerts)
4326 4316  {
4327 4317          KMF_RETURN rv = KMF_OK;
4328 4318          KMF_RAW_KEY_DATA key;
4329 4319          int i;
4330 4320  
4331 4321          for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4332      -                /* LINTED E_BAD_PTR_CAST_ALIGN */
4333 4322                  EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
4334 4323                  rv = convertToRawKey(pkey, &key);
4335 4324                  if (rv == KMF_OK)
4336 4325                          rv = add_key_to_list(keylist, &key, nkeys);
4337 4326  
4338 4327                  if (rv != KMF_OK)
4339 4328                          return (rv);
4340 4329          }
4341 4330  
4342 4331          /* Now add the certificate to the certlist */
4343 4332          for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4344      -                /* LINTED E_BAD_PTR_CAST_ALIGN */
4345 4333                  X509 *cert = sk_X509_value(sslcert, i);
4346 4334                  rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
4347 4335                  if (rv != KMF_OK)
4348 4336                          return (rv);
4349 4337          }
4350 4338  
4351 4339          /* Also add any included CA certs to the list */
4352 4340          for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
4353 4341                  X509 *c;
4354 4342                  /*
4355 4343                   * sk_X509_value() is macro that embeds a cast to (X509 *).
4356 4344                   * Here it translates into ((X509 *)sk_value((ca), (i))).
4357 4345                   * Lint is complaining about the embedded casting, and
4358 4346                   * to fix it, you need to fix openssl header files.
4359 4347                   */
4360      -                /* LINTED E_BAD_PTR_CAST_ALIGN */
4361 4348                  c = sk_X509_value(sslcacerts, i);
4362 4349  
4363 4350                  /* Now add the ca cert to the certlist */
4364 4351                  rv = add_cert_to_list(kmfh, c, certlist, ncerts);
4365 4352                  if (rv != KMF_OK)
4366 4353                          return (rv);
4367 4354          }
4368 4355          return (rv);
4369 4356  }
4370 4357  
4371 4358  KMF_RETURN
4372 4359  openssl_import_objects(KMF_HANDLE *kmfh,
4373 4360          char *filename, KMF_CREDENTIAL *cred,
4374 4361          KMF_X509_DER_CERT **certlist, int *ncerts,
4375 4362          KMF_RAW_KEY_DATA **keylist, int *nkeys)
4376 4363  {
4377 4364          KMF_RETURN      rv = KMF_OK;
4378 4365          KMF_ENCODE_FORMAT format;
4379 4366          BIO             *bio = NULL;
4380 4367          STACK_OF(EVP_PKEY)      *privkeys = NULL;
4381 4368          STACK_OF(X509)          *certs = NULL;
4382 4369          STACK_OF(X509)          *cacerts = NULL;
4383 4370  
4384 4371          /*
4385 4372           * auto-detect the file format, regardless of what
4386 4373           * the 'format' parameters in the params say.
4387 4374           */
4388 4375          rv = kmf_get_file_format(filename, &format);
4389 4376          if (rv != KMF_OK) {
4390 4377                  return (rv);
4391 4378          }
4392 4379  
4393 4380          /* This function only works for PEM or PKCS#12 files */
4394 4381          if (format != KMF_FORMAT_PEM &&
4395 4382              format != KMF_FORMAT_PEM_KEYPAIR &&
4396 4383              format != KMF_FORMAT_PKCS12)
4397 4384                  return (KMF_ERR_ENCODING);
4398 4385  
4399 4386          *certlist = NULL;
4400 4387          *keylist = NULL;
4401 4388          *ncerts = 0;
4402 4389          *nkeys = 0;
4403 4390  
4404 4391          if (format == KMF_FORMAT_PKCS12) {
4405 4392                  bio = BIO_new_file(filename, "rb");
4406 4393                  if (bio == NULL) {
4407 4394                          SET_ERROR(kmfh, ERR_get_error());
4408 4395                          rv = KMF_ERR_OPEN_FILE;
4409 4396                          goto end;
4410 4397                  }
4411 4398  
4412 4399                  rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
4413 4400                      (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
4414 4401  
4415 4402                  if (rv  == KMF_OK)
4416 4403                          /* Convert keys and certs to exportable format */
4417 4404                          rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
4418 4405                              keylist, nkeys, certlist, ncerts);
4419 4406          } else {
4420 4407                  EVP_PKEY *pkey;
4421 4408                  KMF_DATA *certdata = NULL;
4422 4409                  KMF_X509_DER_CERT *kmfcerts = NULL;
4423 4410                  int i;
4424 4411                  rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
4425 4412                      (uchar_t *)cred->cred, (uint32_t)cred->credlen,
4426 4413                      &pkey, &certdata, ncerts);
4427 4414  
4428 4415                  /* Reached end of import file? */
4429 4416                  if (rv == KMF_OK && pkey != NULL) {
4430 4417                          privkeys = sk_EVP_PKEY_new_null();
4431 4418                          if (privkeys == NULL) {
4432 4419                                  rv = KMF_ERR_MEMORY;
4433 4420                                  goto end;
4434 4421                          }
4435 4422                          (void) sk_EVP_PKEY_push(privkeys, pkey);
4436 4423                          /* convert the certificate list here */
4437 4424                          if (*ncerts > 0 && certlist != NULL) {
4438 4425                                  kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
4439 4426                                      sizeof (KMF_X509_DER_CERT));
4440 4427                                  if (kmfcerts == NULL) {
4441 4428                                          rv = KMF_ERR_MEMORY;
4442 4429                                          goto end;
4443 4430                                  }
4444 4431                                  for (i = 0; i < *ncerts; i++) {
4445 4432                                          kmfcerts[i].certificate = certdata[i];
4446 4433                                          kmfcerts[i].kmf_private.keystore_type =
4447 4434                                              KMF_KEYSTORE_OPENSSL;
4448 4435                                  }
4449 4436                                  *certlist = kmfcerts;
4450 4437                          }
4451 4438                          /*
4452 4439                           * Convert keys to exportable format, the certs
4453 4440                           * are already OK.
4454 4441                           */
4455 4442                          rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
4456 4443                              keylist, nkeys, NULL, NULL);
4457 4444                  }
4458 4445          }
4459 4446  end:
4460 4447          if (bio != NULL)
4461 4448                  (void) BIO_free(bio);
4462 4449  
4463 4450          if (privkeys)
4464 4451                  sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
4465 4452          if (certs)
4466 4453                  sk_X509_pop_free(certs, X509_free);
4467 4454          if (cacerts)
4468 4455                  sk_X509_pop_free(cacerts, X509_free);
4469 4456  
4470 4457          return (rv);
4471 4458  }
4472 4459  
4473 4460  static KMF_RETURN
4474 4461  create_deskey(DES_cblock **deskey)
4475 4462  {
4476 4463          DES_cblock *key;
4477 4464  
4478 4465          key = (DES_cblock *) malloc(sizeof (DES_cblock));
4479 4466          if (key == NULL) {
4480 4467                  return (KMF_ERR_MEMORY);
4481 4468          }
4482 4469  
4483 4470          if (DES_random_key(key) == 0) {
4484 4471                  free(key);
4485 4472                  return (KMF_ERR_KEYGEN_FAILED);
4486 4473          }
4487 4474  
4488 4475          *deskey = key;
4489 4476          return (KMF_OK);
4490 4477  }
4491 4478  
4492 4479  #define KEYGEN_RETRY 3
4493 4480  #define DES3_KEY_SIZE 24
4494 4481  
4495 4482  static KMF_RETURN
4496 4483  create_des3key(unsigned char **des3key)
4497 4484  {
4498 4485          KMF_RETURN ret = KMF_OK;
4499 4486          DES_cblock *deskey1 = NULL;
4500 4487          DES_cblock *deskey2 = NULL;
4501 4488          DES_cblock *deskey3 = NULL;
4502 4489          unsigned char *newkey = NULL;
4503 4490          int retry;
4504 4491  
4505 4492          if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
4506 4493                  return (KMF_ERR_MEMORY);
4507 4494          }
4508 4495  
4509 4496          /* create the 1st DES key */
4510 4497          if ((ret = create_deskey(&deskey1)) != KMF_OK) {
4511 4498                  goto out;
4512 4499          }
4513 4500  
4514 4501          /*
4515 4502           * Create the 2nd DES key and make sure its value is different
4516 4503           * from the 1st DES key.
4517 4504           */
4518 4505          retry = 0;
4519 4506          do {
4520 4507                  if (deskey2 != NULL) {
4521 4508                          free(deskey2);
4522 4509                          deskey2 = NULL;
4523 4510                  }
4524 4511  
4525 4512                  if ((ret = create_deskey(&deskey2)) != KMF_OK) {
4526 4513                          goto out;
4527 4514                  }
4528 4515  
4529 4516                  if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
4530 4517                      == 0) {
4531 4518                          ret = KMF_ERR_KEYGEN_FAILED;
4532 4519                          retry++;
4533 4520                  }
4534 4521          } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4535 4522  
4536 4523          if (ret != KMF_OK) {
4537 4524                  goto out;
4538 4525          }
4539 4526  
4540 4527          /*
4541 4528           * Create the 3rd DES key and make sure its value is different
4542 4529           * from the 2nd DES key.
4543 4530           */
4544 4531          retry = 0;
4545 4532          do {
4546 4533                  if (deskey3 != NULL) {
4547 4534                          free(deskey3);
4548 4535                          deskey3 = NULL;
4549 4536                  }
4550 4537  
4551 4538                  if ((ret = create_deskey(&deskey3)) != KMF_OK) {
4552 4539                          goto out;
4553 4540                  }
4554 4541  
4555 4542                  if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
4556 4543                      == 0) {
4557 4544                          ret = KMF_ERR_KEYGEN_FAILED;
4558 4545                          retry++;
4559 4546                  }
4560 4547          } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4561 4548  
4562 4549          if (ret != KMF_OK) {
4563 4550                  goto out;
4564 4551          }
4565 4552  
4566 4553          /* Concatenate 3 DES keys into a DES3 key */
4567 4554          (void) memcpy((void *)newkey, (const void *)deskey1, 8);
4568 4555          (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
4569 4556          (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
4570 4557          *des3key = newkey;
4571 4558  
4572 4559  out:
4573 4560          if (deskey1 != NULL)
4574 4561                  free(deskey1);
4575 4562  
4576 4563          if (deskey2 != NULL)
4577 4564                  free(deskey2);
4578 4565  
4579 4566          if (deskey3 != NULL)
4580 4567                  free(deskey3);
4581 4568  
4582 4569          if (ret != KMF_OK && newkey != NULL)
4583 4570                  free(newkey);
4584 4571  
4585 4572          return (ret);
4586 4573  }
4587 4574  
4588 4575  KMF_RETURN
4589 4576  OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
4590 4577          int numattr, KMF_ATTRIBUTE *attrlist)
4591 4578  {
4592 4579          KMF_RETURN ret = KMF_OK;
4593 4580          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4594 4581          char *fullpath = NULL;
4595 4582          KMF_RAW_SYM_KEY *rkey = NULL;
4596 4583          DES_cblock *deskey = NULL;
4597 4584          unsigned char *des3key = NULL;
4598 4585          unsigned char *random = NULL;
4599 4586          int fd = -1;
4600 4587          KMF_KEY_HANDLE *symkey;
4601 4588          KMF_KEY_ALG keytype;
4602 4589          uint32_t keylen;
4603 4590          uint32_t keylen_size = sizeof (keylen);
4604 4591          char *dirpath;
4605 4592          char *keyfile;
4606 4593  
4607 4594          if (kmfh == NULL)
4608 4595                  return (KMF_ERR_UNINITIALIZED);
4609 4596  
4610 4597          symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
4611 4598          if (symkey == NULL)
4612 4599                  return (KMF_ERR_BAD_PARAMETER);
4613 4600  
4614 4601          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4615 4602  
4616 4603          keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
4617 4604          if (keyfile == NULL)
4618 4605                  return (KMF_ERR_BAD_PARAMETER);
4619 4606  
4620 4607          ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
4621 4608              (void *)&keytype, NULL);
4622 4609          if (ret != KMF_OK)
4623 4610                  return (KMF_ERR_BAD_PARAMETER);
4624 4611  
4625 4612          ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
4626 4613              &keylen, &keylen_size);
4627 4614          if (ret == KMF_ERR_ATTR_NOT_FOUND &&
4628 4615              (keytype == KMF_DES || keytype == KMF_DES3))
4629 4616                  /* keylength is not required for DES and 3DES */
4630 4617                  ret = KMF_OK;
4631 4618          if (ret != KMF_OK)
4632 4619                  return (KMF_ERR_BAD_PARAMETER);
4633 4620  
4634 4621          fullpath = get_fullpath(dirpath, keyfile);
4635 4622          if (fullpath == NULL)
4636 4623                  return (KMF_ERR_BAD_PARAMETER);
4637 4624  
4638 4625          /* If the requested file exists, return an error */
4639 4626          if (test_for_file(fullpath, 0400) == 1) {
4640 4627                  free(fullpath);
4641 4628                  return (KMF_ERR_DUPLICATE_KEYFILE);
4642 4629          }
4643 4630  
4644 4631          fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
4645 4632          if (fd == -1) {
4646 4633                  ret = KMF_ERR_OPEN_FILE;
4647 4634                  goto out;
4648 4635          }
4649 4636  
4650 4637          rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
4651 4638          if (rkey == NULL) {
4652 4639                  ret = KMF_ERR_MEMORY;
4653 4640                  goto out;
4654 4641          }
4655 4642          (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
4656 4643  
4657 4644          if (keytype == KMF_DES) {
4658 4645                  if ((ret = create_deskey(&deskey)) != KMF_OK) {
4659 4646                          goto out;
4660 4647                  }
4661 4648                  rkey->keydata.val = (uchar_t *)deskey;
4662 4649                  rkey->keydata.len = 8;
4663 4650  
4664 4651                  symkey->keyalg = KMF_DES;
4665 4652  
4666 4653          } else if (keytype == KMF_DES3) {
4667 4654                  if ((ret = create_des3key(&des3key)) != KMF_OK) {
4668 4655                          goto out;
4669 4656                  }
4670 4657                  rkey->keydata.val = (uchar_t *)des3key;
4671 4658                  rkey->keydata.len = DES3_KEY_SIZE;
4672 4659                  symkey->keyalg = KMF_DES3;
4673 4660  
4674 4661          } else if (keytype == KMF_AES || keytype == KMF_RC4 ||
4675 4662              keytype == KMF_GENERIC_SECRET) {
4676 4663                  int bytes;
4677 4664  
4678 4665                  if (keylen % 8 != 0) {
4679 4666                          ret = KMF_ERR_BAD_KEY_SIZE;
4680 4667                          goto out;
4681 4668                  }
4682 4669  
4683 4670                  if (keytype == KMF_AES) {
4684 4671                          if (keylen != 128 &&
4685 4672                              keylen != 192 &&
4686 4673                              keylen != 256) {
4687 4674                                  ret = KMF_ERR_BAD_KEY_SIZE;
4688 4675                                  goto out;
4689 4676                          }
4690 4677                  }
4691 4678  
4692 4679                  bytes = keylen/8;
4693 4680                  random = malloc(bytes);
4694 4681                  if (random == NULL) {
4695 4682                          ret = KMF_ERR_MEMORY;
4696 4683                          goto out;
4697 4684                  }
4698 4685                  if (RAND_bytes(random, bytes) != 1) {
4699 4686                          ret = KMF_ERR_KEYGEN_FAILED;
4700 4687                          goto out;
4701 4688                  }
4702 4689  
4703 4690                  rkey->keydata.val = (uchar_t *)random;
4704 4691                  rkey->keydata.len = bytes;
4705 4692                  symkey->keyalg = keytype;
4706 4693  
4707 4694          } else {
4708 4695                  ret = KMF_ERR_BAD_KEY_TYPE;
4709 4696                  goto out;
4710 4697          }
4711 4698  
4712 4699          (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
4713 4700  
4714 4701          symkey->kstype = KMF_KEYSTORE_OPENSSL;
4715 4702          symkey->keyclass = KMF_SYMMETRIC;
4716 4703          symkey->keylabel = (char *)fullpath;
4717 4704          symkey->israw = TRUE;
4718 4705          symkey->keyp = rkey;
4719 4706  
4720 4707  out:
4721 4708          if (fd != -1)
4722 4709                  (void) close(fd);
4723 4710  
4724 4711          if (ret != KMF_OK && fullpath != NULL) {
4725 4712                  free(fullpath);
4726 4713          }
4727 4714          if (ret != KMF_OK) {
4728 4715                  kmf_free_raw_sym_key(rkey);
4729 4716                  symkey->keyp = NULL;
4730 4717                  symkey->keyalg = KMF_KEYALG_NONE;
4731 4718          }
4732 4719  
4733 4720          return (ret);
4734 4721  }
4735 4722  
4736 4723  /*
4737 4724   * Check a file to see if it is a CRL file with PEM or DER format.
4738 4725   * If success, return its format in the "pformat" argument.
4739 4726   */
4740 4727  KMF_RETURN
4741 4728  OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
4742 4729  {
4743 4730          KMF_RETURN      ret = KMF_OK;
4744 4731          KMF_HANDLE      *kmfh = (KMF_HANDLE *)handle;
4745 4732          BIO             *bio = NULL;
4746 4733          X509_CRL        *xcrl = NULL;
4747 4734  
4748 4735          if (filename == NULL) {
4749 4736                  return (KMF_ERR_BAD_PARAMETER);
4750 4737          }
4751 4738  
4752 4739          bio = BIO_new_file(filename, "rb");
4753 4740          if (bio == NULL)        {
4754 4741                  SET_ERROR(kmfh, ERR_get_error());
4755 4742                  ret = KMF_ERR_OPEN_FILE;
4756 4743                  goto out;
4757 4744          }
4758 4745  
4759 4746          if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
4760 4747                  *pformat = KMF_FORMAT_PEM;
4761 4748                  goto out;
4762 4749          }
4763 4750          (void) BIO_free(bio);
4764 4751  
4765 4752          /*
4766 4753           * Now try to read it as raw DER data.
4767 4754           */
4768 4755          bio = BIO_new_file(filename, "rb");
4769 4756          if (bio == NULL)        {
4770 4757                  SET_ERROR(kmfh, ERR_get_error());
4771 4758                  ret = KMF_ERR_OPEN_FILE;
4772 4759                  goto out;
4773 4760          }
4774 4761  
4775 4762          if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
4776 4763                  *pformat = KMF_FORMAT_ASN1;
4777 4764          } else {
4778 4765                  ret = KMF_ERR_BAD_CRLFILE;
4779 4766          }
4780 4767  
4781 4768  out:
4782 4769          if (bio != NULL)
4783 4770                  (void) BIO_free(bio);
4784 4771  
4785 4772          if (xcrl != NULL)
4786 4773                  X509_CRL_free(xcrl);
4787 4774  
4788 4775          return (ret);
4789 4776  }
4790 4777  
4791 4778  KMF_RETURN
4792 4779  OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
4793 4780      KMF_RAW_SYM_KEY *rkey)
4794 4781  {
4795 4782          KMF_RETURN      rv = KMF_OK;
4796 4783          KMF_HANDLE      *kmfh = (KMF_HANDLE *)handle;
4797 4784          KMF_DATA        keyvalue;
4798 4785  
4799 4786          if (kmfh == NULL)
4800 4787                  return (KMF_ERR_UNINITIALIZED);
4801 4788  
4802 4789          if (symkey == NULL || rkey == NULL)
4803 4790                  return (KMF_ERR_BAD_PARAMETER);
4804 4791          else if (symkey->keyclass != KMF_SYMMETRIC)
4805 4792                  return (KMF_ERR_BAD_KEY_CLASS);
4806 4793  
4807 4794          if (symkey->israw) {
4808 4795                  KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
4809 4796  
4810 4797                  if (rawkey == NULL ||
4811 4798                      rawkey->keydata.val == NULL ||
4812 4799                      rawkey->keydata.len == 0)
4813 4800                          return (KMF_ERR_BAD_KEYHANDLE);
4814 4801  
4815 4802                  rkey->keydata.len = rawkey->keydata.len;
4816 4803                  if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
4817 4804                          return (KMF_ERR_MEMORY);
4818 4805                  (void) memcpy(rkey->keydata.val, rawkey->keydata.val,
4819 4806                      rkey->keydata.len);
4820 4807          } else {
4821 4808                  rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
4822 4809                  if (rv != KMF_OK)
4823 4810                          return (rv);
4824 4811                  rkey->keydata.len = keyvalue.Length;
4825 4812                  rkey->keydata.val = keyvalue.Data;
4826 4813          }
4827 4814  
4828 4815          return (rv);
4829 4816  }
4830 4817  
4831 4818  /*
4832 4819   * substitute for the unsafe access(2) function.
4833 4820   * If the file in question already exists, return 1.
4834 4821   * else 0.  If an error occurs during testing (other
4835 4822   * than EEXIST), return -1.
4836 4823   */
4837 4824  static int
4838 4825  test_for_file(char *filename, mode_t mode)
4839 4826  {
4840 4827          int fd;
4841 4828  
4842 4829          /*
4843 4830           * Try to create the file with the EXCL flag.
4844 4831           * The call should fail if the file exists.
4845 4832           */
4846 4833          fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
4847 4834          if (fd == -1 && errno == EEXIST)
4848 4835                  return (1);
4849 4836          else if (fd == -1) /* some other error */
4850 4837                  return (-1);
4851 4838  
4852 4839          /* The file did NOT exist.  Delete the testcase. */
4853 4840          (void) close(fd);
4854 4841          (void) unlink(filename);
4855 4842          return (0);
4856 4843  }
4857 4844  
4858 4845  KMF_RETURN
4859 4846  OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
4860 4847          KMF_ATTRIBUTE *attrlist)
4861 4848  {
4862 4849          KMF_RETURN rv = KMF_OK;
4863 4850          KMF_HANDLE      *kmfh = (KMF_HANDLE *)handle;
4864 4851          KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
4865 4852          KMF_RAW_KEY_DATA *rawkey;
4866 4853          EVP_PKEY *pkey = NULL;
4867 4854          KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
4868 4855          KMF_CREDENTIAL cred = {NULL, 0};
4869 4856          BIO *out = NULL;
4870 4857          int keys = 0;
4871 4858          char *fullpath = NULL;
4872 4859          char *keyfile = NULL;
4873 4860          char *dirpath = NULL;
4874 4861  
4875 4862          pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
4876 4863          if (pubkey != NULL)
4877 4864                  keys++;
4878 4865  
4879 4866          prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
4880 4867          if (prikey != NULL)
4881 4868                  keys++;
4882 4869  
4883 4870          rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
4884 4871          if (rawkey != NULL)
4885 4872                  keys++;
4886 4873  
4887 4874          /*
4888 4875           * Exactly 1 type of key must be passed to this function.
4889 4876           */
4890 4877          if (keys != 1)
4891 4878                  return (KMF_ERR_BAD_PARAMETER);
4892 4879  
4893 4880          keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
4894 4881              numattr);
4895 4882          if (keyfile == NULL)
4896 4883                  return (KMF_ERR_BAD_PARAMETER);
4897 4884  
4898 4885          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4899 4886  
4900 4887          fullpath = get_fullpath(dirpath, keyfile);
4901 4888  
4902 4889          /* Once we have the full path, we don't need the pieces */
4903 4890          if (fullpath == NULL)
4904 4891                  return (KMF_ERR_BAD_PARAMETER);
4905 4892  
4906 4893          /* If the requested file exists, return an error */
4907 4894          if (test_for_file(fullpath, 0400) == 1) {
4908 4895                  free(fullpath);
4909 4896                  return (KMF_ERR_DUPLICATE_KEYFILE);
4910 4897          }
4911 4898  
4912 4899          rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
4913 4900              &format, NULL);
4914 4901          if (rv != KMF_OK)
4915 4902                  /* format is optional. */
4916 4903                  rv = KMF_OK;
4917 4904  
4918 4905          /* CRED is not required for OpenSSL files */
4919 4906          (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
4920 4907              &cred, NULL);
4921 4908  
4922 4909          /* Store the private key to the keyfile */
4923 4910          out = BIO_new_file(fullpath, "wb");
4924 4911          if (out == NULL) {
4925 4912                  SET_ERROR(kmfh, ERR_get_error());
4926 4913                  rv = KMF_ERR_OPEN_FILE;
4927 4914                  goto end;
4928 4915          }
4929 4916  
4930 4917          if (prikey != NULL && prikey->keyp != NULL) {
4931 4918                  if (prikey->keyalg == KMF_RSA ||
4932 4919                      prikey->keyalg == KMF_DSA) {
4933 4920                          pkey = (EVP_PKEY *)prikey->keyp;
4934 4921  
4935 4922                          rv = ssl_write_key(kmfh, format,
4936 4923                              out, &cred, pkey, TRUE);
4937 4924  
4938 4925                          if (rv == KMF_OK && prikey->keylabel == NULL) {
4939 4926                                  prikey->keylabel = strdup(fullpath);
4940 4927                                  if (prikey->keylabel == NULL)
4941 4928                                          rv = KMF_ERR_MEMORY;
4942 4929                          }
4943 4930                  }
4944 4931          } else if (pubkey != NULL && pubkey->keyp != NULL) {
4945 4932                  if (pubkey->keyalg == KMF_RSA ||
4946 4933                      pubkey->keyalg == KMF_DSA) {
4947 4934                          pkey = (EVP_PKEY *)pubkey->keyp;
4948 4935  
4949 4936                          rv = ssl_write_key(kmfh, format,
4950 4937                              out, &cred, pkey, FALSE);
4951 4938  
4952 4939                          if (rv == KMF_OK && pubkey->keylabel == NULL) {
4953 4940                                  pubkey->keylabel = strdup(fullpath);
4954 4941                                  if (pubkey->keylabel == NULL)
4955 4942                                          rv = KMF_ERR_MEMORY;
4956 4943                          }
4957 4944                  }
4958 4945          } else if (rawkey != NULL) {
4959 4946                  if (rawkey->keytype == KMF_RSA) {
4960 4947                          pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
4961 4948                  } else if (rawkey->keytype == KMF_DSA) {
4962 4949                          pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
4963 4950                  } else {
4964 4951                          rv = KMF_ERR_BAD_PARAMETER;
4965 4952                  }
4966 4953                  if (pkey != NULL) {
4967 4954                          KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
4968 4955  
4969 4956                          rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
4970 4957                              (void *)&kclass, NULL);
4971 4958                          if (rv != KMF_OK)
4972 4959                                  rv = KMF_OK;
4973 4960                          rv = ssl_write_key(kmfh, format, out,
4974 4961                              &cred, pkey, (kclass == KMF_ASYM_PRI));
4975 4962                          EVP_PKEY_free(pkey);
4976 4963                  }
4977 4964          }
4978 4965  
4979 4966  end:
4980 4967  
4981 4968          if (out)
4982 4969                  (void) BIO_free(out);
4983 4970  
4984 4971  
4985 4972          if (rv == KMF_OK)
4986 4973                  (void) chmod(fullpath, 0400);
4987 4974  
4988 4975          free(fullpath);
4989 4976          return (rv);
4990 4977  }
4991 4978  
4992 4979  KMF_RETURN
4993 4980  OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
4994 4981  {
4995 4982          KMF_RETURN ret = KMF_OK;
4996 4983          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4997 4984          X509_CRL *xcrl = NULL;
4998 4985          X509 *xcert = NULL;
4999 4986          EVP_PKEY *pkey;
5000 4987          KMF_ENCODE_FORMAT format;
5001 4988          BIO *in = NULL, *out = NULL;
5002 4989          int openssl_ret = 0;
5003 4990          KMF_ENCODE_FORMAT outformat;
5004 4991          boolean_t crlcheck = FALSE;
5005 4992          char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
5006 4993  
5007 4994          if (numattr == 0 || attrlist == NULL) {
5008 4995                  return (KMF_ERR_BAD_PARAMETER);
5009 4996          }
5010 4997  
5011 4998          /* CRL check is optional */
5012 4999          (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
5013 5000              &crlcheck, NULL);
5014 5001  
5015 5002          certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5016 5003          if (crlcheck == B_TRUE && certfile == NULL) {
5017 5004                  return (KMF_ERR_BAD_CERTFILE);
5018 5005          }
5019 5006  
5020 5007          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5021 5008          incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
5022 5009          outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
5023 5010  
5024 5011          crlfile = get_fullpath(dirpath, incrl);
5025 5012  
5026 5013          if (crlfile == NULL)
5027 5014                  return (KMF_ERR_BAD_CRLFILE);
5028 5015  
5029 5016          outcrlfile = get_fullpath(dirpath, outcrl);
5030 5017          if (outcrlfile == NULL)
5031 5018                  return (KMF_ERR_BAD_CRLFILE);
5032 5019  
5033 5020          if (isdir(outcrlfile)) {
5034 5021                  free(outcrlfile);
5035 5022                  return (KMF_ERR_BAD_CRLFILE);
5036 5023          }
5037 5024  
5038 5025          ret = kmf_is_crl_file(handle, crlfile, &format);
5039 5026          if (ret != KMF_OK) {
5040 5027                  free(outcrlfile);
5041 5028                  return (ret);
5042 5029          }
5043 5030  
5044 5031          in = BIO_new_file(crlfile, "rb");
5045 5032          if (in == NULL) {
5046 5033                  SET_ERROR(kmfh, ERR_get_error());
5047 5034                  ret = KMF_ERR_OPEN_FILE;
5048 5035                  goto end;
5049 5036          }
5050 5037  
5051 5038          if (format == KMF_FORMAT_ASN1) {
5052 5039                  xcrl = d2i_X509_CRL_bio(in, NULL);
5053 5040          } else if (format == KMF_FORMAT_PEM) {
5054 5041                  xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5055 5042          }
5056 5043  
5057 5044          if (xcrl == NULL) {
5058 5045                  SET_ERROR(kmfh, ERR_get_error());
5059 5046                  ret = KMF_ERR_BAD_CRLFILE;
5060 5047                  goto end;
5061 5048          }
5062 5049  
5063 5050          /* If bypasscheck is specified, no need to verify. */
5064 5051          if (crlcheck == B_FALSE)
5065 5052                  goto output;
5066 5053  
5067 5054          ret = kmf_is_cert_file(handle, certfile, &format);
5068 5055          if (ret != KMF_OK)
5069 5056                  goto end;
5070 5057  
5071 5058          /* Read in the CA cert file and convert to X509 */
5072 5059          if (BIO_read_filename(in, certfile) <= 0) {
5073 5060                  SET_ERROR(kmfh, ERR_get_error());
5074 5061                  ret = KMF_ERR_OPEN_FILE;
5075 5062                  goto end;
5076 5063          }
5077 5064  
5078 5065          if (format == KMF_FORMAT_ASN1) {
5079 5066                  xcert = d2i_X509_bio(in, NULL);
5080 5067          } else if (format == KMF_FORMAT_PEM) {
5081 5068                  xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5082 5069          } else {
5083 5070                  ret = KMF_ERR_BAD_CERT_FORMAT;
5084 5071                  goto end;
5085 5072          }
5086 5073  
5087 5074          if (xcert == NULL) {
5088 5075                  SET_ERROR(kmfh, ERR_get_error());
5089 5076                  ret = KMF_ERR_BAD_CERT_FORMAT;
5090 5077                  goto end;
5091 5078          }
5092 5079          /* Now get the public key from the CA cert */
5093 5080          pkey = X509_get_pubkey(xcert);
5094 5081          if (pkey == NULL) {
5095 5082                  SET_ERROR(kmfh, ERR_get_error());
5096 5083                  ret = KMF_ERR_BAD_CERTFILE;
5097 5084                  goto end;
5098 5085          }
5099 5086  
5100 5087          /* Verify the CRL with the CA's public key */
5101 5088          openssl_ret = X509_CRL_verify(xcrl, pkey);
5102 5089          EVP_PKEY_free(pkey);
5103 5090          if (openssl_ret > 0) {
5104 5091                  ret = KMF_OK;  /* verify succeed */
5105 5092          } else {
5106 5093                  SET_ERROR(kmfh, openssl_ret);
5107 5094                  ret = KMF_ERR_BAD_CRLFILE;
5108 5095          }
5109 5096  
5110 5097  output:
5111 5098          ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
5112 5099              &outformat, NULL);
5113 5100          if (ret != KMF_OK) {
5114 5101                  ret = KMF_OK;
5115 5102                  outformat = KMF_FORMAT_PEM;
5116 5103          }
5117 5104  
5118 5105          out = BIO_new_file(outcrlfile, "wb");
5119 5106          if (out == NULL) {
5120 5107                  SET_ERROR(kmfh, ERR_get_error());
5121 5108                  ret = KMF_ERR_OPEN_FILE;
5122 5109                  goto end;
5123 5110          }
5124 5111  
5125 5112          if (outformat == KMF_FORMAT_ASN1) {
5126 5113                  openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
5127 5114          } else if (outformat == KMF_FORMAT_PEM) {
5128 5115                  openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
5129 5116          } else {
5130 5117                  ret = KMF_ERR_BAD_PARAMETER;
5131 5118                  goto end;
5132 5119          }
5133 5120  
5134 5121          if (openssl_ret <= 0) {
5135 5122                  SET_ERROR(kmfh, ERR_get_error());
5136 5123                  ret = KMF_ERR_WRITE_FILE;
5137 5124          } else {
5138 5125                  ret = KMF_OK;
5139 5126          }
5140 5127  
5141 5128  end:
5142 5129          if (xcrl != NULL)
5143 5130                  X509_CRL_free(xcrl);
5144 5131  
5145 5132          if (xcert != NULL)
5146 5133                  X509_free(xcert);
5147 5134  
5148 5135          if (in != NULL)
5149 5136                  (void) BIO_free(in);
5150 5137  
5151 5138          if (out != NULL)
5152 5139                  (void) BIO_free(out);
5153 5140  
5154 5141          if (outcrlfile != NULL)
5155 5142                  free(outcrlfile);
5156 5143  
5157 5144          return (ret);
5158 5145  }
5159 5146  
5160 5147  KMF_RETURN
5161 5148  OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5162 5149  {
5163 5150          KMF_RETURN ret = KMF_OK;
5164 5151          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5165 5152          X509_CRL   *x = NULL;
5166 5153          KMF_ENCODE_FORMAT format;
5167 5154          char *crlfile = NULL;
5168 5155          BIO *in = NULL;
5169 5156          BIO *mem = NULL;
5170 5157          long len;
5171 5158          char *memptr;
5172 5159          char *data = NULL;
5173 5160          char **crldata;
5174 5161          char *crlfilename, *dirpath;
5175 5162  
5176 5163          if (numattr == 0 || attrlist == NULL) {
5177 5164                  return (KMF_ERR_BAD_PARAMETER);
5178 5165          }
5179 5166          crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5180 5167              attrlist, numattr);
5181 5168          if (crlfilename == NULL)
5182 5169                  return (KMF_ERR_BAD_CRLFILE);
5183 5170  
5184 5171          crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
5185 5172              attrlist, numattr);
5186 5173  
5187 5174          if (crldata == NULL)
5188 5175                  return (KMF_ERR_BAD_PARAMETER);
5189 5176  
5190 5177          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5191 5178  
5192 5179          crlfile = get_fullpath(dirpath, crlfilename);
5193 5180  
5194 5181          if (crlfile == NULL)
5195 5182                  return (KMF_ERR_BAD_CRLFILE);
5196 5183  
5197 5184          if (isdir(crlfile)) {
5198 5185                  free(crlfile);
5199 5186                  return (KMF_ERR_BAD_CRLFILE);
5200 5187          }
5201 5188  
5202 5189          ret = kmf_is_crl_file(handle, crlfile, &format);
5203 5190          if (ret != KMF_OK) {
5204 5191                  free(crlfile);
5205 5192                  return (ret);
5206 5193          }
5207 5194  
5208 5195          if (bio_err == NULL)
5209 5196                  bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
5210 5197  
5211 5198          in = BIO_new_file(crlfile, "rb");
5212 5199          if (in == NULL) {
5213 5200                  SET_ERROR(kmfh, ERR_get_error());
5214 5201                  ret = KMF_ERR_OPEN_FILE;
5215 5202                  goto end;
5216 5203          }
5217 5204  
5218 5205          if (format == KMF_FORMAT_ASN1) {
5219 5206                  x = d2i_X509_CRL_bio(in, NULL);
5220 5207          } else if (format == KMF_FORMAT_PEM) {
5221 5208                  x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5222 5209          }
5223 5210  
5224 5211          if (x == NULL) { /* should not happen */
5225 5212                  SET_ERROR(kmfh, ERR_get_error());
5226 5213                  ret = KMF_ERR_OPEN_FILE;
5227 5214                  goto end;
5228 5215          }
5229 5216  
5230 5217          mem = BIO_new(BIO_s_mem());
5231 5218          if (mem == NULL) {
5232 5219                  SET_ERROR(kmfh, ERR_get_error());
5233 5220                  ret = KMF_ERR_MEMORY;
5234 5221                  goto end;
5235 5222          }
5236 5223  
5237 5224          (void) X509_CRL_print(mem, x);
5238 5225          len = BIO_get_mem_data(mem, &memptr);
5239 5226          if (len <= 0) {
5240 5227                  SET_ERROR(kmfh, ERR_get_error());
5241 5228                  ret = KMF_ERR_MEMORY;
5242 5229                  goto end;
5243 5230          }
5244 5231  
5245 5232          data = malloc(len + 1);
5246 5233          if (data == NULL) {
5247 5234                  ret = KMF_ERR_MEMORY;
5248 5235                  goto end;
5249 5236          }
5250 5237  
5251 5238          (void) memcpy(data, memptr, len);
5252 5239          data[len] = '\0';
5253 5240          *crldata = data;
5254 5241  
5255 5242  end:
5256 5243          if (x != NULL)
5257 5244                  X509_CRL_free(x);
5258 5245  
5259 5246          if (crlfile != NULL)
5260 5247                  free(crlfile);
5261 5248  
5262 5249          if (in != NULL)
5263 5250                  (void) BIO_free(in);
5264 5251  
5265 5252          if (mem != NULL)
5266 5253                  (void) BIO_free(mem);
5267 5254  
5268 5255          return (ret);
5269 5256  }
5270 5257  
5271 5258  KMF_RETURN
5272 5259  OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5273 5260  {
5274 5261          KMF_RETURN ret = KMF_OK;
5275 5262          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5276 5263          KMF_ENCODE_FORMAT format;
5277 5264          char *crlfile = NULL;
5278 5265          BIO *in = NULL;
5279 5266          char *crlfilename, *dirpath;
5280 5267  
5281 5268          if (numattr == 0 || attrlist == NULL) {
5282 5269                  return (KMF_ERR_BAD_PARAMETER);
5283 5270          }
5284 5271  
5285 5272          crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5286 5273              attrlist, numattr);
5287 5274  
5288 5275          if (crlfilename == NULL)
5289 5276                  return (KMF_ERR_BAD_CRLFILE);
5290 5277  
5291 5278          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5292 5279  
5293 5280          crlfile = get_fullpath(dirpath, crlfilename);
5294 5281  
5295 5282          if (crlfile == NULL)
5296 5283                  return (KMF_ERR_BAD_CRLFILE);
5297 5284  
5298 5285          if (isdir(crlfile)) {
5299 5286                  ret = KMF_ERR_BAD_CRLFILE;
5300 5287                  goto end;
5301 5288          }
5302 5289  
5303 5290          ret = kmf_is_crl_file(handle, crlfile, &format);
5304 5291          if (ret != KMF_OK)
5305 5292                  goto end;
5306 5293  
5307 5294          if (unlink(crlfile) != 0) {
5308 5295                  SET_SYS_ERROR(kmfh, errno);
5309 5296                  ret = KMF_ERR_INTERNAL;
5310 5297                  goto end;
5311 5298          }
5312 5299  
5313 5300  end:
5314 5301          if (in != NULL)
5315 5302                  (void) BIO_free(in);
5316 5303          if (crlfile != NULL)
5317 5304                  free(crlfile);
5318 5305  
5319 5306          return (ret);
5320 5307  }
5321 5308  
5322 5309  KMF_RETURN
5323 5310  OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5324 5311  {
5325 5312          KMF_RETURN ret = KMF_OK;
5326 5313          KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5327 5314          KMF_ENCODE_FORMAT format;
5328 5315          BIO *in = NULL;
5329 5316          X509   *xcert = NULL;
5330 5317          X509_CRL   *xcrl = NULL;
5331 5318          STACK_OF(X509_REVOKED) *revoke_stack = NULL;
5332 5319          X509_REVOKED *revoke;
5333 5320          int i;
5334 5321          char *crlfilename, *crlfile, *dirpath, *certfile;
5335 5322  
5336 5323          if (numattr == 0 || attrlist == NULL) {
5337 5324                  return (KMF_ERR_BAD_PARAMETER);
5338 5325          }
5339 5326  
5340 5327          crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5341 5328              attrlist, numattr);
5342 5329  
5343 5330          if (crlfilename == NULL)
5344 5331                  return (KMF_ERR_BAD_CRLFILE);
5345 5332  
5346 5333          certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5347 5334          if (certfile == NULL)
5348 5335                  return (KMF_ERR_BAD_CRLFILE);
5349 5336  
5350 5337          dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5351 5338  
5352 5339          crlfile = get_fullpath(dirpath, crlfilename);
5353 5340  
5354 5341          if (crlfile == NULL)
5355 5342                  return (KMF_ERR_BAD_CRLFILE);
5356 5343  
5357 5344          if (isdir(crlfile)) {
5358 5345                  ret = KMF_ERR_BAD_CRLFILE;
5359 5346                  goto end;
5360 5347          }
5361 5348  
5362 5349          ret = kmf_is_crl_file(handle, crlfile, &format);
5363 5350          if (ret != KMF_OK)
5364 5351                  goto end;
5365 5352  
5366 5353          /* Read the CRL file and load it into a X509_CRL structure */
5367 5354          in = BIO_new_file(crlfilename, "rb");
5368 5355          if (in == NULL) {
5369 5356                  SET_ERROR(kmfh, ERR_get_error());
5370 5357                  ret = KMF_ERR_OPEN_FILE;
5371 5358                  goto end;
5372 5359          }
5373 5360  
5374 5361          if (format == KMF_FORMAT_ASN1) {
5375 5362                  xcrl = d2i_X509_CRL_bio(in, NULL);
5376 5363          } else if (format == KMF_FORMAT_PEM) {
5377 5364                  xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5378 5365          }
5379 5366  
5380 5367          if (xcrl == NULL) {
5381 5368                  SET_ERROR(kmfh, ERR_get_error());
5382 5369                  ret = KMF_ERR_BAD_CRLFILE;
5383 5370                  goto end;
5384 5371          }
5385 5372          (void) BIO_free(in);
5386 5373  
5387 5374          /* Read the Certificate file and load it into a X509 structure */
5388 5375          ret = kmf_is_cert_file(handle, certfile, &format);
5389 5376          if (ret != KMF_OK)
5390 5377                  goto end;
5391 5378  
5392 5379          in = BIO_new_file(certfile, "rb");
5393 5380          if (in == NULL) {
5394 5381                  SET_ERROR(kmfh, ERR_get_error());
5395 5382                  ret = KMF_ERR_OPEN_FILE;
5396 5383                  goto end;
5397 5384          }
5398 5385  
5399 5386          if (format == KMF_FORMAT_ASN1) {
5400 5387                  xcert = d2i_X509_bio(in, NULL);
5401 5388          } else if (format == KMF_FORMAT_PEM) {
5402 5389                  xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5403 5390          }
5404 5391  
5405 5392          if (xcert == NULL) {
5406 5393                  SET_ERROR(kmfh, ERR_get_error());
5407 5394                  ret = KMF_ERR_BAD_CERTFILE;
5408 5395                  goto end;
5409 5396          }
5410 5397  
5411 5398          /* Check if the certificate and the CRL have same issuer */
5412 5399          if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
5413 5400                  ret = KMF_ERR_ISSUER;
5414 5401                  goto end;
5415 5402          }
5416 5403  
  
    | ↓ open down ↓ | 1046 lines elided | ↑ open up ↑ | 
5417 5404          /* Check to see if the certificate serial number is revoked */
5418 5405          revoke_stack = X509_CRL_get_REVOKED(xcrl);
5419 5406          if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
5420 5407                  /* No revoked certificates in the CRL file */
5421 5408                  SET_ERROR(kmfh, ERR_get_error());
5422 5409                  ret = KMF_ERR_EMPTY_CRL;
5423 5410                  goto end;
5424 5411          }
5425 5412  
5426 5413          for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5427      -                /* LINTED E_BAD_PTR_CAST_ALIGN */
5428 5414                  revoke = sk_X509_REVOKED_value(revoke_stack, i);
5429 5415                  if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
5430 5416                      revoke->serialNumber) == 0) {
5431 5417                          break;
5432 5418                  }
5433 5419          }
5434 5420  
5435 5421          if (i < sk_X509_REVOKED_num(revoke_stack)) {
5436 5422                  ret = KMF_OK;
5437 5423          } else {
5438 5424                  ret = KMF_ERR_NOT_REVOKED;
5439 5425          }
5440 5426  
5441 5427  end:
5442 5428          if (in != NULL)
5443 5429                  (void) BIO_free(in);
5444 5430          if (xcrl != NULL)
5445 5431                  X509_CRL_free(xcrl);
5446 5432          if (xcert != NULL)
5447 5433                  X509_free(xcert);
5448 5434  
5449 5435          return (ret);
5450 5436  }
5451 5437  
5452 5438  KMF_RETURN
5453 5439  OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
5454 5440  {
5455 5441          KMF_RETURN      ret = KMF_OK;
5456 5442          KMF_HANDLE      *kmfh = (KMF_HANDLE *)handle;
5457 5443          BIO             *bcrl = NULL;
5458 5444          X509_CRL        *xcrl = NULL;
5459 5445          X509            *xcert = NULL;
5460 5446          EVP_PKEY        *pkey;
5461 5447          int             sslret;
5462 5448          KMF_ENCODE_FORMAT crl_format;
5463 5449          unsigned char   *p;
5464 5450          long            len;
5465 5451  
5466 5452          if (handle == NULL || crlname == NULL || tacert == NULL) {
5467 5453                  return (KMF_ERR_BAD_PARAMETER);
5468 5454          }
5469 5455  
5470 5456          ret = kmf_get_file_format(crlname, &crl_format);
5471 5457          if (ret != KMF_OK)
5472 5458                  return (ret);
5473 5459  
5474 5460          bcrl = BIO_new_file(crlname, "rb");
5475 5461          if (bcrl == NULL)       {
5476 5462                  SET_ERROR(kmfh, ERR_get_error());
5477 5463                  ret = KMF_ERR_OPEN_FILE;
5478 5464                  goto cleanup;
5479 5465          }
5480 5466  
5481 5467          if (crl_format == KMF_FORMAT_ASN1) {
5482 5468                  xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5483 5469          } else if (crl_format == KMF_FORMAT_PEM) {
5484 5470                  xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5485 5471          } else {
5486 5472                  ret = KMF_ERR_BAD_PARAMETER;
5487 5473                  goto cleanup;
5488 5474          }
5489 5475  
5490 5476          if (xcrl == NULL) {
5491 5477                  SET_ERROR(kmfh, ERR_get_error());
5492 5478                  ret = KMF_ERR_BAD_CRLFILE;
5493 5479                  goto cleanup;
5494 5480          }
5495 5481  
5496 5482          p = tacert->Data;
5497 5483          len = tacert->Length;
5498 5484          xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
5499 5485  
5500 5486          if (xcert == NULL) {
5501 5487                  SET_ERROR(kmfh, ERR_get_error());
5502 5488                  ret = KMF_ERR_BAD_CERTFILE;
5503 5489                  goto cleanup;
5504 5490          }
5505 5491  
5506 5492          /* Get issuer certificate public key */
5507 5493          pkey = X509_get_pubkey(xcert);
5508 5494          if (pkey == NULL) {
5509 5495                  SET_ERROR(kmfh, ERR_get_error());
5510 5496                  ret = KMF_ERR_BAD_CERT_FORMAT;
5511 5497                  goto cleanup;
5512 5498          }
5513 5499  
5514 5500          /* Verify CRL signature */
5515 5501          sslret = X509_CRL_verify(xcrl, pkey);
5516 5502          EVP_PKEY_free(pkey);
5517 5503          if (sslret > 0) {
5518 5504                  ret = KMF_OK;
5519 5505          } else {
5520 5506                  SET_ERROR(kmfh, sslret);
5521 5507                  ret = KMF_ERR_BAD_CRLFILE;
5522 5508          }
5523 5509  
5524 5510  cleanup:
5525 5511          if (bcrl != NULL)
5526 5512                  (void) BIO_free(bcrl);
5527 5513  
5528 5514          if (xcrl != NULL)
5529 5515                  X509_CRL_free(xcrl);
5530 5516  
5531 5517          if (xcert != NULL)
5532 5518                  X509_free(xcert);
5533 5519  
5534 5520          return (ret);
5535 5521  
5536 5522  }
5537 5523  
5538 5524  KMF_RETURN
5539 5525  OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
5540 5526  {
5541 5527          KMF_RETURN      ret = KMF_OK;
5542 5528          KMF_HANDLE      *kmfh = (KMF_HANDLE *)handle;
5543 5529          KMF_ENCODE_FORMAT crl_format;
5544 5530          BIO             *bcrl = NULL;
5545 5531          X509_CRL        *xcrl = NULL;
5546 5532          int             i;
5547 5533  
5548 5534          if (handle == NULL || crlname == NULL) {
5549 5535                  return (KMF_ERR_BAD_PARAMETER);
5550 5536          }
5551 5537  
5552 5538          ret = kmf_is_crl_file(handle, crlname, &crl_format);
5553 5539          if (ret != KMF_OK)
5554 5540                  return (ret);
5555 5541  
5556 5542          bcrl = BIO_new_file(crlname, "rb");
5557 5543          if (bcrl == NULL) {
5558 5544                  SET_ERROR(kmfh, ERR_get_error());
5559 5545                  ret = KMF_ERR_OPEN_FILE;
5560 5546                  goto cleanup;
5561 5547          }
5562 5548  
5563 5549          if (crl_format == KMF_FORMAT_ASN1)
5564 5550                  xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5565 5551          else if (crl_format == KMF_FORMAT_PEM)
5566 5552                  xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5567 5553  
5568 5554          if (xcrl == NULL) {
5569 5555                  SET_ERROR(kmfh, ERR_get_error());
5570 5556                  ret = KMF_ERR_BAD_CRLFILE;
5571 5557                  goto cleanup;
5572 5558          }
5573 5559          i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
5574 5560          if (i >= 0) {
5575 5561                  ret = KMF_ERR_VALIDITY_PERIOD;
5576 5562                  goto cleanup;
5577 5563          }
5578 5564          if (X509_CRL_get_nextUpdate(xcrl)) {
5579 5565                  i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
5580 5566  
5581 5567                  if (i <= 0) {
5582 5568                          ret = KMF_ERR_VALIDITY_PERIOD;
5583 5569                          goto cleanup;
5584 5570                  }
5585 5571          }
5586 5572  
5587 5573          ret = KMF_OK;
5588 5574  
5589 5575  cleanup:
5590 5576          if (bcrl != NULL)
5591 5577                  (void) BIO_free(bcrl);
5592 5578  
5593 5579          if (xcrl != NULL)
5594 5580                  X509_CRL_free(xcrl);
5595 5581  
5596 5582          return (ret);
5597 5583  }
  
    | ↓ open down ↓ | 160 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX