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(OPENSSL) && defined(HAVE_OPENSSL_ECDSA)
00022
00023 #if !defined(HAVE_EVP_SHA256) || !defined(HAVE_EVP_SHA384)
00024 #error "ECDSA without EVP for SHA2?"
00025 #endif
00026
00027 #include <isc/entropy.h>
00028 #include <isc/mem.h>
00029 #include <isc/sha2.h>
00030 #include <isc/string.h>
00031 #include <isc/util.h>
00032
00033 #include <dns/keyvalues.h>
00034 #include <dst/result.h>
00035
00036 #include "dst_internal.h"
00037 #include "dst_openssl.h"
00038 #include "dst_parse.h"
00039
00040 #include <openssl/err.h>
00041 #include <openssl/objects.h>
00042 #include <openssl/ecdsa.h>
00043 #include <openssl/bn.h>
00044
00045 #ifndef NID_X9_62_prime256v1
00046 #error "P-256 group is not known (NID_X9_62_prime256v1)"
00047 #endif
00048 #ifndef NID_secp384r1
00049 #error "P-384 group is not known (NID_secp384r1)"
00050 #endif
00051
00052 #define DST_RET(a) {ret = a; goto err;}
00053
00054 static isc_result_t opensslecdsa_todns(const dst_key_t *key,
00055 isc_buffer_t *data);
00056
00057 static isc_result_t
00058 opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
00059 EVP_MD_CTX *evp_md_ctx;
00060 const EVP_MD *type = NULL;
00061
00062 UNUSED(key);
00063 REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
00064 dctx->key->key_alg == DST_ALG_ECDSA384);
00065
00066 evp_md_ctx = EVP_MD_CTX_create();
00067 if (evp_md_ctx == NULL)
00068 return (ISC_R_NOMEMORY);
00069 if (dctx->key->key_alg == DST_ALG_ECDSA256)
00070 type = EVP_sha256();
00071 else
00072 type = EVP_sha384();
00073
00074 if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) {
00075 EVP_MD_CTX_destroy(evp_md_ctx);
00076 return (dst__openssl_toresult3(dctx->category,
00077 "EVP_DigestInit_ex",
00078 ISC_R_FAILURE));
00079 }
00080
00081 dctx->ctxdata.evp_md_ctx = evp_md_ctx;
00082
00083 return (ISC_R_SUCCESS);
00084 }
00085
00086 static void
00087 opensslecdsa_destroyctx(dst_context_t *dctx) {
00088 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00089
00090 REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
00091 dctx->key->key_alg == DST_ALG_ECDSA384);
00092
00093 if (evp_md_ctx != NULL) {
00094 EVP_MD_CTX_destroy(evp_md_ctx);
00095 dctx->ctxdata.evp_md_ctx = NULL;
00096 }
00097 }
00098
00099 static isc_result_t
00100 opensslecdsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
00101 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00102
00103 REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
00104 dctx->key->key_alg == DST_ALG_ECDSA384);
00105
00106 if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length))
00107 return (dst__openssl_toresult3(dctx->category,
00108 "EVP_DigestUpdate",
00109 ISC_R_FAILURE));
00110
00111 return (ISC_R_SUCCESS);
00112 }
00113
00114 static int
00115 BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
00116 int bytes = size - BN_num_bytes(bn);
00117
00118 while (bytes-- > 0)
00119 *buf++ = 0;
00120 BN_bn2bin(bn, buf);
00121 return (size);
00122 }
00123
00124 static isc_result_t
00125 opensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
00126 isc_result_t ret;
00127 dst_key_t *key = dctx->key;
00128 isc_region_t r;
00129 ECDSA_SIG *ecdsasig;
00130 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00131 EVP_PKEY *pkey = key->keydata.pkey;
00132 EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey);
00133 unsigned int dgstlen, siglen;
00134 unsigned char digest[EVP_MAX_MD_SIZE];
00135
00136 REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
00137 key->key_alg == DST_ALG_ECDSA384);
00138
00139 if (eckey == NULL)
00140 return (ISC_R_FAILURE);
00141
00142 if (key->key_alg == DST_ALG_ECDSA256)
00143 siglen = DNS_SIG_ECDSA256SIZE;
00144 else
00145 siglen = DNS_SIG_ECDSA384SIZE;
00146
00147 isc_buffer_availableregion(sig, &r);
00148 if (r.length < siglen)
00149 DST_RET(ISC_R_NOSPACE);
00150
00151 if (!EVP_DigestFinal(evp_md_ctx, digest, &dgstlen))
00152 DST_RET(dst__openssl_toresult3(dctx->category,
00153 "EVP_DigestFinal",
00154 ISC_R_FAILURE));
00155
00156 ecdsasig = ECDSA_do_sign(digest, dgstlen, eckey);
00157 if (ecdsasig == NULL)
00158 DST_RET(dst__openssl_toresult3(dctx->category,
00159 "ECDSA_do_sign",
00160 DST_R_SIGNFAILURE));
00161 BN_bn2bin_fixed(ecdsasig->r, r.base, siglen / 2);
00162 r.base += siglen / 2;
00163 BN_bn2bin_fixed(ecdsasig->s, r.base, siglen / 2);
00164 r.base += siglen / 2;
00165 ECDSA_SIG_free(ecdsasig);
00166 isc_buffer_add(sig, siglen);
00167 ret = ISC_R_SUCCESS;
00168
00169 err:
00170 if (eckey != NULL)
00171 EC_KEY_free(eckey);
00172 return (ret);
00173 }
00174
00175 static isc_result_t
00176 opensslecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
00177 isc_result_t ret;
00178 dst_key_t *key = dctx->key;
00179 int status;
00180 unsigned char *cp = sig->base;
00181 ECDSA_SIG *ecdsasig = NULL;
00182 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00183 EVP_PKEY *pkey = key->keydata.pkey;
00184 EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey);
00185 unsigned int dgstlen, siglen;
00186 unsigned char digest[EVP_MAX_MD_SIZE];
00187
00188 REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
00189 key->key_alg == DST_ALG_ECDSA384);
00190
00191 if (eckey == NULL)
00192 return (ISC_R_FAILURE);
00193
00194 if (key->key_alg == DST_ALG_ECDSA256)
00195 siglen = DNS_SIG_ECDSA256SIZE;
00196 else
00197 siglen = DNS_SIG_ECDSA384SIZE;
00198
00199 if (sig->length != siglen)
00200 return (DST_R_VERIFYFAILURE);
00201
00202 if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &dgstlen))
00203 DST_RET (dst__openssl_toresult3(dctx->category,
00204 "EVP_DigestFinal_ex",
00205 ISC_R_FAILURE));
00206
00207 ecdsasig = ECDSA_SIG_new();
00208 if (ecdsasig == NULL)
00209 DST_RET (ISC_R_NOMEMORY);
00210 if (ecdsasig->r != NULL)
00211 BN_free(ecdsasig->r);
00212 ecdsasig->r = BN_bin2bn(cp, siglen / 2, NULL);
00213 cp += siglen / 2;
00214 if (ecdsasig->s != NULL)
00215 BN_free(ecdsasig->s);
00216 ecdsasig->s = BN_bin2bn(cp, siglen / 2, NULL);
00217
00218
00219 status = ECDSA_do_verify(digest, dgstlen, ecdsasig, eckey);
00220 switch (status) {
00221 case 1:
00222 ret = ISC_R_SUCCESS;
00223 break;
00224 case 0:
00225 ret = dst__openssl_toresult(DST_R_VERIFYFAILURE);
00226 break;
00227 default:
00228 ret = dst__openssl_toresult3(dctx->category,
00229 "ECDSA_do_verify",
00230 DST_R_VERIFYFAILURE);
00231 break;
00232 }
00233
00234 err:
00235 if (ecdsasig != NULL)
00236 ECDSA_SIG_free(ecdsasig);
00237 if (eckey != NULL)
00238 EC_KEY_free(eckey);
00239 return (ret);
00240 }
00241
00242 static isc_boolean_t
00243 opensslecdsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
00244 isc_boolean_t ret;
00245 int status;
00246 EVP_PKEY *pkey1 = key1->keydata.pkey;
00247 EVP_PKEY *pkey2 = key2->keydata.pkey;
00248 EC_KEY *eckey1 = NULL;
00249 EC_KEY *eckey2 = NULL;
00250 const BIGNUM *priv1, *priv2;
00251
00252 if (pkey1 == NULL && pkey2 == NULL)
00253 return (ISC_TRUE);
00254 else if (pkey1 == NULL || pkey2 == NULL)
00255 return (ISC_FALSE);
00256
00257 eckey1 = EVP_PKEY_get1_EC_KEY(pkey1);
00258 eckey2 = EVP_PKEY_get1_EC_KEY(pkey2);
00259 if (eckey1 == NULL && eckey2 == NULL) {
00260 DST_RET (ISC_TRUE);
00261 } else if (eckey1 == NULL || eckey2 == NULL)
00262 DST_RET (ISC_FALSE);
00263
00264 status = EVP_PKEY_cmp(pkey1, pkey2);
00265 if (status != 1)
00266 DST_RET (ISC_FALSE);
00267
00268 priv1 = EC_KEY_get0_private_key(eckey1);
00269 priv2 = EC_KEY_get0_private_key(eckey2);
00270 if (priv1 != NULL || priv2 != NULL) {
00271 if (priv1 == NULL || priv2 == NULL)
00272 DST_RET (ISC_FALSE);
00273 if (BN_cmp(priv1, priv2) != 0)
00274 DST_RET (ISC_FALSE);
00275 }
00276 ret = ISC_TRUE;
00277
00278 err:
00279 if (eckey1 != NULL)
00280 EC_KEY_free(eckey1);
00281 if (eckey2 != NULL)
00282 EC_KEY_free(eckey2);
00283 return (ret);
00284 }
00285
00286 static isc_result_t
00287 opensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
00288 isc_result_t ret;
00289 EVP_PKEY *pkey;
00290 EC_KEY *eckey = NULL;
00291 int group_nid;
00292
00293 REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
00294 key->key_alg == DST_ALG_ECDSA384);
00295 UNUSED(unused);
00296 UNUSED(callback);
00297
00298 if (key->key_alg == DST_ALG_ECDSA256) {
00299 group_nid = NID_X9_62_prime256v1;
00300 key->key_size = DNS_KEY_ECDSA256SIZE * 4;
00301 } else {
00302 group_nid = NID_secp384r1;
00303 key->key_size = DNS_KEY_ECDSA384SIZE * 4;
00304 }
00305
00306 eckey = EC_KEY_new_by_curve_name(group_nid);
00307 if (eckey == NULL)
00308 return (dst__openssl_toresult2("EC_KEY_new_by_curve_name",
00309 DST_R_OPENSSLFAILURE));
00310
00311 if (EC_KEY_generate_key(eckey) != 1)
00312 DST_RET (dst__openssl_toresult2("EC_KEY_generate_key",
00313 DST_R_OPENSSLFAILURE));
00314
00315 pkey = EVP_PKEY_new();
00316 if (pkey == NULL)
00317 DST_RET (ISC_R_NOMEMORY);
00318 if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
00319 EVP_PKEY_free(pkey);
00320 DST_RET (ISC_R_FAILURE);
00321 }
00322 key->keydata.pkey = pkey;
00323 ret = ISC_R_SUCCESS;
00324
00325 err:
00326 if (eckey != NULL)
00327 EC_KEY_free(eckey);
00328 return (ret);
00329 }
00330
00331 static isc_boolean_t
00332 opensslecdsa_isprivate(const dst_key_t *key) {
00333 isc_boolean_t ret;
00334 EVP_PKEY *pkey = key->keydata.pkey;
00335 EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey);
00336
00337 ret = ISC_TF(eckey != NULL && EC_KEY_get0_private_key(eckey) != NULL);
00338 if (eckey != NULL)
00339 EC_KEY_free(eckey);
00340 return (ret);
00341 }
00342
00343 static void
00344 opensslecdsa_destroy(dst_key_t *key) {
00345 EVP_PKEY *pkey = key->keydata.pkey;
00346
00347 EVP_PKEY_free(pkey);
00348 key->keydata.pkey = NULL;
00349 }
00350
00351 static isc_result_t
00352 opensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) {
00353 isc_result_t ret;
00354 EVP_PKEY *pkey;
00355 EC_KEY *eckey = NULL;
00356 isc_region_t r;
00357 int len;
00358 unsigned char *cp;
00359 unsigned char buf[DNS_KEY_ECDSA384SIZE + 1];
00360
00361 REQUIRE(key->keydata.pkey != NULL);
00362
00363 pkey = key->keydata.pkey;
00364 eckey = EVP_PKEY_get1_EC_KEY(pkey);
00365 if (eckey == NULL)
00366 return (dst__openssl_toresult(ISC_R_FAILURE));
00367 len = i2o_ECPublicKey(eckey, NULL);
00368
00369 len--;
00370
00371 isc_buffer_availableregion(data, &r);
00372 if (r.length < (unsigned int) len)
00373 DST_RET (ISC_R_NOSPACE);
00374 cp = buf;
00375 if (!i2o_ECPublicKey(eckey, &cp))
00376 DST_RET (dst__openssl_toresult(ISC_R_FAILURE));
00377 memmove(r.base, buf + 1, len);
00378 isc_buffer_add(data, len);
00379 ret = ISC_R_SUCCESS;
00380
00381 err:
00382 if (eckey != NULL)
00383 EC_KEY_free(eckey);
00384 return (ret);
00385 }
00386
00387 static isc_result_t
00388 opensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
00389 isc_result_t ret;
00390 EVP_PKEY *pkey;
00391 EC_KEY *eckey = NULL;
00392 isc_region_t r;
00393 int group_nid;
00394 unsigned int len;
00395 const unsigned char *cp;
00396 unsigned char buf[DNS_KEY_ECDSA384SIZE + 1];
00397
00398 REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
00399 key->key_alg == DST_ALG_ECDSA384);
00400
00401 if (key->key_alg == DST_ALG_ECDSA256) {
00402 len = DNS_KEY_ECDSA256SIZE;
00403 group_nid = NID_X9_62_prime256v1;
00404 } else {
00405 len = DNS_KEY_ECDSA384SIZE;
00406 group_nid = NID_secp384r1;
00407 }
00408
00409 isc_buffer_remainingregion(data, &r);
00410 if (r.length == 0)
00411 return (ISC_R_SUCCESS);
00412 if (r.length < len)
00413 return (DST_R_INVALIDPUBLICKEY);
00414
00415 eckey = EC_KEY_new_by_curve_name(group_nid);
00416 if (eckey == NULL)
00417 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
00418
00419 buf[0] = POINT_CONVERSION_UNCOMPRESSED;
00420 memmove(buf + 1, r.base, len);
00421 cp = buf;
00422 if (o2i_ECPublicKey(&eckey,
00423 (const unsigned char **) &cp,
00424 (long) len + 1) == NULL)
00425 DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY));
00426 if (EC_KEY_check_key(eckey) != 1)
00427 DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY));
00428
00429 pkey = EVP_PKEY_new();
00430 if (pkey == NULL)
00431 DST_RET (ISC_R_NOMEMORY);
00432 if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
00433 EVP_PKEY_free(pkey);
00434 DST_RET (dst__openssl_toresult(ISC_R_FAILURE));
00435 }
00436
00437 isc_buffer_forward(data, len);
00438 key->keydata.pkey = pkey;
00439 key->key_size = len * 4;
00440 ret = ISC_R_SUCCESS;
00441
00442 err:
00443 if (eckey != NULL)
00444 EC_KEY_free(eckey);
00445 return (ret);
00446 }
00447
00448 static isc_result_t
00449 opensslecdsa_tofile(const dst_key_t *key, const char *directory) {
00450 isc_result_t ret;
00451 EVP_PKEY *pkey;
00452 EC_KEY *eckey = NULL;
00453 const BIGNUM *privkey;
00454 dst_private_t priv;
00455 unsigned char *buf = NULL;
00456
00457 if (key->keydata.pkey == NULL)
00458 return (DST_R_NULLKEY);
00459
00460 if (key->external) {
00461 priv.nelements = 0;
00462 return (dst__privstruct_writefile(key, &priv, directory));
00463 }
00464
00465 pkey = key->keydata.pkey;
00466 eckey = EVP_PKEY_get1_EC_KEY(pkey);
00467 if (eckey == NULL)
00468 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
00469 privkey = EC_KEY_get0_private_key(eckey);
00470 if (privkey == NULL)
00471 DST_RET (ISC_R_FAILURE);
00472
00473 buf = isc_mem_get(key->mctx, BN_num_bytes(privkey));
00474 if (buf == NULL)
00475 DST_RET (ISC_R_NOMEMORY);
00476
00477 priv.elements[0].tag = TAG_ECDSA_PRIVATEKEY;
00478 priv.elements[0].length = BN_num_bytes(privkey);
00479 BN_bn2bin(privkey, buf);
00480 priv.elements[0].data = buf;
00481 priv.nelements = 1;
00482 ret = dst__privstruct_writefile(key, &priv, directory);
00483
00484 err:
00485 if (eckey != NULL)
00486 EC_KEY_free(eckey);
00487 if (buf != NULL)
00488 isc_mem_put(key->mctx, buf, BN_num_bytes(privkey));
00489 return (ret);
00490 }
00491
00492 static isc_result_t
00493 ecdsa_check(EC_KEY *eckey, dst_key_t *pub)
00494 {
00495 isc_result_t ret = ISC_R_FAILURE;
00496 EVP_PKEY *pkey;
00497 EC_KEY *pubeckey = NULL;
00498 const EC_POINT *pubkey;
00499
00500 if (pub == NULL)
00501 return (ISC_R_SUCCESS);
00502 pkey = pub->keydata.pkey;
00503 if (pkey == NULL)
00504 return (ISC_R_SUCCESS);
00505 pubeckey = EVP_PKEY_get1_EC_KEY(pkey);
00506 if (pubeckey == NULL)
00507 return (ISC_R_SUCCESS);
00508 pubkey = EC_KEY_get0_public_key(pubeckey);
00509 if (pubkey == NULL)
00510 DST_RET (ISC_R_SUCCESS);
00511 if (EC_KEY_set_public_key(eckey, pubkey) != 1)
00512 DST_RET (ISC_R_SUCCESS);
00513 if (EC_KEY_check_key(eckey) == 1)
00514 DST_RET (ISC_R_SUCCESS);
00515
00516 err:
00517 if (pubeckey != NULL)
00518 EC_KEY_free(pubeckey);
00519 return (ret);
00520 }
00521
00522 static isc_result_t
00523 opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
00524 dst_private_t priv;
00525 isc_result_t ret;
00526 EVP_PKEY *pkey;
00527 EC_KEY *eckey = NULL;
00528 BIGNUM *privkey = NULL;
00529 int group_nid;
00530 isc_mem_t *mctx = key->mctx;
00531
00532 REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
00533 key->key_alg == DST_ALG_ECDSA384);
00534
00535
00536 ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv);
00537 if (ret != ISC_R_SUCCESS)
00538 goto err;
00539
00540 if (key->external) {
00541 if (priv.nelements != 0)
00542 DST_RET(DST_R_INVALIDPRIVATEKEY);
00543 if (pub == NULL)
00544 DST_RET(DST_R_INVALIDPRIVATEKEY);
00545 key->keydata.pkey = pub->keydata.pkey;
00546 pub->keydata.pkey = NULL;
00547 dst__privstruct_free(&priv, mctx);
00548 memset(&priv, 0, sizeof(priv));
00549 return (ISC_R_SUCCESS);
00550 }
00551
00552 if (key->key_alg == DST_ALG_ECDSA256)
00553 group_nid = NID_X9_62_prime256v1;
00554 else
00555 group_nid = NID_secp384r1;
00556
00557 eckey = EC_KEY_new_by_curve_name(group_nid);
00558 if (eckey == NULL)
00559 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
00560
00561 privkey = BN_bin2bn(priv.elements[0].data,
00562 priv.elements[0].length, NULL);
00563 if (privkey == NULL)
00564 DST_RET(ISC_R_NOMEMORY);
00565 if (!EC_KEY_set_private_key(eckey, privkey))
00566 DST_RET(ISC_R_NOMEMORY);
00567 if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS)
00568 DST_RET(DST_R_INVALIDPRIVATEKEY);
00569
00570 pkey = EVP_PKEY_new();
00571 if (pkey == NULL)
00572 DST_RET (ISC_R_NOMEMORY);
00573 if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
00574 EVP_PKEY_free(pkey);
00575 DST_RET (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
00576 }
00577 key->keydata.pkey = pkey;
00578 if (key->key_alg == DST_ALG_ECDSA256)
00579 key->key_size = DNS_KEY_ECDSA256SIZE * 4;
00580 else
00581 key->key_size = DNS_KEY_ECDSA384SIZE * 4;
00582 ret = ISC_R_SUCCESS;
00583
00584 err:
00585 if (privkey != NULL)
00586 BN_clear_free(privkey);
00587 if (eckey != NULL)
00588 EC_KEY_free(eckey);
00589 dst__privstruct_free(&priv, mctx);
00590 memset(&priv, 0, sizeof(priv));
00591 return (ret);
00592 }
00593
00594 static dst_func_t opensslecdsa_functions = {
00595 opensslecdsa_createctx,
00596 NULL,
00597 opensslecdsa_destroyctx,
00598 opensslecdsa_adddata,
00599 opensslecdsa_sign,
00600 opensslecdsa_verify,
00601 NULL,
00602 NULL,
00603 opensslecdsa_compare,
00604 NULL,
00605 opensslecdsa_generate,
00606 opensslecdsa_isprivate,
00607 opensslecdsa_destroy,
00608 opensslecdsa_todns,
00609 opensslecdsa_fromdns,
00610 opensslecdsa_tofile,
00611 opensslecdsa_parse,
00612 NULL,
00613 NULL,
00614 NULL,
00615 NULL,
00616 };
00617
00618 isc_result_t
00619 dst__opensslecdsa_init(dst_func_t **funcp) {
00620 REQUIRE(funcp != NULL);
00621 if (*funcp == NULL)
00622 *funcp = &opensslecdsa_functions;
00623 return (ISC_R_SUCCESS);
00624 }
00625
00626 #else
00627
00628 #include <isc/util.h>
00629
00630 EMPTY_TRANSLATION_UNIT
00631
00632 #endif
00633