xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/openssl_crypto.c (revision 7affbacab9bd5b509bcf92dddc4a53cd447fef4c)
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.17 2009/10/07 16:19:51 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 int
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 	if ((hash->data = calloc(1, sizeof(MD5_CTX))) == NULL) {
112 		(void) fprintf(stderr, "md5_init: bad alloc\n");
113 		return 0;
114 	}
115 	MD5_Init(hash->data);
116 	return 1;
117 }
118 
119 static void
120 md5_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
121 {
122 	MD5_Update(hash->data, data, length);
123 }
124 
125 static unsigned
126 md5_finish(__ops_hash_t *hash, unsigned char *out)
127 {
128 	MD5_Final(out, hash->data);
129 	free(hash->data);
130 	hash->data = NULL;
131 	return 16;
132 }
133 
134 static const __ops_hash_t md5 = {
135 	OPS_HASH_MD5,
136 	MD5_DIGEST_LENGTH,
137 	"MD5",
138 	md5_init,
139 	md5_add,
140 	md5_finish,
141 	NULL
142 };
143 
144 /**
145    \ingroup Core_Crypto
146    \brief Initialise to MD5
147    \param hash Hash to initialise
148 */
149 void
150 __ops_hash_md5(__ops_hash_t *hash)
151 {
152 	*hash = md5;
153 }
154 
155 static int
156 sha1_init(__ops_hash_t *hash)
157 {
158 	if (__ops_get_debug_level(__FILE__)) {
159 		fprintf(stderr, "***\n***\nsha1_init\n***\n");
160 	}
161 	if (hash->data) {
162 		(void) fprintf(stderr, "sha1_init: hash data non-null\n");
163 	}
164 	if ((hash->data = calloc(1, sizeof(SHA_CTX))) == NULL) {
165 		(void) fprintf(stderr, "sha1_init: bad alloc\n");
166 		return 0;
167 	}
168 	SHA1_Init(hash->data);
169 	return 1;
170 }
171 
172 static void
173 sha1_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
174 {
175 	if (__ops_get_debug_level(__FILE__)) {
176 		unsigned int    i;
177 
178 		(void) fprintf(stderr, "adding %u to hash:\n ", length);
179 		for (i = 0; i < length; i++) {
180 			(void) fprintf(stderr, "0x%02x ", data[i]);
181 			if (!((i + 1) % 16)) {
182 				(void) fprintf(stderr, "\n");
183 			} else if (!((i + 1) % 8)) {
184 				(void) fprintf(stderr, "  ");
185 			}
186 		}
187 		(void) fprintf(stderr, "\n");
188 	}
189 	SHA1_Update(hash->data, data, length);
190 }
191 
192 static unsigned
193 sha1_finish(__ops_hash_t *hash, unsigned char *out)
194 {
195 	SHA1_Final(out, hash->data);
196 	if (__ops_get_debug_level(__FILE__)) {
197 		unsigned        i;
198 
199 		(void) fprintf(stderr, "***\n***\nsha1_finish\n***\n");
200 		for (i = 0; i < OPS_SHA1_HASH_SIZE; i++)
201 			(void) fprintf(stderr, "0x%02x ", out[i]);
202 		(void) fprintf(stderr, "\n");
203 	}
204 	free(hash->data);
205 	hash->data = NULL;
206 	return OPS_SHA1_HASH_SIZE;
207 }
208 
209 static const __ops_hash_t sha1 = {
210 	OPS_HASH_SHA1,
211 	OPS_SHA1_HASH_SIZE,
212 	"SHA1",
213 	sha1_init,
214 	sha1_add,
215 	sha1_finish,
216 	NULL
217 };
218 
219 /**
220    \ingroup Core_Crypto
221    \brief Initialise to SHA1
222    \param hash Hash to initialise
223 */
224 void
225 __ops_hash_sha1(__ops_hash_t *hash)
226 {
227 	*hash = sha1;
228 }
229 
230 static int
231 sha256_init(__ops_hash_t *hash)
232 {
233 	if (__ops_get_debug_level(__FILE__)) {
234 		fprintf(stderr, "***\n***\nsha256_init\n***\n");
235 	}
236 	if (hash->data) {
237 		(void) fprintf(stderr, "sha256_init: hash data non-null\n");
238 	}
239 	if ((hash->data = calloc(1, sizeof(SHA256_CTX))) == NULL) {
240 		(void) fprintf(stderr, "sha256_init: bad alloc\n");
241 		return 0;
242 	}
243 	SHA256_Init(hash->data);
244 	return 1;
245 }
246 
247 static void
248 sha256_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
249 {
250 	if (__ops_get_debug_level(__FILE__)) {
251 		unsigned int    i;
252 
253 		(void) fprintf(stderr, "adding %d to hash:\n ", length);
254 		for (i = 0; i < length; i++) {
255 			(void) fprintf(stderr, "0x%02x ", data[i]);
256 			if (!((i + 1) % 16))
257 				(void) fprintf(stderr, "\n");
258 			else if (!((i + 1) % 8))
259 				(void) fprintf(stderr, "  ");
260 		}
261 		(void) fprintf(stderr, "\n");
262 	}
263 	SHA256_Update(hash->data, data, length);
264 }
265 
266 static unsigned
267 sha256_finish(__ops_hash_t *hash, unsigned char *out)
268 {
269 	SHA256_Final(out, hash->data);
270 	if (__ops_get_debug_level(__FILE__)) {
271 		unsigned        i;
272 
273 		(void) fprintf(stderr, "***\n***\nsha1_finish\n***\n");
274 		for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
275 			(void) fprintf(stderr, "0x%02x ", out[i]);
276 		(void) fprintf(stderr, "\n");
277 	}
278 	free(hash->data);
279 	hash->data = NULL;
280 	return SHA256_DIGEST_LENGTH;
281 }
282 
283 static const __ops_hash_t sha256 = {
284 	OPS_HASH_SHA256,
285 	SHA256_DIGEST_LENGTH,
286 	"SHA256",
287 	sha256_init,
288 	sha256_add,
289 	sha256_finish,
290 	NULL
291 };
292 
293 void
294 __ops_hash_sha256(__ops_hash_t *hash)
295 {
296 	*hash = sha256;
297 }
298 
299 /*
300  * SHA384
301  */
302 static int
303 sha384_init(__ops_hash_t *hash)
304 {
305 	if (__ops_get_debug_level(__FILE__)) {
306 		(void) fprintf(stderr, "***\n***\nsha384_init\n***\n");
307 	}
308 	if (hash->data) {
309 		(void) fprintf(stderr, "sha384_init: hash data non-null\n");
310 	}
311 	if ((hash->data = calloc(1, sizeof(SHA512_CTX))) == NULL) {
312 		(void) fprintf(stderr, "sha512_init: bad alloc\n");
313 		return 0;
314 	}
315 	SHA384_Init(hash->data);
316 	return 1;
317 }
318 
319 static void
320 sha384_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
321 {
322 	if (__ops_get_debug_level(__FILE__)) {
323 		unsigned int    i;
324 
325 		(void) fprintf(stderr, "adding %u to hash:\n ", length);
326 		for (i = 0; i < length; i++) {
327 			(void) fprintf(stderr, "0x%02x ", data[i]);
328 			if (!((i + 1) % 16))
329 				(void) fprintf(stderr, "\n");
330 			else if (!((i + 1) % 8))
331 				(void) fprintf(stderr, "  ");
332 		}
333 		(void) fprintf(stderr, "\n");
334 	}
335 	SHA384_Update(hash->data, data, length);
336 }
337 
338 static unsigned
339 sha384_finish(__ops_hash_t *hash, unsigned char *out)
340 {
341 	SHA384_Final(out, hash->data);
342 	if (__ops_get_debug_level(__FILE__)) {
343 		unsigned        i;
344 
345 		(void) fprintf(stderr, "***\n***\nsha1_finish\n***\n");
346 		for (i = 0; i < SHA384_DIGEST_LENGTH; i++)
347 			(void) fprintf(stderr, "0x%02x ", out[i]);
348 		(void) fprintf(stderr, "\n");
349 	}
350 	free(hash->data);
351 	hash->data = NULL;
352 	return SHA384_DIGEST_LENGTH;
353 }
354 
355 static const __ops_hash_t sha384 = {
356 	OPS_HASH_SHA384,
357 	SHA384_DIGEST_LENGTH,
358 	"SHA384",
359 	sha384_init,
360 	sha384_add,
361 	sha384_finish,
362 	NULL
363 };
364 
365 void
366 __ops_hash_sha384(__ops_hash_t *hash)
367 {
368 	*hash = sha384;
369 }
370 
371 /*
372  * SHA512
373  */
374 static int
375 sha512_init(__ops_hash_t *hash)
376 {
377 	if (__ops_get_debug_level(__FILE__)) {
378 		(void) fprintf(stderr, "***\n***\nsha512_init\n***\n");
379 	}
380 	if (hash->data) {
381 		(void) fprintf(stderr, "sha512_init: hash data non-null\n");
382 	}
383 	if ((hash->data = calloc(1, sizeof(SHA512_CTX))) == NULL) {
384 		(void) fprintf(stderr, "sha512_init: bad alloc\n");
385 		return 0;
386 	}
387 	SHA512_Init(hash->data);
388 	return 1;
389 }
390 
391 static void
392 sha512_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
393 {
394 	if (__ops_get_debug_level(__FILE__)) {
395 		unsigned int    i;
396 
397 		(void) fprintf(stderr, "adding %u to hash:\n ", length);
398 		for (i = 0; i < length; i++) {
399 			(void) fprintf(stderr, "0x%02x ", data[i]);
400 			if (!((i + 1) % 16))
401 				(void) fprintf(stderr, "\n");
402 			else if (!((i + 1) % 8))
403 				(void) fprintf(stderr, "  ");
404 		}
405 		(void) fprintf(stderr, "\n");
406 	}
407 	SHA512_Update(hash->data, data, length);
408 }
409 
410 static unsigned
411 sha512_finish(__ops_hash_t *hash, unsigned char *out)
412 {
413 	SHA512_Final(out, hash->data);
414 	if (__ops_get_debug_level(__FILE__)) {
415 		unsigned        i;
416 
417 		(void) fprintf(stderr, "***\n***\nsha1_finish\n***\n");
418 		for (i = 0; i < SHA512_DIGEST_LENGTH; i++)
419 			(void) fprintf(stderr, "0x%02x ", out[i]);
420 		(void) fprintf(stderr, "\n");
421 	}
422 	free(hash->data);
423 	hash->data = NULL;
424 	return SHA512_DIGEST_LENGTH;
425 }
426 
427 static const __ops_hash_t sha512 = {
428 	OPS_HASH_SHA512,
429 	SHA512_DIGEST_LENGTH,
430 	"SHA512",
431 	sha512_init,
432 	sha512_add,
433 	sha512_finish,
434 	NULL
435 };
436 
437 void
438 __ops_hash_sha512(__ops_hash_t *hash)
439 {
440 	*hash = sha512;
441 }
442 
443 /*
444  * SHA224
445  */
446 
447 static int
448 sha224_init(__ops_hash_t *hash)
449 {
450 	if (__ops_get_debug_level(__FILE__)) {
451 		(void) fprintf(stderr, "***\n***\nsha1_init\n***\n");
452 	}
453 	if (hash->data) {
454 		(void) fprintf(stderr, "sha224_init: hash data non-null\n");
455 	}
456 	if ((hash->data = calloc(1, sizeof(SHA256_CTX))) == NULL) {
457 		(void) fprintf(stderr, "sha256_init: bad alloc\n");
458 		return 0;
459 	}
460 	SHA224_Init(hash->data);
461 	return 1;
462 }
463 
464 static void
465 sha224_add(__ops_hash_t *hash, const unsigned char *data, unsigned length)
466 {
467 	if (__ops_get_debug_level(__FILE__)) {
468 		unsigned int    i;
469 
470 		(void) fprintf(stderr, "adding %u to hash:\n ", length);
471 		for (i = 0; i < length; i++) {
472 			(void) fprintf(stderr, "0x%02x ", data[i]);
473 			if (!((i + 1) % 16))
474 				(void) fprintf(stderr, "\n");
475 			else if (!((i + 1) % 8))
476 				(void) fprintf(stderr, "  ");
477 		}
478 		(void) fprintf(stderr, "\n");
479 	}
480 	SHA224_Update(hash->data, data, length);
481 }
482 
483 static unsigned
484 sha224_finish(__ops_hash_t *hash, unsigned char *out)
485 {
486 	SHA224_Final(out, hash->data);
487 	if (__ops_get_debug_level(__FILE__)) {
488 		unsigned        i;
489 
490 		(void) fprintf(stderr, "***\n***\nsha1_finish\n***\n");
491 		for (i = 0; i < SHA224_DIGEST_LENGTH; i++)
492 			(void) fprintf(stderr, "0x%02x ", out[i]);
493 		(void) fprintf(stderr, "\n");
494 	}
495 	free(hash->data);
496 	hash->data = NULL;
497 	return SHA224_DIGEST_LENGTH;
498 }
499 
500 static const __ops_hash_t sha224 = {
501 	OPS_HASH_SHA224,
502 	SHA224_DIGEST_LENGTH,
503 	"SHA224",
504 	sha224_init,
505 	sha224_add,
506 	sha224_finish,
507 	NULL
508 };
509 
510 void
511 __ops_hash_sha224(__ops_hash_t *hash)
512 {
513 	*hash = sha224;
514 }
515 
516 unsigned
517 __ops_dsa_verify(const unsigned char *hash, size_t hash_length,
518 	       const __ops_dsa_sig_t *sig,
519 	       const __ops_dsa_pubkey_t *dsa)
520 {
521 	unsigned	qlen;
522 	DSA_SIG        *osig;
523 	DSA            *odsa;
524 	int             ret;
525 
526 	osig = DSA_SIG_new();
527 	osig->r = sig->r;
528 	osig->s = sig->s;
529 
530 	odsa = DSA_new();
531 	odsa->p = dsa->p;
532 	odsa->q = dsa->q;
533 	odsa->g = dsa->g;
534 	odsa->pub_key = dsa->y;
535 
536 	if (__ops_get_debug_level(__FILE__)) {
537 		unsigned        i;
538 
539 		(void) fprintf(stderr, "hash passed in:\n");
540 		for (i = 0; i < hash_length; i++) {
541 			(void) fprintf(stderr, "%02x ", hash[i]);
542 		}
543 		(void) fprintf(stderr, "\n");
544 		printf("hash_length=%" PRIsize "d\n", hash_length);
545 		printf("Q=%d\n", BN_num_bytes(odsa->q));
546 	}
547 	/* XXX - Flexelint -  Info 732: Loss of sign (assignment) (int to unsigned int) */
548 	if ((qlen = BN_num_bytes(odsa->q)) < hash_length) {
549 		hash_length = qlen;
550 	}
551 	ret = DSA_do_verify(hash, (int)hash_length, osig, odsa);
552 	if (__ops_get_debug_level(__FILE__)) {
553 		(void) fprintf(stderr, "ret=%d\n", ret);
554 	}
555 	if (ret < 0) {
556 		(void) fprintf(stderr, "__ops_dsa_verify: DSA verification\n");
557 		return 0;
558 	}
559 
560 	odsa->p = odsa->q = odsa->g = odsa->pub_key = NULL;
561 	DSA_free(odsa);
562 
563 	osig->r = osig->s = NULL;
564 	DSA_SIG_free(osig);
565 
566 	return (unsigned)ret;
567 }
568 
569 /**
570    \ingroup Core_Crypto
571    \brief Recovers message digest from the signature
572    \param out Where to write decrypted data to
573    \param in Encrypted data
574    \param length Length of encrypted data
575    \param pubkey RSA public key
576    \return size of recovered message digest
577 */
578 int
579 __ops_rsa_public_decrypt(unsigned char *out,
580 			const unsigned char *in,
581 			size_t length,
582 			const __ops_rsa_pubkey_t *pubkey)
583 {
584 	RSA            *orsa;
585 	int             n;
586 
587 	orsa = RSA_new();
588 	orsa->n = pubkey->n;
589 	orsa->e = pubkey->e;
590 
591 	n = RSA_public_decrypt((int)length, in, out, orsa, RSA_NO_PADDING);
592 
593 	orsa->n = orsa->e = NULL;
594 	RSA_free(orsa);
595 
596 	return n;
597 }
598 
599 /**
600    \ingroup Core_Crypto
601    \brief Signs data with RSA
602    \param out Where to write signature
603    \param in Data to sign
604    \param length Length of data
605    \param seckey RSA secret key
606    \param pubkey RSA public key
607    \return number of bytes decrypted
608 */
609 int
610 __ops_rsa_private_encrypt(unsigned char *out,
611 			const unsigned char *in,
612 			size_t length,
613 			const __ops_rsa_seckey_t *seckey,
614 			const __ops_rsa_pubkey_t *pubkey)
615 {
616 	RSA            *orsa;
617 	int             n;
618 
619 	orsa = RSA_new();
620 	orsa->n = pubkey->n;	/* XXX: do we need n? */
621 	orsa->d = seckey->d;
622 	orsa->p = seckey->q;
623 	orsa->q = seckey->p;
624 
625 	/* debug */
626 	orsa->e = pubkey->e;
627 	/* If this isn't set, it's very likely that the programmer hasn't */
628 	/* decrypted the secret key. RSA_check_key segfaults in that case. */
629 	/* Use __ops_decrypt_seckey() to do that. */
630 	if (orsa->d == NULL) {
631 		(void) fprintf(stderr, "orsa is not set\n");
632 		return 0;
633 	}
634 	if (RSA_check_key(orsa) != 1) {
635 		(void) fprintf(stderr, "RSA_check_key is not set\n");
636 		return 0;
637 	}
638 	/* end debug */
639 
640 	n = RSA_private_encrypt((int)length, in, out, orsa, RSA_NO_PADDING);
641 
642 	orsa->n = orsa->d = orsa->p = orsa->q = NULL;
643 	RSA_free(orsa);
644 
645 	return n;
646 }
647 
648 /**
649 \ingroup Core_Crypto
650 \brief Decrypts RSA-encrypted data
651 \param out Where to write the plaintext
652 \param in Encrypted data
653 \param length Length of encrypted data
654 \param seckey RSA secret key
655 \param pubkey RSA public key
656 \return size of recovered plaintext
657 */
658 int
659 __ops_rsa_private_decrypt(unsigned char *out,
660 			const unsigned char *in,
661 			size_t length,
662 			const __ops_rsa_seckey_t *seckey,
663 			const __ops_rsa_pubkey_t *pubkey)
664 {
665 	RSA            *keypair;
666 	int             n;
667 	char            errbuf[1024];
668 
669 	keypair = RSA_new();
670 	keypair->n = pubkey->n;	/* XXX: do we need n? */
671 	keypair->d = seckey->d;
672 	keypair->p = seckey->q;
673 	keypair->q = seckey->p;
674 
675 	/* debug */
676 	keypair->e = pubkey->e;
677 	if (RSA_check_key(keypair) != 1) {
678 		(void) fprintf(stderr, "RSA_check_key is not set\n");
679 		return 0;
680 	}
681 	/* end debug */
682 
683 	n = RSA_private_decrypt((int)length, in, out, keypair, RSA_NO_PADDING);
684 
685 	if (__ops_get_debug_level(__FILE__)) {
686 		printf("__ops_rsa_private_decrypt: n=%d\n",n);
687 	}
688 
689 	errbuf[0] = '\0';
690 	if (n == -1) {
691 		unsigned long   err = ERR_get_error();
692 
693 		ERR_error_string(err, &errbuf[0]);
694 		(void) fprintf(stderr, "openssl error : %s\n", errbuf);
695 	}
696 	keypair->n = keypair->d = keypair->p = keypair->q = NULL;
697 	RSA_free(keypair);
698 
699 	return n;
700 }
701 
702 /**
703    \ingroup Core_Crypto
704    \brief RSA-encrypts data
705    \param out Where to write the encrypted data
706    \param in Plaintext
707    \param length Size of plaintext
708    \param pubkey RSA Public Key
709 */
710 int
711 __ops_rsa_public_encrypt(unsigned char *out,
712 			const unsigned char *in,
713 			size_t length,
714 			const __ops_rsa_pubkey_t *pubkey)
715 {
716 	RSA            *orsa;
717 	int             n;
718 
719 	/* printf("__ops_rsa_public_encrypt: length=%ld\n", length); */
720 
721 	orsa = RSA_new();
722 	orsa->n = pubkey->n;
723 	orsa->e = pubkey->e;
724 
725 	/* printf("len: %ld\n", length); */
726 	/* __ops_print_bn("n: ", orsa->n); */
727 	/* __ops_print_bn("e: ", orsa->e); */
728 	n = RSA_public_encrypt((int)length, in, out, orsa, RSA_NO_PADDING);
729 
730 	if (n == -1) {
731 		BIO            *fd_out;
732 
733 		fd_out = BIO_new_fd(fileno(stderr), BIO_NOCLOSE);
734 		ERR_print_errors(fd_out);
735 	}
736 	orsa->n = orsa->e = NULL;
737 	RSA_free(orsa);
738 
739 	return n;
740 }
741 
742 /**
743    \ingroup Core_Crypto
744    \brief initialises openssl
745    \note Would usually call __ops_init() instead
746    \sa __ops_init()
747 */
748 void
749 __ops_crypto_init(void)
750 {
751 #ifdef DMALLOC
752 	CRYPTO_malloc_debug_init();
753 	CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
754 	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
755 #endif
756 }
757 
758 /**
759    \ingroup Core_Crypto
760    \brief Finalise openssl
761    \note Would usually call __ops_finish() instead
762    \sa __ops_finish()
763 */
764 void
765 __ops_crypto_finish(void)
766 {
767 	CRYPTO_cleanup_all_ex_data();
768 	ERR_remove_state((unsigned long)0);
769 #ifdef DMALLOC
770 	CRYPTO_mem_leaks_fp(stderr);
771 #endif
772 }
773 
774 /**
775    \ingroup Core_Hashes
776    \brief Get Hash name
777    \param hash Hash struct
778    \return Hash name
779 */
780 const char     *
781 __ops_text_from_hash(__ops_hash_t *hash)
782 {
783 	return hash->name;
784 }
785 
786 /**
787  \ingroup HighLevel_KeyGenerate
788  \brief Generates an RSA keypair
789  \param numbits Modulus size
790  \param e Public Exponent
791  \param keydata Pointer to keydata struct to hold new key
792  \return 1 if key generated successfully; otherwise 0
793  \note It is the caller's responsibility to call __ops_keydata_free(keydata)
794 */
795 static unsigned
796 rsa_generate_keypair(__ops_key_t *keydata,
797 			const int numbits,
798 			const unsigned long e)
799 {
800 	__ops_seckey_t *seckey;
801 	RSA            *rsa;
802 	BN_CTX         *ctx;
803 	__ops_output_t *output;
804 	__ops_memory_t   *mem;
805 
806 	ctx = BN_CTX_new();
807 	__ops_keydata_init(keydata, OPS_PTAG_CT_SECRET_KEY);
808 	seckey = __ops_get_writable_seckey(keydata);
809 
810 	/* generate the key pair */
811 
812 	rsa = RSA_generate_key(numbits, e, NULL, NULL);
813 
814 	/* populate __ops key from ssl key */
815 
816 	seckey->pubkey.version = OPS_V4;
817 	seckey->pubkey.birthtime = time(NULL);
818 	seckey->pubkey.days_valid = 0;
819 	seckey->pubkey.alg = OPS_PKA_RSA;
820 
821 	seckey->pubkey.key.rsa.n = BN_dup(rsa->n);
822 	seckey->pubkey.key.rsa.e = BN_dup(rsa->e);
823 
824 	seckey->s2k_usage = OPS_S2KU_ENCRYPTED_AND_HASHED;
825 	seckey->s2k_specifier = OPS_S2KS_SALTED;
826 	/* seckey->s2k_specifier=OPS_S2KS_SIMPLE; */
827 	seckey->alg = OPS_SA_CAST5;	/* \todo make param */
828 	seckey->hash_alg = OPS_HASH_SHA1;	/* \todo make param */
829 	seckey->octetc = 0;
830 	seckey->checksum = 0;
831 
832 	seckey->key.rsa.d = BN_dup(rsa->d);
833 	seckey->key.rsa.p = BN_dup(rsa->p);
834 	seckey->key.rsa.q = BN_dup(rsa->q);
835 	seckey->key.rsa.u = BN_mod_inverse(NULL, rsa->p, rsa->q, ctx);
836 	if (seckey->key.rsa.u == NULL) {
837 		(void) fprintf(stderr, "seckey->key.rsa.u is NULL\n");
838 		return 0;
839 	}
840 	BN_CTX_free(ctx);
841 
842 	RSA_free(rsa);
843 
844 	__ops_keyid(keydata->key_id, OPS_KEY_ID_SIZE,
845 			&keydata->key.seckey.pubkey);
846 	__ops_fingerprint(&keydata->fingerprint, &keydata->key.seckey.pubkey);
847 
848 	/* Generate checksum */
849 
850 	output = NULL;
851 	mem = NULL;
852 
853 	__ops_setup_memory_write(&output, &mem, 128);
854 
855 	__ops_push_checksum_writer(output, seckey);
856 
857 	switch (seckey->pubkey.alg) {
858 		/* case OPS_PKA_DSA: */
859 		/* return __ops_write_mpi(output, key->key.dsa.x); */
860 
861 	case OPS_PKA_RSA:
862 	case OPS_PKA_RSA_ENCRYPT_ONLY:
863 	case OPS_PKA_RSA_SIGN_ONLY:
864 		if (!__ops_write_mpi(output, seckey->key.rsa.d) ||
865 		    !__ops_write_mpi(output, seckey->key.rsa.p) ||
866 		    !__ops_write_mpi(output, seckey->key.rsa.q) ||
867 		    !__ops_write_mpi(output, seckey->key.rsa.u)) {
868 			return 0;
869 		}
870 		break;
871 
872 		/* case OPS_PKA_ELGAMAL: */
873 		/* return __ops_write_mpi(output, key->key.elgamal.x); */
874 
875 	default:
876 		(void) fprintf(stderr, "Bad seckey->pubkey.alg\n");
877 		return 0;
878 	}
879 
880 	/* close rather than pop, since its the only one on the stack */
881 	__ops_writer_close(output);
882 	__ops_teardown_memory_write(output, mem);
883 
884 	/* should now have checksum in seckey struct */
885 
886 	/* test */
887 	if (__ops_get_debug_level(__FILE__)) {
888 		test_seckey(seckey);
889 	}
890 
891 	return 1;
892 }
893 
894 /**
895  \ingroup HighLevel_KeyGenerate
896  \brief Creates a self-signed RSA keypair
897  \param numbits Modulus size
898  \param e Public Exponent
899  \param userid User ID
900  \return The new keypair or NULL
901 
902  \note It is the caller's responsibility to call __ops_keydata_free(keydata)
903  \sa rsa_generate_keypair()
904  \sa __ops_keydata_free()
905 */
906 __ops_key_t  *
907 __ops_rsa_new_selfsign_key(const int numbits,
908 				const unsigned long e,
909 				__ops_userid_t *userid)
910 {
911 	__ops_key_t  *keydata;
912 
913 	keydata = __ops_keydata_new();
914 	if (!rsa_generate_keypair(keydata, numbits, e) ||
915 	    !__ops_add_selfsigned_userid(keydata, userid)) {
916 		__ops_keydata_free(keydata);
917 		return NULL;
918 	}
919 	return keydata;
920 }
921 
922 DSA_SIG        *
923 __ops_dsa_sign(unsigned char *hashbuf,
924 		unsigned hashsize,
925 		const __ops_dsa_seckey_t *secdsa,
926 		const __ops_dsa_pubkey_t *pubdsa)
927 {
928 	DSA_SIG        *dsasig;
929 	DSA            *odsa;
930 
931 	odsa = DSA_new();
932 	odsa->p = pubdsa->p;
933 	odsa->q = pubdsa->q;
934 	odsa->g = pubdsa->g;
935 	odsa->pub_key = pubdsa->y;
936 	odsa->priv_key = secdsa->x;
937 
938 	dsasig = DSA_do_sign(hashbuf, (int)hashsize, odsa);
939 
940 	odsa->p = odsa->q = odsa->g = odsa->pub_key = odsa->priv_key = NULL;
941 	DSA_free(odsa);
942 
943 	return dsasig;
944 }
945