xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/create.c (revision 38beab948a594a8932273fd545578ba9be00d6f8)
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.25 2010/04/14 00:25:10 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 	if (!__ops_write_scalar(output, (unsigned)key->hash_alg, 1)) {
317 		return 0;
318 	}
319 
320 	switch (key->s2k_specifier) {
321 	case OPS_S2KS_SIMPLE:
322 		/* nothing more to do */
323 		break;
324 
325 	case OPS_S2KS_SALTED:
326 		/* 8-octet salt value */
327 		__ops_random(__UNCONST(&key->salt[0]), OPS_SALT_SIZE);
328 		if (!__ops_write(output, key->salt, OPS_SALT_SIZE)) {
329 			return 0;
330 		}
331 		break;
332 
333 		/*
334 		 * \todo case OPS_S2KS_ITERATED_AND_SALTED: // 8-octet salt
335 		 * value // 1-octet count break;
336 		 */
337 
338 	default:
339 		(void) fprintf(stderr,
340 			"invalid/unsupported s2k specifier %d\n",
341 			key->s2k_specifier);
342 		return 0;
343 	}
344 
345 	if (!__ops_write(output, &key->iv[0], __ops_block_size(key->alg))) {
346 		return 0;
347 	}
348 
349 	/*
350 	 * create the session key for encrypting the algorithm-specific
351 	 * fields
352 	 */
353 
354 	switch (key->s2k_specifier) {
355 	case OPS_S2KS_SIMPLE:
356 	case OPS_S2KS_SALTED:
357 		/* RFC4880: section 3.7.1.1 and 3.7.1.2 */
358 
359 		for (done = 0, i = 0; done < CAST_KEY_LENGTH; i++) {
360 			unsigned 	j;
361 			uint8_t		zero = 0;
362 			int             needed;
363 			int             size;
364 
365 			needed = CAST_KEY_LENGTH - done;
366 			size = MIN(needed, OPS_SHA1_HASH_SIZE);
367 
368 			__ops_hash_any(&hash, key->hash_alg);
369 			if (!hash.init(&hash)) {
370 				(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
371 				return 0;
372 			}
373 
374 			/* preload if iterating  */
375 			for (j = 0; j < i; j++) {
376 				/*
377 				 * Coverity shows a DEADCODE error on this
378 				 * line. This is expected since the hardcoded
379 				 * use of SHA1 and CAST5 means that it will
380 				 * not used. This will change however when
381 				 * other algorithms are supported.
382 				 */
383 				hash.add(&hash, &zero, 1);
384 			}
385 
386 			if (key->s2k_specifier == OPS_S2KS_SALTED) {
387 				hash.add(&hash, key->salt, OPS_SALT_SIZE);
388 			}
389 			hash.add(&hash, passphrase, pplen);
390 			hash.finish(&hash, hashed);
391 
392 			/*
393 			 * if more in hash than is needed by session key, use
394 			 * the leftmost octets
395 			 */
396 			(void) memcpy(&sesskey[i * OPS_SHA1_HASH_SIZE],
397 					hashed, (unsigned)size);
398 			done += (unsigned)size;
399 			if (done > CAST_KEY_LENGTH) {
400 				(void) fprintf(stderr,
401 					"write_seckey_body: short add\n");
402 				return 0;
403 			}
404 		}
405 
406 		break;
407 
408 		/*
409 		 * \todo case OPS_S2KS_ITERATED_AND_SALTED: * 8-octet salt
410 		 * value * 1-octet count break;
411 		 */
412 
413 	default:
414 		(void) fprintf(stderr,
415 			"invalid/unsupported s2k specifier %d\n",
416 			key->s2k_specifier);
417 		return 0;
418 	}
419 
420 	/* use this session key to encrypt */
421 
422 	__ops_crypt_any(&crypted, key->alg);
423 	crypted.set_iv(&crypted, key->iv);
424 	crypted.set_crypt_key(&crypted, sesskey);
425 	__ops_encrypt_init(&crypted);
426 
427 	if (__ops_get_debug_level(__FILE__)) {
428 		unsigned	i2;
429 
430 		(void) fprintf(stderr, "\nWRITING:\niv=");
431 		for (i2 = 0; i2 < __ops_block_size(key->alg); i2++) {
432 			(void) fprintf(stderr, "%02x ", key->iv[i2]);
433 		}
434 		(void) fprintf(stderr, "\n");
435 
436 		(void) fprintf(stderr, "key=");
437 		for (i2 = 0; i2 < CAST_KEY_LENGTH; i2++) {
438 			(void) fprintf(stderr, "%02x ", sesskey[i2]);
439 		}
440 		(void) fprintf(stderr, "\n");
441 
442 		(void) fprintf(stderr, "turning encryption on...\n");
443 	}
444 	__ops_push_enc_crypt(output, &crypted);
445 
446 	switch (key->pubkey.alg) {
447 		/* case OPS_PKA_DSA: */
448 		/* return __ops_write_mpi(output, key->key.dsa.x); */
449 
450 	case OPS_PKA_RSA:
451 	case OPS_PKA_RSA_ENCRYPT_ONLY:
452 	case OPS_PKA_RSA_SIGN_ONLY:
453 
454 		if (!__ops_write_mpi(output, key->key.rsa.d) ||
455 		    !__ops_write_mpi(output, key->key.rsa.p) ||
456 		    !__ops_write_mpi(output, key->key.rsa.q) ||
457 		    !__ops_write_mpi(output, key->key.rsa.u)) {
458 			if (__ops_get_debug_level(__FILE__)) {
459 				(void) fprintf(stderr,
460 					"4 x mpi not written - problem\n");
461 			}
462 			return 0;
463 		}
464 		break;
465 
466 		/* case OPS_PKA_ELGAMAL: */
467 		/* return __ops_write_mpi(output, key->key.elgamal.x); */
468 
469 	default:
470 		return 0;
471 	}
472 
473 	if (!__ops_write(output, key->checkhash, OPS_CHECKHASH_SIZE)) {
474 		return 0;
475 	}
476 
477 	__ops_writer_pop(output);
478 
479 	return 1;
480 }
481 
482 /**
483  * \ingroup Core_WritePackets
484  * \brief Writes a Public Key packet
485  * \param key
486  * \param output
487  * \return 1 if OK, otherwise 0
488  */
489 static unsigned
490 write_struct_pubkey(__ops_output_t *output, const __ops_pubkey_t *key)
491 {
492 	if (key->version != 4) {
493 		(void) fprintf(stderr,
494 			"write_struct_pubkey: wrong key version\n");
495 		return 0;
496 	}
497 	return __ops_write_ptag(output, OPS_PTAG_CT_PUBLIC_KEY) &&
498 		__ops_write_length(output, 1 + 4 + 1 + pubkey_length(key)) &&
499 		write_pubkey_body(key, output);
500 }
501 
502 
503 /**
504    \ingroup HighLevel_KeyWrite
505 
506    \brief Writes a transferable PGP public key to the given output stream.
507 
508    \param keydata Key to be written
509    \param armoured Flag is set for armoured output
510    \param output Output stream
511 
512 */
513 
514 unsigned
515 __ops_write_xfer_pubkey(__ops_output_t *output,
516 			const __ops_key_t *key,
517 			const unsigned armoured)
518 {
519 	unsigned    i, j;
520 
521 	if (armoured) {
522 		__ops_writer_push_armoured(output, OPS_PGP_PUBLIC_KEY_BLOCK);
523 	}
524 	/* public key */
525 	if (!write_struct_pubkey(output, &key->key.seckey.pubkey)) {
526 		return 0;
527 	}
528 
529 	/* TODO: revocation signatures go here */
530 
531 	/* user ids and corresponding signatures */
532 	for (i = 0; i < key->uidc; i++) {
533 		if (!__ops_write_struct_userid(output, &key->uids[i])) {
534 			return 0;
535 		}
536 		for (j = 0; j < key->packetc; j++) {
537 			if (!__ops_write(output, key->packets[j].raw, key->packets[j].length)) {
538 				return 0;
539 			}
540 		}
541 	}
542 
543 	/* TODO: user attributes and corresponding signatures */
544 
545 	/*
546 	 * subkey packets and corresponding signatures and optional
547 	 * revocation
548 	 */
549 
550 	if (armoured) {
551 		__ops_writer_info_finalise(&output->errors, &output->writer);
552 		__ops_writer_pop(output);
553 	}
554 	return 1;
555 }
556 
557 /**
558    \ingroup HighLevel_KeyWrite
559 
560    \brief Writes a transferable PGP secret key to the given output stream.
561 
562    \param keydata Key to be written
563    \param passphrase
564    \param pplen
565    \param armoured Flag is set for armoured output
566    \param output Output stream
567 
568 */
569 
570 unsigned
571 __ops_write_xfer_seckey(__ops_output_t *output,
572 				const __ops_key_t *key,
573 				const uint8_t *passphrase,
574 				const size_t pplen,
575 				unsigned armoured)
576 {
577 	unsigned	i, j;
578 
579 	if (armoured) {
580 		__ops_writer_push_armoured(output, OPS_PGP_PRIVATE_KEY_BLOCK);
581 	}
582 	/* public key */
583 	if (!__ops_write_struct_seckey(&key->key.seckey, passphrase,
584 			pplen, output)) {
585 		return 0;
586 	}
587 
588 	/* TODO: revocation signatures go here */
589 
590 	/* user ids and corresponding signatures */
591 	for (i = 0; i < key->uidc; i++) {
592 		if (!__ops_write_struct_userid(output, &key->uids[i])) {
593 			return 0;
594 		}
595 		for (j = 0; j < key->packetc; j++) {
596 			if (!__ops_write(output, key->packets[j].raw, key->packets[j].length)) {
597 				return 0;
598 			}
599 		}
600 	}
601 
602 	/* TODO: user attributes and corresponding signatures */
603 
604 	/*
605 	 * subkey packets and corresponding signatures and optional
606 	 * revocation
607 	 */
608 
609 	if (armoured) {
610 		__ops_writer_info_finalise(&output->errors, &output->writer);
611 		__ops_writer_pop(output);
612 	}
613 	return 1;
614 }
615 
616 /**
617  * \ingroup Core_WritePackets
618  * \brief Writes one RSA public key packet.
619  * \param t Creation time
620  * \param n RSA public modulus
621  * \param e RSA public encryption exponent
622  * \param output Writer settings
623  *
624  * \return 1 if OK, otherwise 0
625  */
626 
627 unsigned
628 __ops_write_rsa_pubkey(time_t t, const BIGNUM *n,
629 			 const BIGNUM *e,
630 			 __ops_output_t *output)
631 {
632 	__ops_pubkey_t key;
633 
634 	__ops_fast_create_rsa_pubkey(&key, t, __UNCONST(n), __UNCONST(e));
635 	return write_struct_pubkey(output, &key);
636 }
637 
638 /**
639  * \ingroup Core_Create
640  * \param out
641  * \param key
642  * \param make_packet
643  */
644 
645 void
646 __ops_build_pubkey(__ops_memory_t *out, const __ops_pubkey_t *key,
647 		     unsigned make_packet)
648 {
649 	__ops_output_t *output;
650 
651 	output = __ops_output_new();
652 	__ops_memory_init(out, 128);
653 	__ops_writer_set_memory(output, out);
654 	write_pubkey_body(key, output);
655 	if (make_packet) {
656 		__ops_memory_make_packet(out, OPS_PTAG_CT_PUBLIC_KEY);
657 	}
658 	__ops_output_delete(output);
659 }
660 
661 /**
662  * \ingroup Core_Create
663  *
664  * Create an RSA secret key structure. If a parameter is marked as
665  * [OPTIONAL], then it can be omitted and will be calculated from
666  * other params - or, in the case of e, will default to 0x10001.
667  *
668  * Parameters are _not_ copied, so will be freed if the structure is
669  * freed.
670  *
671  * \param key The key structure to be initialised.
672  * \param t
673  * \param d The RSA parameter d (=e^-1 mod (p-1)(q-1)) [OPTIONAL]
674  * \param p The RSA parameter p
675  * \param q The RSA parameter q (q > p)
676  * \param u The RSA parameter u (=p^-1 mod q) [OPTIONAL]
677  * \param n The RSA public parameter n (=p*q) [OPTIONAL]
678  * \param e The RSA public parameter e */
679 
680 void
681 __ops_fast_create_rsa_seckey(__ops_seckey_t *key, time_t t,
682 			     BIGNUM *d, BIGNUM *p, BIGNUM *q, BIGNUM *u,
683 			       BIGNUM *n, BIGNUM *e)
684 {
685 	__ops_fast_create_rsa_pubkey(&key->pubkey, t, n, e);
686 
687 	/* XXX: calculate optionals */
688 	key->key.rsa.d = d;
689 	key->key.rsa.p = p;
690 	key->key.rsa.q = q;
691 	key->key.rsa.u = u;
692 
693 	key->s2k_usage = OPS_S2KU_NONE;
694 
695 	/* XXX: sanity check and add errors... */
696 }
697 
698 /**
699  * \ingroup Core_WritePackets
700  * \brief Writes a Secret Key packet.
701  * \param key The secret key
702  * \param passphrase The passphrase
703  * \param pplen Length of passphrase
704  * \param output
705  * \return 1 if OK; else 0
706  */
707 unsigned
708 __ops_write_struct_seckey(const __ops_seckey_t *key,
709 			    const uint8_t *passphrase,
710 			    const size_t pplen,
711 			    __ops_output_t *output)
712 {
713 	int             length = 0;
714 
715 	if (key->pubkey.version != 4) {
716 		(void) fprintf(stderr,
717 			"__ops_write_struct_seckey: public key version\n");
718 		return 0;
719 	}
720 
721 	/* Ref: RFC4880 Section 5.5.3 */
722 
723 	/* pubkey, excluding MPIs */
724 	length += 1 + 4 + 1 + 1;
725 
726 	/* s2k usage */
727 	length += 1;
728 
729 	switch (key->s2k_usage) {
730 	case OPS_S2KU_NONE:
731 		/* nothing to add */
732 		break;
733 
734 	case OPS_S2KU_ENCRYPTED_AND_HASHED:	/* 254 */
735 	case OPS_S2KU_ENCRYPTED:	/* 255 */
736 
737 		/* Ref: RFC4880 Section 3.7 */
738 		length += 1;	/* s2k_specifier */
739 
740 		switch (key->s2k_specifier) {
741 		case OPS_S2KS_SIMPLE:
742 			length += 1;	/* hash algorithm */
743 			break;
744 
745 		case OPS_S2KS_SALTED:
746 			length += 1 + 8;	/* hash algorithm + salt */
747 			break;
748 
749 		case OPS_S2KS_ITERATED_AND_SALTED:
750 			length += 1 + 8 + 1;	/* hash algorithm, salt +
751 						 * count */
752 			break;
753 
754 		default:
755 			(void) fprintf(stderr,
756 				"__ops_write_struct_seckey: s2k spec\n");
757 			return 0;
758 		}
759 		break;
760 
761 	default:
762 		(void) fprintf(stderr,
763 			"__ops_write_struct_seckey: s2k usage\n");
764 		return 0;
765 	}
766 
767 	/* IV */
768 	if (key->s2k_usage) {
769 		length += __ops_block_size(key->alg);
770 	}
771 	/* checksum or hash */
772 	switch (key->s2k_usage) {
773 	case OPS_S2KU_NONE:
774 	case OPS_S2KU_ENCRYPTED:
775 		length += 2;
776 		break;
777 
778 	case OPS_S2KU_ENCRYPTED_AND_HASHED:
779 		length += OPS_CHECKHASH_SIZE;
780 		break;
781 
782 	default:
783 		(void) fprintf(stderr,
784 			"__ops_write_struct_seckey: s2k cksum usage\n");
785 		return 0;
786 	}
787 
788 	/* secret key and public key MPIs */
789 	length += (unsigned)seckey_length(key);
790 
791 	return __ops_write_ptag(output, OPS_PTAG_CT_SECRET_KEY) &&
792 		/* __ops_write_length(output,1+4+1+1+seckey_length(key)+2) && */
793 		__ops_write_length(output, (unsigned)length) &&
794 		write_seckey_body(key, passphrase, pplen, output);
795 }
796 
797 /**
798  * \ingroup Core_Create
799  *
800  * \brief Create a new __ops_output_t structure.
801  *
802  * \return the new structure.
803  * \note It is the responsiblity of the caller to call __ops_output_delete().
804  * \sa __ops_output_delete()
805  */
806 __ops_output_t *
807 __ops_output_new(void)
808 {
809 	return calloc(1, sizeof(__ops_output_t));
810 }
811 
812 /**
813  * \ingroup Core_Create
814  * \brief Delete an __ops_output_t strucut and associated resources.
815  *
816  * Delete an __ops_output_t structure. If a writer is active, then
817  * that is also deleted.
818  *
819  * \param info the structure to be deleted.
820  */
821 void
822 __ops_output_delete(__ops_output_t *output)
823 {
824 	__ops_writer_info_delete(&output->writer);
825 	free(output);
826 }
827 
828 /**
829  \ingroup Core_Create
830  \brief Calculate the checksum for a session key
831  \param sesskey Session Key to use
832  \param cs Checksum to be written
833  \return 1 if OK; else 0
834 */
835 unsigned
836 __ops_calc_sesskey_checksum(__ops_pk_sesskey_t *sesskey, uint8_t cs[2])
837 {
838 	uint32_t   checksum = 0;
839 	unsigned    i;
840 
841 	if (!__ops_is_sa_supported(sesskey->symm_alg)) {
842 		return 0;
843 	}
844 
845 	for (i = 0; i < __ops_key_size(sesskey->symm_alg); i++) {
846 		checksum += sesskey->key[i];
847 	}
848 	checksum = checksum % 65536;
849 
850 	cs[0] = (uint8_t)((checksum >> 8) & 0xff);
851 	cs[1] = (uint8_t)(checksum & 0xff);
852 
853 	if (__ops_get_debug_level(__FILE__)) {
854 		(void) fprintf(stderr,"\nm buf checksum: ");
855 		(void) fprintf(stderr," %2x",cs[0]);
856 		(void) fprintf(stderr," %2x\n",cs[1]);
857 	}
858 	return 1;
859 }
860 
861 static unsigned
862 create_unencoded_m_buf(__ops_pk_sesskey_t *sesskey, uint8_t *m_buf)
863 {
864 	int             i;
865 
866 	/* m_buf is the buffer which will be encoded in PKCS#1 block */
867 	/* encoding to form the "m" value used in the  */
868 	/* Public Key Encrypted Session Key Packet */
869 	/*
870 	 * as defined in RFC Section 5.1 "Public-Key Encrypted Session Key
871 	 * Packet"
872 	 */
873 
874 	m_buf[0] = sesskey->symm_alg;
875 
876 	if (sesskey->symm_alg != OPS_SA_CAST5) {
877 		(void) fprintf(stderr, "create_unencoded_m_buf: symm alg\n");
878 		return 0;
879 	}
880 	for (i = 0; i < CAST_KEY_LENGTH; i++) {
881 		/* XXX - Flexelint - Warning 679: Suspicious Truncation in arithmetic expression combining with pointer */
882 		m_buf[1 + i] = sesskey->key[i];
883 	}
884 
885 	return (__ops_calc_sesskey_checksum(sesskey,
886 				m_buf + 1 + CAST_KEY_LENGTH));
887 }
888 
889 /**
890 \ingroup Core_Create
891 \brief implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC
892 \param M
893 \param mLen
894 \param pubkey
895 \param EM
896 \return 1 if OK; else 0
897 */
898 unsigned
899 encode_m_buf(const uint8_t *M, size_t mLen, const __ops_pubkey_t * pubkey,
900 	     uint8_t *EM)
901 {
902 	unsigned    k;
903 	unsigned        i;
904 
905 	/* implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC */
906 
907 	if (pubkey->alg != OPS_PKA_RSA) {
908 		(void) fprintf(stderr, "encode_m_buf: pubkey algorithm\n");
909 		return 0;
910 	}
911 
912 	k = (unsigned)BN_num_bytes(pubkey->key.rsa.n);
913 	if (mLen > k - 11) {
914 		(void) fprintf(stderr, "encode_m_buf: message too long\n");
915 		return 0;
916 	}
917 	/* these two bytes defined by RFC */
918 	EM[0] = 0x00;
919 	EM[1] = 0x02;
920 
921 	/* add non-zero random bytes of length k - mLen -3 */
922 	for (i = 2; i < (k - mLen) - 1; ++i) {
923 		do {
924 			__ops_random(EM + i, 1);
925 		} while (EM[i] == 0);
926 	}
927 
928 	if (i < 8 + 2) {
929 		(void) fprintf(stderr, "encode_m_buf: bad i len\n");
930 		return 0;
931 	}
932 
933 	EM[i++] = 0;
934 
935 	(void) memcpy(EM + i, M, mLen);
936 
937 	if (__ops_get_debug_level(__FILE__)) {
938 		unsigned    i2;
939 
940 		(void) fprintf(stderr, "Encoded Message: \n");
941 		for (i2 = 0; i2 < mLen; i2++) {
942 			(void) fprintf(stderr, "%2x ", EM[i2]);
943 		}
944 		(void) fprintf(stderr, "\n");
945 	}
946 	return 1;
947 }
948 
949 /**
950  \ingroup Core_Create
951 \brief Creates an __ops_pk_sesskey_t struct from keydata
952 \param key Keydata to use
953 \return __ops_pk_sesskey_t struct
954 \note It is the caller's responsiblity to free the returned pointer
955 \note Currently hard-coded to use CAST5
956 \note Currently hard-coded to use RSA
957 */
958 __ops_pk_sesskey_t *
959 __ops_create_pk_sesskey(const __ops_key_t *key)
960 {
961 	/*
962          * Creates a random session key and encrypts it for the given key
963          *
964          * Session Key is for use with a SK algo,
965          * can be any, we're hardcoding CAST5 for now
966          *
967          * Encryption used is PK,
968          * can be any, we're hardcoding RSA for now
969          */
970 
971 #define SZ_UNENCODED_M_BUF (CAST_KEY_LENGTH + 1 + 2)
972 
973 	const __ops_pubkey_t	*pubkey;
974 	__ops_pk_sesskey_t	*sesskey;
975 	uint8_t			 unencoded_m_buf[SZ_UNENCODED_M_BUF];
976 	uint8_t			*encoded_m_buf;
977 	size_t			 sz_encoded_m_buf;
978 
979 	pubkey = __ops_get_pubkey(key);
980 	sz_encoded_m_buf = BN_num_bytes(pubkey->key.rsa.n);
981 	if ((encoded_m_buf = calloc(1, sz_encoded_m_buf)) == NULL) {
982 		(void) fprintf(stderr,
983 			"__ops_create_pk_sesskey: can't allocate\n");
984 		return NULL;
985 	}
986 	if ((sesskey = calloc(1, sizeof(*sesskey))) == NULL) {
987 		(void) fprintf(stderr,
988 			"__ops_create_pk_sesskey: can't allocate\n");
989 		free(encoded_m_buf);
990 		return NULL;
991 	}
992 	if (key->type != OPS_PTAG_CT_PUBLIC_KEY) {
993 		(void) fprintf(stderr,
994 			"__ops_create_pk_sesskey: bad type\n");
995 		free(encoded_m_buf);
996 		free(sesskey);
997 		return NULL;
998 	}
999 	sesskey->version = OPS_PKSK_V3;
1000 	(void) memcpy(sesskey->key_id, key->key_id,
1001 			sizeof(sesskey->key_id));
1002 
1003 	if (__ops_get_debug_level(__FILE__)) {
1004 		unsigned    i;
1005 
1006 		(void) fprintf(stderr, "Encrypting for RSA key id : ");
1007 		for (i = 0; i < sizeof(sesskey->key_id); i++) {
1008 			(void) fprintf(stderr, "%2x ", key->key_id[i]);
1009 		}
1010 		(void) fprintf(stderr, "\n");
1011 	}
1012 	if (key->key.pubkey.alg != OPS_PKA_RSA) {
1013 		(void) fprintf(stderr,
1014 			"__ops_create_pk_sesskey: bad pubkey algorithm\n");
1015 		free(encoded_m_buf);
1016 		free(sesskey);
1017 		return NULL;
1018 	}
1019 	sesskey->alg = key->key.pubkey.alg;
1020 
1021 	/* \todo allow user to specify other algorithm */
1022 	sesskey->symm_alg = OPS_SA_CAST5;
1023 	__ops_random(sesskey->key, CAST_KEY_LENGTH);
1024 
1025 	if (__ops_get_debug_level(__FILE__)) {
1026 		unsigned    i;
1027 
1028 		(void) fprintf(stderr,
1029 			"CAST5 session key created (len=%d):\n ",
1030 			CAST_KEY_LENGTH);
1031 		for (i = 0; i < CAST_KEY_LENGTH; i++) {
1032 			(void) fprintf(stderr, "%2x ", sesskey->key[i]);
1033 		}
1034 		(void) fprintf(stderr, "\n");
1035 	}
1036 	if (create_unencoded_m_buf(sesskey, &unencoded_m_buf[0]) == 0) {
1037 		free(encoded_m_buf);
1038 		free(sesskey);
1039 		return NULL;
1040 	}
1041 	if (__ops_get_debug_level(__FILE__)) {
1042 		unsigned    i;
1043 
1044 		printf("unencoded m buf:\n");
1045 		for (i = 0; i < SZ_UNENCODED_M_BUF; i++) {
1046 			printf("%2x ", unencoded_m_buf[i]);
1047 		}
1048 		printf("\n");
1049 	}
1050 	encode_m_buf(&unencoded_m_buf[0], SZ_UNENCODED_M_BUF, pubkey,
1051 			&encoded_m_buf[0]);
1052 
1053 	/* and encrypt it */
1054 	if (!__ops_rsa_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey,
1055 			&sesskey->params)) {
1056 		free(encoded_m_buf);
1057 		free(sesskey);
1058 		return NULL;
1059 	}
1060 	free(encoded_m_buf);
1061 	return sesskey;
1062 }
1063 
1064 /**
1065 \ingroup Core_WritePackets
1066 \brief Writes Public Key Session Key packet
1067 \param info Write settings
1068 \param pksk Public Key Session Key to write out
1069 \return 1 if OK; else 0
1070 */
1071 unsigned
1072 __ops_write_pk_sesskey(__ops_output_t *output, __ops_pk_sesskey_t *pksk)
1073 {
1074 	/* XXX - Flexelint - Pointer parameter 'pksk' (line 1076) could be declared as pointing to const */
1075 	if (pksk == NULL) {
1076 		(void) fprintf(stderr,
1077 			"__ops_write_pk_sesskey: NULL pksk\n");
1078 		return 0;
1079 	}
1080 	if (pksk->alg != OPS_PKA_RSA) {
1081 		(void) fprintf(stderr,
1082 			"__ops_write_pk_sesskey: bad algorithm\n");
1083 		return 0;
1084 	}
1085 	return __ops_write_ptag(output, OPS_PTAG_CT_PK_SESSION_KEY) &&
1086 		__ops_write_length(output, (unsigned)(1 + 8 + 1 +
1087 			BN_num_bytes(pksk->params.rsa.encrypted_m) + 2)) &&
1088 		__ops_write_scalar(output, (unsigned)pksk->version, 1) &&
1089 		__ops_write(output, pksk->key_id, 8) &&
1090 		__ops_write_scalar(output, (unsigned)pksk->alg, 1) &&
1091 		__ops_write_mpi(output, pksk->params.rsa.encrypted_m)
1092 	/* ??	&& __ops_write_scalar(output, 0, 2); */
1093 		;
1094 }
1095 
1096 /**
1097 \ingroup Core_WritePackets
1098 \brief Writes MDC packet
1099 \param hashed Hash for MDC
1100 \param output Write settings
1101 \return 1 if OK; else 0
1102 */
1103 
1104 unsigned
1105 __ops_write_mdc(__ops_output_t *output, const uint8_t *hashed)
1106 {
1107 	/* write it out */
1108 	return __ops_write_ptag(output, OPS_PTAG_CT_MDC) &&
1109 		__ops_write_length(output, OPS_SHA1_HASH_SIZE) &&
1110 		__ops_write(output, hashed, OPS_SHA1_HASH_SIZE);
1111 }
1112 
1113 /**
1114 \ingroup Core_WritePackets
1115 \brief Writes Literal Data packet from buffer
1116 \param data Buffer to write out
1117 \param maxlen Max length of buffer
1118 \param type Literal Data Type
1119 \param output Write settings
1120 \return 1 if OK; else 0
1121 */
1122 unsigned
1123 __ops_write_litdata(__ops_output_t *output,
1124 			const uint8_t *data,
1125 			const int maxlen,
1126 			const __ops_litdata_type_t type)
1127 {
1128 	/*
1129          * RFC4880 does not specify a meaning for filename or date.
1130          * It is implementation-dependent.
1131          * We will not implement them.
1132          */
1133 	/* \todo do we need to check text data for <cr><lf> line endings ? */
1134 	return __ops_write_ptag(output, OPS_PTAG_CT_LITDATA) &&
1135 		__ops_write_length(output, (unsigned)(1 + 1 + 4 + maxlen)) &&
1136 		__ops_write_scalar(output, (unsigned)type, 1) &&
1137 		__ops_write_scalar(output, 0, 1) &&
1138 		__ops_write_scalar(output, 0, 4) &&
1139 		__ops_write(output, data, (unsigned)maxlen);
1140 }
1141 
1142 /**
1143 \ingroup Core_WritePackets
1144 \brief Writes Literal Data packet from contents of file
1145 \param filename Name of file to read from
1146 \param type Literal Data Type
1147 \param output Write settings
1148 \return 1 if OK; else 0
1149 */
1150 
1151 unsigned
1152 __ops_fileread_litdata(const char *filename,
1153 				 const __ops_litdata_type_t type,
1154 				 __ops_output_t *output)
1155 {
1156 	__ops_memory_t	*mem;
1157 	unsigned   	 ret;
1158 	int		 len;
1159 
1160 	mem = __ops_memory_new();
1161 	if (!__ops_mem_readfile(mem, filename)) {
1162 		(void) fprintf(stderr, "__ops_mem_readfile of '%s' failed\n", filename);
1163 		return 0;
1164 	}
1165 	len = (size_t)__ops_mem_len(mem);
1166 	ret = __ops_write_litdata(output, __ops_mem_data(mem), len, type);
1167 	__ops_memory_free(mem);
1168 	return ret;
1169 }
1170 
1171 /**
1172    \ingroup HighLevel_General
1173 
1174    \brief Writes contents of buffer into file
1175 
1176    \param filename Filename to write to
1177    \param buf Buffer to write to file
1178    \param len Size of buffer
1179    \param overwrite Flag to set whether to overwrite an existing file
1180    \return 1 if OK; 0 if error
1181 */
1182 
1183 int
1184 __ops_filewrite(const char *filename, const char *buf,
1185 			const size_t len, const unsigned overwrite)
1186 {
1187 	int		flags;
1188 	int		fd;
1189 
1190 	flags = O_WRONLY | O_CREAT;
1191 	if (overwrite) {
1192 		flags |= O_TRUNC;
1193 	} else {
1194 		flags |= O_EXCL;
1195 	}
1196 #ifdef O_BINARY
1197 	flags |= O_BINARY;
1198 #endif
1199 	fd = open(filename, flags, 0600);
1200 	if (fd < 0) {
1201 		(void) fprintf(stderr, "can't open '%s'\n", filename);
1202 		return 0;
1203 	}
1204 	if (write(fd, buf, len) != (int)len) {
1205 		(void) close(fd);
1206 		return 0;
1207 	}
1208 
1209 	return (close(fd) == 0);
1210 }
1211 
1212 /**
1213 \ingroup Core_WritePackets
1214 \brief Write Symmetrically Encrypted packet
1215 \param data Data to encrypt
1216 \param len Length of data
1217 \param output Write settings
1218 \return 1 if OK; else 0
1219 \note Hard-coded to use AES256
1220 */
1221 unsigned
1222 __ops_write_symm_enc_data(const uint8_t *data,
1223 				       const int len,
1224 				       __ops_output_t * output)
1225 {
1226 	__ops_crypt_t	crypt_info;
1227 	uint8_t		*encrypted = (uint8_t *) NULL;
1228 	size_t		encrypted_sz;
1229 	int             done = 0;
1230 
1231 	/* \todo assume AES256 for now */
1232 	__ops_crypt_any(&crypt_info, OPS_SA_AES_256);
1233 	__ops_encrypt_init(&crypt_info);
1234 
1235 	encrypted_sz = (size_t)(len + crypt_info.blocksize + 2);
1236 	if ((encrypted = calloc(1, encrypted_sz)) == NULL) {
1237 		(void) fprintf(stderr, "can't allocate %" PRIsize "d\n",
1238 			encrypted_sz);
1239 		return 0;
1240 	}
1241 
1242 	done = __ops_encrypt_se(&crypt_info, encrypted, data, (unsigned)len);
1243 	if (done != len) {
1244 		(void) fprintf(stderr,
1245 			"__ops_write_symm_enc_data: done != len\n");
1246 		return 0;
1247 	}
1248 
1249 	return __ops_write_ptag(output, OPS_PTAG_CT_SE_DATA) &&
1250 		__ops_write_length(output, 1 + encrypted_sz) &&
1251 		__ops_write(output, data, (unsigned)len);
1252 }
1253 
1254 /**
1255 \ingroup Core_WritePackets
1256 \brief Write a One Pass Signature packet
1257 \param seckey Secret Key to use
1258 \param hash_alg Hash Algorithm to use
1259 \param sig_type Signature type
1260 \param output Write settings
1261 \return 1 if OK; else 0
1262 */
1263 unsigned
1264 __ops_write_one_pass_sig(__ops_output_t *output,
1265 			const __ops_seckey_t *seckey,
1266 			const __ops_hash_alg_t hash_alg,
1267 			const __ops_sig_type_t sig_type)
1268 {
1269 	uint8_t   keyid[OPS_KEY_ID_SIZE];
1270 
1271 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1272 	return __ops_write_ptag(output, OPS_PTAG_CT_1_PASS_SIG) &&
1273 		__ops_write_length(output, 1 + 1 + 1 + 1 + 8 + 1) &&
1274 		__ops_write_scalar(output, 3, 1)	/* version */ &&
1275 		__ops_write_scalar(output, (unsigned)sig_type, 1) &&
1276 		__ops_write_scalar(output, (unsigned)hash_alg, 1) &&
1277 		__ops_write_scalar(output, (unsigned)seckey->pubkey.alg, 1) &&
1278 		__ops_write(output, keyid, 8) &&
1279 		__ops_write_scalar(output, 1, 1);
1280 }
1281