2 * Portions Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
12 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
19 * Permission to use, copy, modify, and/or distribute this software for any
20 * purpose with or without fee is hereby granted, provided that the above
21 * copyright notice and this permission notice appear in all copies.
23 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
24 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
26 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
28 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
29 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 /* $Id: openssldsa_link.c,v 1.11.92.2 2009/01/14 23:46:33 tbox Exp $ */
40 #include <isc/entropy.h>
45 #include <dst/result.h>
47 #include "dst_internal.h"
48 #include "dst_openssl.h"
49 #include "dst_parse.h"
51 #include <openssl/dsa.h>
53 static isc_result_t
openssldsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
);
56 openssldsa_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
61 sha1ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_sha1_t
));
62 isc_sha1_init(sha1ctx
);
63 dctx
->ctxdata
.sha1ctx
= sha1ctx
;
64 return (ISC_R_SUCCESS
);
68 openssldsa_destroyctx(dst_context_t
*dctx
) {
69 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
71 if (sha1ctx
!= NULL
) {
72 isc_sha1_invalidate(sha1ctx
);
73 isc_mem_put(dctx
->mctx
, sha1ctx
, sizeof(isc_sha1_t
));
74 dctx
->ctxdata
.sha1ctx
= NULL
;
79 openssldsa_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
80 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
82 isc_sha1_update(sha1ctx
, data
->base
, data
->length
);
83 return (ISC_R_SUCCESS
);
87 BN_bn2bin_fixed(BIGNUM
*bn
, unsigned char *buf
, int size
) {
88 int bytes
= size
- BN_num_bytes(bn
);
96 openssldsa_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
97 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
98 dst_key_t
*key
= dctx
->key
;
99 DSA
*dsa
= key
->keydata
.dsa
;
102 unsigned char digest
[ISC_SHA1_DIGESTLENGTH
];
104 isc_buffer_availableregion(sig
, &r
);
105 if (r
.length
< ISC_SHA1_DIGESTLENGTH
* 2 + 1)
106 return (ISC_R_NOSPACE
);
108 isc_sha1_final(sha1ctx
, digest
);
110 dsasig
= DSA_do_sign(digest
, ISC_SHA1_DIGESTLENGTH
, dsa
);
112 return (dst__openssl_toresult(DST_R_SIGNFAILURE
));
114 *r
.base
++ = (key
->key_size
- 512)/64;
115 BN_bn2bin_fixed(dsasig
->r
, r
.base
, ISC_SHA1_DIGESTLENGTH
);
116 r
.base
+= ISC_SHA1_DIGESTLENGTH
;
117 BN_bn2bin_fixed(dsasig
->s
, r
.base
, ISC_SHA1_DIGESTLENGTH
);
118 r
.base
+= ISC_SHA1_DIGESTLENGTH
;
119 DSA_SIG_free(dsasig
);
120 isc_buffer_add(sig
, ISC_SHA1_DIGESTLENGTH
* 2 + 1);
122 return (ISC_R_SUCCESS
);
126 openssldsa_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
127 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
128 dst_key_t
*key
= dctx
->key
;
129 DSA
*dsa
= key
->keydata
.dsa
;
132 unsigned char digest
[ISC_SHA1_DIGESTLENGTH
];
133 unsigned char *cp
= sig
->base
;
135 isc_sha1_final(sha1ctx
, digest
);
137 if (sig
->length
< 2 * ISC_SHA1_DIGESTLENGTH
+ 1)
138 return (DST_R_VERIFYFAILURE
);
141 dsasig
= DSA_SIG_new();
142 dsasig
->r
= BN_bin2bn(cp
, ISC_SHA1_DIGESTLENGTH
, NULL
);
143 cp
+= ISC_SHA1_DIGESTLENGTH
;
144 dsasig
->s
= BN_bin2bn(cp
, ISC_SHA1_DIGESTLENGTH
, NULL
);
145 cp
+= ISC_SHA1_DIGESTLENGTH
;
147 status
= DSA_do_verify(digest
, ISC_SHA1_DIGESTLENGTH
, dsasig
, dsa
);
148 DSA_SIG_free(dsasig
);
150 return (dst__openssl_toresult(DST_R_VERIFYFAILURE
));
152 return (ISC_R_SUCCESS
);
156 openssldsa_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
160 dsa1
= key1
->keydata
.dsa
;
161 dsa2
= key2
->keydata
.dsa
;
163 if (dsa1
== NULL
&& dsa2
== NULL
)
165 else if (dsa1
== NULL
|| dsa2
== NULL
)
168 status
= BN_cmp(dsa1
->p
, dsa2
->p
) ||
169 BN_cmp(dsa1
->q
, dsa2
->q
) ||
170 BN_cmp(dsa1
->g
, dsa2
->g
) ||
171 BN_cmp(dsa1
->pub_key
, dsa2
->pub_key
);
176 if (dsa1
->priv_key
!= NULL
|| dsa2
->priv_key
!= NULL
) {
177 if (dsa1
->priv_key
== NULL
|| dsa2
->priv_key
== NULL
)
179 if (BN_cmp(dsa1
->priv_key
, dsa2
->priv_key
))
186 openssldsa_generate(dst_key_t
*key
, int unused
) {
187 #if OPENSSL_VERSION_NUMBER > 0x00908000L
191 unsigned char rand_array
[ISC_SHA1_DIGESTLENGTH
];
196 result
= dst__entropy_getdata(rand_array
, sizeof(rand_array
),
198 if (result
!= ISC_R_SUCCESS
)
201 #if OPENSSL_VERSION_NUMBER > 0x00908000L
204 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
206 BN_GENCB_set_old(&cb
, NULL
, NULL
);
208 if (!DSA_generate_parameters_ex(dsa
, key
->key_size
, rand_array
,
209 ISC_SHA1_DIGESTLENGTH
, NULL
, NULL
,
213 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
216 dsa
= DSA_generate_parameters(key
->key_size
, rand_array
,
217 ISC_SHA1_DIGESTLENGTH
, NULL
, NULL
,
220 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
223 if (DSA_generate_key(dsa
) == 0) {
225 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
227 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
229 key
->keydata
.dsa
= dsa
;
231 return (ISC_R_SUCCESS
);
235 openssldsa_isprivate(const dst_key_t
*key
) {
236 DSA
*dsa
= key
->keydata
.dsa
;
237 return (ISC_TF(dsa
!= NULL
&& dsa
->priv_key
!= NULL
));
241 openssldsa_destroy(dst_key_t
*key
) {
242 DSA
*dsa
= key
->keydata
.dsa
;
244 key
->keydata
.dsa
= NULL
;
249 openssldsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
253 unsigned int t
, p_bytes
;
255 REQUIRE(key
->keydata
.dsa
!= NULL
);
257 dsa
= key
->keydata
.dsa
;
259 isc_buffer_availableregion(data
, &r
);
261 t
= (BN_num_bytes(dsa
->p
) - 64) / 8;
263 return (DST_R_INVALIDPUBLICKEY
);
264 p_bytes
= 64 + 8 * t
;
266 dnslen
= 1 + (key
->key_size
* 3)/8 + ISC_SHA1_DIGESTLENGTH
;
267 if (r
.length
< (unsigned int) dnslen
)
268 return (ISC_R_NOSPACE
);
271 BN_bn2bin_fixed(dsa
->q
, r
.base
, ISC_SHA1_DIGESTLENGTH
);
272 r
.base
+= ISC_SHA1_DIGESTLENGTH
;
273 BN_bn2bin_fixed(dsa
->p
, r
.base
, key
->key_size
/8);
275 BN_bn2bin_fixed(dsa
->g
, r
.base
, key
->key_size
/8);
277 BN_bn2bin_fixed(dsa
->pub_key
, r
.base
, key
->key_size
/8);
280 isc_buffer_add(data
, dnslen
);
282 return (ISC_R_SUCCESS
);
286 openssldsa_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
289 unsigned int t
, p_bytes
;
290 isc_mem_t
*mctx
= key
->mctx
;
294 isc_buffer_remainingregion(data
, &r
);
296 return (ISC_R_SUCCESS
);
300 return (ISC_R_NOMEMORY
);
301 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
303 t
= (unsigned int) *r
.base
++;
306 return (DST_R_INVALIDPUBLICKEY
);
308 p_bytes
= 64 + 8 * t
;
310 if (r
.length
< 1 + ISC_SHA1_DIGESTLENGTH
+ 3 * p_bytes
) {
312 return (DST_R_INVALIDPUBLICKEY
);
315 dsa
->q
= BN_bin2bn(r
.base
, ISC_SHA1_DIGESTLENGTH
, NULL
);
316 r
.base
+= ISC_SHA1_DIGESTLENGTH
;
318 dsa
->p
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
321 dsa
->g
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
324 dsa
->pub_key
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
327 key
->key_size
= p_bytes
* 8;
329 isc_buffer_forward(data
, 1 + ISC_SHA1_DIGESTLENGTH
+ 3 * p_bytes
);
331 key
->keydata
.dsa
= dsa
;
333 return (ISC_R_SUCCESS
);
338 openssldsa_tofile(const dst_key_t
*key
, const char *directory
) {
342 unsigned char bufs
[5][128];
344 if (key
->keydata
.dsa
== NULL
)
345 return (DST_R_NULLKEY
);
347 dsa
= key
->keydata
.dsa
;
349 priv
.elements
[cnt
].tag
= TAG_DSA_PRIME
;
350 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->p
);
351 BN_bn2bin(dsa
->p
, bufs
[cnt
]);
352 priv
.elements
[cnt
].data
= bufs
[cnt
];
355 priv
.elements
[cnt
].tag
= TAG_DSA_SUBPRIME
;
356 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->q
);
357 BN_bn2bin(dsa
->q
, bufs
[cnt
]);
358 priv
.elements
[cnt
].data
= bufs
[cnt
];
361 priv
.elements
[cnt
].tag
= TAG_DSA_BASE
;
362 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->g
);
363 BN_bn2bin(dsa
->g
, bufs
[cnt
]);
364 priv
.elements
[cnt
].data
= bufs
[cnt
];
367 priv
.elements
[cnt
].tag
= TAG_DSA_PRIVATE
;
368 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->priv_key
);
369 BN_bn2bin(dsa
->priv_key
, bufs
[cnt
]);
370 priv
.elements
[cnt
].data
= bufs
[cnt
];
373 priv
.elements
[cnt
].tag
= TAG_DSA_PUBLIC
;
374 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->pub_key
);
375 BN_bn2bin(dsa
->pub_key
, bufs
[cnt
]);
376 priv
.elements
[cnt
].data
= bufs
[cnt
];
379 priv
.nelements
= cnt
;
380 return (dst__privstruct_writefile(key
, &priv
, directory
));
384 openssldsa_parse(dst_key_t
*key
, isc_lex_t
*lexer
) {
389 isc_mem_t
*mctx
= key
->mctx
;
390 #define DST_RET(a) {ret = a; goto err;}
392 /* read private key file */
393 ret
= dst__privstruct_parse(key
, DST_ALG_DSA
, lexer
, mctx
, &priv
);
394 if (ret
!= ISC_R_SUCCESS
)
399 DST_RET(ISC_R_NOMEMORY
);
400 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
401 key
->keydata
.dsa
= dsa
;
403 for (i
=0; i
< priv
.nelements
; i
++) {
405 bn
= BN_bin2bn(priv
.elements
[i
].data
,
406 priv
.elements
[i
].length
, NULL
);
408 DST_RET(ISC_R_NOMEMORY
);
410 switch (priv
.elements
[i
].tag
) {
414 case TAG_DSA_SUBPRIME
:
420 case TAG_DSA_PRIVATE
:
428 dst__privstruct_free(&priv
, mctx
);
430 key
->key_size
= BN_num_bits(dsa
->p
);
432 return (ISC_R_SUCCESS
);
435 openssldsa_destroy(key
);
436 dst__privstruct_free(&priv
, mctx
);
437 memset(&priv
, 0, sizeof(priv
));
441 static dst_func_t openssldsa_functions
= {
442 openssldsa_createctx
,
443 openssldsa_destroyctx
,
447 NULL
, /*%< computesecret */
449 NULL
, /*%< paramcompare */
451 openssldsa_isprivate
,
457 NULL
, /*%< cleanup */
461 dst__openssldsa_init(dst_func_t
**funcp
) {
462 REQUIRE(funcp
!= NULL
);
464 *funcp
= &openssldsa_functions
;
465 return (ISC_R_SUCCESS
);
470 #include <isc/util.h>
472 EMPTY_TRANSLATION_UNIT