2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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 DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
19 * Principal Author: Brian Wellington
20 * $Id: opensslrsa_link.c,v 1.12.2.6 2004/03/09 06:11:42 marka Exp $
26 #include <isc/entropy.h>
30 #include <isc/string.h>
33 #include <dst/result.h>
35 #include "dst_internal.h"
36 #include "dst_parse.h"
38 #include <openssl/err.h>
39 #include <openssl/objects.h>
40 #include <openssl/rsa.h>
42 static isc_result_t
opensslrsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
);
45 opensslrsa_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
48 if (dctx
->key
->key_alg
== DST_ALG_RSAMD5
) {
51 md5ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_md5_t
));
53 dctx
->opaque
= md5ctx
;
57 sha1ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_sha1_t
));
58 isc_sha1_init(sha1ctx
);
59 dctx
->opaque
= sha1ctx
;
62 return (ISC_R_SUCCESS
);
66 opensslrsa_destroyctx(dst_context_t
*dctx
) {
67 if (dctx
->key
->key_alg
== DST_ALG_RSAMD5
) {
68 isc_md5_t
*md5ctx
= dctx
->opaque
;
71 isc_md5_invalidate(md5ctx
);
72 isc_mem_put(dctx
->mctx
, md5ctx
, sizeof(isc_md5_t
));
75 isc_sha1_t
*sha1ctx
= dctx
->opaque
;
77 if (sha1ctx
!= NULL
) {
78 isc_sha1_invalidate(sha1ctx
);
79 isc_mem_put(dctx
->mctx
, sha1ctx
, sizeof(isc_sha1_t
));
86 opensslrsa_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
87 if (dctx
->key
->key_alg
== DST_ALG_RSAMD5
) {
88 isc_md5_t
*md5ctx
= dctx
->opaque
;
89 isc_md5_update(md5ctx
, data
->base
, data
->length
);
91 isc_sha1_t
*sha1ctx
= dctx
->opaque
;
92 isc_sha1_update(sha1ctx
, data
->base
, data
->length
);
94 return (ISC_R_SUCCESS
);
98 opensslrsa_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
99 dst_key_t
*key
= dctx
->key
;
100 RSA
*rsa
= key
->opaque
;
102 /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
103 unsigned char digest
[ISC_SHA1_DIGESTLENGTH
];
107 unsigned int digestlen
;
109 isc_buffer_availableregion(sig
, &r
);
111 if (r
.length
< (unsigned int) RSA_size(rsa
))
112 return (ISC_R_NOSPACE
);
114 if (dctx
->key
->key_alg
== DST_ALG_RSAMD5
) {
115 isc_md5_t
*md5ctx
= dctx
->opaque
;
116 isc_md5_final(md5ctx
, digest
);
118 digestlen
= ISC_MD5_DIGESTLENGTH
;
120 isc_sha1_t
*sha1ctx
= dctx
->opaque
;
121 isc_sha1_final(sha1ctx
, digest
);
123 digestlen
= ISC_SHA1_DIGESTLENGTH
;
126 status
= RSA_sign(type
, digest
, digestlen
, r
.base
, &siglen
, rsa
);
129 return (DST_R_SIGNFAILURE
);
132 isc_buffer_add(sig
, siglen
);
134 return (ISC_R_SUCCESS
);
138 opensslrsa_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
139 dst_key_t
*key
= dctx
->key
;
140 RSA
*rsa
= key
->opaque
;
141 /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
142 unsigned char digest
[ISC_SHA1_DIGESTLENGTH
];
145 unsigned int digestlen
;
147 if (dctx
->key
->key_alg
== DST_ALG_RSAMD5
) {
148 isc_md5_t
*md5ctx
= dctx
->opaque
;
149 isc_md5_final(md5ctx
, digest
);
151 digestlen
= ISC_MD5_DIGESTLENGTH
;
153 isc_sha1_t
*sha1ctx
= dctx
->opaque
;
154 isc_sha1_final(sha1ctx
, digest
);
156 digestlen
= ISC_SHA1_DIGESTLENGTH
;
159 if (sig
->length
< (unsigned int) RSA_size(rsa
))
160 return (DST_R_VERIFYFAILURE
);
162 status
= RSA_verify(type
, digest
, digestlen
, sig
->base
,
166 return (DST_R_VERIFYFAILURE
);
169 return (ISC_R_SUCCESS
);
173 opensslrsa_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
177 rsa1
= (RSA
*) key1
->opaque
;
178 rsa2
= (RSA
*) key2
->opaque
;
180 if (rsa1
== NULL
&& rsa2
== NULL
)
182 else if (rsa1
== NULL
|| rsa2
== NULL
)
185 status
= BN_cmp(rsa1
->n
, rsa2
->n
) ||
186 BN_cmp(rsa1
->e
, rsa2
->e
);
191 if (rsa1
->d
!= NULL
|| rsa2
->d
!= NULL
) {
192 if (rsa1
->d
== NULL
|| rsa2
->d
== NULL
)
194 status
= BN_cmp(rsa1
->d
, rsa2
->d
) ||
195 BN_cmp(rsa1
->p
, rsa2
->p
) ||
196 BN_cmp(rsa1
->q
, rsa2
->q
);
205 opensslrsa_generate(dst_key_t
*key
, int exp
) {
213 rsa
= RSA_generate_key(key
->key_size
, e
, NULL
, NULL
);
216 return (DST_R_OPENSSLFAILURE
);
219 rsa
->flags
&= ~(RSA_FLAG_CACHE_PUBLIC
| RSA_FLAG_CACHE_PRIVATE
);
220 rsa
->flags
|= RSA_FLAG_BLINDING
;
224 return (ISC_R_SUCCESS
);
228 opensslrsa_isprivate(const dst_key_t
*key
) {
229 RSA
*rsa
= (RSA
*) key
->opaque
;
230 return (ISC_TF(rsa
!= NULL
&& rsa
->d
!= NULL
));
234 opensslrsa_issymmetric(void) {
239 opensslrsa_destroy(dst_key_t
*key
) {
240 RSA
*rsa
= key
->opaque
;
247 opensslrsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
250 unsigned int e_bytes
;
251 unsigned int mod_bytes
;
253 REQUIRE(key
->opaque
!= NULL
);
255 rsa
= (RSA
*) key
->opaque
;
257 isc_buffer_availableregion(data
, &r
);
259 e_bytes
= BN_num_bytes(rsa
->e
);
260 mod_bytes
= BN_num_bytes(rsa
->n
);
262 if (e_bytes
< 256) { /* key exponent is <= 2040 bits */
264 return (ISC_R_NOSPACE
);
265 isc_buffer_putuint8(data
, (isc_uint8_t
) e_bytes
);
268 return (ISC_R_NOSPACE
);
269 isc_buffer_putuint8(data
, 0);
270 isc_buffer_putuint16(data
, (isc_uint16_t
) e_bytes
);
273 if (r
.length
< e_bytes
+ mod_bytes
)
274 return (ISC_R_NOSPACE
);
275 isc_buffer_availableregion(data
, &r
);
277 BN_bn2bin(rsa
->e
, r
.base
);
279 BN_bn2bin(rsa
->n
, r
.base
);
281 isc_buffer_add(data
, e_bytes
+ mod_bytes
);
283 return (ISC_R_SUCCESS
);
287 opensslrsa_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
290 unsigned int e_bytes
;
292 isc_buffer_remainingregion(data
, &r
);
294 return (ISC_R_SUCCESS
);
298 return (ISC_R_NOMEMORY
);
299 rsa
->flags
&= ~(RSA_FLAG_CACHE_PUBLIC
| RSA_FLAG_CACHE_PRIVATE
);
300 rsa
->flags
|= RSA_FLAG_BLINDING
;
304 return (DST_R_INVALIDPUBLICKEY
);
312 return (DST_R_INVALIDPUBLICKEY
);
314 e_bytes
= ((*r
.base
++) << 8);
315 e_bytes
+= *r
.base
++;
319 if (r
.length
< e_bytes
) {
321 return (DST_R_INVALIDPUBLICKEY
);
323 rsa
->e
= BN_bin2bn(r
.base
, e_bytes
, NULL
);
327 rsa
->n
= BN_bin2bn(r
.base
, r
.length
, NULL
);
329 key
->key_size
= BN_num_bits(rsa
->n
);
331 isc_buffer_forward(data
, r
.length
);
333 key
->opaque
= (void *) rsa
;
335 return (ISC_R_SUCCESS
);
340 opensslrsa_tofile(const dst_key_t
*key
, const char *directory
) {
344 unsigned char *bufs
[8];
347 if (key
->opaque
== NULL
)
348 return (DST_R_NULLKEY
);
350 rsa
= (RSA
*) key
->opaque
;
352 for (i
= 0; i
< 8; i
++) {
353 bufs
[i
] = isc_mem_get(key
->mctx
, BN_num_bytes(rsa
->n
));
354 if (bufs
[i
] == NULL
) {
355 result
= ISC_R_NOMEMORY
;
362 priv
.elements
[i
].tag
= TAG_RSA_MODULUS
;
363 priv
.elements
[i
].length
= BN_num_bytes(rsa
->n
);
364 BN_bn2bin(rsa
->n
, bufs
[i
]);
365 priv
.elements
[i
].data
= bufs
[i
];
368 priv
.elements
[i
].tag
= TAG_RSA_PUBLICEXPONENT
;
369 priv
.elements
[i
].length
= BN_num_bytes(rsa
->e
);
370 BN_bn2bin(rsa
->e
, bufs
[i
]);
371 priv
.elements
[i
].data
= bufs
[i
];
374 priv
.elements
[i
].tag
= TAG_RSA_PRIVATEEXPONENT
;
375 priv
.elements
[i
].length
= BN_num_bytes(rsa
->d
);
376 BN_bn2bin(rsa
->d
, bufs
[i
]);
377 priv
.elements
[i
].data
= bufs
[i
];
380 priv
.elements
[i
].tag
= TAG_RSA_PRIME1
;
381 priv
.elements
[i
].length
= BN_num_bytes(rsa
->p
);
382 BN_bn2bin(rsa
->p
, bufs
[i
]);
383 priv
.elements
[i
].data
= bufs
[i
];
386 priv
.elements
[i
].tag
= TAG_RSA_PRIME2
;
387 priv
.elements
[i
].length
= BN_num_bytes(rsa
->q
);
388 BN_bn2bin(rsa
->q
, bufs
[i
]);
389 priv
.elements
[i
].data
= bufs
[i
];
392 priv
.elements
[i
].tag
= TAG_RSA_EXPONENT1
;
393 priv
.elements
[i
].length
= BN_num_bytes(rsa
->dmp1
);
394 BN_bn2bin(rsa
->dmp1
, bufs
[i
]);
395 priv
.elements
[i
].data
= bufs
[i
];
398 priv
.elements
[i
].tag
= TAG_RSA_EXPONENT2
;
399 priv
.elements
[i
].length
= BN_num_bytes(rsa
->dmq1
);
400 BN_bn2bin(rsa
->dmq1
, bufs
[i
]);
401 priv
.elements
[i
].data
= bufs
[i
];
404 priv
.elements
[i
].tag
= TAG_RSA_COEFFICIENT
;
405 priv
.elements
[i
].length
= BN_num_bytes(rsa
->iqmp
);
406 BN_bn2bin(rsa
->iqmp
, bufs
[i
]);
407 priv
.elements
[i
].data
= bufs
[i
];
411 result
= dst__privstruct_writefile(key
, &priv
, directory
);
413 for (i
= 0; i
< 8; i
++) {
416 isc_mem_put(key
->mctx
, bufs
[i
], BN_num_bytes(rsa
->n
));
422 opensslrsa_fromfile(dst_key_t
*key
, const char *filename
) {
427 isc_mem_t
*mctx
= key
->mctx
;
428 #define DST_RET(a) {ret = a; goto err;}
430 /* read private key file */
431 ret
= dst__privstruct_parsefile(key
, filename
, mctx
, &priv
);
432 if (ret
!= ISC_R_SUCCESS
)
437 DST_RET(ISC_R_NOMEMORY
);
438 rsa
->flags
&= ~(RSA_FLAG_CACHE_PUBLIC
| RSA_FLAG_CACHE_PRIVATE
);
439 rsa
->flags
|= RSA_FLAG_BLINDING
;
442 for (i
= 0; i
< priv
.nelements
; i
++) {
444 bn
= BN_bin2bn(priv
.elements
[i
].data
,
445 priv
.elements
[i
].length
, NULL
);
447 DST_RET(ISC_R_NOMEMORY
);
449 switch (priv
.elements
[i
].tag
) {
450 case TAG_RSA_MODULUS
:
453 case TAG_RSA_PUBLICEXPONENT
:
456 case TAG_RSA_PRIVATEEXPONENT
:
465 case TAG_RSA_EXPONENT1
:
468 case TAG_RSA_EXPONENT2
:
471 case TAG_RSA_COEFFICIENT
:
476 dst__privstruct_free(&priv
, mctx
);
478 key
->key_size
= BN_num_bits(rsa
->n
);
480 return (ISC_R_SUCCESS
);
483 opensslrsa_destroy(key
);
484 dst__privstruct_free(&priv
, mctx
);
485 memset(&priv
, 0, sizeof(priv
));
489 static dst_func_t opensslrsa_functions
= {
490 opensslrsa_createctx
,
491 opensslrsa_destroyctx
,
495 NULL
, /* computesecret */
497 NULL
, /* paramcompare */
499 opensslrsa_isprivate
,
500 opensslrsa_issymmetric
,
509 dst__opensslrsa_init(dst_func_t
**funcp
) {
510 REQUIRE(funcp
!= NULL
&& *funcp
== NULL
);
511 *funcp
= &opensslrsa_functions
;
512 return (ISC_R_SUCCESS
);
516 dst__opensslrsa_destroy(void) {