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 $ */
27 #include <isc/entropy.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
);
42 openssldsa_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
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
);
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
));
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
);
73 BN_bn2bin_fixed(BIGNUM
*bn
, unsigned char *buf
, int size
) {
74 int bytes
= size
- BN_num_bytes(bn
);
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
;
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
);
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
);
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
;
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
);
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
);
136 return (DST_R_VERIFYFAILURE
);
138 return (ISC_R_SUCCESS
);
142 openssldsa_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
146 dsa1
= (DSA
*) key1
->opaque
;
147 dsa2
= (DSA
*) key2
->opaque
;
149 if (dsa1
== NULL
&& dsa2
== NULL
)
151 else if (dsa1
== NULL
|| dsa2
== NULL
)
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
);
162 if (dsa1
->priv_key
!= NULL
|| dsa2
->priv_key
!= NULL
) {
163 if (dsa1
->priv_key
== NULL
|| dsa2
->priv_key
== NULL
)
165 if (BN_cmp(dsa1
->priv_key
, dsa2
->priv_key
))
172 openssldsa_generate(dst_key_t
*key
, int unused
) {
174 unsigned char rand_array
[ISC_SHA1_DIGESTLENGTH
];
179 result
= dst__entropy_getdata(rand_array
, sizeof(rand_array
),
181 if (result
!= ISC_R_SUCCESS
)
184 dsa
= DSA_generate_parameters(key
->key_size
, rand_array
,
185 ISC_SHA1_DIGESTLENGTH
, NULL
, NULL
,
189 return (DST_R_OPENSSLFAILURE
);
191 if (DSA_generate_key(dsa
) == 0) {
193 return (DST_R_OPENSSLFAILURE
);
195 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
199 return (ISC_R_SUCCESS
);
203 openssldsa_isprivate(const dst_key_t
*key
) {
204 DSA
*dsa
= (DSA
*) key
->opaque
;
205 return (ISC_TF(dsa
!= NULL
&& dsa
->priv_key
!= NULL
));
209 openssldsa_issymmetric(void) {
214 openssldsa_destroy(dst_key_t
*key
) {
215 DSA
*dsa
= key
->opaque
;
222 openssldsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
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;
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
);
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);
248 BN_bn2bin_fixed(dsa
->g
, r
.base
, key
->key_size
/8);
250 BN_bn2bin_fixed(dsa
->pub_key
, r
.base
, key
->key_size
/8);
253 isc_buffer_add(data
, dnslen
);
255 return (ISC_R_SUCCESS
);
259 openssldsa_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
262 unsigned int t
, p_bytes
;
263 isc_mem_t
*mctx
= key
->mctx
;
267 isc_buffer_remainingregion(data
, &r
);
269 return (ISC_R_SUCCESS
);
273 return (ISC_R_NOMEMORY
);
274 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
276 t
= (unsigned int) *r
.base
++;
279 return (DST_R_INVALIDPUBLICKEY
);
281 p_bytes
= 64 + 8 * t
;
283 if (r
.length
< 1 + ISC_SHA1_DIGESTLENGTH
+ 3 * p_bytes
) {
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
);
294 dsa
->g
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
297 dsa
->pub_key
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
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
);
311 openssldsa_tofile(const dst_key_t
*key
, const char *directory
) {
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
];
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
];
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
];
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
];
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
];
352 priv
.nelements
= cnt
;
353 return (dst__privstruct_writefile(key
, &priv
, directory
));
357 openssldsa_fromfile(dst_key_t
*key
, const char *filename
) {
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
)
372 DST_RET(ISC_R_NOMEMORY
);
373 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
376 for (i
=0; i
< priv
.nelements
; i
++) {
378 bn
= BN_bin2bn(priv
.elements
[i
].data
,
379 priv
.elements
[i
].length
, NULL
);
381 DST_RET(ISC_R_NOMEMORY
);
383 switch (priv
.elements
[i
].tag
) {
387 case TAG_DSA_SUBPRIME
:
393 case TAG_DSA_PRIVATE
:
401 dst__privstruct_free(&priv
, mctx
);
403 key
->key_size
= BN_num_bits(dsa
->p
);
405 return (ISC_R_SUCCESS
);
408 openssldsa_destroy(key
);
409 dst__privstruct_free(&priv
, mctx
);
410 memset(&priv
, 0, sizeof(priv
));
414 static dst_func_t openssldsa_functions
= {
415 openssldsa_createctx
,
416 openssldsa_destroyctx
,
420 NULL
, /* computesecret */
422 NULL
, /* paramcompare */
424 openssldsa_isprivate
,
425 openssldsa_issymmetric
,
434 dst__openssldsa_init(dst_func_t
**funcp
) {
435 REQUIRE(funcp
!= NULL
&& *funcp
== NULL
);
436 *funcp
= &openssldsa_functions
;
437 return (ISC_R_SUCCESS
);
441 dst__openssldsa_destroy(void) {