xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/create.c (revision d21b929e261d70bb2c7a8e48b531593c2eec962c)
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: create.c,v 1.16 2009/05/31 23:26:20 agc Exp $");
61 #endif
62 
63 #include <sys/types.h>
64 #include <sys/param.h>
65 #include <sys/stat.h>
66 #include <sys/mman.h>
67 
68 #ifdef HAVE_FCNTL_H
69 #include <fcntl.h>
70 #endif
71 
72 #include <string.h>
73 
74 #ifdef HAVE_UNISTD_H
75 #include <unistd.h>
76 #endif
77 
78 #ifdef HAVE_OPENSSL_CAST_H
79 #include <openssl/cast.h>
80 #endif
81 
82 #include "create.h"
83 #include "keyring.h"
84 #include "packet.h"
85 #include "signature.h"
86 #include "writer.h"
87 #include "readerwriter.h"
88 #include "memory.h"
89 #include "netpgpdefs.h"
90 #include "netpgpdigest.h"
91 
92 /**
93  * \ingroup Core_Create
94  * \param length
95  * \param type
96  * \param output
97  * \return 1 if OK, otherwise 0
98  */
99 
100 unsigned
101 __ops_write_ss_header(__ops_output_t *output,
102 			unsigned length,
103 			__ops_content_tag_t type)
104 {
105 	return __ops_write_length(output, length) &&
106 		__ops_write_scalar(output, (unsigned)(type -
107 				OPS_PTAG_SIG_SUBPKT_BASE), 1);
108 }
109 
110 /*
111  * XXX: the general idea of _fast_ is that it doesn't copy stuff the safe
112  * (i.e. non _fast_) version will, and so will also need to be freed.
113  */
114 
115 /**
116  * \ingroup Core_Create
117  *
118  * __ops_fast_create_userid() sets id->userid to the given userid.
119  * This is fast because it is only copying a char*. However, if userid
120  * is changed or freed in the future, this could have injurious results.
121  * \param id
122  * \param userid
123  */
124 
125 void
126 __ops_fast_create_userid(__ops_userid_t *id, unsigned char *userid)
127 {
128 	id->userid = userid;
129 }
130 
131 /**
132  * \ingroup Core_WritePackets
133  * \brief Writes a User Id packet
134  * \param id
135  * \param output
136  * \return 1 if OK, otherwise 0
137  */
138 unsigned
139 __ops_write_struct_userid(__ops_output_t *output, __ops_userid_t *id)
140 {
141 	return __ops_write_ptag(output, OPS_PTAG_CT_USER_ID) &&
142 		__ops_write_length(output, strlen((char *) id->userid)) &&
143 		__ops_write(output, id->userid, strlen((char *) id->userid));
144 }
145 
146 /**
147  * \ingroup Core_WritePackets
148  * \brief Write a User Id packet.
149  * \param userid
150  * \param output
151  *
152  * \return return value from __ops_write_struct_userid()
153  */
154 unsigned
155 __ops_write_userid(const unsigned char *userid, __ops_output_t *output)
156 {
157 	__ops_userid_t   id;
158 
159 	id.userid = __UNCONST(userid);
160 	return __ops_write_struct_userid(output, &id);
161 }
162 
163 /**
164 \ingroup Core_MPI
165 */
166 static unsigned
167 mpi_length(const BIGNUM *bn)
168 {
169 	return 2 + (BN_num_bits(bn) + 7) / 8;
170 }
171 
172 static unsigned
173 pubkey_length(const __ops_pubkey_t *key)
174 {
175 	switch (key->alg) {
176 	case OPS_PKA_RSA:
177 		return mpi_length(key->key.rsa.n) + mpi_length(key->key.rsa.e);
178 
179 	default:
180 		(void) fprintf(stderr,
181 			"pubkey_length: unknown key algorithm\n");
182 	}
183 	return 0;
184 }
185 
186 static unsigned
187 seckey_length(const __ops_seckey_t *key)
188 {
189 	int             len;
190 
191 	len = 0;
192 	switch (key->pubkey.alg) {
193 	case OPS_PKA_RSA:
194 		len = mpi_length(key->key.rsa.d) + mpi_length(key->key.rsa.p) +
195 			mpi_length(key->key.rsa.q) + mpi_length(key->key.rsa.u);
196 
197 		return len + pubkey_length(&key->pubkey);
198 	default:
199 		(void) fprintf(stderr,
200 			"seckey_length: unknown key algorithm\n");
201 	}
202 	return 0;
203 }
204 
205 /**
206  * \ingroup Core_Create
207  * \param key
208  * \param t
209  * \param n
210  * \param e
211 */
212 void
213 __ops_fast_create_rsa_pubkey(__ops_pubkey_t *key, time_t t,
214 			       BIGNUM *n, BIGNUM *e)
215 {
216 	key->version = 4;
217 	key->birthtime = t;
218 	key->alg = OPS_PKA_RSA;
219 	key->key.rsa.n = n;
220 	key->key.rsa.e = e;
221 }
222 
223 /*
224  * Note that we support v3 keys here because they're needed for for
225  * verification - the writer doesn't allow them, though
226  */
227 static unsigned
228 write_pubkey_body(const __ops_pubkey_t *key, __ops_output_t *output)
229 {
230 	if (!(__ops_write_scalar(output, (unsigned)key->version, 1) &&
231 	      __ops_write_scalar(output, (unsigned)key->birthtime, 4))) {
232 		return 0;
233 	}
234 
235 	if (key->version != 4 &&
236 	    !__ops_write_scalar(output, key->days_valid, 2)) {
237 		return 0;
238 	}
239 
240 	if (!__ops_write_scalar(output, (unsigned)key->alg, 1)) {
241 		return 0;
242 	}
243 
244 	switch (key->alg) {
245 	case OPS_PKA_DSA:
246 		return __ops_write_mpi(output, key->key.dsa.p) &&
247 			__ops_write_mpi(output, key->key.dsa.q) &&
248 			__ops_write_mpi(output, key->key.dsa.g) &&
249 			__ops_write_mpi(output, key->key.dsa.y);
250 
251 	case OPS_PKA_RSA:
252 	case OPS_PKA_RSA_ENCRYPT_ONLY:
253 	case OPS_PKA_RSA_SIGN_ONLY:
254 		return __ops_write_mpi(output, key->key.rsa.n) &&
255 			__ops_write_mpi(output, key->key.rsa.e);
256 
257 	case OPS_PKA_ELGAMAL:
258 		return __ops_write_mpi(output, key->key.elgamal.p) &&
259 			__ops_write_mpi(output, key->key.elgamal.g) &&
260 			__ops_write_mpi(output, key->key.elgamal.y);
261 
262 	default:
263 		(void) fprintf(stderr,
264 			"write_pubkey_body: bad algorithm\n");
265 		break;
266 	}
267 	return 0;
268 }
269 
270 /*
271  * Note that we support v3 keys here because they're needed for
272  * verification - the writer doesn't allow them, though
273  */
274 static unsigned
275 write_seckey_body(const __ops_seckey_t *key,
276 		      const unsigned char *passphrase,
277 		      const size_t pplen,
278 		      __ops_output_t *output)
279 {
280 	/* RFC4880 Section 5.5.3 Secret-Key Packet Formats */
281 
282 	__ops_crypt_t     crypted;
283 	__ops_hash_t      hash;
284 	unsigned char   hashed[OPS_SHA1_HASH_SIZE];
285 	unsigned char   sesskey[CAST_KEY_LENGTH];
286 	unsigned int    done = 0;
287 	unsigned int    i = 0;
288 
289 	if (!write_pubkey_body(&key->pubkey, output)) {
290 		return 0;
291 	}
292 	if (key->s2k_usage != OPS_S2KU_ENCRYPTED_AND_HASHED) {
293 		(void) fprintf(stderr, "write_seckey_body: s2k usage\n");
294 		return 0;
295 	}
296 	if (!__ops_write_scalar(output, (unsigned)key->s2k_usage, 1)) {
297 		return 0;
298 	}
299 
300 	if (key->alg != OPS_SA_CAST5) {
301 		(void) fprintf(stderr, "write_seckey_body: algorithm\n");
302 		return 0;
303 	}
304 	if (!__ops_write_scalar(output, (unsigned)key->alg, 1)) {
305 		return 0;
306 	}
307 
308 	if (key->s2k_specifier != OPS_S2KS_SIMPLE &&
309 	    key->s2k_specifier != OPS_S2KS_SALTED) {
310 		/* = 1 \todo could also be iterated-and-salted */
311 		(void) fprintf(stderr, "write_seckey_body: s2k spec\n");
312 		return 0;
313 	}
314 	if (!__ops_write_scalar(output, (unsigned)key->s2k_specifier, 1)) {
315 		return 0;
316 	}
317 
318 	if (key->hash_alg != OPS_HASH_SHA1) {
319 		(void) fprintf(stderr, "write_seckey_body: hash alg\n");
320 		return 0;
321 	}
322 	if (!__ops_write_scalar(output, (unsigned)key->hash_alg, 1)) {
323 		return 0;
324 	}
325 
326 	switch (key->s2k_specifier) {
327 	case OPS_S2KS_SIMPLE:
328 		/* nothing more to do */
329 		break;
330 
331 	case OPS_S2KS_SALTED:
332 		/* 8-octet salt value */
333 		__ops_random(__UNCONST(&key->salt[0]), OPS_SALT_SIZE);
334 		if (!__ops_write(output, key->salt, OPS_SALT_SIZE)) {
335 			return 0;
336 		}
337 		break;
338 
339 		/*
340 		 * \todo case OPS_S2KS_ITERATED_AND_SALTED: // 8-octet salt
341 		 * value // 1-octet count break;
342 		 */
343 
344 	default:
345 		(void) fprintf(stderr,
346 			"invalid/unsupported s2k specifier %d\n",
347 			key->s2k_specifier);
348 		return 0;
349 	}
350 
351 	if (!__ops_write(output, &key->iv[0], __ops_block_size(key->alg))) {
352 		return 0;
353 	}
354 
355 	/*
356 	 * create the session key for encrypting the algorithm-specific
357 	 * fields
358 	 */
359 
360 	switch (key->s2k_specifier) {
361 	case OPS_S2KS_SIMPLE:
362 	case OPS_S2KS_SALTED:
363 		/* RFC4880: section 3.7.1.1 and 3.7.1.2 */
364 
365 		done = 0;
366 		for (i = 0; done < CAST_KEY_LENGTH; i++) {
367 			unsigned int    j = 0;
368 			unsigned char   zero = 0;
369 			int             needed;
370 			int             size;
371 
372 			needed = CAST_KEY_LENGTH - done;
373 			size = MIN(needed, OPS_SHA1_HASH_SIZE);
374 
375 			__ops_hash_any(&hash, key->hash_alg);
376 			hash.init(&hash);
377 
378 			/* preload if iterating  */
379 			for (j = 0; j < i; j++) {
380 				/*
381 				 * Coverity shows a DEADCODE error on this
382 				 * line. This is expected since the hardcoded
383 				 * use of SHA1 and CAST5 means that it will
384 				 * not used. This will change however when
385 				 * other algorithms are supported.
386 				 */
387 				hash.add(&hash, &zero, 1);
388 			}
389 
390 			if (key->s2k_specifier == OPS_S2KS_SALTED) {
391 				hash.add(&hash, key->salt, OPS_SALT_SIZE);
392 			}
393 			hash.add(&hash, passphrase, pplen);
394 			hash.finish(&hash, hashed);
395 
396 			/*
397 			 * if more in hash than is needed by session key, use
398 			 * the leftmost octets
399 			 */
400 			(void) memcpy(sesskey + (i * OPS_SHA1_HASH_SIZE),
401 					hashed, (unsigned)size);
402 			done += size;
403 			if (done > CAST_KEY_LENGTH) {
404 				(void) fprintf(stderr,
405 					"write_seckey_body: short add\n");
406 				return 0;
407 			}
408 		}
409 
410 		break;
411 
412 		/*
413 		 * \todo case OPS_S2KS_ITERATED_AND_SALTED: * 8-octet salt
414 		 * value * 1-octet count break;
415 		 */
416 
417 	default:
418 		(void) fprintf(stderr,
419 			"invalid/unsupported s2k specifier %d\n",
420 			key->s2k_specifier);
421 		return 0;
422 	}
423 
424 	/* use this session key to encrypt */
425 
426 	__ops_crypt_any(&crypted, key->alg);
427 	crypted.set_iv(&crypted, key->iv);
428 	crypted.set_key(&crypted, sesskey);
429 	__ops_encrypt_init(&crypted);
430 
431 	if (__ops_get_debug_level(__FILE__)) {
432 		unsigned int    i2 = 0;
433 
434 		(void) fprintf(stderr, "\nWRITING:\niv=");
435 		for (i2 = 0; i2 < __ops_block_size(key->alg); i2++) {
436 			(void) fprintf(stderr, "%02x ", key->iv[i2]);
437 		}
438 		(void) fprintf(stderr, "\n");
439 
440 		(void) fprintf(stderr, "key=");
441 		for (i2 = 0; i2 < CAST_KEY_LENGTH; i2++) {
442 			(void) fprintf(stderr, "%02x ", sesskey[i2]);
443 		}
444 		(void) fprintf(stderr, "\n");
445 
446 		(void) fprintf(stderr, "turning encryption on...\n");
447 	}
448 	__ops_push_enc_crypt(output, &crypted);
449 
450 	switch (key->pubkey.alg) {
451 		/* case OPS_PKA_DSA: */
452 		/* return __ops_write_mpi(output, key->key.dsa.x); */
453 
454 	case OPS_PKA_RSA:
455 	case OPS_PKA_RSA_ENCRYPT_ONLY:
456 	case OPS_PKA_RSA_SIGN_ONLY:
457 
458 		if (!__ops_write_mpi(output, key->key.rsa.d) ||
459 		    !__ops_write_mpi(output, key->key.rsa.p) ||
460 		    !__ops_write_mpi(output, key->key.rsa.q) ||
461 		    !__ops_write_mpi(output, key->key.rsa.u)) {
462 			if (__ops_get_debug_level(__FILE__)) {
463 				(void) fprintf(stderr,
464 					"4 x mpi not written - problem\n");
465 			}
466 			return 0;
467 		}
468 		break;
469 
470 		/* case OPS_PKA_ELGAMAL: */
471 		/* return __ops_write_mpi(output, key->key.elgamal.x); */
472 
473 	default:
474 		return 0;
475 	}
476 
477 	if (!__ops_write(output, key->checkhash, OPS_CHECKHASH_SIZE)) {
478 		return 0;
479 	}
480 
481 	__ops_writer_pop(output);
482 
483 	return 1;
484 }
485 
486 /**
487  * \ingroup Core_WritePackets
488  * \brief Writes a Public Key packet
489  * \param key
490  * \param output
491  * \return 1 if OK, otherwise 0
492  */
493 static unsigned
494 write_struct_pubkey(__ops_output_t *output, const __ops_pubkey_t *key)
495 {
496 	if (key->version != 4) {
497 		(void) fprintf(stderr,
498 			"write_struct_pubkey: wrong key version\n");
499 		return 0;
500 	}
501 	return __ops_write_ptag(output, OPS_PTAG_CT_PUBLIC_KEY) &&
502 		__ops_write_length(output, 1 + 4 + 1 + pubkey_length(key)) &&
503 		write_pubkey_body(key, output);
504 }
505 
506 
507 /**
508    \ingroup HighLevel_KeyWrite
509 
510    \brief Writes a transferable PGP public key to the given output stream.
511 
512    \param keydata Key to be written
513    \param armoured Flag is set for armoured output
514    \param output Output stream
515 
516 */
517 
518 unsigned
519 __ops_write_xfer_pubkey(__ops_output_t *output,
520 			const __ops_keydata_t *keydata,
521 			const unsigned armoured)
522 {
523 	unsigned int    i = 0, j = 0;
524 
525 	if (armoured) {
526 		__ops_writer_push_armoured(output, OPS_PGP_PUBLIC_KEY_BLOCK);
527 	}
528 	/* public key */
529 	if (!write_struct_pubkey(output, &keydata->key.seckey.pubkey)) {
530 		return 0;
531 	}
532 
533 	/* TODO: revocation signatures go here */
534 
535 	/* user ids and corresponding signatures */
536 	for (i = 0; i < keydata->nuids; i++) {
537 		__ops_userid_t  *uid = &keydata->uids[i];
538 
539 		if (!__ops_write_struct_userid(output, uid)) {
540 			return 0;
541 		}
542 
543 		/* find signature for this packet if it exists */
544 		for (j = 0; j < keydata->nsigs; j++) {
545 			sigpacket_t    *sig = &keydata->sigs[i];
546 
547 			if (strcmp((char *) sig->userid->userid,
548 					(char *) uid->userid) == 0) {
549 				if (!__ops_write(output, sig->packet->raw,
550 						sig->packet->length)) {
551 					return 0;
552 				}
553 			}
554 		}
555 	}
556 
557 	/* TODO: user attributes and corresponding signatures */
558 
559 	/*
560 	 * subkey packets and corresponding signatures and optional
561 	 * revocation
562 	 */
563 
564 	if (armoured) {
565 		writer_info_finalise(&output->errors, &output->writer);
566 		__ops_writer_pop(output);
567 	}
568 	return 1;
569 }
570 
571 /**
572    \ingroup HighLevel_KeyWrite
573 
574    \brief Writes a transferable PGP secret key to the given output stream.
575 
576    \param keydata Key to be written
577    \param passphrase
578    \param pplen
579    \param armoured Flag is set for armoured output
580    \param output Output stream
581 
582 */
583 
584 unsigned
585 __ops_write_xfer_seckey(__ops_output_t *output,
586 				const __ops_keydata_t *keydata,
587 				const unsigned char *passphrase,
588 				const size_t pplen,
589 				unsigned armoured)
590 {
591 	unsigned	i = 0, j = 0;
592 
593 	if (armoured) {
594 		__ops_writer_push_armoured(output, OPS_PGP_PRIVATE_KEY_BLOCK);
595 	}
596 	/* public key */
597 	if (!__ops_write_struct_seckey(&keydata->key.seckey, passphrase,
598 			pplen, output)) {
599 		return 0;
600 	}
601 
602 	/* TODO: revocation signatures go here */
603 
604 	/* user ids and corresponding signatures */
605 	for (i = 0; i < keydata->nuids; i++) {
606 		__ops_userid_t  *uid = &keydata->uids[i];
607 
608 		if (!__ops_write_struct_userid(output, uid)) {
609 			return 0;
610 		}
611 
612 		/* find signature for this packet if it exists */
613 		for (j = 0; j < keydata->nsigs; j++) {
614 			sigpacket_t    *sig = &keydata->sigs[i];
615 
616 			if (strcmp((char *) sig->userid->userid,
617 					(char *) uid->userid) == 0) {
618 				if (!__ops_write(output, sig->packet->raw,
619 						sig->packet->length)) {
620 					return 0;
621 				}
622 			}
623 		}
624 	}
625 
626 	/* TODO: user attributes and corresponding signatures */
627 
628 	/*
629 	 * subkey packets and corresponding signatures and optional
630 	 * revocation
631 	 */
632 
633 	if (armoured) {
634 		writer_info_finalise(&output->errors, &output->writer);
635 		__ops_writer_pop(output);
636 	}
637 	return 1;
638 }
639 
640 /**
641  * \ingroup Core_WritePackets
642  * \brief Writes one RSA public key packet.
643  * \param t Creation time
644  * \param n RSA public modulus
645  * \param e RSA public encryption exponent
646  * \param output Writer settings
647  *
648  * \return 1 if OK, otherwise 0
649  */
650 
651 unsigned
652 __ops_write_rsa_pubkey(time_t t, const BIGNUM *n,
653 			 const BIGNUM *e,
654 			 __ops_output_t *output)
655 {
656 	__ops_pubkey_t key;
657 
658 	__ops_fast_create_rsa_pubkey(&key, t, __UNCONST(n), __UNCONST(e));
659 	return write_struct_pubkey(output, &key);
660 }
661 
662 /**
663  * \ingroup Core_Create
664  * \param out
665  * \param key
666  * \param make_packet
667  */
668 
669 void
670 __ops_build_pubkey(__ops_memory_t *out, const __ops_pubkey_t *key,
671 		     unsigned make_packet)
672 {
673 	__ops_output_t *output;
674 
675 	output = __ops_output_new();
676 	__ops_memory_init(out, 128);
677 	__ops_writer_set_memory(output, out);
678 	write_pubkey_body(key, output);
679 	if (make_packet) {
680 		__ops_memory_make_packet(out, OPS_PTAG_CT_PUBLIC_KEY);
681 	}
682 	__ops_output_delete(output);
683 }
684 
685 /**
686  * \ingroup Core_Create
687  *
688  * Create an RSA secret key structure. If a parameter is marked as
689  * [OPTIONAL], then it can be omitted and will be calculated from
690  * other parameters - or, in the case of e, will default to 0x10001.
691  *
692  * Parameters are _not_ copied, so will be freed if the structure is
693  * freed.
694  *
695  * \param key The key structure to be initialised.
696  * \param t
697  * \param d The RSA parameter d (=e^-1 mod (p-1)(q-1)) [OPTIONAL]
698  * \param p The RSA parameter p
699  * \param q The RSA parameter q (q > p)
700  * \param u The RSA parameter u (=p^-1 mod q) [OPTIONAL]
701  * \param n The RSA public parameter n (=p*q) [OPTIONAL]
702  * \param e The RSA public parameter e */
703 
704 void
705 __ops_fast_create_rsa_seckey(__ops_seckey_t *key, time_t t,
706 			     BIGNUM *d, BIGNUM *p, BIGNUM *q, BIGNUM *u,
707 			       BIGNUM *n, BIGNUM *e)
708 {
709 	__ops_fast_create_rsa_pubkey(&key->pubkey, t, n, e);
710 
711 	/* XXX: calculate optionals */
712 	key->key.rsa.d = d;
713 	key->key.rsa.p = p;
714 	key->key.rsa.q = q;
715 	key->key.rsa.u = u;
716 
717 	key->s2k_usage = OPS_S2KU_NONE;
718 
719 	/* XXX: sanity check and add errors... */
720 }
721 
722 /**
723  * \ingroup Core_WritePackets
724  * \brief Writes a Secret Key packet.
725  * \param key The secret key
726  * \param passphrase The passphrase
727  * \param pplen Length of passphrase
728  * \param output
729  * \return 1 if OK; else 0
730  */
731 unsigned
732 __ops_write_struct_seckey(const __ops_seckey_t *key,
733 			    const unsigned char *passphrase,
734 			    const size_t pplen,
735 			    __ops_output_t *output)
736 {
737 	int             length = 0;
738 
739 	if (key->pubkey.version != 4) {
740 		(void) fprintf(stderr,
741 			"__ops_write_struct_seckey: public key version\n");
742 		return 0;
743 	}
744 
745 	/* Ref: RFC4880 Section 5.5.3 */
746 
747 	/* pubkey, excluding MPIs */
748 	length += 1 + 4 + 1 + 1;
749 
750 	/* s2k usage */
751 	length += 1;
752 
753 	switch (key->s2k_usage) {
754 	case OPS_S2KU_NONE:
755 		/* nothing to add */
756 		break;
757 
758 	case OPS_S2KU_ENCRYPTED_AND_HASHED:	/* 254 */
759 	case OPS_S2KU_ENCRYPTED:	/* 255 */
760 
761 		/* Ref: RFC4880 Section 3.7 */
762 		length += 1;	/* s2k_specifier */
763 
764 		switch (key->s2k_specifier) {
765 		case OPS_S2KS_SIMPLE:
766 			length += 1;	/* hash algorithm */
767 			break;
768 
769 		case OPS_S2KS_SALTED:
770 			length += 1 + 8;	/* hash algorithm + salt */
771 			break;
772 
773 		case OPS_S2KS_ITERATED_AND_SALTED:
774 			length += 1 + 8 + 1;	/* hash algorithm, salt +
775 						 * count */
776 			break;
777 
778 		default:
779 			(void) fprintf(stderr,
780 				"__ops_write_struct_seckey: s2k spec\n");
781 			return 0;
782 		}
783 		break;
784 
785 	default:
786 		(void) fprintf(stderr,
787 			"__ops_write_struct_seckey: s2k usage\n");
788 		return 0;
789 	}
790 
791 	/* IV */
792 	if (key->s2k_usage) {
793 		length += __ops_block_size(key->alg);
794 	}
795 	/* checksum or hash */
796 	switch (key->s2k_usage) {
797 	case 0:
798 	case 255:
799 		length += 2;
800 		break;
801 
802 	case 254:
803 		length += OPS_CHECKHASH_SIZE;
804 		break;
805 
806 	default:
807 		(void) fprintf(stderr,
808 			"__ops_write_struct_seckey: s2k cksum usage\n");
809 		return 0;
810 	}
811 
812 	/* secret key and public key MPIs */
813 	length += seckey_length(key);
814 
815 	return __ops_write_ptag(output, OPS_PTAG_CT_SECRET_KEY) &&
816 		/* __ops_write_length(output,1+4+1+1+seckey_length(key)+2) && */
817 		__ops_write_length(output, (unsigned)length) &&
818 		write_seckey_body(key, passphrase, pplen, output);
819 }
820 
821 /**
822  * \ingroup Core_Create
823  *
824  * \brief Create a new __ops_output_t structure.
825  *
826  * \return the new structure.
827  * \note It is the responsiblity of the caller to call __ops_output_delete().
828  * \sa __ops_output_delete()
829  */
830 __ops_output_t *
831 __ops_output_new(void)
832 {
833 	return calloc(1, sizeof(__ops_output_t));
834 }
835 
836 /**
837  * \ingroup Core_Create
838  * \brief Delete an __ops_output_t strucut and associated resources.
839  *
840  * Delete an __ops_output_t structure. If a writer is active, then
841  * that is also deleted.
842  *
843  * \param info the structure to be deleted.
844  */
845 void
846 __ops_output_delete(__ops_output_t *output)
847 {
848 	writer_info_delete(&output->writer);
849 	(void) free(output);
850 }
851 
852 /**
853  \ingroup Core_Create
854  \brief Calculate the checksum for a session key
855  \param sesskey Session Key to use
856  \param cs Checksum to be written
857  \return 1 if OK; else 0
858 */
859 unsigned
860 __ops_calc_sesskey_checksum(__ops_pk_sesskey_t *sesskey, unsigned char cs[2])
861 {
862 	unsigned int    i = 0;
863 	unsigned long   checksum = 0;
864 
865 	if (!__ops_is_sa_supported(sesskey->symm_alg)) {
866 		return 0;
867 	}
868 
869 	for (i = 0; i < __ops_key_size(sesskey->symm_alg); i++) {
870 		checksum += sesskey->key[i];
871 	}
872 	checksum = checksum % 65536;
873 
874 	cs[0] = (unsigned char)((checksum >> 8) & 0xff);
875 	cs[1] = (unsigned char)(checksum & 0xff);
876 
877 	if (__ops_get_debug_level(__FILE__)) {
878 		(void) fprintf(stderr,"\nm buf checksum: ");
879 		(void) fprintf(stderr," %2x",cs[0]);
880 		(void) fprintf(stderr," %2x\n",cs[1]);
881 	}
882 	return 1;
883 }
884 
885 static unsigned
886 create_unencoded_m_buf(__ops_pk_sesskey_t *sesskey, unsigned char *m_buf)
887 {
888 	int             i = 0;
889 
890 	/* m_buf is the buffer which will be encoded in PKCS#1 block */
891 	/* encoding to form the "m" value used in the  */
892 	/* Public Key Encrypted Session Key Packet */
893 	/*
894 	 * as defined in RFC Section 5.1 "Public-Key Encrypted Session Key
895 	 * Packet"
896 	 */
897 
898 	m_buf[0] = sesskey->symm_alg;
899 
900 	if (sesskey->symm_alg != OPS_SA_CAST5) {
901 		(void) fprintf(stderr, "create_unencoded_m_buf: symm alg\n");
902 		return 0;
903 	}
904 	for (i = 0; i < CAST_KEY_LENGTH; i++) {
905 		m_buf[1 + i] = sesskey->key[i];
906 	}
907 
908 	return (__ops_calc_sesskey_checksum(sesskey,
909 				m_buf + 1 + CAST_KEY_LENGTH));
910 }
911 
912 /**
913 \ingroup Core_Create
914 \brief implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC
915 \param M
916 \param mLen
917 \param pubkey
918 \param EM
919 \return 1 if OK; else 0
920 */
921 unsigned
922 encode_m_buf(const unsigned char *M, size_t mLen,
923 	     const __ops_pubkey_t * pubkey,
924 	     unsigned char *EM)
925 {
926 	unsigned int    k;
927 	unsigned        i;
928 
929 	/* implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC */
930 
931 	if (pubkey->alg != OPS_PKA_RSA) {
932 		(void) fprintf(stderr, "encode_m_buf: pubkey algorithm\n");
933 		return 0;
934 	}
935 
936 	k = BN_num_bytes(pubkey->key.rsa.n);
937 	if (mLen > k - 11) {
938 		(void) fprintf(stderr, "encode_m_buf: message too long\n");
939 		return 0;
940 	}
941 	/* these two bytes defined by RFC */
942 	EM[0] = 0x00;
943 	EM[1] = 0x02;
944 
945 	/* add non-zero random bytes of length k - mLen -3 */
946 	for (i = 2; i < k - mLen - 1; ++i) {
947 		do {
948 			__ops_random(EM + i, 1);
949 		} while (EM[i] == 0);
950 	}
951 
952 	if (i < 8 + 2) {
953 		(void) fprintf(stderr, "encode_m_buf: bad i len\n");
954 		return 0;
955 	}
956 
957 	EM[i++] = 0;
958 
959 	(void) memcpy(EM + i, M, mLen);
960 
961 	if (__ops_get_debug_level(__FILE__)) {
962 		unsigned int    i2 = 0;
963 
964 		(void) fprintf(stderr, "Encoded Message: \n");
965 		for (i2 = 0; i2 < mLen; i2++) {
966 			(void) fprintf(stderr, "%2x ", EM[i2]);
967 		}
968 		(void) fprintf(stderr, "\n");
969 	}
970 	return 1;
971 }
972 
973 /**
974  \ingroup Core_Create
975 \brief Creates an __ops_pk_sesskey_t struct from keydata
976 \param key Keydata to use
977 \return __ops_pk_sesskey_t struct
978 \note It is the caller's responsiblity to free the returned pointer
979 \note Currently hard-coded to use CAST5
980 \note Currently hard-coded to use RSA
981 */
982 __ops_pk_sesskey_t *
983 __ops_create_pk_sesskey(const __ops_keydata_t *key)
984 {
985 	/*
986          * Creates a random session key and encrypts it for the given key
987          *
988          * Session Key is for use with a SK algo,
989          * can be any, we're hardcoding CAST5 for now
990          *
991          * Encryption used is PK,
992          * can be any, we're hardcoding RSA for now
993          */
994 
995 	const __ops_pubkey_t *pubkey = __ops_get_pubkey(key);
996 #define SZ_UNENCODED_M_BUF CAST_KEY_LENGTH+1+2
997 	unsigned char   unencoded_m_buf[SZ_UNENCODED_M_BUF];
998 	const size_t    sz_encoded_m_buf = BN_num_bytes(pubkey->key.rsa.n);
999 	unsigned char  *encoded_m_buf = calloc(1, sz_encoded_m_buf);
1000 
1001 	__ops_pk_sesskey_t *sesskey = calloc(1, sizeof(*sesskey));
1002 	if (key->type != OPS_PTAG_CT_PUBLIC_KEY) {
1003 		(void) fprintf(stderr,
1004 			"__ops_create_pk_sesskey: bad type\n");
1005 		return NULL;
1006 	}
1007 	sesskey->version = OPS_PKSK_V3;
1008 	(void) memcpy(sesskey->key_id, key->key_id,
1009 			sizeof(sesskey->key_id));
1010 
1011 	if (__ops_get_debug_level(__FILE__)) {
1012 		unsigned int    i = 0;
1013 
1014 		(void) fprintf(stderr, "Encrypting for RSA key id : ");
1015 		for (i = 0; i < sizeof(sesskey->key_id); i++) {
1016 			(void) fprintf(stderr, "%2x ", key->key_id[i]);
1017 		}
1018 		(void) fprintf(stderr, "\n");
1019 	}
1020 	if (key->key.pubkey.alg != OPS_PKA_RSA) {
1021 		(void) fprintf(stderr,
1022 			"__ops_create_pk_sesskey: bad pubkey algorithm\n");
1023 		return NULL;
1024 	}
1025 	sesskey->alg = key->key.pubkey.alg;
1026 
1027 	/* \todo allow user to specify other algorithm */
1028 	sesskey->symm_alg = OPS_SA_CAST5;
1029 	__ops_random(sesskey->key, CAST_KEY_LENGTH);
1030 
1031 	if (__ops_get_debug_level(__FILE__)) {
1032 		unsigned int    i = 0;
1033 
1034 		(void) fprintf(stderr,
1035 			"CAST5 session key created (len=%d):\n ",
1036 			CAST_KEY_LENGTH);
1037 		for (i = 0; i < CAST_KEY_LENGTH; i++) {
1038 			(void) fprintf(stderr, "%2x ", sesskey->key[i]);
1039 		}
1040 		(void) fprintf(stderr, "\n");
1041 	}
1042 	if (create_unencoded_m_buf(sesskey, &unencoded_m_buf[0]) == 0) {
1043 		(void) free(encoded_m_buf);
1044 		return NULL;
1045 	}
1046 	if (__ops_get_debug_level(__FILE__)) {
1047 		unsigned int    i = 0;
1048 
1049 		printf("unencoded m buf:\n");
1050 		for (i = 0; i < SZ_UNENCODED_M_BUF; i++) {
1051 			printf("%2x ", unencoded_m_buf[i]);
1052 		}
1053 		printf("\n");
1054 	}
1055 	encode_m_buf(&unencoded_m_buf[0], SZ_UNENCODED_M_BUF, pubkey,
1056 			&encoded_m_buf[0]);
1057 
1058 	/* and encrypt it */
1059 	if (!__ops_rsa_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey,
1060 			&sesskey->parameters)) {
1061 		(void) free(encoded_m_buf);
1062 		return NULL;
1063 	}
1064 	(void) free(encoded_m_buf);
1065 	return sesskey;
1066 }
1067 
1068 /**
1069 \ingroup Core_WritePackets
1070 \brief Writes Public Key Session Key packet
1071 \param info Write settings
1072 \param pksk Public Key Session Key to write out
1073 \return 1 if OK; else 0
1074 */
1075 unsigned
1076 __ops_write_pk_sesskey(__ops_output_t *output, __ops_pk_sesskey_t *pksk)
1077 {
1078 	if (pksk == NULL) {
1079 		(void) fprintf(stderr,
1080 			"__ops_write_pk_sesskey: NULL pksk\n");
1081 		return 0;
1082 	}
1083 	if (pksk->alg != OPS_PKA_RSA) {
1084 		(void) fprintf(stderr,
1085 			"__ops_write_pk_sesskey: bad algorithm\n");
1086 		return 0;
1087 	}
1088 
1089 	return __ops_write_ptag(output, OPS_PTAG_CT_PK_SESSION_KEY) &&
1090 		__ops_write_length(output, (unsigned)(1 + 8 + 1 +
1091 			BN_num_bytes(pksk->parameters.rsa.encrypted_m) + 2)) &&
1092 		__ops_write_scalar(output, (unsigned)pksk->version, 1) &&
1093 		__ops_write(output, pksk->key_id, 8) &&
1094 		__ops_write_scalar(output, (unsigned)pksk->alg, 1) &&
1095 		__ops_write_mpi(output, pksk->parameters.rsa.encrypted_m)
1096 	/* ??	&& __ops_write_scalar(output, 0, 2); */
1097 		;
1098 }
1099 
1100 /**
1101 \ingroup Core_WritePackets
1102 \brief Writes MDC packet
1103 \param hashed Hash for MDC
1104 \param output Write settings
1105 \return 1 if OK; else 0
1106 */
1107 
1108 unsigned
1109 __ops_write_mdc(const unsigned char *hashed, __ops_output_t *output)
1110 {
1111 	/* write it out */
1112 	return __ops_write_ptag(output, OPS_PTAG_CT_MDC) &&
1113 		__ops_write_length(output, OPS_SHA1_HASH_SIZE) &&
1114 		__ops_write(output, hashed, OPS_SHA1_HASH_SIZE);
1115 }
1116 
1117 /**
1118 \ingroup Core_WritePackets
1119 \brief Writes Literal Data packet from buffer
1120 \param data Buffer to write out
1121 \param maxlen Max length of buffer
1122 \param type Literal Data Type
1123 \param output Write settings
1124 \return 1 if OK; else 0
1125 */
1126 unsigned
1127 __ops_write_litdata(__ops_output_t *output,
1128 			const unsigned char *data,
1129 			const int maxlen,
1130 			const __ops_litdata_type_t type)
1131 {
1132 	/*
1133          * RFC4880 does not specify a meaning for filename or date.
1134          * It is implementation-dependent.
1135          * We will not implement them.
1136          */
1137 	/* \todo do we need to check text data for <cr><lf> line endings ? */
1138 	return __ops_write_ptag(output, OPS_PTAG_CT_LITERAL_DATA) &&
1139 		__ops_write_length(output, (unsigned)(1 + 1 + 4 + maxlen)) &&
1140 		__ops_write_scalar(output, (unsigned)type, 1) &&
1141 		__ops_write_scalar(output, 0, 1) &&
1142 		__ops_write_scalar(output, 0, 4) &&
1143 		__ops_write(output, data, (unsigned)maxlen);
1144 }
1145 
1146 /**
1147 \ingroup Core_WritePackets
1148 \brief Writes Literal Data packet from contents of file
1149 \param filename Name of file to read from
1150 \param type Literal Data Type
1151 \param output Write settings
1152 \return 1 if OK; else 0
1153 */
1154 
1155 unsigned
1156 __ops_fileread_litdata(const char *filename,
1157 				 const __ops_litdata_type_t type,
1158 				 __ops_output_t *output)
1159 {
1160 	__ops_memory_t	*mem = NULL;
1161 	unsigned   	 ret;
1162 	size_t		 len;
1163 
1164 	mem = __ops_memory_new();
1165 	if (!__ops_mem_readfile(mem, filename)) {
1166 		return 0;
1167 	}
1168 	len = __ops_mem_len(mem);
1169 	ret = __ops_write_ptag(output, OPS_PTAG_CT_LITERAL_DATA) &&
1170 		__ops_write_length(output, 1 + 1 + 4 + len) &&
1171 		__ops_write_scalar(output, (unsigned)type, 1) &&
1172 		__ops_write_scalar(output, 0, 1) /* filename */ &&
1173 		__ops_write_scalar(output, 0, 4) /* date */ &&
1174 		__ops_write(output, __ops_mem_data(mem), len);
1175 	__ops_memory_free(mem);
1176 	return ret;
1177 }
1178 
1179 /**
1180    \ingroup HighLevel_General
1181 
1182    \brief Writes contents of buffer into file
1183 
1184    \param filename Filename to write to
1185    \param buf Buffer to write to file
1186    \param len Size of buffer
1187    \param overwrite Flag to set whether to overwrite an existing file
1188    \return 1 if OK; 0 if error
1189 */
1190 
1191 int
1192 __ops_filewrite(const char *filename, const char *buf,
1193 			const size_t len, const unsigned overwrite)
1194 {
1195 	int		flags = 0;
1196 	int		fd = 0;
1197 
1198 	flags = O_WRONLY | O_CREAT;
1199 	if (overwrite) {
1200 		flags |= O_TRUNC;
1201 	} else {
1202 		flags |= O_EXCL;
1203 	}
1204 #ifdef O_BINARY
1205 	flags |= O_BINARY;
1206 #endif
1207 	fd = open(filename, flags, 0600);
1208 	if (fd < 0) {
1209 		perror(NULL);
1210 		return 0;
1211 	}
1212 	if (write(fd, buf, len) != (int)len) {
1213 		return 0;
1214 	}
1215 
1216 	return (close(fd) == 0);
1217 }
1218 
1219 /**
1220 \ingroup Core_WritePackets
1221 \brief Write Symmetrically Encrypted packet
1222 \param data Data to encrypt
1223 \param len Length of data
1224 \param output Write settings
1225 \return 1 if OK; else 0
1226 \note Hard-coded to use AES256
1227 */
1228 unsigned
1229 __ops_write_symm_enc_data(const unsigned char *data,
1230 				       const int len,
1231 				       __ops_output_t * output)
1232 {
1233 			/* buffer to write encrypted data to */
1234 	unsigned char  *encrypted = (unsigned char *) NULL;
1235 	__ops_crypt_t	crypt_info;
1236 	size_t		encrypted_sz = 0;	/* size of encrypted data */
1237 	int             done = 0;
1238 
1239 	/* \todo assume AES256 for now */
1240 	__ops_crypt_any(&crypt_info, OPS_SA_AES_256);
1241 	__ops_encrypt_init(&crypt_info);
1242 
1243 	encrypted_sz = len + crypt_info.blocksize + 2;
1244 	encrypted = calloc(1, encrypted_sz);
1245 
1246 	done = __ops_encrypt_se(&crypt_info, encrypted, data, (unsigned)len);
1247 	if (done != len) {
1248 		(void) fprintf(stderr,
1249 			"__ops_write_symm_enc_data: done != len\n");
1250 		return 0;
1251 	}
1252 
1253 	return __ops_write_ptag(output, OPS_PTAG_CT_SE_DATA) &&
1254 		__ops_write_length(output, 1 + encrypted_sz) &&
1255 		__ops_write(output, data, (unsigned)len);
1256 }
1257 
1258 /**
1259 \ingroup Core_WritePackets
1260 \brief Write a One Pass Signature packet
1261 \param seckey Secret Key to use
1262 \param hash_alg Hash Algorithm to use
1263 \param sig_type Signature type
1264 \param output Write settings
1265 \return 1 if OK; else 0
1266 */
1267 unsigned
1268 __ops_write_one_pass_sig(__ops_output_t *output,
1269 			const __ops_seckey_t *seckey,
1270 			const __ops_hash_alg_t hash_alg,
1271 			const __ops_sig_type_t sig_type)
1272 {
1273 	unsigned char   keyid[OPS_KEY_ID_SIZE];
1274 
1275 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, OPS_KEY_ID_SIZE, &seckey->pubkey);
1276 	return __ops_write_ptag(output, OPS_PTAG_CT_1_PASS_SIG) &&
1277 		__ops_write_length(output, 1 + 1 + 1 + 1 + 8 + 1) &&
1278 		__ops_write_scalar(output, 3, 1)	/* version */ &&
1279 		__ops_write_scalar(output, (unsigned)sig_type, 1) &&
1280 		__ops_write_scalar(output, (unsigned)hash_alg, 1) &&
1281 		__ops_write_scalar(output, (unsigned)seckey->pubkey.alg, 1) &&
1282 		__ops_write(output, keyid, 8) &&
1283 		__ops_write_scalar(output, 1, 1);
1284 }
1285