xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/openssl_crypto.c (revision da9817918ec7e88db2912a2882967c7570a83f47)
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.15 2009/06/11 01:12:42 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 __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 %d 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 	(void) free(hash->data);
197 	hash->data = NULL;
198 	return OPS_SHA1_HASH_SIZE;
199 }
200 
201 static __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 	(void) free(hash->data);
267 	hash->data = NULL;
268 	return SHA256_DIGEST_LENGTH;
269 }
270 
271 static __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 %d 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 	(void) free(hash->data);
335 	hash->data = NULL;
336 	return SHA384_DIGEST_LENGTH;
337 }
338 
339 static __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 %d 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 	(void) free(hash->data);
403 	hash->data = NULL;
404 	return SHA512_DIGEST_LENGTH;
405 }
406 
407 static __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 %d 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 	(void) free(hash->data);
472 	hash->data = NULL;
473 	return SHA224_DIGEST_LENGTH;
474 }
475 
476 static __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=%u\n", BN_num_bytes(odsa->q));
522 	}
523 	if ((qlen = BN_num_bytes(odsa->q)) < hash_length) {
524 		hash_length = qlen;
525 	}
526 	ret = DSA_do_verify(hash, (int)hash_length, osig, odsa);
527 	if (__ops_get_debug_level(__FILE__)) {
528 		(void) fprintf(stderr, "ret=%d\n", ret);
529 	}
530 	if (ret < 0) {
531 		(void) fprintf(stderr, "__ops_dsa_verify: DSA verification\n");
532 		return 0;
533 	}
534 
535 	odsa->p = odsa->q = odsa->g = odsa->pub_key = NULL;
536 	DSA_free(odsa);
537 
538 	osig->r = osig->s = NULL;
539 	DSA_SIG_free(osig);
540 
541 	return ret;
542 }
543 
544 /**
545    \ingroup Core_Crypto
546    \brief Recovers message digest from the signature
547    \param out Where to write decrypted data to
548    \param in Encrypted data
549    \param length Length of encrypted data
550    \param pubkey RSA public key
551    \return size of recovered message digest
552 */
553 int
554 __ops_rsa_public_decrypt(unsigned char *out,
555 			const unsigned char *in,
556 			size_t length,
557 			const __ops_rsa_pubkey_t *pubkey)
558 {
559 	RSA            *orsa;
560 	int             n;
561 
562 	orsa = RSA_new();
563 	orsa->n = pubkey->n;
564 	orsa->e = pubkey->e;
565 
566 	n = RSA_public_decrypt((int)length, in, out, orsa, RSA_NO_PADDING);
567 
568 	orsa->n = orsa->e = NULL;
569 	RSA_free(orsa);
570 
571 	return n;
572 }
573 
574 /**
575    \ingroup Core_Crypto
576    \brief Signs data with RSA
577    \param out Where to write signature
578    \param in Data to sign
579    \param length Length of data
580    \param seckey RSA secret key
581    \param pubkey RSA public key
582    \return number of bytes decrypted
583 */
584 int
585 __ops_rsa_private_encrypt(unsigned char *out,
586 			const unsigned char *in,
587 			size_t length,
588 			const __ops_rsa_seckey_t *seckey,
589 			const __ops_rsa_pubkey_t *pubkey)
590 {
591 	RSA            *orsa;
592 	int             n;
593 
594 	orsa = RSA_new();
595 	orsa->n = pubkey->n;	/* XXX: do we need n? */
596 	orsa->d = seckey->d;
597 	orsa->p = seckey->q;
598 	orsa->q = seckey->p;
599 
600 	/* debug */
601 	orsa->e = pubkey->e;
602 	/* If this isn't set, it's very likely that the programmer hasn't */
603 	/* decrypted the secret key. RSA_check_key segfaults in that case. */
604 	/* Use __ops_decrypt_seckey() to do that. */
605 	if (orsa->d == NULL) {
606 		(void) fprintf(stderr, "orsa is not set\n");
607 		return 0;
608 	}
609 	if (RSA_check_key(orsa) != 1) {
610 		(void) fprintf(stderr, "RSA_check_key is not set\n");
611 		return 0;
612 	}
613 	/* end debug */
614 
615 	n = RSA_private_encrypt((int)length, in, out, orsa, RSA_NO_PADDING);
616 
617 	orsa->n = orsa->d = orsa->p = orsa->q = NULL;
618 	RSA_free(orsa);
619 
620 	return n;
621 }
622 
623 /**
624 \ingroup Core_Crypto
625 \brief Decrypts RSA-encrypted data
626 \param out Where to write the plaintext
627 \param in Encrypted data
628 \param length Length of encrypted data
629 \param seckey RSA secret key
630 \param pubkey RSA public key
631 \return size of recovered plaintext
632 */
633 int
634 __ops_rsa_private_decrypt(unsigned char *out,
635 			const unsigned char *in,
636 			size_t length,
637 			const __ops_rsa_seckey_t *seckey,
638 			const __ops_rsa_pubkey_t *pubkey)
639 {
640 	RSA            *keypair;
641 	int             n;
642 	char            errbuf[1024];
643 
644 	keypair = RSA_new();
645 	keypair->n = pubkey->n;	/* XXX: do we need n? */
646 	keypair->d = seckey->d;
647 	keypair->p = seckey->q;
648 	keypair->q = seckey->p;
649 
650 	/* debug */
651 	keypair->e = pubkey->e;
652 	if (RSA_check_key(keypair) != 1) {
653 		(void) fprintf(stderr, "RSA_check_key is not set\n");
654 		return 0;
655 	}
656 	/* end debug */
657 
658 	n = RSA_private_decrypt((int)length, in, out, keypair, RSA_NO_PADDING);
659 
660 	if (__ops_get_debug_level(__FILE__)) {
661 		printf("__ops_rsa_private_decrypt: n=%d\n",n);
662 	}
663 
664 	errbuf[0] = '\0';
665 	if (n == -1) {
666 		unsigned long   err = ERR_get_error();
667 
668 		ERR_error_string(err, &errbuf[0]);
669 		(void) fprintf(stderr, "openssl error : %s\n", errbuf);
670 	}
671 	keypair->n = keypair->d = keypair->p = keypair->q = NULL;
672 	RSA_free(keypair);
673 
674 	return n;
675 }
676 
677 /**
678    \ingroup Core_Crypto
679    \brief RSA-encrypts data
680    \param out Where to write the encrypted data
681    \param in Plaintext
682    \param length Size of plaintext
683    \param pubkey RSA Public Key
684 */
685 int
686 __ops_rsa_public_encrypt(unsigned char *out,
687 			const unsigned char *in,
688 			size_t length,
689 			const __ops_rsa_pubkey_t *pubkey)
690 {
691 	RSA            *orsa;
692 	int             n;
693 
694 	/* printf("__ops_rsa_public_encrypt: length=%ld\n", length); */
695 
696 	orsa = RSA_new();
697 	orsa->n = pubkey->n;
698 	orsa->e = pubkey->e;
699 
700 	/* printf("len: %ld\n", length); */
701 	/* __ops_print_bn("n: ", orsa->n); */
702 	/* __ops_print_bn("e: ", orsa->e); */
703 	n = RSA_public_encrypt((int)length, in, out, orsa, RSA_NO_PADDING);
704 
705 	if (n == -1) {
706 		BIO            *fd_out;
707 
708 		fd_out = BIO_new_fd(fileno(stderr), BIO_NOCLOSE);
709 		ERR_print_errors(fd_out);
710 	}
711 	orsa->n = orsa->e = NULL;
712 	RSA_free(orsa);
713 
714 	return n;
715 }
716 
717 /**
718    \ingroup Core_Crypto
719    \brief initialises openssl
720    \note Would usually call __ops_init() instead
721    \sa __ops_init()
722 */
723 void
724 __ops_crypto_init(void)
725 {
726 #ifdef DMALLOC
727 	CRYPTO_malloc_debug_init();
728 	CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
729 	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
730 #endif
731 }
732 
733 /**
734    \ingroup Core_Crypto
735    \brief Finalise openssl
736    \note Would usually call __ops_finish() instead
737    \sa __ops_finish()
738 */
739 void
740 __ops_crypto_finish(void)
741 {
742 	CRYPTO_cleanup_all_ex_data();
743 	ERR_remove_state((unsigned long)0);
744 #ifdef DMALLOC
745 	CRYPTO_mem_leaks_fp(stderr);
746 #endif
747 }
748 
749 /**
750    \ingroup Core_Hashes
751    \brief Get Hash name
752    \param hash Hash struct
753    \return Hash name
754 */
755 const char     *
756 __ops_text_from_hash(__ops_hash_t *hash)
757 {
758 	return hash->name;
759 }
760 
761 /**
762  \ingroup HighLevel_KeyGenerate
763  \brief Generates an RSA keypair
764  \param numbits Modulus size
765  \param e Public Exponent
766  \param keydata Pointer to keydata struct to hold new key
767  \return 1 if key generated successfully; otherwise 0
768  \note It is the caller's responsibility to call __ops_keydata_free(keydata)
769 */
770 static unsigned
771 rsa_generate_keypair(__ops_key_t *keydata,
772 			const int numbits,
773 			const unsigned long e)
774 {
775 	__ops_seckey_t *seckey = NULL;
776 	RSA            *rsa = NULL;
777 	BN_CTX         *ctx = BN_CTX_new();
778 	__ops_output_t *output;
779 	__ops_memory_t   *mem;
780 
781 	__ops_keydata_init(keydata, OPS_PTAG_CT_SECRET_KEY);
782 	seckey = __ops_get_writable_seckey(keydata);
783 
784 	/* generate the key pair */
785 
786 	rsa = RSA_generate_key(numbits, e, NULL, NULL);
787 
788 	/* populate __ops key from ssl key */
789 
790 	seckey->pubkey.version = 4;
791 	seckey->pubkey.birthtime = time(NULL);
792 	seckey->pubkey.days_valid = 0;
793 	seckey->pubkey.alg = OPS_PKA_RSA;
794 
795 	seckey->pubkey.key.rsa.n = BN_dup(rsa->n);
796 	seckey->pubkey.key.rsa.e = BN_dup(rsa->e);
797 
798 	seckey->s2k_usage = OPS_S2KU_ENCRYPTED_AND_HASHED;
799 	seckey->s2k_specifier = OPS_S2KS_SALTED;
800 	/* seckey->s2k_specifier=OPS_S2KS_SIMPLE; */
801 	seckey->alg = OPS_SA_CAST5;	/* \todo make param */
802 	seckey->hash_alg = OPS_HASH_SHA1;	/* \todo make param */
803 	seckey->octetc = 0;
804 	seckey->checksum = 0;
805 
806 	seckey->key.rsa.d = BN_dup(rsa->d);
807 	seckey->key.rsa.p = BN_dup(rsa->p);
808 	seckey->key.rsa.q = BN_dup(rsa->q);
809 	seckey->key.rsa.u = BN_mod_inverse(NULL, rsa->p, rsa->q, ctx);
810 	if (seckey->key.rsa.u == NULL) {
811 		(void) fprintf(stderr, "seckey->key.rsa.u is NULL\n");
812 		return 0;
813 	}
814 	BN_CTX_free(ctx);
815 
816 	RSA_free(rsa);
817 
818 	__ops_keyid(keydata->key_id, OPS_KEY_ID_SIZE,
819 			&keydata->key.seckey.pubkey);
820 	__ops_fingerprint(&keydata->fingerprint, &keydata->key.seckey.pubkey);
821 
822 	/* Generate checksum */
823 
824 	output = NULL;
825 	mem = NULL;
826 
827 	__ops_setup_memory_write(&output, &mem, 128);
828 
829 	__ops_push_checksum_writer(output, seckey);
830 
831 	switch (seckey->pubkey.alg) {
832 		/* case OPS_PKA_DSA: */
833 		/* return __ops_write_mpi(output, key->key.dsa.x); */
834 
835 	case OPS_PKA_RSA:
836 	case OPS_PKA_RSA_ENCRYPT_ONLY:
837 	case OPS_PKA_RSA_SIGN_ONLY:
838 		if (!__ops_write_mpi(output, seckey->key.rsa.d) ||
839 		    !__ops_write_mpi(output, seckey->key.rsa.p) ||
840 		    !__ops_write_mpi(output, seckey->key.rsa.q) ||
841 		    !__ops_write_mpi(output, seckey->key.rsa.u)) {
842 			return 0;
843 		}
844 		break;
845 
846 		/* case OPS_PKA_ELGAMAL: */
847 		/* return __ops_write_mpi(output, key->key.elgamal.x); */
848 
849 	default:
850 		(void) fprintf(stderr, "Bad seckey->pubkey.alg\n");
851 		return 0;
852 	}
853 
854 	/* close rather than pop, since its the only one on the stack */
855 	__ops_writer_close(output);
856 	__ops_teardown_memory_write(output, mem);
857 
858 	/* should now have checksum in seckey struct */
859 
860 	/* test */
861 	if (__ops_get_debug_level(__FILE__)) {
862 		test_seckey(seckey);
863 	}
864 
865 	return 1;
866 }
867 
868 /**
869  \ingroup HighLevel_KeyGenerate
870  \brief Creates a self-signed RSA keypair
871  \param numbits Modulus size
872  \param e Public Exponent
873  \param userid User ID
874  \return The new keypair or NULL
875 
876  \note It is the caller's responsibility to call __ops_keydata_free(keydata)
877  \sa rsa_generate_keypair()
878  \sa __ops_keydata_free()
879 */
880 __ops_key_t  *
881 __ops_rsa_new_selfsign_key(const int numbits,
882 				const unsigned long e,
883 				__ops_userid_t *userid)
884 {
885 	__ops_key_t  *keydata = NULL;
886 
887 	keydata = __ops_keydata_new();
888 	if (!rsa_generate_keypair(keydata, numbits, e) ||
889 	    !__ops_add_selfsigned_userid(keydata, userid)) {
890 		__ops_keydata_free(keydata);
891 		return NULL;
892 	}
893 	return keydata;
894 }
895 
896 DSA_SIG        *
897 __ops_dsa_sign(unsigned char *hashbuf,
898 		unsigned hashsize,
899 		const __ops_dsa_seckey_t *secdsa,
900 		const __ops_dsa_pubkey_t *pubdsa)
901 {
902 	DSA_SIG        *dsasig;
903 	DSA            *odsa;
904 
905 	odsa = DSA_new();
906 	odsa->p = pubdsa->p;
907 	odsa->q = pubdsa->q;
908 	odsa->g = pubdsa->g;
909 	odsa->pub_key = pubdsa->y;
910 	odsa->priv_key = secdsa->x;
911 
912 	dsasig = DSA_do_sign(hashbuf, (int)hashsize, odsa);
913 
914 	odsa->p = odsa->q = odsa->g = odsa->pub_key = odsa->priv_key = NULL;
915 	DSA_free(odsa);
916 
917 	return dsasig;
918 }
919