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