Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / sec / dst / openssldsa_link.c
blob769de88164b30664e9ff0e40a9c6998488dbb73e
1 /*
2 * Portions Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2001 Internet Software Consortium.
4 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
6 * Permission to use, copy, modify, and 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.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
13 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
16 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 /* $Id: openssldsa_link.c,v 1.4.2.2 2004/03/09 06:11:42 marka Exp $ */
21 #ifdef OPENSSL
23 #include <config.h>
25 #include <string.h>
27 #include <isc/entropy.h>
28 #include <isc/mem.h>
29 #include <isc/sha1.h>
30 #include <isc/util.h>
32 #include <dst/result.h>
34 #include "dst_internal.h"
35 #include "dst_parse.h"
37 #include <openssl/dsa.h>
39 static isc_result_t openssldsa_todns(const dst_key_t *key, isc_buffer_t *data);
41 static isc_result_t
42 openssldsa_createctx(dst_key_t *key, dst_context_t *dctx) {
43 isc_sha1_t *sha1ctx;
45 UNUSED(key);
47 sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
48 isc_sha1_init(sha1ctx);
49 dctx->opaque = sha1ctx;
50 return (ISC_R_SUCCESS);
53 static void
54 openssldsa_destroyctx(dst_context_t *dctx) {
55 isc_sha1_t *sha1ctx = dctx->opaque;
57 if (sha1ctx != NULL) {
58 isc_sha1_invalidate(sha1ctx);
59 isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
60 dctx->opaque = NULL;
64 static isc_result_t
65 openssldsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
66 isc_sha1_t *sha1ctx = dctx->opaque;
68 isc_sha1_update(sha1ctx, data->base, data->length);
69 return (ISC_R_SUCCESS);
72 static int
73 BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
74 int bytes = size - BN_num_bytes(bn);
75 while (bytes-- > 0)
76 *buf++ = 0;
77 BN_bn2bin(bn, buf);
78 return (size);
81 static isc_result_t
82 openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
83 isc_sha1_t *sha1ctx = dctx->opaque;
84 dst_key_t *key = dctx->key;
85 DSA *dsa = key->opaque;
86 DSA_SIG *dsasig;
87 isc_region_t r;
88 unsigned char digest[ISC_SHA1_DIGESTLENGTH];
90 isc_buffer_availableregion(sig, &r);
91 if (r.length < ISC_SHA1_DIGESTLENGTH * 2 + 1)
92 return (ISC_R_NOSPACE);
94 isc_sha1_final(sha1ctx, digest);
96 dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
97 if (dsasig == NULL)
98 return (DST_R_SIGNFAILURE);
100 *r.base++ = (key->key_size - 512)/64;
101 BN_bn2bin_fixed(dsasig->r, r.base, ISC_SHA1_DIGESTLENGTH);
102 r.base += ISC_SHA1_DIGESTLENGTH;
103 BN_bn2bin_fixed(dsasig->s, r.base, ISC_SHA1_DIGESTLENGTH);
104 r.base += ISC_SHA1_DIGESTLENGTH;
105 DSA_SIG_free(dsasig);
106 isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1);
108 return (ISC_R_SUCCESS);
111 static isc_result_t
112 openssldsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
113 isc_sha1_t *sha1ctx = dctx->opaque;
114 dst_key_t *key = dctx->key;
115 DSA *dsa = key->opaque;
116 DSA_SIG *dsasig;
117 int status = 0;
118 unsigned char digest[ISC_SHA1_DIGESTLENGTH];
119 unsigned char *cp = sig->base;
121 isc_sha1_final(sha1ctx, digest);
123 if (sig->length < 2 * ISC_SHA1_DIGESTLENGTH + 1)
124 return (DST_R_VERIFYFAILURE);
126 cp++; /* Skip T */
127 dsasig = DSA_SIG_new();
128 dsasig->r = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
129 cp += ISC_SHA1_DIGESTLENGTH;
130 dsasig->s = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
131 cp += ISC_SHA1_DIGESTLENGTH;
133 status = DSA_do_verify(digest, ISC_SHA1_DIGESTLENGTH, dsasig, dsa);
134 DSA_SIG_free(dsasig);
135 if (status == 0)
136 return (DST_R_VERIFYFAILURE);
138 return (ISC_R_SUCCESS);
141 static isc_boolean_t
142 openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
143 int status;
144 DSA *dsa1, *dsa2;
146 dsa1 = (DSA *) key1->opaque;
147 dsa2 = (DSA *) key2->opaque;
149 if (dsa1 == NULL && dsa2 == NULL)
150 return (ISC_TRUE);
151 else if (dsa1 == NULL || dsa2 == NULL)
152 return (ISC_FALSE);
154 status = BN_cmp(dsa1->p, dsa2->p) ||
155 BN_cmp(dsa1->q, dsa2->q) ||
156 BN_cmp(dsa1->g, dsa2->g) ||
157 BN_cmp(dsa1->pub_key, dsa2->pub_key);
159 if (status != 0)
160 return (ISC_FALSE);
162 if (dsa1->priv_key != NULL || dsa2->priv_key != NULL) {
163 if (dsa1->priv_key == NULL || dsa2->priv_key == NULL)
164 return (ISC_FALSE);
165 if (BN_cmp(dsa1->priv_key, dsa2->priv_key))
166 return (ISC_FALSE);
168 return (ISC_TRUE);
171 static isc_result_t
172 openssldsa_generate(dst_key_t *key, int unused) {
173 DSA *dsa;
174 unsigned char rand_array[ISC_SHA1_DIGESTLENGTH];
175 isc_result_t result;
177 UNUSED(unused);
179 result = dst__entropy_getdata(rand_array, sizeof(rand_array),
180 ISC_FALSE);
181 if (result != ISC_R_SUCCESS)
182 return (result);
184 dsa = DSA_generate_parameters(key->key_size, rand_array,
185 ISC_SHA1_DIGESTLENGTH, NULL, NULL,
186 NULL, NULL);
188 if (dsa == NULL)
189 return (DST_R_OPENSSLFAILURE);
191 if (DSA_generate_key(dsa) == 0) {
192 DSA_free(dsa);
193 return (DST_R_OPENSSLFAILURE);
195 dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
197 key->opaque = dsa;
199 return (ISC_R_SUCCESS);
202 static isc_boolean_t
203 openssldsa_isprivate(const dst_key_t *key) {
204 DSA *dsa = (DSA *) key->opaque;
205 return (ISC_TF(dsa != NULL && dsa->priv_key != NULL));
208 static isc_boolean_t
209 openssldsa_issymmetric(void) {
210 return (ISC_FALSE);
213 static void
214 openssldsa_destroy(dst_key_t *key) {
215 DSA *dsa = key->opaque;
216 DSA_free(dsa);
217 key->opaque = NULL;
221 static isc_result_t
222 openssldsa_todns(const dst_key_t *key, isc_buffer_t *data) {
223 DSA *dsa;
224 isc_region_t r;
225 int dnslen;
226 unsigned int t, p_bytes;
228 REQUIRE(key->opaque != NULL);
230 dsa = (DSA *) key->opaque;
232 isc_buffer_availableregion(data, &r);
234 t = (BN_num_bytes(dsa->p) - 64) / 8;
235 if (t > 8)
236 return (DST_R_INVALIDPUBLICKEY);
237 p_bytes = 64 + 8 * t;
239 dnslen = 1 + (key->key_size * 3)/8 + ISC_SHA1_DIGESTLENGTH;
240 if (r.length < (unsigned int) dnslen)
241 return (ISC_R_NOSPACE);
243 *r.base++ = t;
244 BN_bn2bin_fixed(dsa->q, r.base, ISC_SHA1_DIGESTLENGTH);
245 r.base += ISC_SHA1_DIGESTLENGTH;
246 BN_bn2bin_fixed(dsa->p, r.base, key->key_size/8);
247 r.base += p_bytes;
248 BN_bn2bin_fixed(dsa->g, r.base, key->key_size/8);
249 r.base += p_bytes;
250 BN_bn2bin_fixed(dsa->pub_key, r.base, key->key_size/8);
251 r.base += p_bytes;
253 isc_buffer_add(data, dnslen);
255 return (ISC_R_SUCCESS);
258 static isc_result_t
259 openssldsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
260 DSA *dsa;
261 isc_region_t r;
262 unsigned int t, p_bytes;
263 isc_mem_t *mctx = key->mctx;
265 UNUSED(mctx);
267 isc_buffer_remainingregion(data, &r);
268 if (r.length == 0)
269 return (ISC_R_SUCCESS);
271 dsa = DSA_new();
272 if (dsa == NULL)
273 return (ISC_R_NOMEMORY);
274 dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
276 t = (unsigned int) *r.base++;
277 if (t > 8) {
278 DSA_free(dsa);
279 return (DST_R_INVALIDPUBLICKEY);
281 p_bytes = 64 + 8 * t;
283 if (r.length < 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) {
284 DSA_free(dsa);
285 return (DST_R_INVALIDPUBLICKEY);
288 dsa->q = BN_bin2bn(r.base, ISC_SHA1_DIGESTLENGTH, NULL);
289 r.base += ISC_SHA1_DIGESTLENGTH;
291 dsa->p = BN_bin2bn(r.base, p_bytes, NULL);
292 r.base += p_bytes;
294 dsa->g = BN_bin2bn(r.base, p_bytes, NULL);
295 r.base += p_bytes;
297 dsa->pub_key = BN_bin2bn(r.base, p_bytes, NULL);
298 r.base += p_bytes;
300 key->key_size = p_bytes * 8;
302 isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes);
304 key->opaque = (void *) dsa;
306 return (ISC_R_SUCCESS);
310 static isc_result_t
311 openssldsa_tofile(const dst_key_t *key, const char *directory) {
312 int cnt = 0;
313 DSA *dsa;
314 dst_private_t priv;
315 unsigned char bufs[5][128];
317 if (key->opaque == NULL)
318 return (DST_R_NULLKEY);
320 dsa = (DSA *) key->opaque;
322 priv.elements[cnt].tag = TAG_DSA_PRIME;
323 priv.elements[cnt].length = BN_num_bytes(dsa->p);
324 BN_bn2bin(dsa->p, bufs[cnt]);
325 priv.elements[cnt].data = bufs[cnt];
326 cnt++;
328 priv.elements[cnt].tag = TAG_DSA_SUBPRIME;
329 priv.elements[cnt].length = BN_num_bytes(dsa->q);
330 BN_bn2bin(dsa->q, bufs[cnt]);
331 priv.elements[cnt].data = bufs[cnt];
332 cnt++;
334 priv.elements[cnt].tag = TAG_DSA_BASE;
335 priv.elements[cnt].length = BN_num_bytes(dsa->g);
336 BN_bn2bin(dsa->g, bufs[cnt]);
337 priv.elements[cnt].data = bufs[cnt];
338 cnt++;
340 priv.elements[cnt].tag = TAG_DSA_PRIVATE;
341 priv.elements[cnt].length = BN_num_bytes(dsa->priv_key);
342 BN_bn2bin(dsa->priv_key, bufs[cnt]);
343 priv.elements[cnt].data = bufs[cnt];
344 cnt++;
346 priv.elements[cnt].tag = TAG_DSA_PUBLIC;
347 priv.elements[cnt].length = BN_num_bytes(dsa->pub_key);
348 BN_bn2bin(dsa->pub_key, bufs[cnt]);
349 priv.elements[cnt].data = bufs[cnt];
350 cnt++;
352 priv.nelements = cnt;
353 return (dst__privstruct_writefile(key, &priv, directory));
356 static isc_result_t
357 openssldsa_fromfile(dst_key_t *key, const char *filename) {
358 dst_private_t priv;
359 isc_result_t ret;
360 int i;
361 DSA *dsa = NULL;
362 isc_mem_t *mctx = key->mctx;
363 #define DST_RET(a) {ret = a; goto err;}
365 /* read private key file */
366 ret = dst__privstruct_parsefile(key, filename, mctx, &priv);
367 if (ret != ISC_R_SUCCESS)
368 return (ret);
370 dsa = DSA_new();
371 if (dsa == NULL)
372 DST_RET(ISC_R_NOMEMORY);
373 dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
374 key->opaque = dsa;
376 for (i=0; i < priv.nelements; i++) {
377 BIGNUM *bn;
378 bn = BN_bin2bn(priv.elements[i].data,
379 priv.elements[i].length, NULL);
380 if (bn == NULL)
381 DST_RET(ISC_R_NOMEMORY);
383 switch (priv.elements[i].tag) {
384 case TAG_DSA_PRIME:
385 dsa->p = bn;
386 break;
387 case TAG_DSA_SUBPRIME:
388 dsa->q = bn;
389 break;
390 case TAG_DSA_BASE:
391 dsa->g = bn;
392 break;
393 case TAG_DSA_PRIVATE:
394 dsa->priv_key = bn;
395 break;
396 case TAG_DSA_PUBLIC:
397 dsa->pub_key = bn;
398 break;
401 dst__privstruct_free(&priv, mctx);
403 key->key_size = BN_num_bits(dsa->p);
405 return (ISC_R_SUCCESS);
407 err:
408 openssldsa_destroy(key);
409 dst__privstruct_free(&priv, mctx);
410 memset(&priv, 0, sizeof(priv));
411 return (ret);
414 static dst_func_t openssldsa_functions = {
415 openssldsa_createctx,
416 openssldsa_destroyctx,
417 openssldsa_adddata,
418 openssldsa_sign,
419 openssldsa_verify,
420 NULL, /* computesecret */
421 openssldsa_compare,
422 NULL, /* paramcompare */
423 openssldsa_generate,
424 openssldsa_isprivate,
425 openssldsa_issymmetric,
426 openssldsa_destroy,
427 openssldsa_todns,
428 openssldsa_fromdns,
429 openssldsa_tofile,
430 openssldsa_fromfile,
433 isc_result_t
434 dst__openssldsa_init(dst_func_t **funcp) {
435 REQUIRE(funcp != NULL && *funcp == NULL);
436 *funcp = &openssldsa_functions;
437 return (ISC_R_SUCCESS);
440 void
441 dst__openssldsa_destroy(void) {
444 #endif /* OPENSSL */