1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  *
  26  * Copyright 2017 Jason King.
  27  * Copyright (c) 2017, Joyent, Inc.
  28  */
  29 
  30 #include <syslog.h>
  31 #include <assert.h>
  32 #include <string.h>
  33 #include <ipsec_util.h>
  34 #include <locale.h>
  35 #include <security/cryptoki.h>
  36 #include <pthread.h>
  37 #include <sys/debug.h>
  38 #include <note.h>
  39 #include "pkcs11.h"
  40 #include "defs.h"
  41 
  42 /*
  43  * per usr/src/lib/pkcs11/libpkcs11/common/metaGlobal.h, the metaslot
  44  * is always slot 0
  45  */
  46 #define METASLOT_ID     (0)
  47 
  48 CK_INFO                 pkcs11_info = { 0 };
  49 CK_SESSION_HANDLE       p11h = CK_INVALID_HANDLE;
  50 
  51 #define PKCS11_FUNC             "func"
  52 #define PKCS11_RC               "errnum"
  53 #define PKCS11_ERRMSG           "err"
  54 
  55 static void fmtstr(char *, size_t, CK_UTF8CHAR *, size_t);
  56 static CK_RV pkcs11_callback_handler(CK_SESSION_HANDLE, CK_NOTIFICATION,
  57     void *);
  58 static void log_slotinfo(CK_SLOT_ID);
  59 
  60 /*
  61  * Locates the metaslot among the available slots.  If the metaslot
  62  * is inable to be located, we terminate.
  63  */
  64 void
  65 pkcs11_init(void)
  66 {
  67         CK_RV                   rv = CKR_OK;
  68         CK_ULONG                nslot = 0;
  69         CK_C_INITIALIZE_ARGS    args = {
  70                 NULL_PTR,               /* CreateMutex */
  71                 NULL_PTR,               /* DestroyMutex */
  72                 NULL_PTR,               /* LockMutex */
  73                 NULL_PTR,               /* UnlockMutex */
  74                 CKF_OS_LOCKING_OK,      /* flags */
  75                 NULL_PTR                /* reserved */
  76         };
  77 
  78         if ((rv = C_Initialize(&args)) != CKR_OK) {
  79                 PKCS11ERR(fatal, log, "C_Initialize", rv);
  80                 exit(1);
  81         }
  82 
  83         if ((rv = C_GetInfo(&pkcs11_info)) != CKR_OK) {
  84                 PKCS11ERR(fatal, log, "C_Info", rv);
  85                 exit(1);
  86         }
  87 
  88         if ((rv = C_GetSlotList(CK_FALSE, NULL, &nslot)) != CKR_OK) {
  89                 PKCS11ERR(fatal, log, "C_GetSlotList", rv);
  90                 exit(1);
  91         }
  92 
  93         CK_SLOT_ID slots[nslot];
  94 
  95         if ((rv = C_GetSlotList(CK_FALSE, slots, &nslot)) != CKR_OK) {
  96                 PKCS11ERR(fatal, log, "C_GetSlotList", rv);
  97                 exit(1);
  98         }
  99 
 100         {
 101                 char manf[33];
 102                 char libdesc[33];
 103 
 104                 fmtstr(manf, sizeof (manf), pkcs11_info.manufacturerID,
 105                     sizeof (pkcs11_info.manufacturerID));
 106                 fmtstr(libdesc, sizeof (libdesc),
 107                     pkcs11_info.libraryDescription,
 108                     sizeof (pkcs11_info.libraryDescription));
 109 
 110                 (void) bunyan_debug(log, "PKCS#11 provider info",
 111                     BUNYAN_T_STRING, "manufacturer", manf,
 112                     BUNYAN_T_UINT32, "version.major",
 113                     (uint32_t)pkcs11_info.cryptokiVersion.major,
 114                     BUNYAN_T_UINT32, "version.minor",
 115                     (uint32_t)pkcs11_info.cryptokiVersion.minor,
 116                     BUNYAN_T_UINT64, "flags",
 117                     (uint64_t)pkcs11_info.flags,
 118                     BUNYAN_T_STRING, "library", libdesc,
 119                     BUNYAN_T_UINT32, "lib.major",
 120                     (uint32_t)pkcs11_info.libraryVersion.major,
 121                     BUNYAN_T_UINT32, "lib.minor",
 122                     (uint32_t)pkcs11_info.libraryVersion.minor,
 123                     BUNYAN_T_UINT32, "numslots", nslot,
 124                     BUNYAN_T_END);
 125         }
 126 
 127         for (size_t i = 0; i < nslot; i++)
 128                 log_slotinfo(slots[i]);
 129 
 130         rv = C_OpenSession(METASLOT_ID, CKF_SERIAL_SESSION, NULL,
 131             pkcs11_callback_handler, &p11h);
 132         if (rv != CKR_OK) {
 133                 PKCS11ERR(fatal, log, "C_OpenSession", rv);
 134                 exit(1);
 135         }
 136 
 137         (void) bunyan_trace(log, "PKCS#11 session opened",
 138             BUNYAN_T_UINT64, "pkcs11 handle", (uint64_t)p11h,
 139             BUNYAN_T_END);
 140 }
 141 
 142 static void
 143 log_slotinfo(CK_SLOT_ID slot)
 144 {
 145         CK_SLOT_INFO info = { 0 };
 146         char manuf[33]; /* sizeof info.manufacturerID NUL */
 147         CK_RV rv;
 148 
 149         rv = C_GetSlotInfo(slot, &info);
 150         if (rv != CKR_OK) {
 151                 PKCS11ERR(error, log, "C_GetSlotInfo", rv);
 152                 return;
 153         }
 154 
 155         {
 156                 char desc[65];  /* sizeof info.description + NUL */
 157                 fmtstr(desc, sizeof (desc), info.slotDescription,
 158                     sizeof (info.slotDescription));
 159                 fmtstr(manuf, sizeof (manuf), info.manufacturerID,
 160                     sizeof (info.manufacturerID));
 161 
 162                 (void) bunyan_debug(log, "PKCS#11 slot Info",
 163                     BUNYAN_T_UINT64, "slot", (uint64_t)slot,
 164                     BUNYAN_T_STRING, "desc", desc,
 165                     BUNYAN_T_STRING, "manufacturer", manuf,
 166                     BUNYAN_T_UINT32, "hwversion.major",
 167                     (uint32_t)info.hardwareVersion.major,
 168                     BUNYAN_T_UINT32, "hwversion.minor",
 169                     (uint32_t)info.hardwareVersion.minor,
 170                     BUNYAN_T_UINT32, "fwversion.major",
 171                     (uint32_t)info.firmwareVersion.major,
 172                     BUNYAN_T_UINT32, "fwversion.minor",
 173                     (uint32_t)info.firmwareVersion.minor,
 174                     BUNYAN_T_UINT64, "flags", (uint64_t)info.flags,
 175                     BUNYAN_T_BOOLEAN, "present",
 176                     !!(info.flags & CKF_TOKEN_PRESENT),
 177                     BUNYAN_T_BOOLEAN, "removable",
 178                     !!(info.flags & CKF_REMOVABLE_DEVICE),
 179                     BUNYAN_T_BOOLEAN, "hwslot", !!(info.flags & CKF_HW_SLOT),
 180                     BUNYAN_T_END);
 181         }
 182 
 183         if (!(info.flags & CKF_TOKEN_PRESENT))
 184                 return;
 185 
 186         CK_TOKEN_INFO tinfo = { 0 };
 187         rv = C_GetTokenInfo(slot, &tinfo);
 188         if (rv != CKR_OK)
 189                 PKCS11ERR(error, log, "C_GetTokenInfo", rv);
 190 
 191         char label[33];         /* sizeof tinfo.label + NUL */
 192         char model[17];         /* sizeof tinfo.model + NUL */
 193         char serial[17];        /* sizeof tinfo.serialNumber + NUL */
 194         char utctime[17];       /* sizeof tinfo.utsTime + NUL */
 195 
 196         fmtstr(manuf, sizeof (manuf), tinfo.manufacturerID,
 197             sizeof (tinfo.manufacturerID));
 198         fmtstr(label, sizeof (label), tinfo.label, sizeof (tinfo.label));
 199         fmtstr(model, sizeof (model), tinfo.model, sizeof (tinfo.model));
 200         fmtstr(serial, sizeof (serial), tinfo.serialNumber,
 201             sizeof (tinfo.serialNumber));
 202         fmtstr(utctime, sizeof (utctime), tinfo.utcTime,
 203             sizeof (tinfo.utcTime));
 204 
 205 #define F(_inf, _flg) BUNYAN_T_BOOLEAN, #_flg, !!((_inf).flags & (_flg))
 206 
 207         (void) bunyan_debug(log, "PKCS#11 token info",
 208             BUNYAN_T_UINT32, "slot", (uint32_t)slot,
 209             BUNYAN_T_STRING, "label", label,
 210             BUNYAN_T_STRING, "manuf", manuf,
 211             BUNYAN_T_STRING, "model", model,
 212             BUNYAN_T_STRING, "serial", serial,
 213             BUNYAN_T_UINT64, "flags", (uint64_t)tinfo.flags,
 214             F(info, CKF_RNG),
 215             F(info, CKF_WRITE_PROTECTED),
 216             F(info, CKF_LOGIN_REQUIRED),
 217             F(info, CKF_USER_PIN_INITIALIZED),
 218             F(info, CKF_RESTORE_KEY_NOT_NEEDED),
 219             F(info, CKF_CLOCK_ON_TOKEN),
 220             F(info, CKF_PROTECTED_AUTHENTICATION_PATH),
 221             F(info, CKF_DUAL_CRYPTO_OPERATIONS),
 222             F(info, CKF_TOKEN_INITIALIZED),
 223             F(info, CKF_SECONDARY_AUTHENTICATION),
 224             F(info, CKF_USER_PIN_COUNT_LOW),
 225             F(info, CKF_USER_PIN_FINAL_TRY),
 226             F(info, CKF_USER_PIN_LOCKED),
 227             F(info, CKF_USER_PIN_TO_BE_CHANGED),
 228             F(info, CKF_SO_PIN_COUNT_LOW),
 229             F(info, CKF_SO_PIN_FINAL_TRY),
 230             F(info, CKF_SO_PIN_LOCKED),
 231             F(info, CKF_SO_PIN_TO_BE_CHANGED),
 232             F(info, CKF_ERROR_STATE),
 233             BUNYAN_T_END);
 234 #undef F
 235 }
 236 
 237 void
 238 pkcs11_fini(void)
 239 {
 240         CK_RV rv;
 241 
 242         rv = C_CloseSession(p11h);
 243         if (rv != CKR_OK)
 244                 PKCS11ERR(error, log, "C_CloseSession", rv);
 245 
 246         rv = C_Finalize(NULL_PTR);
 247         if (rv != CKR_OK)
 248                 PKCS11ERR(error, log, "C_Finalize", rv);
 249 }
 250 
 251 /*
 252  * We explicitly avoid using the default: case in these switch statements
 253  * so that the addition of new IKEv2 encryption algs will cause compilation
 254  * errors if they are not added to these functions.
 255  */
 256 CK_MECHANISM_TYPE
 257 ikev2_encr_to_p11(ikev2_xf_encr_t encr)
 258 {
 259         switch (encr) {
 260         case IKEV2_ENCR_NONE:
 261         case IKEV2_ENCR_NULL_AES_GMAC:
 262         case IKEV2_ENCR_NULL:
 263         case IKEV2_ENCR_3IDEA:
 264         case IKEV2_ENCR_XTS_AES:
 265                 INVALID("encr");
 266                 /*NOTREACHED*/
 267                 return (0);
 268         case IKEV2_ENCR_DES_IV64:
 269         case IKEV2_ENCR_DES:
 270         case IKEV2_ENCR_DES_IV32:
 271                 return (CKM_DES_CBC);
 272         case IKEV2_ENCR_3DES:
 273                 return (CKM_DES3_CBC);
 274         case IKEV2_ENCR_RC5:
 275                 return (CKM_RC5_CBC);
 276         case IKEV2_ENCR_IDEA:
 277                 return (CKM_IDEA_CBC);
 278         case IKEV2_ENCR_CAST:
 279                 return (CKM_CAST5_CBC);
 280         case IKEV2_ENCR_BLOWFISH:
 281                 return (CKM_BLOWFISH_CBC);
 282         case IKEV2_ENCR_RC4:
 283                 return (CKM_RC4);
 284         case IKEV2_ENCR_AES_CBC:
 285                 return (CKM_AES_CBC);
 286         case IKEV2_ENCR_AES_CTR:
 287                 return (CKM_AES_CTR);
 288         case IKEV2_ENCR_AES_CCM_8:
 289         case IKEV2_ENCR_AES_CCM_12:
 290         case IKEV2_ENCR_AES_CCM_16:
 291                 return (CKM_AES_CCM);
 292         case IKEV2_ENCR_AES_GCM_8:
 293         case IKEV2_ENCR_AES_GCM_12:
 294         case IKEV2_ENCR_AES_GCM_16:
 295                 return (CKM_AES_GCM);
 296         case IKEV2_ENCR_CAMELLIA_CBC:
 297                 return (CKM_CAMELLIA_CBC);
 298         case IKEV2_ENCR_CAMELLIA_CTR:
 299                 return (CKM_CAMELLIA_CTR);
 300         case IKEV2_ENCR_CAMELLIA_CCM_8:
 301         case IKEV2_ENCR_CAMELLIA_CCM_12:
 302         case IKEV2_ENCR_CAMELLIA_CCM_16:
 303                 return (CKM_CAMELLIA_CBC);
 304         }
 305         /*NOTREACHED*/
 306         return (0);
 307 }
 308 
 309 size_t
 310 ikev2_encr_block_size(ikev2_xf_encr_t encr)
 311 {
 312         switch (encr) {
 313         case IKEV2_ENCR_NONE:
 314         case IKEV2_ENCR_NULL:
 315         case IKEV2_ENCR_NULL_AES_GMAC:
 316                 return (0);
 317         case IKEV2_ENCR_DES_IV64:
 318         case IKEV2_ENCR_DES:
 319         case IKEV2_ENCR_DES_IV32:
 320         case IKEV2_ENCR_3DES:
 321         case IKEV2_ENCR_RC5:
 322         case IKEV2_ENCR_RC4:
 323         case IKEV2_ENCR_IDEA:
 324         case IKEV2_ENCR_CAST:
 325         case IKEV2_ENCR_BLOWFISH:
 326         case IKEV2_ENCR_3IDEA:
 327                 return (8);
 328         case IKEV2_ENCR_AES_CBC:
 329         case IKEV2_ENCR_AES_CTR:
 330         case IKEV2_ENCR_XTS_AES:
 331         case IKEV2_ENCR_AES_CCM_8:
 332         case IKEV2_ENCR_AES_CCM_12:
 333         case IKEV2_ENCR_AES_CCM_16:
 334         case IKEV2_ENCR_AES_GCM_8:
 335         case IKEV2_ENCR_AES_GCM_12:
 336         case IKEV2_ENCR_AES_GCM_16:
 337         case IKEV2_ENCR_CAMELLIA_CBC:
 338         case IKEV2_ENCR_CAMELLIA_CTR:
 339         case IKEV2_ENCR_CAMELLIA_CCM_8:
 340         case IKEV2_ENCR_CAMELLIA_CCM_12:
 341         case IKEV2_ENCR_CAMELLIA_CCM_16:
 342                 return (16);
 343         }
 344         /*NOTREACHED*/
 345         return (0);
 346 }
 347 
 348 size_t
 349 ikev2_encr_iv_size(ikev2_xf_encr_t encr)
 350 {
 351         switch (encr) {
 352         case IKEV2_ENCR_NONE:
 353         case IKEV2_ENCR_NULL:
 354                 return (0);
 355         case IKEV2_ENCR_DES_IV32:
 356                 return (4);
 357         case IKEV2_ENCR_DES_IV64:
 358                 return (8);
 359         default:
 360                 return (ikev2_encr_block_size(encr));
 361         }
 362 }
 363 
 364 encr_modes_t
 365 ikev2_encr_mode(ikev2_xf_encr_t encr)
 366 {
 367         switch (encr) {
 368         case IKEV2_ENCR_NONE:
 369         case IKEV2_ENCR_NULL:
 370         case IKEV2_ENCR_NULL_AES_GMAC:
 371         case IKEV2_ENCR_XTS_AES:
 372                 return (MODE_NONE);
 373         case IKEV2_ENCR_DES_IV64:
 374         case IKEV2_ENCR_DES:
 375         case IKEV2_ENCR_DES_IV32:
 376         case IKEV2_ENCR_3DES:
 377         case IKEV2_ENCR_RC5:
 378         case IKEV2_ENCR_RC4:
 379         case IKEV2_ENCR_IDEA:
 380         case IKEV2_ENCR_CAST:
 381         case IKEV2_ENCR_BLOWFISH:
 382         case IKEV2_ENCR_3IDEA:
 383         case IKEV2_ENCR_AES_CBC:
 384         case IKEV2_ENCR_CAMELLIA_CBC:
 385                 return (MODE_CBC);
 386         case IKEV2_ENCR_AES_CTR:
 387         case IKEV2_ENCR_CAMELLIA_CTR:
 388                 return (MODE_CTR);
 389         case IKEV2_ENCR_AES_CCM_8:
 390         case IKEV2_ENCR_AES_CCM_12:
 391         case IKEV2_ENCR_AES_CCM_16:
 392         case IKEV2_ENCR_CAMELLIA_CCM_8:
 393         case IKEV2_ENCR_CAMELLIA_CCM_12:
 394         case IKEV2_ENCR_CAMELLIA_CCM_16:
 395                 return (MODE_CCM);
 396         case IKEV2_ENCR_AES_GCM_8:
 397         case IKEV2_ENCR_AES_GCM_12:
 398         case IKEV2_ENCR_AES_GCM_16:
 399                 return (MODE_GCM);
 400         }
 401         /*NOTREACHED*/
 402         return (MODE_NONE);
 403 }
 404 
 405 CK_MECHANISM_TYPE
 406 ikev2_auth_to_p11(ikev2_xf_auth_t auth)
 407 {
 408         switch (auth) {
 409         case IKEV2_XF_AUTH_NONE:
 410                 return (0);
 411         case IKEV2_XF_AUTH_HMAC_MD5_96:
 412                 return (CKM_MD5_HMAC);
 413         case IKEV2_XF_AUTH_HMAC_SHA1_96:
 414                 return (CKM_SHA_1_HMAC);
 415         case IKEV2_XF_AUTH_DES_MAC:
 416                 return (CKM_DES_MAC);
 417         case IKEV2_XF_AUTH_KPDK_MD5:
 418                 return (CKM_MD5_HMAC);  /* XXX: verify */
 419         case IKEV2_XF_AUTH_AES_XCBC_96:
 420                 return (CKM_AES_XCBC_MAC_96);
 421         case IKEV2_XF_AUTH_HMAC_MD5_128:
 422                 return (CKM_MD5_HMAC);
 423         case IKEV2_XF_AUTH_HMAC_SHA1_160:
 424                 return (CKM_SHA_1_HMAC);
 425         case IKEV2_XF_AUTH_AES_CMAC_96:
 426                 return (CKM_AES_CMAC);
 427         case IKEV2_XF_AUTH_AES_128_GMAC:
 428         case IKEV2_XF_AUTH_AES_192_GMAC:
 429         case IKEV2_XF_AUTH_AES_256_GMAC:
 430                 return (CKM_AES_GMAC);
 431         case IKEV2_XF_AUTH_HMAC_SHA2_256_128:
 432                 return (CKM_SHA256_HMAC);
 433         case IKEV2_XF_AUTH_HMAC_SHA2_384_192:
 434                 return (CKM_SHA384_HMAC);
 435         case IKEV2_XF_AUTH_HMAC_SHA2_512_256:
 436                 return (CKM_SHA512_HMAC);
 437         }
 438 
 439         /*NOTREACHED*/
 440         return (0);
 441 }
 442 
 443 size_t
 444 ikev2_auth_icv_size(ikev2_xf_encr_t encr, ikev2_xf_auth_t auth)
 445 {
 446         switch (encr) {
 447         case IKEV2_ENCR_NONE:
 448         case IKEV2_ENCR_NULL:
 449         case IKEV2_ENCR_NULL_AES_GMAC:
 450         case IKEV2_ENCR_DES_IV64:
 451         case IKEV2_ENCR_DES:
 452         case IKEV2_ENCR_DES_IV32:
 453         case IKEV2_ENCR_3DES:
 454         case IKEV2_ENCR_RC5:
 455         case IKEV2_ENCR_RC4:
 456         case IKEV2_ENCR_IDEA:
 457         case IKEV2_ENCR_CAST:
 458         case IKEV2_ENCR_BLOWFISH:
 459         case IKEV2_ENCR_3IDEA:
 460         case IKEV2_ENCR_AES_CBC:
 461         case IKEV2_ENCR_AES_CTR:
 462         case IKEV2_ENCR_XTS_AES:
 463         case IKEV2_ENCR_CAMELLIA_CBC:
 464         case IKEV2_ENCR_CAMELLIA_CTR:
 465                 break;
 466         case IKEV2_ENCR_AES_CCM_8:
 467         case IKEV2_ENCR_AES_GCM_8:
 468         case IKEV2_ENCR_CAMELLIA_CCM_8:
 469                 ASSERT3S(auth, ==, IKEV2_XF_AUTH_NONE);
 470                 return (8);
 471         case IKEV2_ENCR_AES_CCM_12:
 472         case IKEV2_ENCR_AES_GCM_12:
 473         case IKEV2_ENCR_CAMELLIA_CCM_12:
 474                 ASSERT3S(auth, ==, IKEV2_XF_AUTH_NONE);
 475                 return (12);
 476         case IKEV2_ENCR_AES_CCM_16:
 477         case IKEV2_ENCR_AES_GCM_16:
 478         case IKEV2_ENCR_CAMELLIA_CCM_16:
 479                 ASSERT3S(auth, ==, IKEV2_XF_AUTH_NONE);
 480                 return (16);
 481         }
 482 
 483         switch (auth) {
 484         case IKEV2_XF_AUTH_NONE:
 485                 return (0);
 486         case IKEV2_XF_AUTH_HMAC_MD5_96:
 487         case IKEV2_XF_AUTH_HMAC_SHA1_96:
 488         case IKEV2_XF_AUTH_AES_XCBC_96:
 489         case IKEV2_XF_AUTH_AES_CMAC_96:
 490                 return (12);
 491         case IKEV2_XF_AUTH_DES_MAC:     /* a guess */
 492         case IKEV2_XF_AUTH_KPDK_MD5:
 493         case IKEV2_XF_AUTH_HMAC_MD5_128:
 494         case IKEV2_XF_AUTH_AES_128_GMAC:
 495         case IKEV2_XF_AUTH_HMAC_SHA2_256_128:
 496                 return (16);
 497         case IKEV2_XF_AUTH_HMAC_SHA1_160:
 498                 return (20);
 499         case IKEV2_XF_AUTH_AES_192_GMAC:
 500         case IKEV2_XF_AUTH_HMAC_SHA2_384_192:
 501                 return (24);
 502         case IKEV2_XF_AUTH_AES_256_GMAC:
 503         case IKEV2_XF_AUTH_HMAC_SHA2_512_256:
 504                 return (32);
 505         }
 506         /*NOTREACHED*/
 507         return (0);
 508 }
 509 
 510 /*
 511  * Destroy a PKCS#11 object with nicer error messages in case of failure.
 512  */
 513 void
 514 pkcs11_destroy_obj(const char *name, CK_OBJECT_HANDLE_PTR objp,
 515     bunyan_logger_t *l)
 516 {
 517         CK_RV ret;
 518 
 519         if (objp == NULL || *objp == CK_INVALID_HANDLE)
 520                 return;
 521 
 522         if ((ret = C_DestroyObject(p11h, *objp)) != CKR_OK) {
 523                 PKCS11ERR(error, (l == NULL) ? log : l, "C_DestroyObject", ret);
 524         } else {
 525                 *objp = CK_INVALID_HANDLE;
 526         }
 527 }
 528 
 529 /*
 530  * Scatter/gather digest calculation.  Upon failure, B_FALSE is returned.
 531  */
 532 boolean_t
 533 pkcs11_digest(CK_MECHANISM_TYPE alg, const buf_t *restrict in, size_t n,
 534     buf_t *restrict out, bunyan_logger_t *l)
 535 {
 536         CK_MECHANISM    mech;
 537         CK_RV           ret;
 538 
 539         mech.mechanism = alg;
 540         mech.pParameter = NULL_PTR;
 541         mech.ulParameterLen = 0;
 542 
 543         if ((ret = C_DigestInit(p11h, &mech)) != CKR_OK) {
 544                 PKCS11ERR(error, l, "C_DigestInit", ret);
 545                 return (B_FALSE);
 546         }
 547 
 548         for (size_t i = 0; i < n; i++) {
 549                 ret = C_DigestUpdate(p11h, in[i].b_ptr, buf_left(&in[i]));
 550                 if (ret != CKR_OK) {
 551                         PKCS11ERR(error, l, "C_DigestUpdate", ret);
 552                         return (B_FALSE);
 553                 }
 554         }
 555 
 556         CK_ULONG len = out->b_len;
 557 
 558         ret = C_DigestFinal(p11h, out->b_ptr, &len);
 559         if (ret != CKR_OK) {
 560                 PKCS11ERR(error, l, "C_DigestFinal", ret);
 561                 return (B_FALSE);
 562         }
 563 
 564         if (len > buf_left(out)) {
 565                 bunyan_error(l, "Output buffer for C_Digest was too small",
 566                     BUNYAN_T_STRING, "func", __func__,
 567                     BUNYAN_T_STRING, "file", __FILE__,
 568                     BUNYAN_T_INT32, "line", __LINE__,
 569                     BUNYAN_T_UINT32, "outsz", (uint32_t)buf_left(out),
 570                     BUNYAN_T_UINT32, "digestsz", (uint32_t)len,
 571                     BUNYAN_T_END);
 572                 return (B_FALSE);
 573         }
 574 
 575         return (B_TRUE);
 576 }
 577 
 578 static CK_RV
 579 pkcs11_callback_handler(CK_SESSION_HANDLE session, CK_NOTIFICATION surrender,
 580     void *context)
 581 {
 582         _NOTE(ARGUNUSED(session, context));
 583         VERIFY3U(surrender, ==, CKN_SURRENDER);
 584 
 585         return (CKR_OK);
 586 }
 587 
 588 /*
 589  * Sadly, string fields in PKCS#11 structs are not NUL-terminated and
 590  * are space padded, so this converts it into a more traditional C-string
 591  * with quoting so space padding is evident
 592  */
 593 static void
 594 fmtstr(char *buf, size_t buflen, CK_UTF8CHAR *src, size_t srclen)
 595 {
 596         ASSERT3U(srclen + 1, <=, buflen);
 597 
 598         (void) memset(buf, 0, buflen);
 599         (void) memcpy(buf, src, srclen);
 600 
 601         for (char *p = buf + strlen(buf) - 1; p >= buf && *p == ' '; p--)
 602                 *p = '\0';
 603 }