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