1 /* $NetBSD: pkcs11dh_link.c,v 1.1.1.5 2015/09/03 07:21:36 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifdef PKCS11CRYPTO 20 21 #include <config.h> 22 23 #include <ctype.h> 24 25 #include <isc/mem.h> 26 #include <isc/string.h> 27 #include <isc/util.h> 28 29 #include <dst/result.h> 30 31 #include "dst_internal.h" 32 #include "dst_parse.h" 33 #include "dst_pkcs11.h" 34 35 #include <pk11/pk11.h> 36 #include <pk11/internal.h> 37 #define WANT_DH_PRIMES 38 #include <pk11/constants.h> 39 40 #include <pkcs11/pkcs11.h> 41 42 /* 43 * PKCS#3 DH keys: 44 * mechanisms: 45 * CKM_DH_PKCS_PARAMETER_GEN, 46 * CKM_DH_PKCS_KEY_PAIR_GEN, 47 * CKM_DH_PKCS_DERIVE 48 * domain parameters: 49 * object class CKO_DOMAIN_PARAMETERS 50 * key type CKK_DH 51 * attribute CKA_PRIME (prime p) 52 * attribute CKA_BASE (base g) 53 * optional attribute CKA_PRIME_BITS (p length in bits) 54 * public key: 55 * object class CKO_PUBLIC_KEY 56 * key type CKK_DH 57 * attribute CKA_PRIME (prime p) 58 * attribute CKA_BASE (base g) 59 * attribute CKA_VALUE (public value y) 60 * private key: 61 * object class CKO_PRIVATE_KEY 62 * key type CKK_DH 63 * attribute CKA_PRIME (prime p) 64 * attribute CKA_BASE (base g) 65 * attribute CKA_VALUE (private value x) 66 * optional attribute CKA_VALUE_BITS (x length in bits) 67 * reuse CKA_PRIVATE_EXPONENT for key pair private value 68 */ 69 70 #define CKA_VALUE2 CKA_PRIVATE_EXPONENT 71 72 static CK_BBOOL truevalue = TRUE; 73 static CK_BBOOL falsevalue = FALSE; 74 75 #define DST_RET(a) {ret = a; goto err;} 76 77 static void pkcs11dh_destroy(dst_key_t *key); 78 static isc_result_t pkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data); 79 80 static isc_result_t 81 pkcs11dh_loadpriv(const dst_key_t *key, 82 CK_SESSION_HANDLE session, 83 CK_OBJECT_HANDLE *hKey) 84 { 85 CK_RV rv; 86 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; 87 CK_KEY_TYPE keyType = CKK_DH; 88 CK_ATTRIBUTE keyTemplate[] = 89 { 90 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, 91 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, 92 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 93 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 94 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 95 { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) }, 96 { CKA_PRIME, NULL, 0 }, 97 { CKA_BASE, NULL, 0 }, 98 { CKA_VALUE, NULL, 0 } 99 }; 100 CK_ATTRIBUTE *attr; 101 const pk11_object_t *priv; 102 isc_result_t ret; 103 unsigned int i; 104 105 priv = key->keydata.pkey; 106 if ((priv->object != CK_INVALID_HANDLE) && priv->ontoken) { 107 *hKey = priv->object; 108 return (ISC_R_SUCCESS); 109 } 110 111 attr = pk11_attribute_bytype(priv, CKA_PRIME); 112 if (attr == NULL) 113 return (DST_R_INVALIDPRIVATEKEY); 114 keyTemplate[6].pValue = isc_mem_get(key->mctx, attr->ulValueLen); 115 if (keyTemplate[6].pValue == NULL) 116 DST_RET(ISC_R_NOMEMORY); 117 memmove(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen); 118 keyTemplate[6].ulValueLen = attr->ulValueLen; 119 120 attr = pk11_attribute_bytype(priv, CKA_BASE); 121 if (attr == NULL) 122 DST_RET(DST_R_INVALIDPRIVATEKEY); 123 keyTemplate[7].pValue = isc_mem_get(key->mctx, attr->ulValueLen); 124 if (keyTemplate[7].pValue == NULL) 125 DST_RET(ISC_R_NOMEMORY); 126 memmove(keyTemplate[7].pValue, attr->pValue, attr->ulValueLen); 127 keyTemplate[7].ulValueLen = attr->ulValueLen; 128 129 attr = pk11_attribute_bytype(priv, CKA_VALUE2); 130 if (attr == NULL) 131 DST_RET(DST_R_INVALIDPRIVATEKEY); 132 keyTemplate[8].pValue = isc_mem_get(key->mctx, attr->ulValueLen); 133 if (keyTemplate[8].pValue == NULL) 134 DST_RET(ISC_R_NOMEMORY); 135 memmove(keyTemplate[8].pValue, attr->pValue, attr->ulValueLen); 136 keyTemplate[8].ulValueLen = attr->ulValueLen; 137 138 PK11_CALL(pkcs_C_CreateObject, 139 (session, keyTemplate, (CK_ULONG) 9, hKey), 140 DST_R_COMPUTESECRETFAILURE); 141 if (rv == CKR_OK) 142 ret = ISC_R_SUCCESS; 143 144 err: 145 for (i = 6; i <= 8; i++) 146 if (keyTemplate[i].pValue != NULL) { 147 memset(keyTemplate[i].pValue, 0, 148 keyTemplate[i].ulValueLen); 149 isc_mem_put(key->mctx, 150 keyTemplate[i].pValue, 151 keyTemplate[i].ulValueLen); 152 } 153 return (ret); 154 } 155 156 static isc_result_t 157 pkcs11dh_computesecret(const dst_key_t *pub, const dst_key_t *priv, 158 isc_buffer_t *secret) 159 { 160 CK_RV rv; 161 CK_MECHANISM mech = { CKM_DH_PKCS_DERIVE, NULL, 0 }; 162 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 163 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 164 CK_OBJECT_HANDLE hDerived = CK_INVALID_HANDLE; 165 CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; 166 CK_ATTRIBUTE *attr; 167 CK_ULONG secLen; 168 CK_ATTRIBUTE keyTemplate[] = 169 { 170 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, 171 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, 172 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 173 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 174 { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, 175 { CKA_VALUE_LEN, &secLen, (CK_ULONG) sizeof(secLen) } 176 }; 177 CK_ATTRIBUTE valTemplate[] = 178 { 179 { CKA_VALUE, NULL, 0 } 180 }; 181 CK_BYTE *secValue; 182 pk11_context_t ctx; 183 isc_result_t ret; 184 unsigned int i; 185 isc_region_t r; 186 187 REQUIRE(pub->keydata.pkey != NULL); 188 REQUIRE(priv->keydata.pkey != NULL); 189 REQUIRE(priv->keydata.pkey->repr != NULL); 190 attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_PRIME); 191 if (attr == NULL) 192 return (DST_R_INVALIDPUBLICKEY); 193 REQUIRE(attr != NULL); 194 secLen = attr->ulValueLen; 195 attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_VALUE); 196 if (attr == NULL) 197 return (DST_R_INVALIDPUBLICKEY); 198 199 ret = pk11_get_session(&ctx, OP_DH, ISC_TRUE, ISC_FALSE, ISC_FALSE, 200 NULL, pk11_get_best_token(OP_DH)); 201 if (ret != ISC_R_SUCCESS) 202 return (ret); 203 204 mech.ulParameterLen = attr->ulValueLen; 205 mech.pParameter = isc_mem_get(pub->mctx, mech.ulParameterLen); 206 if (mech.pParameter == NULL) 207 DST_RET(ISC_R_NOMEMORY); 208 memmove(mech.pParameter, attr->pValue, mech.ulParameterLen); 209 210 ret = pkcs11dh_loadpriv(priv, ctx.session, &hKey); 211 if (ret != ISC_R_SUCCESS) 212 goto err; 213 214 PK11_RET(pkcs_C_DeriveKey, 215 (ctx.session, &mech, hKey, 216 keyTemplate, (CK_ULONG) 6, &hDerived), 217 DST_R_COMPUTESECRETFAILURE); 218 219 attr = valTemplate; 220 PK11_RET(pkcs_C_GetAttributeValue, 221 (ctx.session, hDerived, attr, (CK_ULONG) 1), 222 DST_R_CRYPTOFAILURE); 223 attr->pValue = isc_mem_get(pub->mctx, attr->ulValueLen); 224 if (attr->pValue == NULL) 225 DST_RET(ISC_R_NOMEMORY); 226 memset(attr->pValue, 0, attr->ulValueLen); 227 PK11_RET(pkcs_C_GetAttributeValue, 228 (ctx.session, hDerived, attr, (CK_ULONG) 1), 229 DST_R_CRYPTOFAILURE); 230 231 /* strip leading zeros */ 232 secValue = (CK_BYTE_PTR) attr->pValue; 233 for (i = 0; i < attr->ulValueLen; i++) 234 if (secValue[i] != 0) 235 break; 236 isc_buffer_availableregion(secret, &r); 237 if (r.length < attr->ulValueLen - i) 238 DST_RET(ISC_R_NOSPACE); 239 memmove(r.base, secValue + i, attr->ulValueLen - i); 240 isc_buffer_add(secret, attr->ulValueLen - i); 241 ret = ISC_R_SUCCESS; 242 243 err: 244 if (hDerived != CK_INVALID_HANDLE) 245 (void) pkcs_C_DestroyObject(ctx.session, hDerived); 246 if (valTemplate[0].pValue != NULL) { 247 memset(valTemplate[0].pValue, 0, valTemplate[0].ulValueLen); 248 isc_mem_put(pub->mctx, 249 valTemplate[0].pValue, 250 valTemplate[0].ulValueLen); 251 } 252 if ((hKey != CK_INVALID_HANDLE) && !priv->keydata.pkey->ontoken) 253 (void) pkcs_C_DestroyObject(ctx.session, hKey); 254 if (mech.pParameter != NULL) { 255 memset(mech.pParameter, 0, mech.ulParameterLen); 256 isc_mem_put(pub->mctx, mech.pParameter, mech.ulParameterLen); 257 } 258 pk11_return_session(&ctx); 259 return (ret); 260 } 261 262 static isc_boolean_t 263 pkcs11dh_compare(const dst_key_t *key1, const dst_key_t *key2) { 264 pk11_object_t *dh1, *dh2; 265 CK_ATTRIBUTE *attr1, *attr2; 266 267 dh1 = key1->keydata.pkey; 268 dh2 = key2->keydata.pkey; 269 270 if ((dh1 == NULL) && (dh2 == NULL)) 271 return (ISC_TRUE); 272 else if ((dh1 == NULL) || (dh2 == NULL)) 273 return (ISC_FALSE); 274 275 attr1 = pk11_attribute_bytype(dh1, CKA_PRIME); 276 attr2 = pk11_attribute_bytype(dh2, CKA_PRIME); 277 if ((attr1 == NULL) && (attr2 == NULL)) 278 return (ISC_TRUE); 279 else if ((attr1 == NULL) || (attr2 == NULL) || 280 (attr1->ulValueLen != attr2->ulValueLen) || 281 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) 282 return (ISC_FALSE); 283 284 attr1 = pk11_attribute_bytype(dh1, CKA_BASE); 285 attr2 = pk11_attribute_bytype(dh2, CKA_BASE); 286 if ((attr1 == NULL) && (attr2 == NULL)) 287 return (ISC_TRUE); 288 else if ((attr1 == NULL) || (attr2 == NULL) || 289 (attr1->ulValueLen != attr2->ulValueLen) || 290 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) 291 return (ISC_FALSE); 292 293 attr1 = pk11_attribute_bytype(dh1, CKA_VALUE); 294 attr2 = pk11_attribute_bytype(dh2, CKA_VALUE); 295 if ((attr1 == NULL) && (attr2 == NULL)) 296 return (ISC_TRUE); 297 else if ((attr1 == NULL) || (attr2 == NULL) || 298 (attr1->ulValueLen != attr2->ulValueLen) || 299 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) 300 return (ISC_FALSE); 301 302 attr1 = pk11_attribute_bytype(dh1, CKA_VALUE2); 303 attr2 = pk11_attribute_bytype(dh2, CKA_VALUE2); 304 if (((attr1 != NULL) || (attr2 != NULL)) && 305 ((attr1 == NULL) || (attr2 == NULL) || 306 (attr1->ulValueLen != attr2->ulValueLen) || 307 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))) 308 return (ISC_FALSE); 309 310 if (!dh1->ontoken && !dh2->ontoken) 311 return (ISC_TRUE); 312 else if (dh1->ontoken || dh2->ontoken || 313 (dh1->object != dh2->object)) 314 return (ISC_FALSE); 315 316 return (ISC_TRUE); 317 } 318 319 static isc_boolean_t 320 pkcs11dh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { 321 pk11_object_t *dh1, *dh2; 322 CK_ATTRIBUTE *attr1, *attr2; 323 324 dh1 = key1->keydata.pkey; 325 dh2 = key2->keydata.pkey; 326 327 if ((dh1 == NULL) && (dh2 == NULL)) 328 return (ISC_TRUE); 329 else if ((dh1 == NULL) || (dh2 == NULL)) 330 return (ISC_FALSE); 331 332 attr1 = pk11_attribute_bytype(dh1, CKA_PRIME); 333 attr2 = pk11_attribute_bytype(dh2, CKA_PRIME); 334 if ((attr1 == NULL) && (attr2 == NULL)) 335 return (ISC_TRUE); 336 else if ((attr1 == NULL) || (attr2 == NULL) || 337 (attr1->ulValueLen != attr2->ulValueLen) || 338 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) 339 return (ISC_FALSE); 340 341 attr1 = pk11_attribute_bytype(dh1, CKA_BASE); 342 attr2 = pk11_attribute_bytype(dh2, CKA_BASE); 343 if ((attr1 == NULL) && (attr2 == NULL)) 344 return (ISC_TRUE); 345 else if ((attr1 == NULL) || (attr2 == NULL) || 346 (attr1->ulValueLen != attr2->ulValueLen) || 347 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) 348 return (ISC_FALSE); 349 350 return (ISC_TRUE); 351 } 352 353 static isc_result_t 354 pkcs11dh_generate(dst_key_t *key, int generator, void (*callback)(int)) { 355 CK_RV rv; 356 CK_MECHANISM mech = { CKM_DH_PKCS_PARAMETER_GEN, NULL, 0 }; 357 CK_OBJECT_HANDLE domainparams = CK_INVALID_HANDLE; 358 CK_OBJECT_CLASS dClass = CKO_DOMAIN_PARAMETERS; 359 CK_KEY_TYPE keyType = CKK_DH; 360 CK_ULONG bits = 0; 361 CK_ATTRIBUTE dTemplate[] = 362 { 363 { CKA_CLASS, &dClass, (CK_ULONG) sizeof(dClass) }, 364 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, 365 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 366 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 367 { CKA_PRIME_BITS, &bits, (CK_ULONG) sizeof(bits) } 368 }; 369 CK_ATTRIBUTE pTemplate[] = 370 { 371 { CKA_PRIME, NULL, 0 }, 372 { CKA_BASE, NULL, 0 } 373 }; 374 CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; 375 CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; 376 CK_ATTRIBUTE pubTemplate[] = 377 { 378 { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) }, 379 { CKA_KEY_TYPE,&keyType, (CK_ULONG) sizeof(keyType) }, 380 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 381 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 382 { CKA_PRIME, NULL, 0 }, 383 { CKA_BASE, NULL, 0 }, 384 }; 385 CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; 386 CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY; 387 CK_ATTRIBUTE privTemplate[] = 388 { 389 { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) }, 390 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, 391 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 392 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 393 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 394 { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, 395 { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) }, 396 }; 397 CK_ATTRIBUTE *attr; 398 pk11_object_t *dh = NULL; 399 pk11_context_t *pk11_ctx; 400 isc_result_t ret; 401 402 UNUSED(callback); 403 404 pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, 405 sizeof(*pk11_ctx)); 406 if (pk11_ctx == NULL) 407 return (ISC_R_NOMEMORY); 408 ret = pk11_get_session(pk11_ctx, OP_DH, ISC_TRUE, ISC_FALSE, 409 ISC_FALSE, NULL, pk11_get_best_token(OP_DH)); 410 if (ret != ISC_R_SUCCESS) 411 goto err; 412 413 bits = key->key_size; 414 if ((generator == 0) && 415 ((bits == 768) || (bits == 1024) || (bits == 1536))) { 416 if (bits == 768) { 417 pubTemplate[4].pValue = 418 isc_mem_get(key->mctx, sizeof(pk11_dh_bn768)); 419 if (pubTemplate[4].pValue == NULL) 420 DST_RET(ISC_R_NOMEMORY); 421 memmove(pubTemplate[4].pValue, 422 pk11_dh_bn768, sizeof(pk11_dh_bn768)); 423 pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn768); 424 } else if (bits == 1024) { 425 pubTemplate[4].pValue = 426 isc_mem_get(key->mctx, sizeof(pk11_dh_bn1024)); 427 if (pubTemplate[4].pValue == NULL) 428 DST_RET(ISC_R_NOMEMORY); 429 memmove(pubTemplate[4].pValue, 430 pk11_dh_bn1024, sizeof(pk11_dh_bn1024)); 431 pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn1024); 432 } else { 433 pubTemplate[4].pValue = 434 isc_mem_get(key->mctx, sizeof(pk11_dh_bn1536)); 435 if (pubTemplate[4].pValue == NULL) 436 DST_RET(ISC_R_NOMEMORY); 437 memmove(pubTemplate[4].pValue, 438 pk11_dh_bn1536, sizeof(pk11_dh_bn1536)); 439 pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn1536); 440 } 441 pubTemplate[5].pValue = isc_mem_get(key->mctx, 442 sizeof(pk11_dh_bn2)); 443 if (pubTemplate[5].pValue == NULL) 444 DST_RET(ISC_R_NOMEMORY); 445 memmove(pubTemplate[5].pValue, pk11_dh_bn2, 446 sizeof(pk11_dh_bn2)); 447 pubTemplate[5].ulValueLen = sizeof(pk11_dh_bn2); 448 } else { 449 PK11_RET(pkcs_C_GenerateKey, 450 (pk11_ctx->session, &mech, 451 dTemplate, (CK_ULONG) 5, &domainparams), 452 DST_R_CRYPTOFAILURE); 453 PK11_RET(pkcs_C_GetAttributeValue, 454 (pk11_ctx->session, domainparams, 455 pTemplate, (CK_ULONG) 2), 456 DST_R_CRYPTOFAILURE); 457 pTemplate[0].pValue = isc_mem_get(key->mctx, 458 pTemplate[0].ulValueLen); 459 if (pTemplate[0].pValue == NULL) 460 DST_RET(ISC_R_NOMEMORY); 461 memset(pTemplate[0].pValue, 0, pTemplate[0].ulValueLen); 462 pTemplate[1].pValue = isc_mem_get(key->mctx, 463 pTemplate[1].ulValueLen); 464 if (pTemplate[1].pValue == NULL) 465 DST_RET(ISC_R_NOMEMORY); 466 memset(pTemplate[1].pValue, 0, pTemplate[1].ulValueLen); 467 PK11_RET(pkcs_C_GetAttributeValue, 468 (pk11_ctx->session, domainparams, 469 pTemplate, (CK_ULONG) 2), 470 DST_R_CRYPTOFAILURE); 471 472 pubTemplate[4].pValue = pTemplate[0].pValue; 473 pubTemplate[4].ulValueLen = pTemplate[0].ulValueLen; 474 pTemplate[0].pValue = NULL; 475 pubTemplate[5].pValue = pTemplate[1].pValue; 476 pubTemplate[5].ulValueLen = pTemplate[1].ulValueLen; 477 pTemplate[1].pValue = NULL; 478 } 479 480 mech.mechanism = CKM_DH_PKCS_KEY_PAIR_GEN; 481 PK11_RET(pkcs_C_GenerateKeyPair, 482 (pk11_ctx->session, &mech, 483 pubTemplate, (CK_ULONG) 6, 484 privTemplate, (CK_ULONG) 7, 485 &pub, &priv), 486 DST_R_CRYPTOFAILURE); 487 488 dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh)); 489 if (dh == NULL) 490 DST_RET(ISC_R_NOMEMORY); 491 memset(dh, 0, sizeof(*dh)); 492 key->keydata.pkey = dh; 493 dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4); 494 if (dh->repr == NULL) 495 DST_RET(ISC_R_NOMEMORY); 496 memset(dh->repr, 0, sizeof(*attr) * 4); 497 dh->attrcnt = 4; 498 499 attr = dh->repr; 500 attr[0].type = CKA_PRIME; 501 attr[0].pValue = pubTemplate[4].pValue; 502 attr[0].ulValueLen = pubTemplate[4].ulValueLen; 503 pubTemplate[4].pValue = NULL; 504 505 attr[1].type = CKA_BASE; 506 attr[1].pValue = pubTemplate[5].pValue; 507 attr[1].ulValueLen = pubTemplate[5].ulValueLen; 508 pubTemplate[5].pValue =NULL; 509 510 attr += 2; 511 attr->type = CKA_VALUE; 512 PK11_RET(pkcs_C_GetAttributeValue, 513 (pk11_ctx->session, pub, attr, 1), 514 DST_R_CRYPTOFAILURE); 515 attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); 516 if (attr->pValue == NULL) 517 DST_RET(ISC_R_NOMEMORY); 518 memset(attr->pValue, 0, attr->ulValueLen); 519 PK11_RET(pkcs_C_GetAttributeValue, 520 (pk11_ctx->session, pub, attr, 1), 521 DST_R_CRYPTOFAILURE); 522 523 attr++; 524 attr->type = CKA_VALUE; 525 PK11_RET(pkcs_C_GetAttributeValue, 526 (pk11_ctx->session, priv, attr, 1), 527 DST_R_CRYPTOFAILURE); 528 attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); 529 if (attr->pValue == NULL) 530 DST_RET(ISC_R_NOMEMORY); 531 memset(attr->pValue, 0, attr->ulValueLen); 532 PK11_RET(pkcs_C_GetAttributeValue, 533 (pk11_ctx->session, priv, attr, 1), 534 DST_R_CRYPTOFAILURE); 535 attr->type = CKA_VALUE2; 536 537 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); 538 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); 539 (void) pkcs_C_DestroyObject(pk11_ctx->session, domainparams); 540 pk11_return_session(pk11_ctx); 541 memset(pk11_ctx, 0, sizeof(*pk11_ctx)); 542 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); 543 544 return (ISC_R_SUCCESS); 545 546 err: 547 pkcs11dh_destroy(key); 548 if (priv != CK_INVALID_HANDLE) 549 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); 550 if (pub != CK_INVALID_HANDLE) 551 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); 552 if (domainparams != CK_INVALID_HANDLE) 553 (void) pkcs_C_DestroyObject(pk11_ctx->session, domainparams); 554 555 if (pubTemplate[4].pValue != NULL) { 556 memset(pubTemplate[4].pValue, 0, pubTemplate[4].ulValueLen); 557 isc_mem_put(key->mctx, 558 pubTemplate[4].pValue, 559 pubTemplate[4].ulValueLen); 560 } 561 if (pubTemplate[5].pValue != NULL) { 562 memset(pubTemplate[5].pValue, 0, pubTemplate[5].ulValueLen); 563 isc_mem_put(key->mctx, 564 pubTemplate[5].pValue, 565 pubTemplate[5].ulValueLen); 566 } 567 if (pTemplate[0].pValue != NULL) { 568 memset(pTemplate[0].pValue, 0, pTemplate[0].ulValueLen); 569 isc_mem_put(key->mctx, 570 pTemplate[0].pValue, 571 pTemplate[0].ulValueLen); 572 } 573 if (pTemplate[1].pValue != NULL) { 574 memset(pTemplate[1].pValue, 0, pTemplate[1].ulValueLen); 575 isc_mem_put(key->mctx, 576 pTemplate[1].pValue, 577 pTemplate[1].ulValueLen); 578 } 579 580 pk11_return_session(pk11_ctx); 581 memset(pk11_ctx, 0, sizeof(*pk11_ctx)); 582 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); 583 584 return (ret); 585 } 586 587 static isc_boolean_t 588 pkcs11dh_isprivate(const dst_key_t *key) { 589 pk11_object_t *dh = key->keydata.pkey; 590 CK_ATTRIBUTE *attr; 591 592 if (dh == NULL) 593 return (ISC_FALSE); 594 attr = pk11_attribute_bytype(dh, CKA_VALUE2); 595 return (ISC_TF((attr != NULL) || dh->ontoken)); 596 } 597 598 static void 599 pkcs11dh_destroy(dst_key_t *key) { 600 pk11_object_t *dh = key->keydata.pkey; 601 CK_ATTRIBUTE *attr; 602 603 if (dh == NULL) 604 return; 605 606 INSIST((dh->object == CK_INVALID_HANDLE) || dh->ontoken); 607 608 for (attr = pk11_attribute_first(dh); 609 attr != NULL; 610 attr = pk11_attribute_next(dh, attr)) 611 switch (attr->type) { 612 case CKA_VALUE: 613 case CKA_VALUE2: 614 case CKA_PRIME: 615 case CKA_BASE: 616 if (attr->pValue != NULL) { 617 memset(attr->pValue, 0, attr->ulValueLen); 618 isc_mem_put(key->mctx, 619 attr->pValue, 620 attr->ulValueLen); 621 } 622 break; 623 } 624 if (dh->repr != NULL) { 625 memset(dh->repr, 0, dh->attrcnt * sizeof(*attr)); 626 isc_mem_put(key->mctx, dh->repr, dh->attrcnt * sizeof(*attr)); 627 } 628 memset(dh, 0, sizeof(*dh)); 629 isc_mem_put(key->mctx, dh, sizeof(*dh)); 630 key->keydata.pkey = NULL; 631 } 632 633 static void 634 uint16_toregion(isc_uint16_t val, isc_region_t *region) { 635 *region->base = (val & 0xff00) >> 8; 636 isc_region_consume(region, 1); 637 *region->base = (val & 0x00ff); 638 isc_region_consume(region, 1); 639 } 640 641 static isc_uint16_t 642 uint16_fromregion(isc_region_t *region) { 643 isc_uint16_t val; 644 unsigned char *cp = region->base; 645 646 val = ((unsigned int)(cp[0])) << 8; 647 val |= ((unsigned int)(cp[1])); 648 649 isc_region_consume(region, 2); 650 651 return (val); 652 } 653 654 static isc_result_t 655 pkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data) { 656 pk11_object_t *dh; 657 CK_ATTRIBUTE *attr; 658 isc_region_t r; 659 isc_uint16_t dnslen, plen = 0, glen = 0, publen = 0; 660 CK_BYTE *prime = NULL, *base = NULL, *pub = NULL; 661 662 REQUIRE(key->keydata.pkey != NULL); 663 664 dh = key->keydata.pkey; 665 666 for (attr = pk11_attribute_first(dh); 667 attr != NULL; 668 attr = pk11_attribute_next(dh, attr)) 669 switch (attr->type) { 670 case CKA_VALUE: 671 pub = (CK_BYTE *) attr->pValue; 672 publen = (isc_uint16_t) attr->ulValueLen; 673 break; 674 case CKA_PRIME: 675 prime = (CK_BYTE *) attr->pValue; 676 plen = (isc_uint16_t) attr->ulValueLen; 677 break; 678 case CKA_BASE: 679 base = (CK_BYTE *) attr->pValue; 680 glen = (isc_uint16_t) attr->ulValueLen; 681 break; 682 } 683 REQUIRE((prime != NULL) && (base != NULL) && (pub != NULL)); 684 685 isc_buffer_availableregion(data, &r); 686 687 if ((glen == 1) && (memcmp(pk11_dh_bn2, base, glen) == 0) && 688 (((plen == sizeof(pk11_dh_bn768)) && 689 (memcmp(pk11_dh_bn768, prime, plen) == 0)) || 690 ((plen == sizeof(pk11_dh_bn1024)) && 691 (memcmp(pk11_dh_bn1024, prime, plen) == 0)) || 692 ((plen == sizeof(pk11_dh_bn1536)) && 693 (memcmp(pk11_dh_bn1536, prime, plen) == 0)))) { 694 plen = 1; 695 glen = 0; 696 } 697 698 dnslen = plen + glen + publen + 6; 699 if (r.length < (unsigned int) dnslen) 700 return (ISC_R_NOSPACE); 701 702 uint16_toregion(plen, &r); 703 if (plen == 1) { 704 if (memcmp(pk11_dh_bn768, prime, sizeof(pk11_dh_bn768)) == 0) 705 *r.base = 1; 706 else if (memcmp(pk11_dh_bn1024, prime, 707 sizeof(pk11_dh_bn1024)) == 0) 708 *r.base = 2; 709 else 710 *r.base = 3; 711 } 712 else 713 memmove(r.base, prime, plen); 714 isc_region_consume(&r, plen); 715 716 uint16_toregion(glen, &r); 717 if (glen > 0) 718 memmove(r.base, base, glen); 719 isc_region_consume(&r, glen); 720 721 uint16_toregion(publen, &r); 722 memmove(r.base, pub, publen); 723 isc_region_consume(&r, publen); 724 725 isc_buffer_add(data, dnslen); 726 727 return (ISC_R_SUCCESS); 728 } 729 730 static isc_result_t 731 pkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) { 732 pk11_object_t *dh; 733 isc_region_t r; 734 isc_uint16_t plen, glen, plen_, glen_, publen; 735 CK_BYTE *prime = NULL, *base = NULL, *pub = NULL; 736 CK_ATTRIBUTE *attr; 737 int special = 0; 738 739 isc_buffer_remainingregion(data, &r); 740 if (r.length == 0) 741 return (ISC_R_SUCCESS); 742 743 dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh)); 744 if (dh == NULL) 745 return (ISC_R_NOMEMORY); 746 memset(dh, 0, sizeof(*dh)); 747 748 /* 749 * Read the prime length. 1 & 2 are table entries, > 16 means a 750 * prime follows, otherwise an error. 751 */ 752 if (r.length < 2) { 753 memset(dh, 0, sizeof(*dh)); 754 isc_mem_put(key->mctx, dh, sizeof(*dh)); 755 return (DST_R_INVALIDPUBLICKEY); 756 } 757 plen = uint16_fromregion(&r); 758 if (plen < 16 && plen != 1 && plen != 2) { 759 memset(dh, 0, sizeof(*dh)); 760 isc_mem_put(key->mctx, dh, sizeof(*dh)); 761 return (DST_R_INVALIDPUBLICKEY); 762 } 763 if (r.length < plen) { 764 memset(dh, 0, sizeof(*dh)); 765 isc_mem_put(key->mctx, dh, sizeof(*dh)); 766 return (DST_R_INVALIDPUBLICKEY); 767 } 768 plen_ = plen; 769 if (plen == 1 || plen == 2) { 770 if (plen == 1) { 771 special = *r.base; 772 isc_region_consume(&r, 1); 773 } else { 774 special = uint16_fromregion(&r); 775 } 776 switch (special) { 777 case 1: 778 prime = pk11_dh_bn768; 779 plen_ = sizeof(pk11_dh_bn768); 780 break; 781 case 2: 782 prime = pk11_dh_bn1024; 783 plen_ = sizeof(pk11_dh_bn1024); 784 break; 785 case 3: 786 prime = pk11_dh_bn1536; 787 plen_ = sizeof(pk11_dh_bn1536); 788 break; 789 default: 790 memset(dh, 0, sizeof(*dh)); 791 isc_mem_put(key->mctx, dh, sizeof(*dh)); 792 return (DST_R_INVALIDPUBLICKEY); 793 } 794 } 795 else { 796 prime = r.base; 797 isc_region_consume(&r, plen); 798 } 799 800 /* 801 * Read the generator length. This should be 0 if the prime was 802 * special, but it might not be. If it's 0 and the prime is not 803 * special, we have a problem. 804 */ 805 if (r.length < 2) { 806 memset(dh, 0, sizeof(*dh)); 807 isc_mem_put(key->mctx, dh, sizeof(*dh)); 808 return (DST_R_INVALIDPUBLICKEY); 809 } 810 glen = uint16_fromregion(&r); 811 if (r.length < glen) { 812 memset(dh, 0, sizeof(*dh)); 813 isc_mem_put(key->mctx, dh, sizeof(*dh)); 814 return (DST_R_INVALIDPUBLICKEY); 815 } 816 glen_ = glen; 817 if (special != 0) { 818 if (glen == 0) { 819 base = pk11_dh_bn2; 820 glen_ = sizeof(pk11_dh_bn2); 821 } 822 else { 823 base = r.base; 824 if (memcmp(base, pk11_dh_bn2, glen) == 0) { 825 base = pk11_dh_bn2; 826 glen_ = sizeof(pk11_dh_bn2); 827 } 828 else { 829 memset(dh, 0, sizeof(*dh)); 830 isc_mem_put(key->mctx, dh, sizeof(*dh)); 831 return (DST_R_INVALIDPUBLICKEY); 832 } 833 } 834 } 835 else { 836 if (glen == 0) { 837 memset(dh, 0, sizeof(*dh)); 838 isc_mem_put(key->mctx, dh, sizeof(*dh)); 839 return (DST_R_INVALIDPUBLICKEY); 840 } 841 base = r.base; 842 } 843 isc_region_consume(&r, glen); 844 845 if (r.length < 2) { 846 memset(dh, 0, sizeof(*dh)); 847 isc_mem_put(key->mctx, dh, sizeof(*dh)); 848 return (DST_R_INVALIDPUBLICKEY); 849 } 850 publen = uint16_fromregion(&r); 851 if (r.length < publen) { 852 memset(dh, 0, sizeof(*dh)); 853 isc_mem_put(key->mctx, dh, sizeof(*dh)); 854 return (DST_R_INVALIDPUBLICKEY); 855 } 856 pub = r.base; 857 isc_region_consume(&r, publen); 858 859 key->key_size = pk11_numbits(prime, plen_); 860 861 dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3); 862 if (dh->repr == NULL) 863 goto nomemory; 864 memset(dh->repr, 0, sizeof(*attr) * 3); 865 dh->attrcnt = 3; 866 867 attr = dh->repr; 868 attr[0].type = CKA_PRIME; 869 attr[0].pValue = isc_mem_get(key->mctx, plen_); 870 if (attr[0].pValue == NULL) 871 goto nomemory; 872 memmove(attr[0].pValue, prime, plen_); 873 attr[0].ulValueLen = (CK_ULONG) plen_; 874 875 attr[1].type = CKA_BASE; 876 attr[1].pValue = isc_mem_get(key->mctx, glen_); 877 if (attr[1].pValue == NULL) 878 goto nomemory; 879 memmove(attr[1].pValue, base, glen_); 880 attr[1].ulValueLen = (CK_ULONG) glen_; 881 882 attr[2].type = CKA_VALUE; 883 attr[2].pValue = isc_mem_get(key->mctx, publen); 884 if (attr[2].pValue == NULL) 885 goto nomemory; 886 memmove(attr[2].pValue, pub, publen); 887 attr[2].ulValueLen = (CK_ULONG) publen; 888 889 isc_buffer_forward(data, plen + glen + publen + 6); 890 891 key->keydata.pkey = dh; 892 893 return (ISC_R_SUCCESS); 894 895 nomemory: 896 for (attr = pk11_attribute_first(dh); 897 attr != NULL; 898 attr = pk11_attribute_next(dh, attr)) 899 switch (attr->type) { 900 case CKA_VALUE: 901 case CKA_PRIME: 902 case CKA_BASE: 903 if (attr->pValue != NULL) { 904 memset(attr->pValue, 0, attr->ulValueLen); 905 isc_mem_put(key->mctx, 906 attr->pValue, 907 attr->ulValueLen); 908 } 909 break; 910 } 911 if (dh->repr != NULL) { 912 memset(dh->repr, 0, dh->attrcnt * sizeof(*attr)); 913 isc_mem_put(key->mctx, dh->repr, dh->attrcnt * sizeof(*attr)); 914 } 915 memset(dh, 0, sizeof(*dh)); 916 isc_mem_put(key->mctx, dh, sizeof(*dh)); 917 return (ISC_R_NOMEMORY); 918 } 919 920 static isc_result_t 921 pkcs11dh_tofile(const dst_key_t *key, const char *directory) { 922 int i; 923 pk11_object_t *dh; 924 CK_ATTRIBUTE *attr; 925 CK_ATTRIBUTE *prime = NULL, *base = NULL, *pub = NULL, *prv = NULL; 926 dst_private_t priv; 927 unsigned char *bufs[4]; 928 isc_result_t result; 929 930 if (key->keydata.pkey == NULL) 931 return (DST_R_NULLKEY); 932 933 if (key->external) 934 return (DST_R_EXTERNALKEY); 935 936 dh = key->keydata.pkey; 937 938 for (attr = pk11_attribute_first(dh); 939 attr != NULL; 940 attr = pk11_attribute_next(dh, attr)) 941 switch (attr->type) { 942 case CKA_VALUE: 943 pub = attr; 944 break; 945 case CKA_VALUE2: 946 prv = attr; 947 break; 948 case CKA_PRIME: 949 prime = attr; 950 break; 951 case CKA_BASE: 952 base = attr; 953 break; 954 } 955 if ((prime == NULL) || (base == NULL) || 956 (pub == NULL) || (prv == NULL)) 957 return (DST_R_NULLKEY); 958 959 memset(bufs, 0, sizeof(bufs)); 960 for (i = 0; i < 4; i++) { 961 bufs[i] = isc_mem_get(key->mctx, prime->ulValueLen); 962 if (bufs[i] == NULL) { 963 result = ISC_R_NOMEMORY; 964 goto fail; 965 } 966 memset(bufs[i], 0, prime->ulValueLen); 967 } 968 969 i = 0; 970 971 priv.elements[i].tag = TAG_DH_PRIME; 972 priv.elements[i].length = (unsigned short) prime->ulValueLen; 973 memmove(bufs[i], prime->pValue, prime->ulValueLen); 974 priv.elements[i].data = bufs[i]; 975 i++; 976 977 priv.elements[i].tag = TAG_DH_GENERATOR; 978 priv.elements[i].length = (unsigned short) base->ulValueLen; 979 memmove(bufs[i], base->pValue, base->ulValueLen); 980 priv.elements[i].data = bufs[i]; 981 i++; 982 983 priv.elements[i].tag = TAG_DH_PRIVATE; 984 priv.elements[i].length = (unsigned short) prv->ulValueLen; 985 memmove(bufs[i], prv->pValue, prv->ulValueLen); 986 priv.elements[i].data = bufs[i]; 987 i++; 988 989 priv.elements[i].tag = TAG_DH_PUBLIC; 990 priv.elements[i].length = (unsigned short) pub->ulValueLen; 991 memmove(bufs[i], pub->pValue, pub->ulValueLen); 992 priv.elements[i].data = bufs[i]; 993 i++; 994 995 priv.nelements = i; 996 result = dst__privstruct_writefile(key, &priv, directory); 997 fail: 998 for (i = 0; i < 4; i++) { 999 if (bufs[i] == NULL) 1000 break; 1001 memset(bufs[i], 0, prime->ulValueLen); 1002 isc_mem_put(key->mctx, bufs[i], prime->ulValueLen); 1003 } 1004 return (result); 1005 } 1006 1007 static isc_result_t 1008 pkcs11dh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { 1009 dst_private_t priv; 1010 isc_result_t ret; 1011 int i; 1012 pk11_object_t *dh = NULL; 1013 CK_ATTRIBUTE *attr; 1014 isc_mem_t *mctx; 1015 1016 UNUSED(pub); 1017 mctx = key->mctx; 1018 1019 /* read private key file */ 1020 ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv); 1021 if (ret != ISC_R_SUCCESS) 1022 return (ret); 1023 1024 if (key->external) 1025 DST_RET(DST_R_EXTERNALKEY); 1026 1027 dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh)); 1028 if (dh == NULL) 1029 DST_RET(ISC_R_NOMEMORY); 1030 memset(dh, 0, sizeof(*dh)); 1031 key->keydata.pkey = dh; 1032 dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4); 1033 if (dh->repr == NULL) 1034 DST_RET(ISC_R_NOMEMORY); 1035 memset(dh->repr, 0, sizeof(*attr) * 4); 1036 dh->attrcnt = 4; 1037 attr = dh->repr; 1038 attr[0].type = CKA_PRIME; 1039 attr[1].type = CKA_BASE; 1040 attr[2].type = CKA_VALUE; 1041 attr[3].type = CKA_VALUE2; 1042 1043 for (i = 0; i < priv.nelements; i++) { 1044 CK_BYTE *bn; 1045 1046 bn = isc_mem_get(key->mctx, priv.elements[i].length); 1047 if (bn == NULL) 1048 DST_RET(ISC_R_NOMEMORY); 1049 memmove(bn, priv.elements[i].data, priv.elements[i].length); 1050 1051 switch (priv.elements[i].tag) { 1052 case TAG_DH_PRIME: 1053 attr = pk11_attribute_bytype(dh, CKA_PRIME); 1054 INSIST(attr != NULL); 1055 attr->pValue = bn; 1056 attr->ulValueLen = priv.elements[i].length; 1057 break; 1058 case TAG_DH_GENERATOR: 1059 attr = pk11_attribute_bytype(dh, CKA_BASE); 1060 INSIST(attr != NULL); 1061 attr->pValue = bn; 1062 attr->ulValueLen = priv.elements[i].length; 1063 break; 1064 case TAG_DH_PRIVATE: 1065 attr = pk11_attribute_bytype(dh, CKA_VALUE2); 1066 INSIST(attr != NULL); 1067 attr->pValue = bn; 1068 attr->ulValueLen = priv.elements[i].length; 1069 break; 1070 case TAG_DH_PUBLIC: 1071 attr = pk11_attribute_bytype(dh, CKA_VALUE); 1072 INSIST(attr != NULL); 1073 attr->pValue = bn; 1074 attr->ulValueLen = priv.elements[i].length; 1075 break; 1076 } 1077 } 1078 dst__privstruct_free(&priv, mctx); 1079 1080 attr = pk11_attribute_bytype(dh, CKA_PRIME); 1081 INSIST(attr != NULL); 1082 key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); 1083 1084 return (ISC_R_SUCCESS); 1085 1086 err: 1087 pkcs11dh_destroy(key); 1088 dst__privstruct_free(&priv, mctx); 1089 memset(&priv, 0, sizeof(priv)); 1090 return (ret); 1091 } 1092 1093 static dst_func_t pkcs11dh_functions = { 1094 NULL, /*%< createctx */ 1095 NULL, /*%< createctx2 */ 1096 NULL, /*%< destroyctx */ 1097 NULL, /*%< adddata */ 1098 NULL, /*%< sign */ 1099 NULL, /*%< verify */ 1100 NULL, /*%< verify2 */ 1101 pkcs11dh_computesecret, 1102 pkcs11dh_compare, 1103 pkcs11dh_paramcompare, 1104 pkcs11dh_generate, 1105 pkcs11dh_isprivate, 1106 pkcs11dh_destroy, 1107 pkcs11dh_todns, 1108 pkcs11dh_fromdns, 1109 pkcs11dh_tofile, 1110 pkcs11dh_parse, 1111 NULL, /*%< cleanup */ 1112 NULL, /*%< fromlabel */ 1113 NULL, /*%< dump */ 1114 NULL, /*%< restore */ 1115 }; 1116 1117 isc_result_t 1118 dst__pkcs11dh_init(dst_func_t **funcp) { 1119 REQUIRE(funcp != NULL); 1120 if (*funcp == NULL) 1121 *funcp = &pkcs11dh_functions; 1122 return (ISC_R_SUCCESS); 1123 } 1124 1125 #else /* PKCS11CRYPTO */ 1126 1127 #include <isc/util.h> 1128 1129 EMPTY_TRANSLATION_UNIT 1130 1131 #endif /* PKCS11CRYPTO */ 1132 /*! \file */ 1133