00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <config.h>
00020
00021 #if defined(PKCS11CRYPTO) && defined(HAVE_PKCS11_ECDSA)
00022
00023 #include <isc/entropy.h>
00024 #include <isc/mem.h>
00025 #include <isc/sha2.h>
00026 #include <isc/string.h>
00027 #include <isc/util.h>
00028
00029 #include <dns/keyvalues.h>
00030 #include <dst/result.h>
00031
00032 #include "dst_internal.h"
00033 #include "dst_parse.h"
00034 #include "dst_pkcs11.h"
00035
00036 #include <pk11/pk11.h>
00037 #include <pk11/internal.h>
00038 #define WANT_ECC_CURVES
00039 #include <pk11/constants.h>
00040
00041 #include <pkcs11/pkcs11.h>
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #define TAG_OCTECT_STRING 0x04
00064 #define UNCOMPRESSED 0x04
00065
00066 #define DST_RET(a) {ret = a; goto err;}
00067
00068 static CK_BBOOL truevalue = TRUE;
00069 static CK_BBOOL falsevalue = FALSE;
00070
00071 static isc_result_t pkcs11ecdsa_todns(const dst_key_t *key,
00072 isc_buffer_t *data);
00073 static void pkcs11ecdsa_destroy(dst_key_t *key);
00074 static isc_result_t pkcs11ecdsa_fetch(dst_key_t *key, const char *engine,
00075 const char *label, dst_key_t *pub);
00076
00077 static isc_result_t
00078 pkcs11ecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
00079 CK_RV rv;
00080 CK_MECHANISM mech = {0, NULL, 0 };
00081 CK_SLOT_ID slotid;
00082 pk11_context_t *pk11_ctx;
00083 pk11_object_t *ec = key->keydata.pkey;
00084 isc_result_t ret;
00085
00086 UNUSED(key);
00087 REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
00088 dctx->key->key_alg == DST_ALG_ECDSA384);
00089
00090 if (dctx->key->key_alg == DST_ALG_ECDSA256)
00091 mech.mechanism = CKM_SHA256;
00092 else
00093 mech.mechanism = CKM_SHA384;
00094
00095 pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
00096 sizeof(*pk11_ctx));
00097 if (pk11_ctx == NULL)
00098 return (ISC_R_NOMEMORY);
00099 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00100 if (ec->ontoken && (dctx->use == DO_SIGN))
00101 slotid = ec->slot;
00102 else
00103 slotid = pk11_get_best_token(OP_EC);
00104 ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE, ISC_FALSE,
00105 NULL, slotid);
00106 if (ret != ISC_R_SUCCESS)
00107 goto err;
00108
00109 PK11_RET(pkcs_C_DigestInit, (pk11_ctx->session, &mech), ISC_R_FAILURE);
00110 dctx->ctxdata.pk11_ctx = pk11_ctx;
00111 return (ISC_R_SUCCESS);
00112
00113 err:
00114 pk11_return_session(pk11_ctx);
00115 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00116 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
00117
00118 return (ret);
00119 }
00120
00121 static void
00122 pkcs11ecdsa_destroyctx(dst_context_t *dctx) {
00123 CK_BYTE garbage[ISC_SHA384_DIGESTLENGTH];
00124 CK_ULONG len = ISC_SHA384_DIGESTLENGTH;
00125 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00126
00127 REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
00128 dctx->key->key_alg == DST_ALG_ECDSA384);
00129
00130 if (pk11_ctx != NULL) {
00131 (void) pkcs_C_DigestFinal(pk11_ctx->session, garbage, &len);
00132 memset(garbage, 0, sizeof(garbage));
00133 pk11_return_session(pk11_ctx);
00134 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00135 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
00136 dctx->ctxdata.pk11_ctx = NULL;
00137 }
00138 }
00139
00140 static isc_result_t
00141 pkcs11ecdsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
00142 CK_RV rv;
00143 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00144 isc_result_t ret = ISC_R_SUCCESS;
00145
00146 REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
00147 dctx->key->key_alg == DST_ALG_ECDSA384);
00148
00149 PK11_CALL(pkcs_C_DigestUpdate,
00150 (pk11_ctx->session,
00151 (CK_BYTE_PTR) data->base,
00152 (CK_ULONG) data->length),
00153 ISC_R_FAILURE);
00154
00155 return (ret);
00156 }
00157
00158 static isc_result_t
00159 pkcs11ecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
00160 CK_RV rv;
00161 CK_MECHANISM mech = { CKM_ECDSA, NULL, 0 };
00162 CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
00163 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
00164 CK_KEY_TYPE keyType = CKK_EC;
00165 CK_ATTRIBUTE keyTemplate[] =
00166 {
00167 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
00168 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00169 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00170 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00171 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
00172 { CKA_EC_PARAMS, NULL, 0 },
00173 { CKA_VALUE, NULL, 0 }
00174 };
00175 CK_ATTRIBUTE *attr;
00176 CK_BYTE digest[ISC_SHA384_DIGESTLENGTH];
00177 CK_ULONG dgstlen;
00178 CK_ULONG siglen;
00179 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00180 dst_key_t *key = dctx->key;
00181 pk11_object_t *ec = key->keydata.pkey;
00182 isc_region_t r;
00183 isc_result_t ret = ISC_R_SUCCESS;
00184 unsigned int i;
00185
00186 REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
00187 key->key_alg == DST_ALG_ECDSA384);
00188 REQUIRE(ec != NULL);
00189
00190 if (key->key_alg == DST_ALG_ECDSA256) {
00191 dgstlen = ISC_SHA256_DIGESTLENGTH;
00192 siglen = DNS_SIG_ECDSA256SIZE;
00193 } else {
00194 siglen = DNS_SIG_ECDSA384SIZE;
00195 dgstlen = ISC_SHA384_DIGESTLENGTH;
00196 }
00197
00198 PK11_RET(pkcs_C_DigestFinal,
00199 (pk11_ctx->session, digest, &dgstlen),
00200 ISC_R_FAILURE);
00201
00202 isc_buffer_availableregion(sig, &r);
00203 if (r.length < siglen)
00204 DST_RET(ISC_R_NOSPACE);
00205
00206 if (ec->ontoken && (ec->object != CK_INVALID_HANDLE)) {
00207 pk11_ctx->ontoken = ec->ontoken;
00208 pk11_ctx->object = ec->object;
00209 goto token_key;
00210 }
00211
00212 for (attr = pk11_attribute_first(ec);
00213 attr != NULL;
00214 attr = pk11_attribute_next(ec, attr))
00215 switch (attr->type) {
00216 case CKA_EC_PARAMS:
00217 INSIST(keyTemplate[5].type == attr->type);
00218 keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
00219 attr->ulValueLen);
00220 if (keyTemplate[5].pValue == NULL)
00221 DST_RET(ISC_R_NOMEMORY);
00222 memmove(keyTemplate[5].pValue, attr->pValue,
00223 attr->ulValueLen);
00224 keyTemplate[5].ulValueLen = attr->ulValueLen;
00225 break;
00226 case CKA_VALUE:
00227 INSIST(keyTemplate[6].type == attr->type);
00228 keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
00229 attr->ulValueLen);
00230 if (keyTemplate[6].pValue == NULL)
00231 DST_RET(ISC_R_NOMEMORY);
00232 memmove(keyTemplate[6].pValue, attr->pValue,
00233 attr->ulValueLen);
00234 keyTemplate[6].ulValueLen = attr->ulValueLen;
00235 break;
00236 }
00237 pk11_ctx->object = CK_INVALID_HANDLE;
00238 pk11_ctx->ontoken = ISC_FALSE;
00239 PK11_RET(pkcs_C_CreateObject,
00240 (pk11_ctx->session,
00241 keyTemplate, (CK_ULONG) 7,
00242 &hKey),
00243 ISC_R_FAILURE);
00244
00245 token_key:
00246
00247 PK11_RET(pkcs_C_SignInit,
00248 (pk11_ctx->session, &mech,
00249 pk11_ctx->ontoken ? pk11_ctx->object : hKey),
00250 ISC_R_FAILURE);
00251
00252 PK11_RET(pkcs_C_Sign,
00253 (pk11_ctx->session,
00254 digest, dgstlen,
00255 (CK_BYTE_PTR) r.base, &siglen),
00256 DST_R_SIGNFAILURE);
00257
00258 isc_buffer_add(sig, (unsigned int) siglen);
00259
00260 err:
00261
00262 if (hKey != CK_INVALID_HANDLE)
00263 (void) pkcs_C_DestroyObject(pk11_ctx->session, hKey);
00264 for (i = 5; i <= 6; i++)
00265 if (keyTemplate[i].pValue != NULL) {
00266 memset(keyTemplate[i].pValue, 0,
00267 keyTemplate[i].ulValueLen);
00268 isc_mem_put(dctx->mctx,
00269 keyTemplate[i].pValue,
00270 keyTemplate[i].ulValueLen);
00271 }
00272 pk11_return_session(pk11_ctx);
00273 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00274 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
00275 dctx->ctxdata.pk11_ctx = NULL;
00276
00277 return (ret);
00278 }
00279
00280 static isc_result_t
00281 pkcs11ecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
00282 CK_RV rv;
00283 CK_MECHANISM mech = { CKM_ECDSA, NULL, 0 };
00284 CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
00285 CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
00286 CK_KEY_TYPE keyType = CKK_EC;
00287 CK_ATTRIBUTE keyTemplate[] =
00288 {
00289 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
00290 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00291 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00292 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00293 { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
00294 { CKA_EC_PARAMS, NULL, 0 },
00295 { CKA_EC_POINT, NULL, 0 }
00296 };
00297 CK_ATTRIBUTE *attr;
00298 CK_BYTE digest[ISC_SHA384_DIGESTLENGTH];
00299 CK_ULONG dgstlen;
00300 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00301 dst_key_t *key = dctx->key;
00302 pk11_object_t *ec = key->keydata.pkey;
00303 isc_result_t ret = ISC_R_SUCCESS;
00304 unsigned int i;
00305
00306 REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
00307 key->key_alg == DST_ALG_ECDSA384);
00308 REQUIRE(ec != NULL);
00309
00310 if (key->key_alg == DST_ALG_ECDSA256)
00311 dgstlen = ISC_SHA256_DIGESTLENGTH;
00312 else
00313 dgstlen = ISC_SHA384_DIGESTLENGTH;
00314
00315 PK11_RET(pkcs_C_DigestFinal,
00316 (pk11_ctx->session, digest, &dgstlen),
00317 ISC_R_FAILURE);
00318
00319 for (attr = pk11_attribute_first(ec);
00320 attr != NULL;
00321 attr = pk11_attribute_next(ec, attr))
00322 switch (attr->type) {
00323 case CKA_EC_PARAMS:
00324 INSIST(keyTemplate[5].type == attr->type);
00325 keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
00326 attr->ulValueLen);
00327 if (keyTemplate[5].pValue == NULL)
00328 DST_RET(ISC_R_NOMEMORY);
00329 memmove(keyTemplate[5].pValue, attr->pValue,
00330 attr->ulValueLen);
00331 keyTemplate[5].ulValueLen = attr->ulValueLen;
00332 break;
00333 case CKA_EC_POINT:
00334 INSIST(keyTemplate[6].type == attr->type);
00335 keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
00336 attr->ulValueLen);
00337 if (keyTemplate[6].pValue == NULL)
00338 DST_RET(ISC_R_NOMEMORY);
00339 memmove(keyTemplate[6].pValue, attr->pValue,
00340 attr->ulValueLen);
00341 keyTemplate[6].ulValueLen = attr->ulValueLen;
00342 break;
00343 }
00344 pk11_ctx->object = CK_INVALID_HANDLE;
00345 pk11_ctx->ontoken = ISC_FALSE;
00346 PK11_RET(pkcs_C_CreateObject,
00347 (pk11_ctx->session,
00348 keyTemplate, (CK_ULONG) 7,
00349 &hKey),
00350 ISC_R_FAILURE);
00351
00352 PK11_RET(pkcs_C_VerifyInit,
00353 (pk11_ctx->session, &mech, hKey),
00354 ISC_R_FAILURE);
00355
00356 PK11_RET(pkcs_C_Verify,
00357 (pk11_ctx->session,
00358 digest, dgstlen,
00359 (CK_BYTE_PTR) sig->base, (CK_ULONG) sig->length),
00360 DST_R_SIGNFAILURE);
00361
00362 err:
00363
00364 if (hKey != CK_INVALID_HANDLE)
00365 (void) pkcs_C_DestroyObject(pk11_ctx->session, hKey);
00366 for (i = 5; i <= 6; i++)
00367 if (keyTemplate[i].pValue != NULL) {
00368 memset(keyTemplate[i].pValue, 0,
00369 keyTemplate[i].ulValueLen);
00370 isc_mem_put(dctx->mctx,
00371 keyTemplate[i].pValue,
00372 keyTemplate[i].ulValueLen);
00373 }
00374 pk11_return_session(pk11_ctx);
00375 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00376 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
00377 dctx->ctxdata.pk11_ctx = NULL;
00378
00379 return (ret);
00380 }
00381
00382 static isc_boolean_t
00383 pkcs11ecdsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
00384 pk11_object_t *ec1, *ec2;
00385 CK_ATTRIBUTE *attr1, *attr2;
00386
00387 ec1 = key1->keydata.pkey;
00388 ec2 = key2->keydata.pkey;
00389
00390 if ((ec1 == NULL) && (ec2 == NULL))
00391 return (ISC_TRUE);
00392 else if ((ec1 == NULL) || (ec2 == NULL))
00393 return (ISC_FALSE);
00394
00395 attr1 = pk11_attribute_bytype(ec1, CKA_EC_PARAMS);
00396 attr2 = pk11_attribute_bytype(ec2, CKA_EC_PARAMS);
00397 if ((attr1 == NULL) && (attr2 == NULL))
00398 return (ISC_TRUE);
00399 else if ((attr1 == NULL) || (attr2 == NULL) ||
00400 (attr1->ulValueLen != attr2->ulValueLen) ||
00401 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
00402 return (ISC_FALSE);
00403
00404 attr1 = pk11_attribute_bytype(ec1, CKA_EC_POINT);
00405 attr2 = pk11_attribute_bytype(ec2, CKA_EC_POINT);
00406 if ((attr1 == NULL) && (attr2 == NULL))
00407 return (ISC_TRUE);
00408 else if ((attr1 == NULL) || (attr2 == NULL) ||
00409 (attr1->ulValueLen != attr2->ulValueLen) ||
00410 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
00411 return (ISC_FALSE);
00412
00413 attr1 = pk11_attribute_bytype(ec1, CKA_VALUE);
00414 attr2 = pk11_attribute_bytype(ec2, CKA_VALUE);
00415 if (((attr1 != NULL) || (attr2 != NULL)) &&
00416 ((attr1 == NULL) || (attr2 == NULL) ||
00417 (attr1->ulValueLen != attr2->ulValueLen) ||
00418 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
00419 return (ISC_FALSE);
00420
00421 if (!ec1->ontoken && !ec2->ontoken)
00422 return (ISC_TRUE);
00423 else if (ec1->ontoken || ec2->ontoken ||
00424 (ec1->object != ec2->object))
00425 return (ISC_FALSE);
00426
00427 return (ISC_TRUE);
00428 }
00429
00430 #define SETCURVE() \
00431 if (key->key_alg == DST_ALG_ECDSA256) { \
00432 attr->pValue = isc_mem_get(key->mctx, \
00433 sizeof(pk11_ecc_prime256v1)); \
00434 if (attr->pValue == NULL) \
00435 DST_RET(ISC_R_NOMEMORY); \
00436 memmove(attr->pValue, \
00437 pk11_ecc_prime256v1, sizeof(pk11_ecc_prime256v1)); \
00438 attr->ulValueLen = sizeof(pk11_ecc_prime256v1); \
00439 } else { \
00440 attr->pValue = isc_mem_get(key->mctx, \
00441 sizeof(pk11_ecc_secp384r1)); \
00442 if (attr->pValue == NULL) \
00443 DST_RET(ISC_R_NOMEMORY); \
00444 memmove(attr->pValue, \
00445 pk11_ecc_secp384r1, sizeof(pk11_ecc_secp384r1)); \
00446 attr->ulValueLen = sizeof(pk11_ecc_secp384r1); \
00447 }
00448
00449 #define FREECURVE() \
00450 if (attr->pValue != NULL) { \
00451 memset(attr->pValue, 0, attr->ulValueLen); \
00452 isc_mem_put(key->mctx, attr->pValue, attr->ulValueLen); \
00453 attr->pValue = NULL; \
00454 }
00455
00456 static isc_result_t
00457 pkcs11ecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
00458 CK_RV rv;
00459 CK_MECHANISM mech = { CKM_EC_KEY_PAIR_GEN, NULL, 0 };
00460 CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
00461 CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
00462 CK_KEY_TYPE keyType = CKK_EC;
00463 CK_ATTRIBUTE pubTemplate[] =
00464 {
00465 { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
00466 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00467 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00468 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00469 { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
00470 { CKA_EC_PARAMS, NULL, 0 }
00471 };
00472 CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
00473 CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY;
00474 CK_ATTRIBUTE privTemplate[] =
00475 {
00476 { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
00477 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00478 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00479 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00480 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00481 { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
00482 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }
00483 };
00484 CK_ATTRIBUTE *attr;
00485 pk11_object_t *ec;
00486 pk11_context_t *pk11_ctx;
00487 isc_result_t ret;
00488
00489 REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
00490 key->key_alg == DST_ALG_ECDSA384);
00491 UNUSED(unused);
00492 UNUSED(callback);
00493
00494 pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
00495 sizeof(*pk11_ctx));
00496 if (pk11_ctx == NULL)
00497 return (ISC_R_NOMEMORY);
00498 ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE,
00499 ISC_FALSE, NULL, pk11_get_best_token(OP_EC));
00500 if (ret != ISC_R_SUCCESS)
00501 goto err;
00502
00503 ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
00504 if (ec == NULL)
00505 DST_RET(ISC_R_NOMEMORY);
00506 memset(ec, 0, sizeof(*ec));
00507 key->keydata.pkey = ec;
00508 ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3);
00509 if (ec->repr == NULL)
00510 DST_RET(ISC_R_NOMEMORY);
00511 memset(ec->repr, 0, sizeof(*attr) * 3);
00512 ec->attrcnt = 3;
00513
00514 attr = ec->repr;
00515 attr[0].type = CKA_EC_PARAMS;
00516 attr[1].type = CKA_EC_POINT;
00517 attr[2].type = CKA_VALUE;
00518
00519 attr = &pubTemplate[5];
00520 SETCURVE();
00521
00522 PK11_RET(pkcs_C_GenerateKeyPair,
00523 (pk11_ctx->session, &mech,
00524 pubTemplate, (CK_ULONG) 6,
00525 privTemplate, (CK_ULONG) 7,
00526 &pub, &priv),
00527 DST_R_CRYPTOFAILURE);
00528
00529 attr = &pubTemplate[5];
00530 FREECURVE();
00531
00532 attr = ec->repr;
00533 SETCURVE();
00534
00535 attr++;
00536 PK11_RET(pkcs_C_GetAttributeValue,
00537 (pk11_ctx->session, pub, attr, 1),
00538 DST_R_CRYPTOFAILURE);
00539 attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
00540 if (attr->pValue == NULL)
00541 DST_RET(ISC_R_NOMEMORY);
00542 memset(attr->pValue, 0, attr->ulValueLen);
00543 PK11_RET(pkcs_C_GetAttributeValue,
00544 (pk11_ctx->session, pub, attr, 1),
00545 DST_R_CRYPTOFAILURE);
00546
00547 attr++;
00548 PK11_RET(pkcs_C_GetAttributeValue,
00549 (pk11_ctx->session, priv, attr, 1),
00550 DST_R_CRYPTOFAILURE);
00551 attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
00552 if (attr->pValue == NULL)
00553 DST_RET(ISC_R_NOMEMORY);
00554 memset(attr->pValue, 0, attr->ulValueLen);
00555 PK11_RET(pkcs_C_GetAttributeValue,
00556 (pk11_ctx->session, priv, attr, 1),
00557 DST_R_CRYPTOFAILURE);
00558
00559 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
00560 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
00561 pk11_return_session(pk11_ctx);
00562 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00563 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
00564
00565 if (key->key_alg == DST_ALG_ECDSA256)
00566 key->key_size = DNS_KEY_ECDSA256SIZE * 4;
00567 else
00568 key->key_size = DNS_KEY_ECDSA384SIZE * 4;
00569
00570 return (ISC_R_SUCCESS);
00571
00572 err:
00573 pkcs11ecdsa_destroy(key);
00574 if (priv != CK_INVALID_HANDLE)
00575 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
00576 if (pub != CK_INVALID_HANDLE)
00577 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
00578 pk11_return_session(pk11_ctx);
00579 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00580 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
00581
00582 return (ret);
00583 }
00584
00585 static isc_boolean_t
00586 pkcs11ecdsa_isprivate(const dst_key_t *key) {
00587 pk11_object_t *ec = key->keydata.pkey;
00588 CK_ATTRIBUTE *attr;
00589
00590 if (ec == NULL)
00591 return (ISC_FALSE);
00592 attr = pk11_attribute_bytype(ec, CKA_VALUE);
00593 return (ISC_TF((attr != NULL) || ec->ontoken));
00594 }
00595
00596 static void
00597 pkcs11ecdsa_destroy(dst_key_t *key) {
00598 pk11_object_t *ec = key->keydata.pkey;
00599 CK_ATTRIBUTE *attr;
00600
00601 if (ec == NULL)
00602 return;
00603
00604 INSIST((ec->object == CK_INVALID_HANDLE) || ec->ontoken);
00605
00606 for (attr = pk11_attribute_first(ec);
00607 attr != NULL;
00608 attr = pk11_attribute_next(ec, attr))
00609 switch (attr->type) {
00610 case CKA_LABEL:
00611 case CKA_ID:
00612 case CKA_EC_PARAMS:
00613 case CKA_EC_POINT:
00614 case CKA_VALUE:
00615 FREECURVE();
00616 break;
00617 }
00618 if (ec->repr != NULL) {
00619 memset(ec->repr, 0, ec->attrcnt * sizeof(*attr));
00620 isc_mem_put(key->mctx,
00621 ec->repr,
00622 ec->attrcnt * sizeof(*attr));
00623 }
00624 memset(ec, 0, sizeof(*ec));
00625 isc_mem_put(key->mctx, ec, sizeof(*ec));
00626 key->keydata.pkey = NULL;
00627 }
00628
00629 static isc_result_t
00630 pkcs11ecdsa_todns(const dst_key_t *key, isc_buffer_t *data) {
00631 pk11_object_t *ec;
00632 isc_region_t r;
00633 unsigned int len;
00634 CK_ATTRIBUTE *attr;
00635
00636 REQUIRE(key->keydata.pkey != NULL);
00637
00638 if (key->key_alg == DST_ALG_ECDSA256)
00639 len = DNS_KEY_ECDSA256SIZE;
00640 else
00641 len = DNS_KEY_ECDSA384SIZE;
00642
00643 ec = key->keydata.pkey;
00644 attr = pk11_attribute_bytype(ec, CKA_EC_POINT);
00645 if ((attr == NULL) ||
00646 (attr->ulValueLen != len + 3) ||
00647 (((CK_BYTE_PTR) attr->pValue)[0] != TAG_OCTECT_STRING) ||
00648 (((CK_BYTE_PTR) attr->pValue)[1] != len + 1) ||
00649 (((CK_BYTE_PTR) attr->pValue)[2] != UNCOMPRESSED))
00650 return (ISC_R_FAILURE);
00651
00652 isc_buffer_availableregion(data, &r);
00653 if (r.length < len)
00654 return (ISC_R_NOSPACE);
00655 memmove(r.base, (CK_BYTE_PTR) attr->pValue + 3, len);
00656 isc_buffer_add(data, len);
00657
00658 return (ISC_R_SUCCESS);
00659 }
00660
00661 static isc_result_t
00662 pkcs11ecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
00663 pk11_object_t *ec;
00664 isc_region_t r;
00665 unsigned int len;
00666 CK_ATTRIBUTE *attr;
00667
00668 REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
00669 key->key_alg == DST_ALG_ECDSA384);
00670
00671 if (key->key_alg == DST_ALG_ECDSA256)
00672 len = DNS_KEY_ECDSA256SIZE;
00673 else
00674 len = DNS_KEY_ECDSA384SIZE;
00675
00676 isc_buffer_remainingregion(data, &r);
00677 if (r.length == 0)
00678 return (ISC_R_SUCCESS);
00679 if (r.length != len)
00680 return (DST_R_INVALIDPUBLICKEY);
00681
00682 ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
00683 if (ec == NULL)
00684 return (ISC_R_NOMEMORY);
00685 memset(ec, 0, sizeof(*ec));
00686 ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
00687 if (ec->repr == NULL)
00688 goto nomemory;
00689 ec->attrcnt = 2;
00690
00691 attr = ec->repr;
00692 attr->type = CKA_EC_PARAMS;
00693 if (key->key_alg == DST_ALG_ECDSA256) {
00694 attr->pValue =
00695 isc_mem_get(key->mctx, sizeof(pk11_ecc_prime256v1));
00696 if (attr->pValue == NULL)
00697 goto nomemory;
00698 memmove(attr->pValue,
00699 pk11_ecc_prime256v1, sizeof(pk11_ecc_prime256v1));
00700 attr->ulValueLen = sizeof(pk11_ecc_prime256v1);
00701 } else {
00702 attr->pValue =
00703 isc_mem_get(key->mctx, sizeof(pk11_ecc_secp384r1));
00704 if (attr->pValue == NULL)
00705 goto nomemory;
00706 memmove(attr->pValue,
00707 pk11_ecc_secp384r1, sizeof(pk11_ecc_secp384r1));
00708 attr->ulValueLen = sizeof(pk11_ecc_secp384r1);
00709 }
00710
00711 attr++;
00712 attr->type = CKA_EC_POINT;
00713 attr->pValue = isc_mem_get(key->mctx, len + 3);
00714 if (attr->pValue == NULL)
00715 goto nomemory;
00716 ((CK_BYTE_PTR) attr->pValue)[0] = TAG_OCTECT_STRING;
00717 ((CK_BYTE_PTR) attr->pValue)[1] = len + 1;
00718 ((CK_BYTE_PTR) attr->pValue)[2] = UNCOMPRESSED;
00719 memmove((CK_BYTE_PTR) attr->pValue + 3, r.base, len);
00720 attr->ulValueLen = len + 3;
00721
00722 isc_buffer_forward(data, len);
00723 key->keydata.pkey = ec;
00724 key->key_size = len * 4;
00725 return (ISC_R_SUCCESS);
00726
00727 nomemory:
00728 for (attr = pk11_attribute_first(ec);
00729 attr != NULL;
00730 attr = pk11_attribute_next(ec, attr))
00731 switch (attr->type) {
00732 case CKA_EC_PARAMS:
00733 case CKA_EC_POINT:
00734 FREECURVE();
00735 break;
00736 }
00737 if (ec->repr != NULL) {
00738 memset(ec->repr, 0, ec->attrcnt * sizeof(*attr));
00739 isc_mem_put(key->mctx,
00740 ec->repr,
00741 ec->attrcnt * sizeof(*attr));
00742 }
00743 memset(ec, 0, sizeof(*ec));
00744 isc_mem_put(key->mctx, ec, sizeof(*ec));
00745 return (ISC_R_NOMEMORY);
00746 }
00747
00748 static isc_result_t
00749 pkcs11ecdsa_tofile(const dst_key_t *key, const char *directory) {
00750 isc_result_t ret;
00751 pk11_object_t *ec;
00752 dst_private_t priv;
00753 unsigned char *buf = NULL;
00754 unsigned int i = 0;
00755 CK_ATTRIBUTE *attr;
00756
00757 if (key->keydata.pkey == NULL)
00758 return (DST_R_NULLKEY);
00759
00760 if (key->external) {
00761 priv.nelements = 0;
00762 return (dst__privstruct_writefile(key, &priv, directory));
00763 }
00764
00765 ec = key->keydata.pkey;
00766 attr = pk11_attribute_bytype(ec, CKA_VALUE);
00767 if (attr != NULL) {
00768 buf = isc_mem_get(key->mctx, attr->ulValueLen);
00769 if (buf == NULL)
00770 return (ISC_R_NOMEMORY);
00771 priv.elements[i].tag = TAG_ECDSA_PRIVATEKEY;
00772 priv.elements[i].length = (unsigned short) attr->ulValueLen;
00773 memmove(buf, attr->pValue, attr->ulValueLen);
00774 priv.elements[i].data = buf;
00775 i++;
00776 }
00777
00778 if (key->engine != NULL) {
00779 priv.elements[i].tag = TAG_ECDSA_ENGINE;
00780 priv.elements[i].length = strlen(key->engine) + 1;
00781 priv.elements[i].data = (unsigned char *)key->engine;
00782 i++;
00783 }
00784
00785 if (key->label != NULL) {
00786 priv.elements[i].tag = TAG_ECDSA_LABEL;
00787 priv.elements[i].length = strlen(key->label) + 1;
00788 priv.elements[i].data = (unsigned char *)key->label;
00789 i++;
00790 }
00791
00792 priv.nelements = i;
00793 ret = dst__privstruct_writefile(key, &priv, directory);
00794
00795 if (buf != NULL) {
00796 memset(buf, 0, attr->ulValueLen);
00797 isc_mem_put(key->mctx, buf, attr->ulValueLen);
00798 }
00799 return (ret);
00800 }
00801
00802 static isc_result_t
00803 pkcs11ecdsa_fetch(dst_key_t *key, const char *engine, const char *label,
00804 dst_key_t *pub)
00805 {
00806 CK_RV rv;
00807 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
00808 CK_KEY_TYPE keyType = CKK_EC;
00809 CK_ATTRIBUTE searchTemplate[] =
00810 {
00811 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
00812 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00813 { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
00814 { CKA_LABEL, NULL, 0 }
00815 };
00816 CK_ULONG cnt;
00817 CK_ATTRIBUTE *attr;
00818 CK_ATTRIBUTE *pubattr;
00819 pk11_object_t *ec;
00820 pk11_object_t *pubec;
00821 pk11_context_t *pk11_ctx = NULL;
00822 isc_result_t ret;
00823
00824 if (label == NULL)
00825 return (DST_R_NOENGINE);
00826
00827 ec = key->keydata.pkey;
00828 pubec = pub->keydata.pkey;
00829
00830 ec->object = CK_INVALID_HANDLE;
00831 ec->ontoken = ISC_TRUE;
00832 ec->reqlogon = ISC_TRUE;
00833 ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
00834 if (ec->repr == NULL)
00835 return (ISC_R_NOMEMORY);
00836 memset(ec->repr, 0, sizeof(*attr) * 2);
00837 ec->attrcnt = 2;
00838 attr = ec->repr;
00839
00840 attr->type = CKA_EC_PARAMS;
00841 pubattr = pk11_attribute_bytype(pubec, CKA_EC_PARAMS);
00842 attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
00843 if (attr->pValue == NULL)
00844 DST_RET(ISC_R_NOMEMORY);
00845 memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
00846 attr->ulValueLen = pubattr->ulValueLen;
00847 attr++;
00848
00849 attr->type = CKA_EC_POINT;
00850 pubattr = pk11_attribute_bytype(pubec, CKA_EC_POINT);
00851 attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
00852 if (attr->pValue == NULL)
00853 DST_RET(ISC_R_NOMEMORY);
00854 memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
00855 attr->ulValueLen = pubattr->ulValueLen;
00856
00857 ret = pk11_parse_uri(ec, label, key->mctx, OP_EC);
00858 if (ret != ISC_R_SUCCESS)
00859 goto err;
00860
00861 pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
00862 sizeof(*pk11_ctx));
00863 if (pk11_ctx == NULL)
00864 DST_RET(ISC_R_NOMEMORY);
00865 ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE,
00866 ec->reqlogon, NULL, ec->slot);
00867 if (ret != ISC_R_SUCCESS)
00868 goto err;
00869
00870 attr = pk11_attribute_bytype(ec, CKA_LABEL);
00871 if (attr == NULL) {
00872 attr = pk11_attribute_bytype(ec, CKA_ID);
00873 INSIST(attr != NULL);
00874 searchTemplate[3].type = CKA_ID;
00875 }
00876 searchTemplate[3].pValue = attr->pValue;
00877 searchTemplate[3].ulValueLen = attr->ulValueLen;
00878
00879 PK11_RET(pkcs_C_FindObjectsInit,
00880 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
00881 DST_R_CRYPTOFAILURE);
00882 PK11_RET(pkcs_C_FindObjects,
00883 (pk11_ctx->session, &ec->object, (CK_ULONG) 1, &cnt),
00884 DST_R_CRYPTOFAILURE);
00885 (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
00886 if (cnt == 0)
00887 DST_RET(ISC_R_NOTFOUND);
00888 if (cnt > 1)
00889 DST_RET(ISC_R_EXISTS);
00890
00891 if (engine != NULL) {
00892 key->engine = isc_mem_strdup(key->mctx, engine);
00893 if (key->engine == NULL)
00894 DST_RET(ISC_R_NOMEMORY);
00895 }
00896
00897 key->label = isc_mem_strdup(key->mctx, label);
00898 if (key->label == NULL)
00899 DST_RET(ISC_R_NOMEMORY);
00900
00901 pk11_return_session(pk11_ctx);
00902 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00903 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
00904 return (ISC_R_SUCCESS);
00905
00906 err:
00907 if (pk11_ctx != NULL) {
00908 pk11_return_session(pk11_ctx);
00909 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00910 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
00911 }
00912 return (ret);
00913 }
00914
00915 static isc_result_t
00916 pkcs11ecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
00917 dst_private_t priv;
00918 isc_result_t ret;
00919 pk11_object_t *ec = NULL;
00920 CK_ATTRIBUTE *attr, *pattr;
00921 isc_mem_t *mctx = key->mctx;
00922 unsigned int i;
00923 const char *engine = NULL, *label = NULL;
00924
00925 REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
00926 key->key_alg == DST_ALG_ECDSA384);
00927
00928 if ((pub == NULL) || (pub->keydata.pkey == NULL))
00929 DST_RET(DST_R_INVALIDPRIVATEKEY);
00930
00931
00932 ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv);
00933 if (ret != ISC_R_SUCCESS)
00934 return (ret);
00935
00936 if (key->external) {
00937 if (priv.nelements != 0)
00938 DST_RET(DST_R_INVALIDPRIVATEKEY);
00939
00940 key->keydata.pkey = pub->keydata.pkey;
00941 pub->keydata.pkey = NULL;
00942 key->key_size = pub->key_size;
00943
00944 dst__privstruct_free(&priv, mctx);
00945 memset(&priv, 0, sizeof(priv));
00946
00947 return (ISC_R_SUCCESS);
00948 }
00949
00950 for (i = 0; i < priv.nelements; i++) {
00951 switch (priv.elements[i].tag) {
00952 case TAG_ECDSA_ENGINE:
00953 engine = (char *)priv.elements[i].data;
00954 break;
00955 case TAG_ECDSA_LABEL:
00956 label = (char *)priv.elements[i].data;
00957 break;
00958 default:
00959 break;
00960 }
00961 }
00962 ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
00963 if (ec == NULL)
00964 DST_RET(ISC_R_NOMEMORY);
00965 memset(ec, 0, sizeof(*ec));
00966 key->keydata.pkey = ec;
00967
00968
00969 if ((label != NULL) || (engine != NULL)) {
00970 ret = pkcs11ecdsa_fetch(key, engine, label, pub);
00971 if (ret != ISC_R_SUCCESS)
00972 goto err;
00973 dst__privstruct_free(&priv, mctx);
00974 memset(&priv, 0, sizeof(priv));
00975 return (ret);
00976 }
00977
00978 ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3);
00979 if (ec->repr == NULL)
00980 DST_RET(ISC_R_NOMEMORY);
00981 memset(ec->repr, 0, sizeof(*attr) * 3);
00982 ec->attrcnt = 3;
00983
00984 attr = ec->repr;
00985 attr->type = CKA_EC_PARAMS;
00986 pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_PARAMS);
00987 INSIST(pattr != NULL);
00988 attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen);
00989 if (attr->pValue == NULL)
00990 DST_RET(ISC_R_NOMEMORY);
00991 memmove(attr->pValue, pattr->pValue, pattr->ulValueLen);
00992 attr->ulValueLen = pattr->ulValueLen;
00993
00994 attr++;
00995 attr->type = CKA_EC_POINT;
00996 pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_POINT);
00997 INSIST(pattr != NULL);
00998 attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen);
00999 if (attr->pValue == NULL)
01000 DST_RET(ISC_R_NOMEMORY);
01001 memmove(attr->pValue, pattr->pValue, pattr->ulValueLen);
01002 attr->ulValueLen = pattr->ulValueLen;
01003
01004 attr++;
01005 attr->type = CKA_VALUE;
01006 attr->pValue = isc_mem_get(key->mctx, priv.elements[0].length);
01007 if (attr->pValue == NULL)
01008 DST_RET(ISC_R_NOMEMORY);
01009 memmove(attr->pValue, priv.elements[0].data, priv.elements[0].length);
01010 attr->ulValueLen = priv.elements[0].length;
01011
01012 dst__privstruct_free(&priv, mctx);
01013 memset(&priv, 0, sizeof(priv));
01014 if (key->key_alg == DST_ALG_ECDSA256)
01015 key->key_size = DNS_KEY_ECDSA256SIZE * 4;
01016 else
01017 key->key_size = DNS_KEY_ECDSA384SIZE * 4;
01018
01019 return (ISC_R_SUCCESS);
01020
01021 err:
01022 pkcs11ecdsa_destroy(key);
01023 dst__privstruct_free(&priv, mctx);
01024 memset(&priv, 0, sizeof(priv));
01025 return (ret);
01026 }
01027
01028 static isc_result_t
01029 pkcs11ecdsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
01030 const char *pin)
01031 {
01032 CK_RV rv;
01033 CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
01034 CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
01035 CK_KEY_TYPE keyType = CKK_EC;
01036 CK_ATTRIBUTE searchTemplate[] =
01037 {
01038 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
01039 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
01040 { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
01041 { CKA_LABEL, NULL, 0 }
01042 };
01043 CK_ULONG cnt;
01044 CK_ATTRIBUTE *attr;
01045 pk11_object_t *ec;
01046 pk11_context_t *pk11_ctx = NULL;
01047 isc_result_t ret;
01048 unsigned int i;
01049
01050 UNUSED(pin);
01051
01052 ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
01053 if (ec == NULL)
01054 return (ISC_R_NOMEMORY);
01055 memset(ec, 0, sizeof(*ec));
01056 ec->object = CK_INVALID_HANDLE;
01057 ec->ontoken = ISC_TRUE;
01058 ec->reqlogon = ISC_TRUE;
01059 key->keydata.pkey = ec;
01060
01061 ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
01062 if (ec->repr == NULL)
01063 DST_RET(ISC_R_NOMEMORY);
01064 memset(ec->repr, 0, sizeof(*attr) * 2);
01065 ec->attrcnt = 2;
01066 attr = ec->repr;
01067 attr[0].type = CKA_EC_PARAMS;
01068 attr[1].type = CKA_EC_POINT;
01069
01070 ret = pk11_parse_uri(ec, label, key->mctx, OP_EC);
01071 if (ret != ISC_R_SUCCESS)
01072 goto err;
01073
01074 pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
01075 sizeof(*pk11_ctx));
01076 if (pk11_ctx == NULL)
01077 DST_RET(ISC_R_NOMEMORY);
01078 ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE,
01079 ec->reqlogon, NULL, ec->slot);
01080 if (ret != ISC_R_SUCCESS)
01081 goto err;
01082
01083 attr = pk11_attribute_bytype(ec, CKA_LABEL);
01084 if (attr == NULL) {
01085 attr = pk11_attribute_bytype(ec, CKA_ID);
01086 INSIST(attr != NULL);
01087 searchTemplate[3].type = CKA_ID;
01088 }
01089 searchTemplate[3].pValue = attr->pValue;
01090 searchTemplate[3].ulValueLen = attr->ulValueLen;
01091
01092 PK11_RET(pkcs_C_FindObjectsInit,
01093 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
01094 DST_R_CRYPTOFAILURE);
01095 PK11_RET(pkcs_C_FindObjects,
01096 (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt),
01097 DST_R_CRYPTOFAILURE);
01098 (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
01099 if (cnt == 0)
01100 DST_RET(ISC_R_NOTFOUND);
01101 if (cnt > 1)
01102 DST_RET(ISC_R_EXISTS);
01103
01104 attr = ec->repr;
01105 PK11_RET(pkcs_C_GetAttributeValue,
01106 (pk11_ctx->session, hKey, attr, 2),
01107 DST_R_CRYPTOFAILURE);
01108 for (i = 0; i <= 1; i++) {
01109 attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
01110 if (attr[i].pValue == NULL)
01111 DST_RET(ISC_R_NOMEMORY);
01112 memset(attr[i].pValue, 0, attr[i].ulValueLen);
01113 }
01114 PK11_RET(pkcs_C_GetAttributeValue,
01115 (pk11_ctx->session, hKey, attr, 2),
01116 DST_R_CRYPTOFAILURE);
01117
01118 keyClass = CKO_PRIVATE_KEY;
01119 PK11_RET(pkcs_C_FindObjectsInit,
01120 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
01121 DST_R_CRYPTOFAILURE);
01122 PK11_RET(pkcs_C_FindObjects,
01123 (pk11_ctx->session, &ec->object, (CK_ULONG) 1, &cnt),
01124 DST_R_CRYPTOFAILURE);
01125 (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
01126 if (cnt == 0)
01127 DST_RET(ISC_R_NOTFOUND);
01128 if (cnt > 1)
01129 DST_RET(ISC_R_EXISTS);
01130
01131 if (engine != NULL) {
01132 key->engine = isc_mem_strdup(key->mctx, engine);
01133 if (key->engine == NULL)
01134 DST_RET(ISC_R_NOMEMORY);
01135 }
01136
01137 key->label = isc_mem_strdup(key->mctx, label);
01138 if (key->label == NULL)
01139 DST_RET(ISC_R_NOMEMORY);
01140 if (key->key_alg == DST_ALG_ECDSA256)
01141 key->key_size = DNS_KEY_ECDSA256SIZE * 4;
01142 else
01143 key->key_size = DNS_KEY_ECDSA384SIZE * 4;
01144
01145 pk11_return_session(pk11_ctx);
01146 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
01147 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
01148 return (ISC_R_SUCCESS);
01149
01150 err:
01151 pkcs11ecdsa_destroy(key);
01152 if (pk11_ctx != NULL) {
01153 pk11_return_session(pk11_ctx);
01154 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
01155 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
01156 }
01157 return (ret);
01158 }
01159
01160 static dst_func_t pkcs11ecdsa_functions = {
01161 pkcs11ecdsa_createctx,
01162 NULL,
01163 pkcs11ecdsa_destroyctx,
01164 pkcs11ecdsa_adddata,
01165 pkcs11ecdsa_sign,
01166 pkcs11ecdsa_verify,
01167 NULL,
01168 NULL,
01169 pkcs11ecdsa_compare,
01170 NULL,
01171 pkcs11ecdsa_generate,
01172 pkcs11ecdsa_isprivate,
01173 pkcs11ecdsa_destroy,
01174 pkcs11ecdsa_todns,
01175 pkcs11ecdsa_fromdns,
01176 pkcs11ecdsa_tofile,
01177 pkcs11ecdsa_parse,
01178 NULL,
01179 pkcs11ecdsa_fromlabel,
01180 NULL,
01181 NULL,
01182 };
01183
01184 isc_result_t
01185 dst__pkcs11ecdsa_init(dst_func_t **funcp) {
01186 REQUIRE(funcp != NULL);
01187 if (*funcp == NULL)
01188 *funcp = &pkcs11ecdsa_functions;
01189 return (ISC_R_SUCCESS);
01190 }
01191
01192 #else
01193
01194 #include <isc/util.h>
01195
01196 EMPTY_TRANSLATION_UNIT
01197
01198 #endif
01199