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