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