xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/openssl_crypto.c (revision b491010d025d48f63aa0021abddcaafa02b3340b)
1 /*-
2  * Copyright (c) 2009 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Alistair Crooks (agc@NetBSD.org)
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 /*
30  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31  * All rights reserved.
32  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33  * their moral rights under the UK Copyright Design and Patents Act 1988 to
34  * be recorded as the authors of this copyright work.
35  *
36  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37  * use this file except in compliance with the License.
38  *
39  * You may obtain a copy of the License at
40  *     http://www.apache.org/licenses/LICENSE-2.0
41  *
42  * Unless required by applicable law or agreed to in writing, software
43  * distributed under the License is distributed on an "AS IS" BASIS,
44  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45  *
46  * See the License for the specific language governing permissions and
47  * limitations under the License.
48  */
49 
50 /** \file
51  */
52 #include "config.h"
53 
54 #ifdef HAVE_SYS_CDEFS_H
55 #include <sys/cdefs.h>
56 #endif
57 
58 #if defined(__NetBSD__)
59 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60 __RCSID("$NetBSD: openssl_crypto.c,v 1.16 2009/10/06 03:30:59 agc Exp $");
61 #endif
62 
63 #ifdef HAVE_OPENSSL_DSA_H
64 #include <openssl/dsa.h>
65 #endif
66 
67 #ifdef HAVE_OPENSSL_RSA_H
68 #include <openssl/rsa.h>
69 #endif
70 
71 #ifdef HAVE_OPENSSL_ERR_H
72 #include <openssl/err.h>
73 #endif
74 
75 #include <stdlib.h>
76 /* Hash size for secret key check */
77 
78 #include "crypto.h"
79 #include "keyring.h"
80 #include "readerwriter.h"
81 #include "netpgpdefs.h"
82 #include "netpgpdigest.h"
83 #include "packet.h"
84 
85 
86 static void
87 test_seckey(const __ops_seckey_t *seckey)
88 {
89 	RSA            *test = RSA_new();
90 
91 	test->n = BN_dup(seckey->pubkey.key.rsa.n);
92 	test->e = BN_dup(seckey->pubkey.key.rsa.e);
93 
94 	test->d = BN_dup(seckey->key.rsa.d);
95 	test->p = BN_dup(seckey->key.rsa.p);
96 	test->q = BN_dup(seckey->key.rsa.q);
97 
98 	if (RSA_check_key(test) != 1) {
99 		(void) fprintf(stderr,
100 			"test_seckey: RSA_check_key failed\n");
101 	}
102 	RSA_free(test);
103 }
104 
105 static void
106 md5_init(__ops_hash_t *hash)
107 {
108 	if (hash->data) {
109 		(void) fprintf(stderr, "md5_init: hash data non-null\n");
110 	}
111 	hash->data = calloc(1, sizeof(MD5_CTX));
112 	MD5_Init(hash->data);
113 }
114 
115 static void
116 md5_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
117 {
118 	MD5_Update(hash->data, data, length);
119 }
120 
121 static unsigned
122 md5_finish(__ops_hash_t *hash, unsigned char *out)
123 {
124 	MD5_Final(out, hash->data);
125 	free(hash->data);
126 	hash->data = NULL;
127 	return 16;
128 }
129 
130 static const __ops_hash_t md5 = {
131 	OPS_HASH_MD5,
132 	MD5_DIGEST_LENGTH,
133 	"MD5",
134 	md5_init,
135 	md5_add,
136 	md5_finish,
137 	NULL
138 };
139 
140 /**
141    \ingroup Core_Crypto
142    \brief Initialise to MD5
143    \param hash Hash to initialise
144 */
145 void
146 __ops_hash_md5(__ops_hash_t *hash)
147 {
148 	*hash = md5;
149 }
150 
151 static void
152 sha1_init(__ops_hash_t *hash)
153 {
154 	if (__ops_get_debug_level(__FILE__)) {
155 		fprintf(stderr, "***\n***\nsha1_init\n***\n");
156 	}
157 	if (hash->data) {
158 		(void) fprintf(stderr, "sha1_init: hash data non-null\n");
159 	}
160 	hash->data = calloc(1, sizeof(SHA_CTX));
161 	SHA1_Init(hash->data);
162 }
163 
164 static void
165 sha1_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
166 {
167 	if (__ops_get_debug_level(__FILE__)) {
168 		unsigned int    i;
169 
170 		(void) fprintf(stderr, "adding %u to hash:\n ", length);
171 		for (i = 0; i < length; i++) {
172 			(void) fprintf(stderr, "0x%02x ", data[i]);
173 			if (!((i + 1) % 16)) {
174 				(void) fprintf(stderr, "\n");
175 			} else if (!((i + 1) % 8)) {
176 				(void) fprintf(stderr, "  ");
177 			}
178 		}
179 		(void) fprintf(stderr, "\n");
180 	}
181 	SHA1_Update(hash->data, data, length);
182 }
183 
184 static unsigned
185 sha1_finish(__ops_hash_t *hash, unsigned char *out)
186 {
187 	SHA1_Final(out, hash->data);
188 	if (__ops_get_debug_level(__FILE__)) {
189 		unsigned        i;
190 
191 		(void) fprintf(stderr, "***\n***\nsha1_finish\n***\n");
192 		for (i = 0; i < OPS_SHA1_HASH_SIZE; i++)
193 			(void) fprintf(stderr, "0x%02x ", out[i]);
194 		(void) fprintf(stderr, "\n");
195 	}
196 	free(hash->data);
197 	hash->data = NULL;
198 	return OPS_SHA1_HASH_SIZE;
199 }
200 
201 static const __ops_hash_t sha1 = {
202 	OPS_HASH_SHA1,
203 	OPS_SHA1_HASH_SIZE,
204 	"SHA1",
205 	sha1_init,
206 	sha1_add,
207 	sha1_finish,
208 	NULL
209 };
210 
211 /**
212    \ingroup Core_Crypto
213    \brief Initialise to SHA1
214    \param hash Hash to initialise
215 */
216 void
217 __ops_hash_sha1(__ops_hash_t *hash)
218 {
219 	*hash = sha1;
220 }
221 
222 static void
223 sha256_init(__ops_hash_t *hash)
224 {
225 	if (__ops_get_debug_level(__FILE__)) {
226 		fprintf(stderr, "***\n***\nsha256_init\n***\n");
227 	}
228 	if (hash->data) {
229 		(void) fprintf(stderr, "sha256_init: hash data non-null\n");
230 	}
231 	hash->data = calloc(1, sizeof(SHA256_CTX));
232 	SHA256_Init(hash->data);
233 }
234 
235 static void
236 sha256_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
237 {
238 	if (__ops_get_debug_level(__FILE__)) {
239 		unsigned int    i;
240 
241 		(void) fprintf(stderr, "adding %d to hash:\n ", length);
242 		for (i = 0; i < length; i++) {
243 			(void) fprintf(stderr, "0x%02x ", data[i]);
244 			if (!((i + 1) % 16))
245 				(void) fprintf(stderr, "\n");
246 			else if (!((i + 1) % 8))
247 				(void) fprintf(stderr, "  ");
248 		}
249 		(void) fprintf(stderr, "\n");
250 	}
251 	SHA256_Update(hash->data, data, length);
252 }
253 
254 static unsigned
255 sha256_finish(__ops_hash_t *hash, unsigned char *out)
256 {
257 	SHA256_Final(out, hash->data);
258 	if (__ops_get_debug_level(__FILE__)) {
259 		unsigned        i;
260 
261 		(void) fprintf(stderr, "***\n***\nsha1_finish\n***\n");
262 		for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
263 			(void) fprintf(stderr, "0x%02x ", out[i]);
264 		(void) fprintf(stderr, "\n");
265 	}
266 	free(hash->data);
267 	hash->data = NULL;
268 	return SHA256_DIGEST_LENGTH;
269 }
270 
271 static const __ops_hash_t sha256 = {
272 	OPS_HASH_SHA256,
273 	SHA256_DIGEST_LENGTH,
274 	"SHA256",
275 	sha256_init,
276 	sha256_add,
277 	sha256_finish,
278 	NULL
279 };
280 
281 void
282 __ops_hash_sha256(__ops_hash_t *hash)
283 {
284 	*hash = sha256;
285 }
286 
287 /*
288  * SHA384
289  */
290 static void
291 sha384_init(__ops_hash_t *hash)
292 {
293 	if (__ops_get_debug_level(__FILE__)) {
294 		(void) fprintf(stderr, "***\n***\nsha384_init\n***\n");
295 	}
296 	if (hash->data) {
297 		(void) fprintf(stderr, "sha384_init: hash data non-null\n");
298 	}
299 	hash->data = calloc(1, sizeof(SHA512_CTX));
300 	SHA384_Init(hash->data);
301 }
302 
303 static void
304 sha384_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
305 {
306 	if (__ops_get_debug_level(__FILE__)) {
307 		unsigned int    i;
308 
309 		(void) fprintf(stderr, "adding %u to hash:\n ", length);
310 		for (i = 0; i < length; i++) {
311 			(void) fprintf(stderr, "0x%02x ", data[i]);
312 			if (!((i + 1) % 16))
313 				(void) fprintf(stderr, "\n");
314 			else if (!((i + 1) % 8))
315 				(void) fprintf(stderr, "  ");
316 		}
317 		(void) fprintf(stderr, "\n");
318 	}
319 	SHA384_Update(hash->data, data, length);
320 }
321 
322 static unsigned
323 sha384_finish(__ops_hash_t *hash, unsigned char *out)
324 {
325 	SHA384_Final(out, hash->data);
326 	if (__ops_get_debug_level(__FILE__)) {
327 		unsigned        i;
328 
329 		(void) fprintf(stderr, "***\n***\nsha1_finish\n***\n");
330 		for (i = 0; i < SHA384_DIGEST_LENGTH; i++)
331 			(void) fprintf(stderr, "0x%02x ", out[i]);
332 		(void) fprintf(stderr, "\n");
333 	}
334 	free(hash->data);
335 	hash->data = NULL;
336 	return SHA384_DIGEST_LENGTH;
337 }
338 
339 static const __ops_hash_t sha384 = {
340 	OPS_HASH_SHA384,
341 	SHA384_DIGEST_LENGTH,
342 	"SHA384",
343 	sha384_init,
344 	sha384_add,
345 	sha384_finish,
346 	NULL
347 };
348 
349 void
350 __ops_hash_sha384(__ops_hash_t *hash)
351 {
352 	*hash = sha384;
353 }
354 
355 /*
356  * SHA512
357  */
358 static void
359 sha512_init(__ops_hash_t *hash)
360 {
361 	if (__ops_get_debug_level(__FILE__)) {
362 		(void) fprintf(stderr, "***\n***\nsha512_init\n***\n");
363 	}
364 	if (hash->data) {
365 		(void) fprintf(stderr, "sha512_init: hash data non-null\n");
366 	}
367 	hash->data = calloc(1, sizeof(SHA512_CTX));
368 	SHA512_Init(hash->data);
369 }
370 
371 static void
372 sha512_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
373 {
374 	if (__ops_get_debug_level(__FILE__)) {
375 		unsigned int    i;
376 
377 		(void) fprintf(stderr, "adding %u to hash:\n ", length);
378 		for (i = 0; i < length; i++) {
379 			(void) fprintf(stderr, "0x%02x ", data[i]);
380 			if (!((i + 1) % 16))
381 				(void) fprintf(stderr, "\n");
382 			else if (!((i + 1) % 8))
383 				(void) fprintf(stderr, "  ");
384 		}
385 		(void) fprintf(stderr, "\n");
386 	}
387 	SHA512_Update(hash->data, data, length);
388 }
389 
390 static unsigned
391 sha512_finish(__ops_hash_t *hash, unsigned char *out)
392 {
393 	SHA512_Final(out, hash->data);
394 	if (__ops_get_debug_level(__FILE__)) {
395 		unsigned        i;
396 
397 		(void) fprintf(stderr, "***\n***\nsha1_finish\n***\n");
398 		for (i = 0; i < SHA512_DIGEST_LENGTH; i++)
399 			(void) fprintf(stderr, "0x%02x ", out[i]);
400 		(void) fprintf(stderr, "\n");
401 	}
402 	free(hash->data);
403 	hash->data = NULL;
404 	return SHA512_DIGEST_LENGTH;
405 }
406 
407 static const __ops_hash_t sha512 = {
408 	OPS_HASH_SHA512,
409 	SHA512_DIGEST_LENGTH,
410 	"SHA512",
411 	sha512_init,
412 	sha512_add,
413 	sha512_finish,
414 	NULL
415 };
416 
417 void
418 __ops_hash_sha512(__ops_hash_t *hash)
419 {
420 	*hash = sha512;
421 }
422 
423 /*
424  * SHA224
425  */
426 
427 static void
428 sha224_init(__ops_hash_t *hash)
429 {
430 	if (__ops_get_debug_level(__FILE__)) {
431 		(void) fprintf(stderr, "***\n***\nsha1_init\n***\n");
432 	}
433 	if (hash->data) {
434 		(void) fprintf(stderr, "sha224_init: hash data non-null\n");
435 	}
436 	hash->data = calloc(1, sizeof(SHA256_CTX));
437 	SHA224_Init(hash->data);
438 }
439 
440 static void
441 sha224_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
442 {
443 	if (__ops_get_debug_level(__FILE__)) {
444 		unsigned int    i;
445 
446 		(void) fprintf(stderr, "adding %u to hash:\n ", length);
447 		for (i = 0; i < length; i++) {
448 			(void) fprintf(stderr, "0x%02x ", data[i]);
449 			if (!((i + 1) % 16))
450 				(void) fprintf(stderr, "\n");
451 			else if (!((i + 1) % 8))
452 				(void) fprintf(stderr, "  ");
453 		}
454 		(void) fprintf(stderr, "\n");
455 	}
456 	SHA224_Update(hash->data, data, length);
457 }
458 
459 static unsigned
460 sha224_finish(__ops_hash_t *hash, unsigned char *out)
461 {
462 	SHA224_Final(out, hash->data);
463 	if (__ops_get_debug_level(__FILE__)) {
464 		unsigned        i;
465 
466 		(void) fprintf(stderr, "***\n***\nsha1_finish\n***\n");
467 		for (i = 0; i < SHA224_DIGEST_LENGTH; i++)
468 			(void) fprintf(stderr, "0x%02x ", out[i]);
469 		(void) fprintf(stderr, "\n");
470 	}
471 	free(hash->data);
472 	hash->data = NULL;
473 	return SHA224_DIGEST_LENGTH;
474 }
475 
476 static const __ops_hash_t sha224 = {
477 	OPS_HASH_SHA224,
478 	SHA224_DIGEST_LENGTH,
479 	"SHA224",
480 	sha224_init,
481 	sha224_add,
482 	sha224_finish,
483 	NULL
484 };
485 
486 void
487 __ops_hash_sha224(__ops_hash_t *hash)
488 {
489 	*hash = sha224;
490 }
491 
492 unsigned
493 __ops_dsa_verify(const unsigned char *hash, size_t hash_length,
494 	       const __ops_dsa_sig_t *sig,
495 	       const __ops_dsa_pubkey_t *dsa)
496 {
497 	unsigned	qlen;
498 	DSA_SIG        *osig;
499 	DSA            *odsa;
500 	int             ret;
501 
502 	osig = DSA_SIG_new();
503 	osig->r = sig->r;
504 	osig->s = sig->s;
505 
506 	odsa = DSA_new();
507 	odsa->p = dsa->p;
508 	odsa->q = dsa->q;
509 	odsa->g = dsa->g;
510 	odsa->pub_key = dsa->y;
511 
512 	if (__ops_get_debug_level(__FILE__)) {
513 		unsigned        i;
514 
515 		(void) fprintf(stderr, "hash passed in:\n");
516 		for (i = 0; i < hash_length; i++) {
517 			(void) fprintf(stderr, "%02x ", hash[i]);
518 		}
519 		(void) fprintf(stderr, "\n");
520 		printf("hash_length=%" PRIsize "d\n", hash_length);
521 		printf("Q=%d\n", BN_num_bytes(odsa->q));
522 	}
523 	/* XXX - Flexelint -  Info 732: Loss of sign (assignment) (int to unsigned int) */
524 	if ((qlen = BN_num_bytes(odsa->q)) < hash_length) {
525 		hash_length = qlen;
526 	}
527 	ret = DSA_do_verify(hash, (int)hash_length, osig, odsa);
528 	if (__ops_get_debug_level(__FILE__)) {
529 		(void) fprintf(stderr, "ret=%d\n", ret);
530 	}
531 	if (ret < 0) {
532 		(void) fprintf(stderr, "__ops_dsa_verify: DSA verification\n");
533 		return 0;
534 	}
535 
536 	odsa->p = odsa->q = odsa->g = odsa->pub_key = NULL;
537 	DSA_free(odsa);
538 
539 	osig->r = osig->s = NULL;
540 	DSA_SIG_free(osig);
541 
542 	return (unsigned)ret;
543 }
544 
545 /**
546    \ingroup Core_Crypto
547    \brief Recovers message digest from the signature
548    \param out Where to write decrypted data to
549    \param in Encrypted data
550    \param length Length of encrypted data
551    \param pubkey RSA public key
552    \return size of recovered message digest
553 */
554 int
555 __ops_rsa_public_decrypt(unsigned char *out,
556 			const unsigned char *in,
557 			size_t length,
558 			const __ops_rsa_pubkey_t *pubkey)
559 {
560 	RSA            *orsa;
561 	int             n;
562 
563 	orsa = RSA_new();
564 	orsa->n = pubkey->n;
565 	orsa->e = pubkey->e;
566 
567 	n = RSA_public_decrypt((int)length, in, out, orsa, RSA_NO_PADDING);
568 
569 	orsa->n = orsa->e = NULL;
570 	RSA_free(orsa);
571 
572 	return n;
573 }
574 
575 /**
576    \ingroup Core_Crypto
577    \brief Signs data with RSA
578    \param out Where to write signature
579    \param in Data to sign
580    \param length Length of data
581    \param seckey RSA secret key
582    \param pubkey RSA public key
583    \return number of bytes decrypted
584 */
585 int
586 __ops_rsa_private_encrypt(unsigned char *out,
587 			const unsigned char *in,
588 			size_t length,
589 			const __ops_rsa_seckey_t *seckey,
590 			const __ops_rsa_pubkey_t *pubkey)
591 {
592 	RSA            *orsa;
593 	int             n;
594 
595 	orsa = RSA_new();
596 	orsa->n = pubkey->n;	/* XXX: do we need n? */
597 	orsa->d = seckey->d;
598 	orsa->p = seckey->q;
599 	orsa->q = seckey->p;
600 
601 	/* debug */
602 	orsa->e = pubkey->e;
603 	/* If this isn't set, it's very likely that the programmer hasn't */
604 	/* decrypted the secret key. RSA_check_key segfaults in that case. */
605 	/* Use __ops_decrypt_seckey() to do that. */
606 	if (orsa->d == NULL) {
607 		(void) fprintf(stderr, "orsa is not set\n");
608 		return 0;
609 	}
610 	if (RSA_check_key(orsa) != 1) {
611 		(void) fprintf(stderr, "RSA_check_key is not set\n");
612 		return 0;
613 	}
614 	/* end debug */
615 
616 	n = RSA_private_encrypt((int)length, in, out, orsa, RSA_NO_PADDING);
617 
618 	orsa->n = orsa->d = orsa->p = orsa->q = NULL;
619 	RSA_free(orsa);
620 
621 	return n;
622 }
623 
624 /**
625 \ingroup Core_Crypto
626 \brief Decrypts RSA-encrypted data
627 \param out Where to write the plaintext
628 \param in Encrypted data
629 \param length Length of encrypted data
630 \param seckey RSA secret key
631 \param pubkey RSA public key
632 \return size of recovered plaintext
633 */
634 int
635 __ops_rsa_private_decrypt(unsigned char *out,
636 			const unsigned char *in,
637 			size_t length,
638 			const __ops_rsa_seckey_t *seckey,
639 			const __ops_rsa_pubkey_t *pubkey)
640 {
641 	RSA            *keypair;
642 	int             n;
643 	char            errbuf[1024];
644 
645 	keypair = RSA_new();
646 	keypair->n = pubkey->n;	/* XXX: do we need n? */
647 	keypair->d = seckey->d;
648 	keypair->p = seckey->q;
649 	keypair->q = seckey->p;
650 
651 	/* debug */
652 	keypair->e = pubkey->e;
653 	if (RSA_check_key(keypair) != 1) {
654 		(void) fprintf(stderr, "RSA_check_key is not set\n");
655 		return 0;
656 	}
657 	/* end debug */
658 
659 	n = RSA_private_decrypt((int)length, in, out, keypair, RSA_NO_PADDING);
660 
661 	if (__ops_get_debug_level(__FILE__)) {
662 		printf("__ops_rsa_private_decrypt: n=%d\n",n);
663 	}
664 
665 	errbuf[0] = '\0';
666 	if (n == -1) {
667 		unsigned long   err = ERR_get_error();
668 
669 		ERR_error_string(err, &errbuf[0]);
670 		(void) fprintf(stderr, "openssl error : %s\n", errbuf);
671 	}
672 	keypair->n = keypair->d = keypair->p = keypair->q = NULL;
673 	RSA_free(keypair);
674 
675 	return n;
676 }
677 
678 /**
679    \ingroup Core_Crypto
680    \brief RSA-encrypts data
681    \param out Where to write the encrypted data
682    \param in Plaintext
683    \param length Size of plaintext
684    \param pubkey RSA Public Key
685 */
686 int
687 __ops_rsa_public_encrypt(unsigned char *out,
688 			const unsigned char *in,
689 			size_t length,
690 			const __ops_rsa_pubkey_t *pubkey)
691 {
692 	RSA            *orsa;
693 	int             n;
694 
695 	/* printf("__ops_rsa_public_encrypt: length=%ld\n", length); */
696 
697 	orsa = RSA_new();
698 	orsa->n = pubkey->n;
699 	orsa->e = pubkey->e;
700 
701 	/* printf("len: %ld\n", length); */
702 	/* __ops_print_bn("n: ", orsa->n); */
703 	/* __ops_print_bn("e: ", orsa->e); */
704 	n = RSA_public_encrypt((int)length, in, out, orsa, RSA_NO_PADDING);
705 
706 	if (n == -1) {
707 		BIO            *fd_out;
708 
709 		fd_out = BIO_new_fd(fileno(stderr), BIO_NOCLOSE);
710 		ERR_print_errors(fd_out);
711 	}
712 	orsa->n = orsa->e = NULL;
713 	RSA_free(orsa);
714 
715 	return n;
716 }
717 
718 /**
719    \ingroup Core_Crypto
720    \brief initialises openssl
721    \note Would usually call __ops_init() instead
722    \sa __ops_init()
723 */
724 void
725 __ops_crypto_init(void)
726 {
727 #ifdef DMALLOC
728 	CRYPTO_malloc_debug_init();
729 	CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
730 	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
731 #endif
732 }
733 
734 /**
735    \ingroup Core_Crypto
736    \brief Finalise openssl
737    \note Would usually call __ops_finish() instead
738    \sa __ops_finish()
739 */
740 void
741 __ops_crypto_finish(void)
742 {
743 	CRYPTO_cleanup_all_ex_data();
744 	ERR_remove_state((unsigned long)0);
745 #ifdef DMALLOC
746 	CRYPTO_mem_leaks_fp(stderr);
747 #endif
748 }
749 
750 /**
751    \ingroup Core_Hashes
752    \brief Get Hash name
753    \param hash Hash struct
754    \return Hash name
755 */
756 const char     *
757 __ops_text_from_hash(__ops_hash_t *hash)
758 {
759 	return hash->name;
760 }
761 
762 /**
763  \ingroup HighLevel_KeyGenerate
764  \brief Generates an RSA keypair
765  \param numbits Modulus size
766  \param e Public Exponent
767  \param keydata Pointer to keydata struct to hold new key
768  \return 1 if key generated successfully; otherwise 0
769  \note It is the caller's responsibility to call __ops_keydata_free(keydata)
770 */
771 static unsigned
772 rsa_generate_keypair(__ops_key_t *keydata,
773 			const int numbits,
774 			const unsigned long e)
775 {
776 	__ops_seckey_t *seckey;
777 	RSA            *rsa;
778 	BN_CTX         *ctx;
779 	__ops_output_t *output;
780 	__ops_memory_t   *mem;
781 
782 	ctx = BN_CTX_new();
783 	__ops_keydata_init(keydata, OPS_PTAG_CT_SECRET_KEY);
784 	seckey = __ops_get_writable_seckey(keydata);
785 
786 	/* generate the key pair */
787 
788 	rsa = RSA_generate_key(numbits, e, NULL, NULL);
789 
790 	/* populate __ops key from ssl key */
791 
792 	seckey->pubkey.version = OPS_V4;
793 	seckey->pubkey.birthtime = time(NULL);
794 	seckey->pubkey.days_valid = 0;
795 	seckey->pubkey.alg = OPS_PKA_RSA;
796 
797 	seckey->pubkey.key.rsa.n = BN_dup(rsa->n);
798 	seckey->pubkey.key.rsa.e = BN_dup(rsa->e);
799 
800 	seckey->s2k_usage = OPS_S2KU_ENCRYPTED_AND_HASHED;
801 	seckey->s2k_specifier = OPS_S2KS_SALTED;
802 	/* seckey->s2k_specifier=OPS_S2KS_SIMPLE; */
803 	seckey->alg = OPS_SA_CAST5;	/* \todo make param */
804 	seckey->hash_alg = OPS_HASH_SHA1;	/* \todo make param */
805 	seckey->octetc = 0;
806 	seckey->checksum = 0;
807 
808 	seckey->key.rsa.d = BN_dup(rsa->d);
809 	seckey->key.rsa.p = BN_dup(rsa->p);
810 	seckey->key.rsa.q = BN_dup(rsa->q);
811 	seckey->key.rsa.u = BN_mod_inverse(NULL, rsa->p, rsa->q, ctx);
812 	if (seckey->key.rsa.u == NULL) {
813 		(void) fprintf(stderr, "seckey->key.rsa.u is NULL\n");
814 		return 0;
815 	}
816 	BN_CTX_free(ctx);
817 
818 	RSA_free(rsa);
819 
820 	__ops_keyid(keydata->key_id, OPS_KEY_ID_SIZE,
821 			&keydata->key.seckey.pubkey);
822 	__ops_fingerprint(&keydata->fingerprint, &keydata->key.seckey.pubkey);
823 
824 	/* Generate checksum */
825 
826 	output = NULL;
827 	mem = NULL;
828 
829 	__ops_setup_memory_write(&output, &mem, 128);
830 
831 	__ops_push_checksum_writer(output, seckey);
832 
833 	switch (seckey->pubkey.alg) {
834 		/* case OPS_PKA_DSA: */
835 		/* return __ops_write_mpi(output, key->key.dsa.x); */
836 
837 	case OPS_PKA_RSA:
838 	case OPS_PKA_RSA_ENCRYPT_ONLY:
839 	case OPS_PKA_RSA_SIGN_ONLY:
840 		if (!__ops_write_mpi(output, seckey->key.rsa.d) ||
841 		    !__ops_write_mpi(output, seckey->key.rsa.p) ||
842 		    !__ops_write_mpi(output, seckey->key.rsa.q) ||
843 		    !__ops_write_mpi(output, seckey->key.rsa.u)) {
844 			return 0;
845 		}
846 		break;
847 
848 		/* case OPS_PKA_ELGAMAL: */
849 		/* return __ops_write_mpi(output, key->key.elgamal.x); */
850 
851 	default:
852 		(void) fprintf(stderr, "Bad seckey->pubkey.alg\n");
853 		return 0;
854 	}
855 
856 	/* close rather than pop, since its the only one on the stack */
857 	__ops_writer_close(output);
858 	__ops_teardown_memory_write(output, mem);
859 
860 	/* should now have checksum in seckey struct */
861 
862 	/* test */
863 	if (__ops_get_debug_level(__FILE__)) {
864 		test_seckey(seckey);
865 	}
866 
867 	return 1;
868 }
869 
870 /**
871  \ingroup HighLevel_KeyGenerate
872  \brief Creates a self-signed RSA keypair
873  \param numbits Modulus size
874  \param e Public Exponent
875  \param userid User ID
876  \return The new keypair or NULL
877 
878  \note It is the caller's responsibility to call __ops_keydata_free(keydata)
879  \sa rsa_generate_keypair()
880  \sa __ops_keydata_free()
881 */
882 __ops_key_t  *
883 __ops_rsa_new_selfsign_key(const int numbits,
884 				const unsigned long e,
885 				__ops_userid_t *userid)
886 {
887 	__ops_key_t  *keydata;
888 
889 	keydata = __ops_keydata_new();
890 	if (!rsa_generate_keypair(keydata, numbits, e) ||
891 	    !__ops_add_selfsigned_userid(keydata, userid)) {
892 		__ops_keydata_free(keydata);
893 		return NULL;
894 	}
895 	return keydata;
896 }
897 
898 DSA_SIG        *
899 __ops_dsa_sign(unsigned char *hashbuf,
900 		unsigned hashsize,
901 		const __ops_dsa_seckey_t *secdsa,
902 		const __ops_dsa_pubkey_t *pubdsa)
903 {
904 	DSA_SIG        *dsasig;
905 	DSA            *odsa;
906 
907 	odsa = DSA_new();
908 	odsa->p = pubdsa->p;
909 	odsa->q = pubdsa->q;
910 	odsa->g = pubdsa->g;
911 	odsa->pub_key = pubdsa->y;
912 	odsa->priv_key = secdsa->x;
913 
914 	dsasig = DSA_do_sign(hashbuf, (int)hashsize, odsa);
915 
916 	odsa->p = odsa->q = odsa->g = odsa->pub_key = odsa->priv_key = NULL;
917 	DSA_free(odsa);
918 
919 	return dsasig;
920 }
921