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