00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifdef OPENSSL
00035 #ifndef USE_EVP
00036 #define USE_EVP 1
00037 #endif
00038
00039 #include <config.h>
00040
00041 #include <string.h>
00042
00043 #include <isc/entropy.h>
00044 #include <isc/mem.h>
00045 #include <isc/sha1.h>
00046 #include <isc/util.h>
00047
00048 #include <dst/result.h>
00049
00050 #include "dst_internal.h"
00051 #include "dst_openssl.h"
00052 #include "dst_parse.h"
00053
00054 #include <openssl/dsa.h>
00055
00056 static isc_result_t openssldsa_todns(const dst_key_t *key, isc_buffer_t *data);
00057
00058 static isc_result_t
00059 openssldsa_createctx(dst_key_t *key, dst_context_t *dctx) {
00060 #if USE_EVP
00061 EVP_MD_CTX *evp_md_ctx;
00062
00063 UNUSED(key);
00064
00065 evp_md_ctx = EVP_MD_CTX_create();
00066 if (evp_md_ctx == NULL)
00067 return (ISC_R_NOMEMORY);
00068
00069 if (!EVP_DigestInit_ex(evp_md_ctx, EVP_dss1(), NULL)) {
00070 EVP_MD_CTX_destroy(evp_md_ctx);
00071 return (ISC_R_FAILURE);
00072 }
00073
00074 dctx->ctxdata.evp_md_ctx = evp_md_ctx;
00075
00076 return (ISC_R_SUCCESS);
00077 #else
00078 isc_sha1_t *sha1ctx;
00079
00080 UNUSED(key);
00081
00082 sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
00083 isc_sha1_init(sha1ctx);
00084 dctx->ctxdata.sha1ctx = sha1ctx;
00085 return (ISC_R_SUCCESS);
00086 #endif
00087 }
00088
00089 static void
00090 openssldsa_destroyctx(dst_context_t *dctx) {
00091 #if USE_EVP
00092 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00093
00094 if (evp_md_ctx != NULL) {
00095 EVP_MD_CTX_destroy(evp_md_ctx);
00096 dctx->ctxdata.evp_md_ctx = NULL;
00097 }
00098 #else
00099 isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
00100
00101 if (sha1ctx != NULL) {
00102 isc_sha1_invalidate(sha1ctx);
00103 isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
00104 dctx->ctxdata.sha1ctx = NULL;
00105 }
00106 #endif
00107 }
00108
00109 static isc_result_t
00110 openssldsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
00111 #if USE_EVP
00112 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00113
00114 if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) {
00115 return (ISC_R_FAILURE);
00116 }
00117 #else
00118 isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
00119
00120 isc_sha1_update(sha1ctx, data->base, data->length);
00121 #endif
00122 return (ISC_R_SUCCESS);
00123 }
00124
00125 static int
00126 BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
00127 int bytes = size - BN_num_bytes(bn);
00128 while (bytes-- > 0)
00129 *buf++ = 0;
00130 BN_bn2bin(bn, buf);
00131 return (size);
00132 }
00133
00134 static isc_result_t
00135 openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
00136 dst_key_t *key = dctx->key;
00137 DSA *dsa = key->keydata.dsa;
00138 isc_region_t r;
00139 DSA_SIG *dsasig;
00140 #if USE_EVP
00141 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00142 EVP_PKEY *pkey;
00143 unsigned char *sigbuf;
00144 const unsigned char *sb;
00145 unsigned int siglen;
00146 #else
00147 isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
00148 unsigned char digest[ISC_SHA1_DIGESTLENGTH];
00149 #endif
00150
00151 isc_buffer_availableregion(sig, &r);
00152 if (r.length < ISC_SHA1_DIGESTLENGTH * 2 + 1)
00153 return (ISC_R_NOSPACE);
00154
00155 #if USE_EVP
00156 pkey = EVP_PKEY_new();
00157 if (pkey == NULL)
00158 return (ISC_R_NOMEMORY);
00159 if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
00160 EVP_PKEY_free(pkey);
00161 return (ISC_R_FAILURE);
00162 }
00163 sigbuf = malloc(EVP_PKEY_size(pkey));
00164 if (sigbuf == NULL) {
00165 EVP_PKEY_free(pkey);
00166 return (ISC_R_NOMEMORY);
00167 }
00168 if (!EVP_SignFinal(evp_md_ctx, sigbuf, &siglen, pkey)) {
00169 EVP_PKEY_free(pkey);
00170 free(sigbuf);
00171 return (dst__openssl_toresult3(dctx->category,
00172 "EVP_SignFinal",
00173 ISC_R_FAILURE));
00174 }
00175 INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
00176 EVP_PKEY_free(pkey);
00177
00178 dsasig = DSA_SIG_new();
00179 if (dsasig == NULL) {
00180 free(sigbuf);
00181 return (ISC_R_NOMEMORY);
00182 }
00183 sb = sigbuf;
00184 if (d2i_DSA_SIG(&dsasig, &sb, (long) siglen) == NULL) {
00185 free(sigbuf);
00186 return (dst__openssl_toresult3(dctx->category,
00187 "d2i_DSA_SIG",
00188 ISC_R_FAILURE));
00189 }
00190 free(sigbuf);
00191 #elif 0
00192
00193 if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
00194 return (dst__openssl_toresult3(dctx->category,
00195 "EVP_DigestFinal_ex",
00196 ISC_R_FAILURE));
00197 }
00198 dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
00199 if (dsasig == NULL)
00200 return (dst__openssl_toresult3(dctx->category,
00201 "DSA_do_sign",
00202 DST_R_SIGNFAILURE));
00203 #else
00204 isc_sha1_final(sha1ctx, digest);
00205
00206 dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
00207 if (dsasig == NULL)
00208 return (dst__openssl_toresult3(dctx->category,
00209 "DSA_do_sign",
00210 DST_R_SIGNFAILURE));
00211 #endif
00212 *r.base++ = (key->key_size - 512)/64;
00213 BN_bn2bin_fixed(dsasig->r, r.base, ISC_SHA1_DIGESTLENGTH);
00214 r.base += ISC_SHA1_DIGESTLENGTH;
00215 BN_bn2bin_fixed(dsasig->s, r.base, ISC_SHA1_DIGESTLENGTH);
00216 r.base += ISC_SHA1_DIGESTLENGTH;
00217 DSA_SIG_free(dsasig);
00218 isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1);
00219
00220 return (ISC_R_SUCCESS);
00221 }
00222
00223 static isc_result_t
00224 openssldsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
00225 dst_key_t *key = dctx->key;
00226 DSA *dsa = key->keydata.dsa;
00227 int status = 0;
00228 unsigned char *cp = sig->base;
00229 DSA_SIG *dsasig;
00230 #if USE_EVP
00231 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00232 #if 0
00233 EVP_PKEY *pkey;
00234 unsigned char *sigbuf;
00235 #endif
00236 unsigned int siglen;
00237 #else
00238 isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
00239 #endif
00240 unsigned char digest[ISC_SHA1_DIGESTLENGTH];
00241
00242
00243 #if USE_EVP
00244 #if 1
00245
00246 if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
00247 return (ISC_R_FAILURE);
00248 }
00249 #endif
00250 #else
00251 isc_sha1_final(sha1ctx, digest);
00252 #endif
00253
00254 if (sig->length != 2 * ISC_SHA1_DIGESTLENGTH + 1) {
00255 return (DST_R_VERIFYFAILURE);
00256 }
00257
00258 cp++;
00259 dsasig = DSA_SIG_new();
00260 if (dsasig == NULL)
00261 return (ISC_R_NOMEMORY);
00262 dsasig->r = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
00263 cp += ISC_SHA1_DIGESTLENGTH;
00264 dsasig->s = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
00265
00266 #if 0
00267 pkey = EVP_PKEY_new();
00268 if (pkey == NULL)
00269 return (ISC_R_NOMEMORY);
00270 if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
00271 EVP_PKEY_free(pkey);
00272 return (ISC_R_FAILURE);
00273 }
00274
00275 sigbuf = malloc(EVP_PKEY_size(pkey) + 50);
00276 if (sigbuf == NULL) {
00277 EVP_PKEY_free(pkey);
00278 return (ISC_R_NOMEMORY);
00279 }
00280 siglen = (unsigned) i2d_DSA_SIG(dsasig, &sigbuf);
00281 INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
00282 status = EVP_VerifyFinal(evp_md_ctx, sigbuf, siglen, pkey);
00283 EVP_PKEY_free(pkey);
00284 free(sigbuf);
00285 #else
00286 status = DSA_do_verify(digest, ISC_SHA1_DIGESTLENGTH, dsasig, dsa);
00287 #endif
00288 DSA_SIG_free(dsasig);
00289 switch (status) {
00290 case 1:
00291 return (ISC_R_SUCCESS);
00292 case 0:
00293 return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
00294 default:
00295 return (dst__openssl_toresult3(dctx->category,
00296 "DSA_do_verify",
00297 DST_R_VERIFYFAILURE));
00298 }
00299 }
00300
00301 static isc_boolean_t
00302 openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
00303 int status;
00304 DSA *dsa1, *dsa2;
00305
00306 dsa1 = key1->keydata.dsa;
00307 dsa2 = key2->keydata.dsa;
00308
00309 if (dsa1 == NULL && dsa2 == NULL)
00310 return (ISC_TRUE);
00311 else if (dsa1 == NULL || dsa2 == NULL)
00312 return (ISC_FALSE);
00313
00314 status = BN_cmp(dsa1->p, dsa2->p) ||
00315 BN_cmp(dsa1->q, dsa2->q) ||
00316 BN_cmp(dsa1->g, dsa2->g) ||
00317 BN_cmp(dsa1->pub_key, dsa2->pub_key);
00318
00319 if (status != 0)
00320 return (ISC_FALSE);
00321
00322 if (dsa1->priv_key != NULL || dsa2->priv_key != NULL) {
00323 if (dsa1->priv_key == NULL || dsa2->priv_key == NULL)
00324 return (ISC_FALSE);
00325 if (BN_cmp(dsa1->priv_key, dsa2->priv_key))
00326 return (ISC_FALSE);
00327 }
00328 return (ISC_TRUE);
00329 }
00330
00331 #if OPENSSL_VERSION_NUMBER > 0x00908000L
00332 static int
00333 progress_cb(int p, int n, BN_GENCB *cb)
00334 {
00335 union {
00336 void *dptr;
00337 void (*fptr)(int);
00338 } u;
00339
00340 UNUSED(n);
00341
00342 u.dptr = cb->arg;
00343 if (u.fptr != NULL)
00344 u.fptr(p);
00345 return (1);
00346 }
00347 #endif
00348
00349 static isc_result_t
00350 openssldsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
00351 DSA *dsa;
00352 unsigned char rand_array[ISC_SHA1_DIGESTLENGTH];
00353 isc_result_t result;
00354 #if OPENSSL_VERSION_NUMBER > 0x00908000L
00355 BN_GENCB cb;
00356 union {
00357 void *dptr;
00358 void (*fptr)(int);
00359 } u;
00360
00361 #else
00362
00363 UNUSED(callback);
00364 #endif
00365 UNUSED(unused);
00366
00367 result = dst__entropy_getdata(rand_array, sizeof(rand_array),
00368 ISC_FALSE);
00369 if (result != ISC_R_SUCCESS)
00370 return (result);
00371
00372 #if OPENSSL_VERSION_NUMBER > 0x00908000L
00373 dsa = DSA_new();
00374 if (dsa == NULL)
00375 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
00376
00377 if (callback == NULL) {
00378 BN_GENCB_set_old(&cb, NULL, NULL);
00379 } else {
00380 u.fptr = callback;
00381 BN_GENCB_set(&cb, &progress_cb, u.dptr);
00382 }
00383
00384 if (!DSA_generate_parameters_ex(dsa, key->key_size, rand_array,
00385 ISC_SHA1_DIGESTLENGTH, NULL, NULL,
00386 &cb))
00387 {
00388 DSA_free(dsa);
00389 return (dst__openssl_toresult2("DSA_generate_parameters_ex",
00390 DST_R_OPENSSLFAILURE));
00391 }
00392 #else
00393 dsa = DSA_generate_parameters(key->key_size, rand_array,
00394 ISC_SHA1_DIGESTLENGTH, NULL, NULL,
00395 NULL, NULL);
00396 if (dsa == NULL)
00397 return (dst__openssl_toresult2("DSA_generate_parameters",
00398 DST_R_OPENSSLFAILURE));
00399 #endif
00400
00401 if (DSA_generate_key(dsa) == 0) {
00402 DSA_free(dsa);
00403 return (dst__openssl_toresult2("DSA_generate_key",
00404 DST_R_OPENSSLFAILURE));
00405 }
00406 dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
00407
00408 key->keydata.dsa = dsa;
00409
00410 return (ISC_R_SUCCESS);
00411 }
00412
00413 static isc_boolean_t
00414 openssldsa_isprivate(const dst_key_t *key) {
00415 DSA *dsa = key->keydata.dsa;
00416 return (ISC_TF(dsa != NULL && dsa->priv_key != NULL));
00417 }
00418
00419 static void
00420 openssldsa_destroy(dst_key_t *key) {
00421 DSA *dsa = key->keydata.dsa;
00422 DSA_free(dsa);
00423 key->keydata.dsa = NULL;
00424 }
00425
00426
00427 static isc_result_t
00428 openssldsa_todns(const dst_key_t *key, isc_buffer_t *data) {
00429 DSA *dsa;
00430 isc_region_t r;
00431 int dnslen;
00432 unsigned int t, p_bytes;
00433
00434 REQUIRE(key->keydata.dsa != NULL);
00435
00436 dsa = key->keydata.dsa;
00437
00438 isc_buffer_availableregion(data, &r);
00439
00440 t = (BN_num_bytes(dsa->p) - 64) / 8;
00441 if (t > 8)
00442 return (DST_R_INVALIDPUBLICKEY);
00443 p_bytes = 64 + 8 * t;
00444
00445 dnslen = 1 + (key->key_size * 3)/8 + ISC_SHA1_DIGESTLENGTH;
00446 if (r.length < (unsigned int) dnslen)
00447 return (ISC_R_NOSPACE);
00448
00449 *r.base++ = t;
00450 BN_bn2bin_fixed(dsa->q, r.base, ISC_SHA1_DIGESTLENGTH);
00451 r.base += ISC_SHA1_DIGESTLENGTH;
00452 BN_bn2bin_fixed(dsa->p, r.base, key->key_size/8);
00453 r.base += p_bytes;
00454 BN_bn2bin_fixed(dsa->g, r.base, key->key_size/8);
00455 r.base += p_bytes;
00456 BN_bn2bin_fixed(dsa->pub_key, r.base, key->key_size/8);
00457 r.base += p_bytes;
00458
00459 isc_buffer_add(data, dnslen);
00460
00461 return (ISC_R_SUCCESS);
00462 }
00463
00464 static isc_result_t
00465 openssldsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
00466 DSA *dsa;
00467 isc_region_t r;
00468 unsigned int t, p_bytes;
00469 isc_mem_t *mctx = key->mctx;
00470
00471 UNUSED(mctx);
00472
00473 isc_buffer_remainingregion(data, &r);
00474 if (r.length == 0)
00475 return (ISC_R_SUCCESS);
00476
00477 dsa = DSA_new();
00478 if (dsa == NULL)
00479 return (ISC_R_NOMEMORY);
00480 dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
00481
00482 t = (unsigned int) *r.base++;
00483 if (t > 8) {
00484 DSA_free(dsa);
00485 return (DST_R_INVALIDPUBLICKEY);
00486 }
00487 p_bytes = 64 + 8 * t;
00488
00489 if (r.length < 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) {
00490 DSA_free(dsa);
00491 return (DST_R_INVALIDPUBLICKEY);
00492 }
00493
00494 dsa->q = BN_bin2bn(r.base, ISC_SHA1_DIGESTLENGTH, NULL);
00495 r.base += ISC_SHA1_DIGESTLENGTH;
00496
00497 dsa->p = BN_bin2bn(r.base, p_bytes, NULL);
00498 r.base += p_bytes;
00499
00500 dsa->g = BN_bin2bn(r.base, p_bytes, NULL);
00501 r.base += p_bytes;
00502
00503 dsa->pub_key = BN_bin2bn(r.base, p_bytes, NULL);
00504 r.base += p_bytes;
00505
00506 key->key_size = p_bytes * 8;
00507
00508 isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes);
00509
00510 key->keydata.dsa = dsa;
00511
00512 return (ISC_R_SUCCESS);
00513 }
00514
00515
00516 static isc_result_t
00517 openssldsa_tofile(const dst_key_t *key, const char *directory) {
00518 int cnt = 0;
00519 DSA *dsa;
00520 dst_private_t priv;
00521 unsigned char bufs[5][128];
00522
00523 if (key->keydata.dsa == NULL)
00524 return (DST_R_NULLKEY);
00525
00526 if (key->external) {
00527 priv.nelements = 0;
00528 return (dst__privstruct_writefile(key, &priv, directory));
00529 }
00530
00531 dsa = key->keydata.dsa;
00532
00533 priv.elements[cnt].tag = TAG_DSA_PRIME;
00534 priv.elements[cnt].length = BN_num_bytes(dsa->p);
00535 BN_bn2bin(dsa->p, bufs[cnt]);
00536 priv.elements[cnt].data = bufs[cnt];
00537 cnt++;
00538
00539 priv.elements[cnt].tag = TAG_DSA_SUBPRIME;
00540 priv.elements[cnt].length = BN_num_bytes(dsa->q);
00541 BN_bn2bin(dsa->q, bufs[cnt]);
00542 priv.elements[cnt].data = bufs[cnt];
00543 cnt++;
00544
00545 priv.elements[cnt].tag = TAG_DSA_BASE;
00546 priv.elements[cnt].length = BN_num_bytes(dsa->g);
00547 BN_bn2bin(dsa->g, bufs[cnt]);
00548 priv.elements[cnt].data = bufs[cnt];
00549 cnt++;
00550
00551 priv.elements[cnt].tag = TAG_DSA_PRIVATE;
00552 priv.elements[cnt].length = BN_num_bytes(dsa->priv_key);
00553 BN_bn2bin(dsa->priv_key, bufs[cnt]);
00554 priv.elements[cnt].data = bufs[cnt];
00555 cnt++;
00556
00557 priv.elements[cnt].tag = TAG_DSA_PUBLIC;
00558 priv.elements[cnt].length = BN_num_bytes(dsa->pub_key);
00559 BN_bn2bin(dsa->pub_key, bufs[cnt]);
00560 priv.elements[cnt].data = bufs[cnt];
00561 cnt++;
00562
00563 priv.nelements = cnt;
00564 return (dst__privstruct_writefile(key, &priv, directory));
00565 }
00566
00567 static isc_result_t
00568 openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
00569 dst_private_t priv;
00570 isc_result_t ret;
00571 int i;
00572 DSA *dsa = NULL;
00573 isc_mem_t *mctx = key->mctx;
00574 #define DST_RET(a) {ret = a; goto err;}
00575
00576
00577 ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv);
00578 if (ret != ISC_R_SUCCESS)
00579 return (ret);
00580
00581 if (key->external) {
00582 if (priv.nelements != 0)
00583 DST_RET(DST_R_INVALIDPRIVATEKEY);
00584 if (pub == NULL)
00585 DST_RET(DST_R_INVALIDPRIVATEKEY);
00586 key->keydata.pkey = pub->keydata.pkey;
00587 pub->keydata.pkey = NULL;
00588 key->key_size = pub->key_size;
00589 dst__privstruct_free(&priv, mctx);
00590 memset(&priv, 0, sizeof(priv));
00591 return (ISC_R_SUCCESS);
00592 }
00593
00594 dsa = DSA_new();
00595 if (dsa == NULL)
00596 DST_RET(ISC_R_NOMEMORY);
00597 dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
00598 key->keydata.dsa = dsa;
00599
00600 for (i = 0; i < priv.nelements; i++) {
00601 BIGNUM *bn;
00602 bn = BN_bin2bn(priv.elements[i].data,
00603 priv.elements[i].length, NULL);
00604 if (bn == NULL)
00605 DST_RET(ISC_R_NOMEMORY);
00606
00607 switch (priv.elements[i].tag) {
00608 case TAG_DSA_PRIME:
00609 dsa->p = bn;
00610 break;
00611 case TAG_DSA_SUBPRIME:
00612 dsa->q = bn;
00613 break;
00614 case TAG_DSA_BASE:
00615 dsa->g = bn;
00616 break;
00617 case TAG_DSA_PRIVATE:
00618 dsa->priv_key = bn;
00619 break;
00620 case TAG_DSA_PUBLIC:
00621 dsa->pub_key = bn;
00622 break;
00623 }
00624 }
00625 dst__privstruct_free(&priv, mctx);
00626 memset(&priv, 0, sizeof(priv));
00627 key->key_size = BN_num_bits(dsa->p);
00628 return (ISC_R_SUCCESS);
00629
00630 err:
00631 openssldsa_destroy(key);
00632 dst__privstruct_free(&priv, mctx);
00633 memset(&priv, 0, sizeof(priv));
00634 return (ret);
00635 }
00636
00637 static dst_func_t openssldsa_functions = {
00638 openssldsa_createctx,
00639 NULL,
00640 openssldsa_destroyctx,
00641 openssldsa_adddata,
00642 openssldsa_sign,
00643 openssldsa_verify,
00644 NULL,
00645 NULL,
00646 openssldsa_compare,
00647 NULL,
00648 openssldsa_generate,
00649 openssldsa_isprivate,
00650 openssldsa_destroy,
00651 openssldsa_todns,
00652 openssldsa_fromdns,
00653 openssldsa_tofile,
00654 openssldsa_parse,
00655 NULL,
00656 NULL,
00657 NULL,
00658 NULL,
00659 };
00660
00661 isc_result_t
00662 dst__openssldsa_init(dst_func_t **funcp) {
00663 REQUIRE(funcp != NULL);
00664 if (*funcp == NULL)
00665 *funcp = &openssldsa_functions;
00666 return (ISC_R_SUCCESS);
00667 }
00668
00669 #else
00670
00671 #include <isc/util.h>
00672
00673 EMPTY_TRANSLATION_UNIT
00674
00675 #endif
00676