xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/create.c (revision 5aae2c74b0a496add3697f16c824210c042d9148)
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.24 2010/03/13 23:30:41 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, uint8_t *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 uint8_t *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 uint8_t *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	done = 0;
284 	unsigned	i = 0;
285 	uint8_t		hashed[OPS_SHA1_HASH_SIZE];
286 	uint8_t		sesskey[CAST_KEY_LENGTH];
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 	j;
366 			uint8_t		zero = 0;
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 *key,
522 			const unsigned armoured)
523 {
524 	unsigned    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, &key->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 < key->uidc; i++) {
538 		if (!__ops_write_struct_userid(output, &key->uids[i])) {
539 			return 0;
540 		}
541 		for (j = 0; j < key->packetc; j++) {
542 			if (!__ops_write(output, key->packets[j].raw, key->packets[j].length)) {
543 				return 0;
544 			}
545 		}
546 	}
547 
548 	/* TODO: user attributes and corresponding signatures */
549 
550 	/*
551 	 * subkey packets and corresponding signatures and optional
552 	 * revocation
553 	 */
554 
555 	if (armoured) {
556 		__ops_writer_info_finalise(&output->errors, &output->writer);
557 		__ops_writer_pop(output);
558 	}
559 	return 1;
560 }
561 
562 /**
563    \ingroup HighLevel_KeyWrite
564 
565    \brief Writes a transferable PGP secret key to the given output stream.
566 
567    \param keydata Key to be written
568    \param passphrase
569    \param pplen
570    \param armoured Flag is set for armoured output
571    \param output Output stream
572 
573 */
574 
575 unsigned
576 __ops_write_xfer_seckey(__ops_output_t *output,
577 				const __ops_key_t *key,
578 				const uint8_t *passphrase,
579 				const size_t pplen,
580 				unsigned armoured)
581 {
582 	unsigned	i, j;
583 
584 	if (armoured) {
585 		__ops_writer_push_armoured(output, OPS_PGP_PRIVATE_KEY_BLOCK);
586 	}
587 	/* public key */
588 	if (!__ops_write_struct_seckey(&key->key.seckey, passphrase,
589 			pplen, output)) {
590 		return 0;
591 	}
592 
593 	/* TODO: revocation signatures go here */
594 
595 	/* user ids and corresponding signatures */
596 	for (i = 0; i < key->uidc; i++) {
597 		if (!__ops_write_struct_userid(output, &key->uids[i])) {
598 			return 0;
599 		}
600 		for (j = 0; j < key->packetc; j++) {
601 			if (!__ops_write(output, key->packets[j].raw, key->packets[j].length)) {
602 				return 0;
603 			}
604 		}
605 	}
606 
607 	/* TODO: user attributes and corresponding signatures */
608 
609 	/*
610 	 * subkey packets and corresponding signatures and optional
611 	 * revocation
612 	 */
613 
614 	if (armoured) {
615 		__ops_writer_info_finalise(&output->errors, &output->writer);
616 		__ops_writer_pop(output);
617 	}
618 	return 1;
619 }
620 
621 /**
622  * \ingroup Core_WritePackets
623  * \brief Writes one RSA public key packet.
624  * \param t Creation time
625  * \param n RSA public modulus
626  * \param e RSA public encryption exponent
627  * \param output Writer settings
628  *
629  * \return 1 if OK, otherwise 0
630  */
631 
632 unsigned
633 __ops_write_rsa_pubkey(time_t t, const BIGNUM *n,
634 			 const BIGNUM *e,
635 			 __ops_output_t *output)
636 {
637 	__ops_pubkey_t key;
638 
639 	__ops_fast_create_rsa_pubkey(&key, t, __UNCONST(n), __UNCONST(e));
640 	return write_struct_pubkey(output, &key);
641 }
642 
643 /**
644  * \ingroup Core_Create
645  * \param out
646  * \param key
647  * \param make_packet
648  */
649 
650 void
651 __ops_build_pubkey(__ops_memory_t *out, const __ops_pubkey_t *key,
652 		     unsigned make_packet)
653 {
654 	__ops_output_t *output;
655 
656 	output = __ops_output_new();
657 	__ops_memory_init(out, 128);
658 	__ops_writer_set_memory(output, out);
659 	write_pubkey_body(key, output);
660 	if (make_packet) {
661 		__ops_memory_make_packet(out, OPS_PTAG_CT_PUBLIC_KEY);
662 	}
663 	__ops_output_delete(output);
664 }
665 
666 /**
667  * \ingroup Core_Create
668  *
669  * Create an RSA secret key structure. If a parameter is marked as
670  * [OPTIONAL], then it can be omitted and will be calculated from
671  * other params - or, in the case of e, will default to 0x10001.
672  *
673  * Parameters are _not_ copied, so will be freed if the structure is
674  * freed.
675  *
676  * \param key The key structure to be initialised.
677  * \param t
678  * \param d The RSA parameter d (=e^-1 mod (p-1)(q-1)) [OPTIONAL]
679  * \param p The RSA parameter p
680  * \param q The RSA parameter q (q > p)
681  * \param u The RSA parameter u (=p^-1 mod q) [OPTIONAL]
682  * \param n The RSA public parameter n (=p*q) [OPTIONAL]
683  * \param e The RSA public parameter e */
684 
685 void
686 __ops_fast_create_rsa_seckey(__ops_seckey_t *key, time_t t,
687 			     BIGNUM *d, BIGNUM *p, BIGNUM *q, BIGNUM *u,
688 			       BIGNUM *n, BIGNUM *e)
689 {
690 	__ops_fast_create_rsa_pubkey(&key->pubkey, t, n, e);
691 
692 	/* XXX: calculate optionals */
693 	key->key.rsa.d = d;
694 	key->key.rsa.p = p;
695 	key->key.rsa.q = q;
696 	key->key.rsa.u = u;
697 
698 	key->s2k_usage = OPS_S2KU_NONE;
699 
700 	/* XXX: sanity check and add errors... */
701 }
702 
703 /**
704  * \ingroup Core_WritePackets
705  * \brief Writes a Secret Key packet.
706  * \param key The secret key
707  * \param passphrase The passphrase
708  * \param pplen Length of passphrase
709  * \param output
710  * \return 1 if OK; else 0
711  */
712 unsigned
713 __ops_write_struct_seckey(const __ops_seckey_t *key,
714 			    const uint8_t *passphrase,
715 			    const size_t pplen,
716 			    __ops_output_t *output)
717 {
718 	int             length = 0;
719 
720 	if (key->pubkey.version != 4) {
721 		(void) fprintf(stderr,
722 			"__ops_write_struct_seckey: public key version\n");
723 		return 0;
724 	}
725 
726 	/* Ref: RFC4880 Section 5.5.3 */
727 
728 	/* pubkey, excluding MPIs */
729 	length += 1 + 4 + 1 + 1;
730 
731 	/* s2k usage */
732 	length += 1;
733 
734 	switch (key->s2k_usage) {
735 	case OPS_S2KU_NONE:
736 		/* nothing to add */
737 		break;
738 
739 	case OPS_S2KU_ENCRYPTED_AND_HASHED:	/* 254 */
740 	case OPS_S2KU_ENCRYPTED:	/* 255 */
741 
742 		/* Ref: RFC4880 Section 3.7 */
743 		length += 1;	/* s2k_specifier */
744 
745 		switch (key->s2k_specifier) {
746 		case OPS_S2KS_SIMPLE:
747 			length += 1;	/* hash algorithm */
748 			break;
749 
750 		case OPS_S2KS_SALTED:
751 			length += 1 + 8;	/* hash algorithm + salt */
752 			break;
753 
754 		case OPS_S2KS_ITERATED_AND_SALTED:
755 			length += 1 + 8 + 1;	/* hash algorithm, salt +
756 						 * count */
757 			break;
758 
759 		default:
760 			(void) fprintf(stderr,
761 				"__ops_write_struct_seckey: s2k spec\n");
762 			return 0;
763 		}
764 		break;
765 
766 	default:
767 		(void) fprintf(stderr,
768 			"__ops_write_struct_seckey: s2k usage\n");
769 		return 0;
770 	}
771 
772 	/* IV */
773 	if (key->s2k_usage) {
774 		length += __ops_block_size(key->alg);
775 	}
776 	/* checksum or hash */
777 	switch (key->s2k_usage) {
778 	case OPS_S2KU_NONE:
779 	case OPS_S2KU_ENCRYPTED:
780 		length += 2;
781 		break;
782 
783 	case OPS_S2KU_ENCRYPTED_AND_HASHED:
784 		length += OPS_CHECKHASH_SIZE;
785 		break;
786 
787 	default:
788 		(void) fprintf(stderr,
789 			"__ops_write_struct_seckey: s2k cksum usage\n");
790 		return 0;
791 	}
792 
793 	/* secret key and public key MPIs */
794 	length += (unsigned)seckey_length(key);
795 
796 	return __ops_write_ptag(output, OPS_PTAG_CT_SECRET_KEY) &&
797 		/* __ops_write_length(output,1+4+1+1+seckey_length(key)+2) && */
798 		__ops_write_length(output, (unsigned)length) &&
799 		write_seckey_body(key, passphrase, pplen, output);
800 }
801 
802 /**
803  * \ingroup Core_Create
804  *
805  * \brief Create a new __ops_output_t structure.
806  *
807  * \return the new structure.
808  * \note It is the responsiblity of the caller to call __ops_output_delete().
809  * \sa __ops_output_delete()
810  */
811 __ops_output_t *
812 __ops_output_new(void)
813 {
814 	return calloc(1, sizeof(__ops_output_t));
815 }
816 
817 /**
818  * \ingroup Core_Create
819  * \brief Delete an __ops_output_t strucut and associated resources.
820  *
821  * Delete an __ops_output_t structure. If a writer is active, then
822  * that is also deleted.
823  *
824  * \param info the structure to be deleted.
825  */
826 void
827 __ops_output_delete(__ops_output_t *output)
828 {
829 	__ops_writer_info_delete(&output->writer);
830 	free(output);
831 }
832 
833 /**
834  \ingroup Core_Create
835  \brief Calculate the checksum for a session key
836  \param sesskey Session Key to use
837  \param cs Checksum to be written
838  \return 1 if OK; else 0
839 */
840 unsigned
841 __ops_calc_sesskey_checksum(__ops_pk_sesskey_t *sesskey, uint8_t cs[2])
842 {
843 	uint32_t   checksum = 0;
844 	unsigned    i;
845 
846 	if (!__ops_is_sa_supported(sesskey->symm_alg)) {
847 		return 0;
848 	}
849 
850 	for (i = 0; i < __ops_key_size(sesskey->symm_alg); i++) {
851 		checksum += sesskey->key[i];
852 	}
853 	checksum = checksum % 65536;
854 
855 	cs[0] = (uint8_t)((checksum >> 8) & 0xff);
856 	cs[1] = (uint8_t)(checksum & 0xff);
857 
858 	if (__ops_get_debug_level(__FILE__)) {
859 		(void) fprintf(stderr,"\nm buf checksum: ");
860 		(void) fprintf(stderr," %2x",cs[0]);
861 		(void) fprintf(stderr," %2x\n",cs[1]);
862 	}
863 	return 1;
864 }
865 
866 static unsigned
867 create_unencoded_m_buf(__ops_pk_sesskey_t *sesskey, uint8_t *m_buf)
868 {
869 	int             i;
870 
871 	/* m_buf is the buffer which will be encoded in PKCS#1 block */
872 	/* encoding to form the "m" value used in the  */
873 	/* Public Key Encrypted Session Key Packet */
874 	/*
875 	 * as defined in RFC Section 5.1 "Public-Key Encrypted Session Key
876 	 * Packet"
877 	 */
878 
879 	m_buf[0] = sesskey->symm_alg;
880 
881 	if (sesskey->symm_alg != OPS_SA_CAST5) {
882 		(void) fprintf(stderr, "create_unencoded_m_buf: symm alg\n");
883 		return 0;
884 	}
885 	for (i = 0; i < CAST_KEY_LENGTH; i++) {
886 		/* XXX - Flexelint - Warning 679: Suspicious Truncation in arithmetic expression combining with pointer */
887 		m_buf[1 + i] = sesskey->key[i];
888 	}
889 
890 	return (__ops_calc_sesskey_checksum(sesskey,
891 				m_buf + 1 + CAST_KEY_LENGTH));
892 }
893 
894 /**
895 \ingroup Core_Create
896 \brief implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC
897 \param M
898 \param mLen
899 \param pubkey
900 \param EM
901 \return 1 if OK; else 0
902 */
903 unsigned
904 encode_m_buf(const uint8_t *M, size_t mLen, const __ops_pubkey_t * pubkey,
905 	     uint8_t *EM)
906 {
907 	unsigned    k;
908 	unsigned        i;
909 
910 	/* implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC */
911 
912 	if (pubkey->alg != OPS_PKA_RSA) {
913 		(void) fprintf(stderr, "encode_m_buf: pubkey algorithm\n");
914 		return 0;
915 	}
916 
917 	k = (unsigned)BN_num_bytes(pubkey->key.rsa.n);
918 	if (mLen > k - 11) {
919 		(void) fprintf(stderr, "encode_m_buf: message too long\n");
920 		return 0;
921 	}
922 	/* these two bytes defined by RFC */
923 	EM[0] = 0x00;
924 	EM[1] = 0x02;
925 
926 	/* add non-zero random bytes of length k - mLen -3 */
927 	for (i = 2; i < (k - mLen) - 1; ++i) {
928 		do {
929 			__ops_random(EM + i, 1);
930 		} while (EM[i] == 0);
931 	}
932 
933 	if (i < 8 + 2) {
934 		(void) fprintf(stderr, "encode_m_buf: bad i len\n");
935 		return 0;
936 	}
937 
938 	EM[i++] = 0;
939 
940 	(void) memcpy(EM + i, M, mLen);
941 
942 	if (__ops_get_debug_level(__FILE__)) {
943 		unsigned    i2;
944 
945 		(void) fprintf(stderr, "Encoded Message: \n");
946 		for (i2 = 0; i2 < mLen; i2++) {
947 			(void) fprintf(stderr, "%2x ", EM[i2]);
948 		}
949 		(void) fprintf(stderr, "\n");
950 	}
951 	return 1;
952 }
953 
954 /**
955  \ingroup Core_Create
956 \brief Creates an __ops_pk_sesskey_t struct from keydata
957 \param key Keydata to use
958 \return __ops_pk_sesskey_t struct
959 \note It is the caller's responsiblity to free the returned pointer
960 \note Currently hard-coded to use CAST5
961 \note Currently hard-coded to use RSA
962 */
963 __ops_pk_sesskey_t *
964 __ops_create_pk_sesskey(const __ops_key_t *key)
965 {
966 	/*
967          * Creates a random session key and encrypts it for the given key
968          *
969          * Session Key is for use with a SK algo,
970          * can be any, we're hardcoding CAST5 for now
971          *
972          * Encryption used is PK,
973          * can be any, we're hardcoding RSA for now
974          */
975 
976 #define SZ_UNENCODED_M_BUF (CAST_KEY_LENGTH + 1 + 2)
977 
978 	const __ops_pubkey_t	*pubkey;
979 	__ops_pk_sesskey_t	*sesskey;
980 	uint8_t			 unencoded_m_buf[SZ_UNENCODED_M_BUF];
981 	uint8_t			*encoded_m_buf;
982 	size_t			 sz_encoded_m_buf;
983 
984 	pubkey = __ops_get_pubkey(key);
985 	sz_encoded_m_buf = BN_num_bytes(pubkey->key.rsa.n);
986 	if ((encoded_m_buf = calloc(1, sz_encoded_m_buf)) == NULL) {
987 		(void) fprintf(stderr,
988 			"__ops_create_pk_sesskey: can't allocate\n");
989 		return NULL;
990 	}
991 	if ((sesskey = calloc(1, sizeof(*sesskey))) == NULL) {
992 		(void) fprintf(stderr,
993 			"__ops_create_pk_sesskey: can't allocate\n");
994 		free(encoded_m_buf);
995 		return NULL;
996 	}
997 	if (key->type != OPS_PTAG_CT_PUBLIC_KEY) {
998 		(void) fprintf(stderr,
999 			"__ops_create_pk_sesskey: bad type\n");
1000 		free(encoded_m_buf);
1001 		free(sesskey);
1002 		return NULL;
1003 	}
1004 	sesskey->version = OPS_PKSK_V3;
1005 	(void) memcpy(sesskey->key_id, key->key_id,
1006 			sizeof(sesskey->key_id));
1007 
1008 	if (__ops_get_debug_level(__FILE__)) {
1009 		unsigned    i;
1010 
1011 		(void) fprintf(stderr, "Encrypting for RSA key id : ");
1012 		for (i = 0; i < sizeof(sesskey->key_id); i++) {
1013 			(void) fprintf(stderr, "%2x ", key->key_id[i]);
1014 		}
1015 		(void) fprintf(stderr, "\n");
1016 	}
1017 	if (key->key.pubkey.alg != OPS_PKA_RSA) {
1018 		(void) fprintf(stderr,
1019 			"__ops_create_pk_sesskey: bad pubkey algorithm\n");
1020 		free(encoded_m_buf);
1021 		free(sesskey);
1022 		return NULL;
1023 	}
1024 	sesskey->alg = key->key.pubkey.alg;
1025 
1026 	/* \todo allow user to specify other algorithm */
1027 	sesskey->symm_alg = OPS_SA_CAST5;
1028 	__ops_random(sesskey->key, CAST_KEY_LENGTH);
1029 
1030 	if (__ops_get_debug_level(__FILE__)) {
1031 		unsigned    i;
1032 
1033 		(void) fprintf(stderr,
1034 			"CAST5 session key created (len=%d):\n ",
1035 			CAST_KEY_LENGTH);
1036 		for (i = 0; i < CAST_KEY_LENGTH; i++) {
1037 			(void) fprintf(stderr, "%2x ", sesskey->key[i]);
1038 		}
1039 		(void) fprintf(stderr, "\n");
1040 	}
1041 	if (create_unencoded_m_buf(sesskey, &unencoded_m_buf[0]) == 0) {
1042 		free(encoded_m_buf);
1043 		free(sesskey);
1044 		return NULL;
1045 	}
1046 	if (__ops_get_debug_level(__FILE__)) {
1047 		unsigned    i;
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->params)) {
1061 		free(encoded_m_buf);
1062 		free(sesskey);
1063 		return NULL;
1064 	}
1065 	free(encoded_m_buf);
1066 	return sesskey;
1067 }
1068 
1069 /**
1070 \ingroup Core_WritePackets
1071 \brief Writes Public Key Session Key packet
1072 \param info Write settings
1073 \param pksk Public Key Session Key to write out
1074 \return 1 if OK; else 0
1075 */
1076 unsigned
1077 __ops_write_pk_sesskey(__ops_output_t *output, __ops_pk_sesskey_t *pksk)
1078 {
1079 	/* XXX - Flexelint - Pointer parameter 'pksk' (line 1076) could be declared as pointing to const */
1080 	if (pksk == NULL) {
1081 		(void) fprintf(stderr,
1082 			"__ops_write_pk_sesskey: NULL pksk\n");
1083 		return 0;
1084 	}
1085 	if (pksk->alg != OPS_PKA_RSA) {
1086 		(void) fprintf(stderr,
1087 			"__ops_write_pk_sesskey: bad algorithm\n");
1088 		return 0;
1089 	}
1090 
1091 	return __ops_write_ptag(output, OPS_PTAG_CT_PK_SESSION_KEY) &&
1092 		__ops_write_length(output, (unsigned)(1 + 8 + 1 +
1093 			BN_num_bytes(pksk->params.rsa.encrypted_m) + 2)) &&
1094 		__ops_write_scalar(output, (unsigned)pksk->version, 1) &&
1095 		__ops_write(output, pksk->key_id, 8) &&
1096 		__ops_write_scalar(output, (unsigned)pksk->alg, 1) &&
1097 		__ops_write_mpi(output, pksk->params.rsa.encrypted_m)
1098 	/* ??	&& __ops_write_scalar(output, 0, 2); */
1099 		;
1100 }
1101 
1102 /**
1103 \ingroup Core_WritePackets
1104 \brief Writes MDC packet
1105 \param hashed Hash for MDC
1106 \param output Write settings
1107 \return 1 if OK; else 0
1108 */
1109 
1110 unsigned
1111 __ops_write_mdc(__ops_output_t *output, const uint8_t *hashed)
1112 {
1113 	/* write it out */
1114 	return __ops_write_ptag(output, OPS_PTAG_CT_MDC) &&
1115 		__ops_write_length(output, OPS_SHA1_HASH_SIZE) &&
1116 		__ops_write(output, hashed, OPS_SHA1_HASH_SIZE);
1117 }
1118 
1119 /**
1120 \ingroup Core_WritePackets
1121 \brief Writes Literal Data packet from buffer
1122 \param data Buffer to write out
1123 \param maxlen Max length of buffer
1124 \param type Literal Data Type
1125 \param output Write settings
1126 \return 1 if OK; else 0
1127 */
1128 unsigned
1129 __ops_write_litdata(__ops_output_t *output,
1130 			const uint8_t *data,
1131 			const int maxlen,
1132 			const __ops_litdata_type_t type)
1133 {
1134 	/*
1135          * RFC4880 does not specify a meaning for filename or date.
1136          * It is implementation-dependent.
1137          * We will not implement them.
1138          */
1139 	/* \todo do we need to check text data for <cr><lf> line endings ? */
1140 	return __ops_write_ptag(output, OPS_PTAG_CT_LITDATA) &&
1141 		__ops_write_length(output, (unsigned)(1 + 1 + 4 + maxlen)) &&
1142 		__ops_write_scalar(output, (unsigned)type, 1) &&
1143 		__ops_write_scalar(output, 0, 1) &&
1144 		__ops_write_scalar(output, 0, 4) &&
1145 		__ops_write(output, data, (unsigned)maxlen);
1146 }
1147 
1148 /**
1149 \ingroup Core_WritePackets
1150 \brief Writes Literal Data packet from contents of file
1151 \param filename Name of file to read from
1152 \param type Literal Data Type
1153 \param output Write settings
1154 \return 1 if OK; else 0
1155 */
1156 
1157 unsigned
1158 __ops_fileread_litdata(const char *filename,
1159 				 const __ops_litdata_type_t type,
1160 				 __ops_output_t *output)
1161 {
1162 	__ops_memory_t	*mem;
1163 	unsigned   	 ret;
1164 	size_t		 len;
1165 
1166 	mem = __ops_memory_new();
1167 	if (!__ops_mem_readfile(mem, filename)) {
1168 		return 0;
1169 	}
1170 	len = __ops_mem_len(mem);
1171 	ret = __ops_write_ptag(output, OPS_PTAG_CT_LITDATA) &&
1172 		__ops_write_length(output, 1 + 1 + 4 + len) &&
1173 		__ops_write_scalar(output, (unsigned)type, 1) &&
1174 		__ops_write_scalar(output, 0, 1) /* filename */ &&
1175 		__ops_write_scalar(output, 0, 4) /* date */ &&
1176 		__ops_write(output, __ops_mem_data(mem), len);
1177 	__ops_memory_free(mem);
1178 	return ret;
1179 }
1180 
1181 /**
1182    \ingroup HighLevel_General
1183 
1184    \brief Writes contents of buffer into file
1185 
1186    \param filename Filename to write to
1187    \param buf Buffer to write to file
1188    \param len Size of buffer
1189    \param overwrite Flag to set whether to overwrite an existing file
1190    \return 1 if OK; 0 if error
1191 */
1192 
1193 int
1194 __ops_filewrite(const char *filename, const char *buf,
1195 			const size_t len, const unsigned overwrite)
1196 {
1197 	int		flags;
1198 	int		fd;
1199 
1200 	flags = O_WRONLY | O_CREAT;
1201 	if (overwrite) {
1202 		flags |= O_TRUNC;
1203 	} else {
1204 		flags |= O_EXCL;
1205 	}
1206 #ifdef O_BINARY
1207 	flags |= O_BINARY;
1208 #endif
1209 	fd = open(filename, flags, 0600);
1210 	if (fd < 0) {
1211 		(void) fprintf(stderr, "can't open '%s'\n", filename);
1212 		return 0;
1213 	}
1214 	if (write(fd, buf, len) != (int)len) {
1215 		(void) close(fd);
1216 		return 0;
1217 	}
1218 
1219 	return (close(fd) == 0);
1220 }
1221 
1222 /**
1223 \ingroup Core_WritePackets
1224 \brief Write Symmetrically Encrypted packet
1225 \param data Data to encrypt
1226 \param len Length of data
1227 \param output Write settings
1228 \return 1 if OK; else 0
1229 \note Hard-coded to use AES256
1230 */
1231 unsigned
1232 __ops_write_symm_enc_data(const uint8_t *data,
1233 				       const int len,
1234 				       __ops_output_t * output)
1235 {
1236 	__ops_crypt_t	crypt_info;
1237 	uint8_t		*encrypted = (uint8_t *) NULL;
1238 	size_t		encrypted_sz;
1239 	int             done = 0;
1240 
1241 	/* \todo assume AES256 for now */
1242 	__ops_crypt_any(&crypt_info, OPS_SA_AES_256);
1243 	__ops_encrypt_init(&crypt_info);
1244 
1245 	encrypted_sz = (size_t)(len + crypt_info.blocksize + 2);
1246 	if ((encrypted = calloc(1, encrypted_sz)) == NULL) {
1247 		(void) fprintf(stderr, "can't allocate %" PRIsize "d\n",
1248 			encrypted_sz);
1249 		return 0;
1250 	}
1251 
1252 	done = __ops_encrypt_se(&crypt_info, encrypted, data, (unsigned)len);
1253 	if (done != len) {
1254 		(void) fprintf(stderr,
1255 			"__ops_write_symm_enc_data: done != len\n");
1256 		return 0;
1257 	}
1258 
1259 	return __ops_write_ptag(output, OPS_PTAG_CT_SE_DATA) &&
1260 		__ops_write_length(output, 1 + encrypted_sz) &&
1261 		__ops_write(output, data, (unsigned)len);
1262 }
1263 
1264 /**
1265 \ingroup Core_WritePackets
1266 \brief Write a One Pass Signature packet
1267 \param seckey Secret Key to use
1268 \param hash_alg Hash Algorithm to use
1269 \param sig_type Signature type
1270 \param output Write settings
1271 \return 1 if OK; else 0
1272 */
1273 unsigned
1274 __ops_write_one_pass_sig(__ops_output_t *output,
1275 			const __ops_seckey_t *seckey,
1276 			const __ops_hash_alg_t hash_alg,
1277 			const __ops_sig_type_t sig_type)
1278 {
1279 	uint8_t   keyid[OPS_KEY_ID_SIZE];
1280 
1281 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1282 	return __ops_write_ptag(output, OPS_PTAG_CT_1_PASS_SIG) &&
1283 		__ops_write_length(output, 1 + 1 + 1 + 1 + 8 + 1) &&
1284 		__ops_write_scalar(output, 3, 1)	/* version */ &&
1285 		__ops_write_scalar(output, (unsigned)sig_type, 1) &&
1286 		__ops_write_scalar(output, (unsigned)hash_alg, 1) &&
1287 		__ops_write_scalar(output, (unsigned)seckey->pubkey.alg, 1) &&
1288 		__ops_write(output, keyid, 8) &&
1289 		__ops_write_scalar(output, 1, 1);
1290 }
1291