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