xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/create.c (revision 0294a66b694d2a57b43f64b66c7a4aee89316c4e)
12232f800Sagc /*-
22232f800Sagc  * Copyright (c) 2009 The NetBSD Foundation, Inc.
32232f800Sagc  * All rights reserved.
42232f800Sagc  *
52232f800Sagc  * This code is derived from software contributed to The NetBSD Foundation
62232f800Sagc  * by Alistair Crooks (agc@NetBSD.org)
72232f800Sagc  *
82232f800Sagc  * Redistribution and use in source and binary forms, with or without
92232f800Sagc  * modification, are permitted provided that the following conditions
102232f800Sagc  * are met:
112232f800Sagc  * 1. Redistributions of source code must retain the above copyright
122232f800Sagc  *    notice, this list of conditions and the following disclaimer.
132232f800Sagc  * 2. Redistributions in binary form must reproduce the above copyright
142232f800Sagc  *    notice, this list of conditions and the following disclaimer in the
152232f800Sagc  *    documentation and/or other materials provided with the distribution.
162232f800Sagc  *
172232f800Sagc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
182232f800Sagc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
192232f800Sagc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
202232f800Sagc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
212232f800Sagc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
222232f800Sagc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
232232f800Sagc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
242232f800Sagc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
252232f800Sagc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
262232f800Sagc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
272232f800Sagc  * POSSIBILITY OF SUCH DAMAGE.
282232f800Sagc  */
2993bf6008Sagc /*
3093bf6008Sagc  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
3193bf6008Sagc  * All rights reserved.
3293bf6008Sagc  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
3393bf6008Sagc  * their moral rights under the UK Copyright Design and Patents Act 1988 to
3493bf6008Sagc  * be recorded as the authors of this copyright work.
3593bf6008Sagc  *
3693bf6008Sagc  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
3793bf6008Sagc  * use this file except in compliance with the License.
3893bf6008Sagc  *
3993bf6008Sagc  * You may obtain a copy of the License at
4093bf6008Sagc  *     http://www.apache.org/licenses/LICENSE-2.0
4193bf6008Sagc  *
4293bf6008Sagc  * Unless required by applicable law or agreed to in writing, software
4393bf6008Sagc  * distributed under the License is distributed on an "AS IS" BASIS,
4493bf6008Sagc  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4593bf6008Sagc  *
4693bf6008Sagc  * See the License for the specific language governing permissions and
4793bf6008Sagc  * limitations under the License.
4893bf6008Sagc  */
4993bf6008Sagc 
5093bf6008Sagc /** \file
5193bf6008Sagc  */
5293bf6008Sagc #include "config.h"
5393bf6008Sagc 
5457324b9fSagc #ifdef HAVE_SYS_CDEFS_H
5557324b9fSagc #include <sys/cdefs.h>
5657324b9fSagc #endif
5757324b9fSagc 
5857324b9fSagc #if defined(__NetBSD__)
5957324b9fSagc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60*0294a66bSjhigh __RCSID("$NetBSD: create.c,v 1.39 2022/08/26 19:18:38 jhigh Exp $");
6157324b9fSagc #endif
6257324b9fSagc 
63bcfd8565Sagc #include <sys/types.h>
642232f800Sagc #include <sys/param.h>
65bcfd8565Sagc #include <sys/stat.h>
66bcfd8565Sagc 
67bcfd8565Sagc #ifdef HAVE_FCNTL_H
68bcfd8565Sagc #include <fcntl.h>
69bcfd8565Sagc #endif
70bcfd8565Sagc 
71bcfd8565Sagc #include <string.h>
72bcfd8565Sagc 
73bcfd8565Sagc #ifdef HAVE_UNISTD_H
74bcfd8565Sagc #include <unistd.h>
75bcfd8565Sagc #endif
76bcfd8565Sagc 
7793bf6008Sagc #ifdef HAVE_OPENSSL_CAST_H
7893bf6008Sagc #include <openssl/cast.h>
7993bf6008Sagc #endif
8093bf6008Sagc 
8193bf6008Sagc #include "create.h"
8293bf6008Sagc #include "keyring.h"
8393bf6008Sagc #include "packet.h"
8493bf6008Sagc #include "signature.h"
8593bf6008Sagc #include "writer.h"
8693bf6008Sagc #include "readerwriter.h"
8793bf6008Sagc #include "memory.h"
8893bf6008Sagc #include "netpgpdefs.h"
896715e11aSagc #include "netpgpdigest.h"
9093bf6008Sagc 
9193bf6008Sagc /**
9293bf6008Sagc  * \ingroup Core_Create
9393bf6008Sagc  * \param length
9493bf6008Sagc  * \param type
9557324b9fSagc  * \param output
964b3a3e18Sagc  * \return 1 if OK, otherwise 0
9793bf6008Sagc  */
9893bf6008Sagc 
994b3a3e18Sagc unsigned
pgp_write_ss_header(pgp_output_t * output,unsigned length,pgp_content_enum type)100fc1f8641Sagc pgp_write_ss_header(pgp_output_t *output,
10157324b9fSagc 			unsigned length,
102fc1f8641Sagc 			pgp_content_enum type)
10393bf6008Sagc {
104fc1f8641Sagc 	return pgp_write_length(output, length) &&
105fc1f8641Sagc 		pgp_write_scalar(output, (unsigned)(type -
106fc1f8641Sagc 				(unsigned)PGP_PTAG_SIG_SUBPKT_BASE), 1);
10793bf6008Sagc }
10893bf6008Sagc 
10993bf6008Sagc /*
11093bf6008Sagc  * XXX: the general idea of _fast_ is that it doesn't copy stuff the safe
11193bf6008Sagc  * (i.e. non _fast_) version will, and so will also need to be freed.
11293bf6008Sagc  */
11393bf6008Sagc 
11493bf6008Sagc /**
11593bf6008Sagc  * \ingroup Core_Create
11693bf6008Sagc  *
117fc1f8641Sagc  * pgp_fast_create_userid() sets id->userid to the given userid.
11857324b9fSagc  * This is fast because it is only copying a char*. However, if userid
11993bf6008Sagc  * is changed or freed in the future, this could have injurious results.
12093bf6008Sagc  * \param id
12157324b9fSagc  * \param userid
12293bf6008Sagc  */
12393bf6008Sagc 
12493bf6008Sagc void
pgp_fast_create_userid(uint8_t ** id,uint8_t * userid)125fc1f8641Sagc pgp_fast_create_userid(uint8_t **id, uint8_t *userid)
12693bf6008Sagc {
127d427c17dSagc 	*id = userid;
12893bf6008Sagc }
12993bf6008Sagc 
13093bf6008Sagc /**
13193bf6008Sagc  * \ingroup Core_WritePackets
13293bf6008Sagc  * \brief Writes a User Id packet
13393bf6008Sagc  * \param id
13457324b9fSagc  * \param output
1354b3a3e18Sagc  * \return 1 if OK, otherwise 0
13693bf6008Sagc  */
1374b3a3e18Sagc unsigned
pgp_write_struct_userid(pgp_output_t * output,const uint8_t * id)138fc1f8641Sagc pgp_write_struct_userid(pgp_output_t *output, const uint8_t *id)
13993bf6008Sagc {
140fc1f8641Sagc 	return pgp_write_ptag(output, PGP_PTAG_CT_USER_ID) &&
141fc1f8641Sagc 		pgp_write_length(output, (unsigned)strlen((const char *) id)) &&
142fc1f8641Sagc 		pgp_write(output, id, (unsigned)strlen((const char *) id));
14393bf6008Sagc }
14493bf6008Sagc 
14593bf6008Sagc /**
14693bf6008Sagc  * \ingroup Core_WritePackets
14793bf6008Sagc  * \brief Write a User Id packet.
14857324b9fSagc  * \param userid
14957324b9fSagc  * \param output
15093bf6008Sagc  *
151fc1f8641Sagc  * \return return value from pgp_write_struct_userid()
15293bf6008Sagc  */
1534b3a3e18Sagc unsigned
pgp_write_userid(const uint8_t * userid,pgp_output_t * output)154fc1f8641Sagc pgp_write_userid(const uint8_t *userid, pgp_output_t *output)
15593bf6008Sagc {
156fc1f8641Sagc 	return pgp_write_struct_userid(output, userid);
15793bf6008Sagc }
15893bf6008Sagc 
15993bf6008Sagc /**
16093bf6008Sagc \ingroup Core_MPI
16193bf6008Sagc */
16293bf6008Sagc static unsigned
mpi_length(const BIGNUM * bn)16393bf6008Sagc mpi_length(const BIGNUM *bn)
16493bf6008Sagc {
1655a83dba0Sagc 	return (unsigned)(2 + (BN_num_bits(bn) + 7) / 8);
16693bf6008Sagc }
16793bf6008Sagc 
16893bf6008Sagc static unsigned
pubkey_length(const pgp_pubkey_t * key)169fc1f8641Sagc pubkey_length(const pgp_pubkey_t *key)
17093bf6008Sagc {
1712232f800Sagc 	switch (key->alg) {
172fc1f8641Sagc 	case PGP_PKA_DSA:
173708e54deSagc 		return mpi_length(key->key.dsa.p) + mpi_length(key->key.dsa.q) +
174708e54deSagc 			mpi_length(key->key.dsa.g) + mpi_length(key->key.dsa.y);
175708e54deSagc 
176fc1f8641Sagc 	case PGP_PKA_RSA:
17793bf6008Sagc 		return mpi_length(key->key.rsa.n) + mpi_length(key->key.rsa.e);
17893bf6008Sagc 
17993bf6008Sagc 	default:
180ed0df671Sagc 		(void) fprintf(stderr,
1813326c4c5Sagc 			"pubkey_length: unknown key algorithm\n");
18293bf6008Sagc 	}
18393bf6008Sagc 	return 0;
18493bf6008Sagc }
18593bf6008Sagc 
18693bf6008Sagc static unsigned
seckey_length(const pgp_seckey_t * key)187fc1f8641Sagc seckey_length(const pgp_seckey_t *key)
18893bf6008Sagc {
189ed0df671Sagc 	int             len;
19093bf6008Sagc 
191ed0df671Sagc 	len = 0;
1922232f800Sagc 	switch (key->pubkey.alg) {
193fc1f8641Sagc 	case PGP_PKA_DSA:
194708e54deSagc 		return (unsigned)(mpi_length(key->key.dsa.x) + pubkey_length(&key->pubkey));
195fc1f8641Sagc 	case PGP_PKA_RSA:
196ed0df671Sagc 		len = mpi_length(key->key.rsa.d) + mpi_length(key->key.rsa.p) +
197bcfd8565Sagc 			mpi_length(key->key.rsa.q) + mpi_length(key->key.rsa.u);
19893bf6008Sagc 
1995a83dba0Sagc 		return (unsigned)(len + pubkey_length(&key->pubkey));
20093bf6008Sagc 	default:
201ed0df671Sagc 		(void) fprintf(stderr,
20257324b9fSagc 			"seckey_length: unknown key algorithm\n");
20393bf6008Sagc 	}
204ed0df671Sagc 	return 0;
20593bf6008Sagc }
20693bf6008Sagc 
20793bf6008Sagc /**
20893bf6008Sagc  * \ingroup Core_Create
20993bf6008Sagc  * \param key
21093bf6008Sagc  * \param t
21193bf6008Sagc  * \param n
21293bf6008Sagc  * \param e
21393bf6008Sagc */
21493bf6008Sagc void
pgp_fast_create_rsa_pubkey(pgp_pubkey_t * key,time_t t,BIGNUM * n,BIGNUM * e)215fc1f8641Sagc pgp_fast_create_rsa_pubkey(pgp_pubkey_t *key, time_t t,
21693bf6008Sagc 			       BIGNUM *n, BIGNUM *e)
21793bf6008Sagc {
218fc1f8641Sagc 	key->version = PGP_V4;
2193326c4c5Sagc 	key->birthtime = t;
220fc1f8641Sagc 	key->alg = PGP_PKA_RSA;
22193bf6008Sagc 	key->key.rsa.n = n;
22293bf6008Sagc 	key->key.rsa.e = e;
22393bf6008Sagc }
22493bf6008Sagc 
22593bf6008Sagc /*
22693bf6008Sagc  * Note that we support v3 keys here because they're needed for for
22793bf6008Sagc  * verification - the writer doesn't allow them, though
22893bf6008Sagc  */
2294b3a3e18Sagc static unsigned
write_pubkey_body(const pgp_pubkey_t * key,pgp_output_t * output)230fc1f8641Sagc write_pubkey_body(const pgp_pubkey_t *key, pgp_output_t *output)
23193bf6008Sagc {
232fc1f8641Sagc 	if (!(pgp_write_scalar(output, (unsigned)key->version, 1) &&
233fc1f8641Sagc 	      pgp_write_scalar(output, (unsigned)key->birthtime, 4))) {
2344b3a3e18Sagc 		return 0;
235bcfd8565Sagc 	}
23693bf6008Sagc 
237bcfd8565Sagc 	if (key->version != 4 &&
238fc1f8641Sagc 	    !pgp_write_scalar(output, key->days_valid, 2)) {
2394b3a3e18Sagc 		return 0;
240bcfd8565Sagc 	}
24193bf6008Sagc 
242fc1f8641Sagc 	if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) {
2434b3a3e18Sagc 		return 0;
244bcfd8565Sagc 	}
24593bf6008Sagc 
2462232f800Sagc 	switch (key->alg) {
247fc1f8641Sagc 	case PGP_PKA_DSA:
248fc1f8641Sagc 		return pgp_write_mpi(output, key->key.dsa.p) &&
249fc1f8641Sagc 			pgp_write_mpi(output, key->key.dsa.q) &&
250fc1f8641Sagc 			pgp_write_mpi(output, key->key.dsa.g) &&
251fc1f8641Sagc 			pgp_write_mpi(output, key->key.dsa.y);
25293bf6008Sagc 
253*0294a66bSjhigh 	case PGP_PKA_ECDSA:
254*0294a66bSjhigh 		return pgp_write(output, &key->key.ecdsa.len, 1) &&
255*0294a66bSjhigh 			pgp_write(output, key->key.ecdsa.oid, key->key.ecdsa.len) &&
256*0294a66bSjhigh 			pgp_write_mpi(output, key->key.ecdsa.p);
257*0294a66bSjhigh 
258fc1f8641Sagc 	case PGP_PKA_RSA:
259fc1f8641Sagc 	case PGP_PKA_RSA_ENCRYPT_ONLY:
260fc1f8641Sagc 	case PGP_PKA_RSA_SIGN_ONLY:
261fc1f8641Sagc 		return pgp_write_mpi(output, key->key.rsa.n) &&
262fc1f8641Sagc 			pgp_write_mpi(output, key->key.rsa.e);
26393bf6008Sagc 
264fc1f8641Sagc 	case PGP_PKA_ELGAMAL:
265fc1f8641Sagc 		return pgp_write_mpi(output, key->key.elgamal.p) &&
266fc1f8641Sagc 			pgp_write_mpi(output, key->key.elgamal.g) &&
267fc1f8641Sagc 			pgp_write_mpi(output, key->key.elgamal.y);
26893bf6008Sagc 
26993bf6008Sagc 	default:
270ed0df671Sagc 		(void) fprintf(stderr,
2713326c4c5Sagc 			"write_pubkey_body: bad algorithm\n");
27293bf6008Sagc 		break;
27393bf6008Sagc 	}
2744b3a3e18Sagc 	return 0;
27593bf6008Sagc }
27693bf6008Sagc 
27793bf6008Sagc /*
27857324b9fSagc  * Note that we support v3 keys here because they're needed for
27944647216Sagc  * verification.
28093bf6008Sagc  */
2814b3a3e18Sagc static unsigned
write_seckey_body(const pgp_seckey_t * key,const uint8_t * passphrase,const size_t pplen,pgp_output_t * output)282fc1f8641Sagc write_seckey_body(const pgp_seckey_t *key,
283b15ec256Sagc 		      const uint8_t *passphrase,
28493bf6008Sagc 		      const size_t pplen,
285fc1f8641Sagc 		      pgp_output_t *output)
28693bf6008Sagc {
28793bf6008Sagc 	/* RFC4880 Section 5.5.3 Secret-Key Packet Formats */
28893bf6008Sagc 
289fc1f8641Sagc 	pgp_crypt_t   crypted;
290fc1f8641Sagc 	pgp_hash_t    hash;
291b15ec256Sagc 	unsigned	done = 0;
292b15ec256Sagc 	unsigned	i = 0;
29305e6b0bbSagc 	uint8_t		*hashed;
294b15ec256Sagc 	uint8_t		sesskey[CAST_KEY_LENGTH];
29593bf6008Sagc 
29657324b9fSagc 	if (!write_pubkey_body(&key->pubkey, output)) {
2974b3a3e18Sagc 		return 0;
298bcfd8565Sagc 	}
299fc1f8641Sagc 	if (key->s2k_usage != PGP_S2KU_ENCRYPTED_AND_HASHED) {
3003326c4c5Sagc 		(void) fprintf(stderr, "write_seckey_body: s2k usage\n");
3014b3a3e18Sagc 		return 0;
302ed0df671Sagc 	}
303fc1f8641Sagc 	if (!pgp_write_scalar(output, (unsigned)key->s2k_usage, 1)) {
3044b3a3e18Sagc 		return 0;
305bcfd8565Sagc 	}
30693bf6008Sagc 
307fc1f8641Sagc 	if (key->alg != PGP_SA_CAST5) {
3083326c4c5Sagc 		(void) fprintf(stderr, "write_seckey_body: algorithm\n");
3094b3a3e18Sagc 		return 0;
310ed0df671Sagc 	}
311fc1f8641Sagc 	if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) {
3124b3a3e18Sagc 		return 0;
313bcfd8565Sagc 	}
31493bf6008Sagc 
315fc1f8641Sagc 	if (key->s2k_specifier != PGP_S2KS_SIMPLE &&
316fc1f8641Sagc 	    key->s2k_specifier != PGP_S2KS_SALTED) {
317bcfd8565Sagc 		/* = 1 \todo could also be iterated-and-salted */
3183326c4c5Sagc 		(void) fprintf(stderr, "write_seckey_body: s2k spec\n");
3194b3a3e18Sagc 		return 0;
320ed0df671Sagc 	}
321fc1f8641Sagc 	if (!pgp_write_scalar(output, (unsigned)key->s2k_specifier, 1)) {
3224b3a3e18Sagc 		return 0;
323bcfd8565Sagc 	}
324fc1f8641Sagc 	if (!pgp_write_scalar(output, (unsigned)key->hash_alg, 1)) {
3254b3a3e18Sagc 		return 0;
326bcfd8565Sagc 	}
32793bf6008Sagc 
32893bf6008Sagc 	switch (key->s2k_specifier) {
329fc1f8641Sagc 	case PGP_S2KS_SIMPLE:
33093bf6008Sagc 		/* nothing more to do */
33193bf6008Sagc 		break;
33293bf6008Sagc 
333fc1f8641Sagc 	case PGP_S2KS_SALTED:
33493bf6008Sagc 		/* 8-octet salt value */
335fc1f8641Sagc 		pgp_random(__UNCONST(&key->salt[0]), PGP_SALT_SIZE);
336fc1f8641Sagc 		if (!pgp_write(output, key->salt, PGP_SALT_SIZE)) {
3374b3a3e18Sagc 			return 0;
338bcfd8565Sagc 		}
33993bf6008Sagc 		break;
34093bf6008Sagc 
34193bf6008Sagc 		/*
342fc1f8641Sagc 		 * \todo case PGP_S2KS_ITERATED_AND_SALTED: // 8-octet salt
34393bf6008Sagc 		 * value // 1-octet count break;
34493bf6008Sagc 		 */
34593bf6008Sagc 
34693bf6008Sagc 	default:
347bcfd8565Sagc 		(void) fprintf(stderr,
348bcfd8565Sagc 			"invalid/unsupported s2k specifier %d\n",
349bcfd8565Sagc 			key->s2k_specifier);
3504b3a3e18Sagc 		return 0;
35193bf6008Sagc 	}
35293bf6008Sagc 
353fc1f8641Sagc 	if (!pgp_write(output, &key->iv[0], pgp_block_size(key->alg))) {
3544b3a3e18Sagc 		return 0;
355bcfd8565Sagc 	}
35693bf6008Sagc 
35793bf6008Sagc 	/*
35893bf6008Sagc 	 * create the session key for encrypting the algorithm-specific
35993bf6008Sagc 	 * fields
36093bf6008Sagc 	 */
36193bf6008Sagc 
36293bf6008Sagc 	switch (key->s2k_specifier) {
363fc1f8641Sagc 	case PGP_S2KS_SIMPLE:
364fc1f8641Sagc 	case PGP_S2KS_SALTED:
36593bf6008Sagc 		/* RFC4880: section 3.7.1.1 and 3.7.1.2 */
36693bf6008Sagc 
3675a83dba0Sagc 		for (done = 0, i = 0; done < CAST_KEY_LENGTH; i++) {
36805e6b0bbSagc 			unsigned 	hashsize;
3695a83dba0Sagc 			unsigned 	j;
37005e6b0bbSagc 			unsigned	needed;
37105e6b0bbSagc 			unsigned	size;
372b15ec256Sagc 			uint8_t		zero = 0;
37393bf6008Sagc 
37405e6b0bbSagc 			/* Hard-coded SHA1 for session key */
37505e6b0bbSagc 			pgp_hash_any(&hash, PGP_HASH_SHA1);
37605e6b0bbSagc 			hashsize = pgp_hash_size(key->hash_alg);
3772232f800Sagc 			needed = CAST_KEY_LENGTH - done;
37805e6b0bbSagc 			size = MIN(needed, hashsize);
37905e6b0bbSagc 			if ((hashed = calloc(1, hashsize)) == NULL) {
38005e6b0bbSagc 				(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
38105e6b0bbSagc 				return 0;
38205e6b0bbSagc 			}
3837affbacaSagc 			if (!hash.init(&hash)) {
3847affbacaSagc 				(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
3857affbacaSagc 				return 0;
3867affbacaSagc 			}
38793bf6008Sagc 
38893bf6008Sagc 			/* preload if iterating  */
38993bf6008Sagc 			for (j = 0; j < i; j++) {
39093bf6008Sagc 				/*
39193bf6008Sagc 				 * Coverity shows a DEADCODE error on this
39293bf6008Sagc 				 * line. This is expected since the hardcoded
39393bf6008Sagc 				 * use of SHA1 and CAST5 means that it will
39493bf6008Sagc 				 * not used. This will change however when
39593bf6008Sagc 				 * other algorithms are supported.
39693bf6008Sagc 				 */
39793bf6008Sagc 				hash.add(&hash, &zero, 1);
39893bf6008Sagc 			}
39993bf6008Sagc 
400fc1f8641Sagc 			if (key->s2k_specifier == PGP_S2KS_SALTED) {
401fc1f8641Sagc 				hash.add(&hash, key->salt, PGP_SALT_SIZE);
40293bf6008Sagc 			}
40369d4f30fSagc 			hash.add(&hash, passphrase, (unsigned)pplen);
40493bf6008Sagc 			hash.finish(&hash, hashed);
40593bf6008Sagc 
40693bf6008Sagc 			/*
40793bf6008Sagc 			 * if more in hash than is needed by session key, use
40893bf6008Sagc 			 * the leftmost octets
40993bf6008Sagc 			 */
41005e6b0bbSagc 			(void) memcpy(&sesskey[i * hashsize],
411d21b929eSagc 					hashed, (unsigned)size);
4125a83dba0Sagc 			done += (unsigned)size;
413ed0df671Sagc 			if (done > CAST_KEY_LENGTH) {
414ed0df671Sagc 				(void) fprintf(stderr,
4153326c4c5Sagc 					"write_seckey_body: short add\n");
4164b3a3e18Sagc 				return 0;
417ed0df671Sagc 			}
41893bf6008Sagc 		}
41993bf6008Sagc 
42093bf6008Sagc 		break;
42193bf6008Sagc 
42293bf6008Sagc 		/*
423fc1f8641Sagc 		 * \todo case PGP_S2KS_ITERATED_AND_SALTED: * 8-octet salt
42493bf6008Sagc 		 * value * 1-octet count break;
42593bf6008Sagc 		 */
42693bf6008Sagc 
42793bf6008Sagc 	default:
428bcfd8565Sagc 		(void) fprintf(stderr,
429bcfd8565Sagc 			"invalid/unsupported s2k specifier %d\n",
430bcfd8565Sagc 			key->s2k_specifier);
4314b3a3e18Sagc 		return 0;
43293bf6008Sagc 	}
43393bf6008Sagc 
43493bf6008Sagc 	/* use this session key to encrypt */
43593bf6008Sagc 
436fc1f8641Sagc 	pgp_crypt_any(&crypted, key->alg);
43793bf6008Sagc 	crypted.set_iv(&crypted, key->iv);
438f72138f8Sagc 	crypted.set_crypt_key(&crypted, sesskey);
439fc1f8641Sagc 	pgp_encrypt_init(&crypted);
44093bf6008Sagc 
441fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
442fc1f8641Sagc 		hexdump(stderr, "writing: iv=", key->iv, pgp_block_size(key->alg));
44347561e26Sagc 		hexdump(stderr, "key= ", sesskey, CAST_KEY_LENGTH);
444651dd288Sagc 		(void) fprintf(stderr, "\nturning encryption on...\n");
44593bf6008Sagc 	}
446fc1f8641Sagc 	pgp_push_enc_crypt(output, &crypted);
44793bf6008Sagc 
4482232f800Sagc 	switch (key->pubkey.alg) {
449fc1f8641Sagc 	case PGP_PKA_RSA:
450fc1f8641Sagc 	case PGP_PKA_RSA_ENCRYPT_ONLY:
451fc1f8641Sagc 	case PGP_PKA_RSA_SIGN_ONLY:
452fc1f8641Sagc 		if (!pgp_write_mpi(output, key->key.rsa.d) ||
453fc1f8641Sagc 		    !pgp_write_mpi(output, key->key.rsa.p) ||
454fc1f8641Sagc 		    !pgp_write_mpi(output, key->key.rsa.q) ||
455fc1f8641Sagc 		    !pgp_write_mpi(output, key->key.rsa.u)) {
456fc1f8641Sagc 			if (pgp_get_debug_level(__FILE__)) {
4573326c4c5Sagc 				(void) fprintf(stderr,
4583326c4c5Sagc 					"4 x mpi not written - problem\n");
45993bf6008Sagc 			}
4604b3a3e18Sagc 			return 0;
46193bf6008Sagc 		}
46293bf6008Sagc 		break;
463fc1f8641Sagc 	case PGP_PKA_DSA:
464fc1f8641Sagc 		return pgp_write_mpi(output, key->key.dsa.x);
465fc1f8641Sagc 	case PGP_PKA_ELGAMAL:
466fc1f8641Sagc 		return pgp_write_mpi(output, key->key.elgamal.x);
46793bf6008Sagc 	default:
4684b3a3e18Sagc 		return 0;
46993bf6008Sagc 	}
47093bf6008Sagc 
471fc1f8641Sagc 	if (!pgp_write(output, key->checkhash, PGP_CHECKHASH_SIZE)) {
4724b3a3e18Sagc 		return 0;
473bcfd8565Sagc 	}
47493bf6008Sagc 
475fc1f8641Sagc 	pgp_writer_pop(output);
47693bf6008Sagc 
4774b3a3e18Sagc 	return 1;
47893bf6008Sagc }
47993bf6008Sagc 
48057324b9fSagc /**
48157324b9fSagc  * \ingroup Core_WritePackets
48257324b9fSagc  * \brief Writes a Public Key packet
48357324b9fSagc  * \param key
48457324b9fSagc  * \param output
48557324b9fSagc  * \return 1 if OK, otherwise 0
48657324b9fSagc  */
48757324b9fSagc static unsigned
write_struct_pubkey(pgp_output_t * output,const pgp_pubkey_t * key)488fc1f8641Sagc write_struct_pubkey(pgp_output_t *output, const pgp_pubkey_t *key)
48957324b9fSagc {
490fc1f8641Sagc 	return pgp_write_ptag(output, PGP_PTAG_CT_PUBLIC_KEY) &&
491fc1f8641Sagc 		pgp_write_length(output, 1 + 4 + 1 + pubkey_length(key)) &&
49257324b9fSagc 		write_pubkey_body(key, output);
49357324b9fSagc }
49457324b9fSagc 
49593bf6008Sagc 
49693bf6008Sagc /**
49793bf6008Sagc    \ingroup HighLevel_KeyWrite
49893bf6008Sagc 
49993bf6008Sagc    \brief Writes a transferable PGP public key to the given output stream.
50093bf6008Sagc 
50193bf6008Sagc    \param keydata Key to be written
50293bf6008Sagc    \param armoured Flag is set for armoured output
50357324b9fSagc    \param output Output stream
50493bf6008Sagc 
50593bf6008Sagc */
50693bf6008Sagc 
5074b3a3e18Sagc unsigned
pgp_write_xfer_pubkey(pgp_output_t * output,const pgp_key_t * key,const unsigned armoured)508fc1f8641Sagc pgp_write_xfer_pubkey(pgp_output_t *output,
509fc1f8641Sagc 			const pgp_key_t *key,
510c64158a1Sagc 			const unsigned armoured)
51193bf6008Sagc {
512b15ec256Sagc 	unsigned    i, j;
51393bf6008Sagc 
51493bf6008Sagc 	if (armoured) {
515fc1f8641Sagc 		pgp_writer_push_armoured(output, PGP_PGP_PUBLIC_KEY_BLOCK);
51693bf6008Sagc 	}
51793bf6008Sagc 	/* public key */
51844647216Sagc 	if (!write_struct_pubkey(output, &key->key.pubkey)) {
51957324b9fSagc 		return 0;
520bcfd8565Sagc 	}
52193bf6008Sagc 
52293bf6008Sagc 	/* TODO: revocation signatures go here */
52393bf6008Sagc 
52493bf6008Sagc 	/* user ids and corresponding signatures */
5255aae2c74Sagc 	for (i = 0; i < key->uidc; i++) {
526fc1f8641Sagc 		if (!pgp_write_struct_userid(output, key->uids[i])) {
52757324b9fSagc 			return 0;
528bcfd8565Sagc 		}
5295aae2c74Sagc 		for (j = 0; j < key->packetc; j++) {
530fc1f8641Sagc 			if (!pgp_write(output, key->packets[j].raw, (unsigned)key->packets[j].length)) {
53157324b9fSagc 				return 0;
53293bf6008Sagc 			}
53393bf6008Sagc 		}
53493bf6008Sagc 	}
53593bf6008Sagc 
53693bf6008Sagc 	/* TODO: user attributes and corresponding signatures */
53793bf6008Sagc 
53893bf6008Sagc 	/*
53993bf6008Sagc 	 * subkey packets and corresponding signatures and optional
54093bf6008Sagc 	 * revocation
54193bf6008Sagc 	 */
54293bf6008Sagc 
54393bf6008Sagc 	if (armoured) {
544fc1f8641Sagc 		pgp_writer_info_finalise(&output->errors, &output->writer);
545fc1f8641Sagc 		pgp_writer_pop(output);
54693bf6008Sagc 	}
54757324b9fSagc 	return 1;
54893bf6008Sagc }
54993bf6008Sagc 
55093bf6008Sagc /**
55193bf6008Sagc    \ingroup HighLevel_KeyWrite
55293bf6008Sagc 
55393bf6008Sagc    \brief Writes a transferable PGP secret key to the given output stream.
55493bf6008Sagc 
55593bf6008Sagc    \param keydata Key to be written
55693bf6008Sagc    \param passphrase
55793bf6008Sagc    \param pplen
55893bf6008Sagc    \param armoured Flag is set for armoured output
55957324b9fSagc    \param output Output stream
56093bf6008Sagc 
56193bf6008Sagc */
56293bf6008Sagc 
5634b3a3e18Sagc unsigned
pgp_write_xfer_seckey(pgp_output_t * output,const pgp_key_t * key,const uint8_t * passphrase,const size_t pplen,unsigned armoured)564fc1f8641Sagc pgp_write_xfer_seckey(pgp_output_t *output,
565fc1f8641Sagc 				const pgp_key_t *key,
566b15ec256Sagc 				const uint8_t *passphrase,
56757324b9fSagc 				const size_t pplen,
56857324b9fSagc 				unsigned armoured)
56993bf6008Sagc {
5705a83dba0Sagc 	unsigned	i, j;
57193bf6008Sagc 
57293bf6008Sagc 	if (armoured) {
573fc1f8641Sagc 		pgp_writer_push_armoured(output, PGP_PGP_PRIVATE_KEY_BLOCK);
57493bf6008Sagc 	}
57593bf6008Sagc 	/* public key */
576fc1f8641Sagc 	if (!pgp_write_struct_seckey(&key->key.seckey, passphrase,
57757324b9fSagc 			pplen, output)) {
57857324b9fSagc 		return 0;
579bcfd8565Sagc 	}
58093bf6008Sagc 
58193bf6008Sagc 	/* TODO: revocation signatures go here */
58293bf6008Sagc 
58393bf6008Sagc 	/* user ids and corresponding signatures */
5845aae2c74Sagc 	for (i = 0; i < key->uidc; i++) {
585fc1f8641Sagc 		if (!pgp_write_struct_userid(output, key->uids[i])) {
58657324b9fSagc 			return 0;
587bcfd8565Sagc 		}
5885aae2c74Sagc 		for (j = 0; j < key->packetc; j++) {
589fc1f8641Sagc 			if (!pgp_write(output, key->packets[j].raw, (unsigned)key->packets[j].length)) {
59057324b9fSagc 				return 0;
59193bf6008Sagc 			}
59293bf6008Sagc 		}
59393bf6008Sagc 	}
59493bf6008Sagc 
59593bf6008Sagc 	/* TODO: user attributes and corresponding signatures */
59693bf6008Sagc 
59793bf6008Sagc 	/*
59893bf6008Sagc 	 * subkey packets and corresponding signatures and optional
59993bf6008Sagc 	 * revocation
60093bf6008Sagc 	 */
60193bf6008Sagc 
60293bf6008Sagc 	if (armoured) {
603fc1f8641Sagc 		pgp_writer_info_finalise(&output->errors, &output->writer);
604fc1f8641Sagc 		pgp_writer_pop(output);
60593bf6008Sagc 	}
60657324b9fSagc 	return 1;
60793bf6008Sagc }
60893bf6008Sagc 
60993bf6008Sagc /**
61093bf6008Sagc  * \ingroup Core_WritePackets
61193bf6008Sagc  * \brief Writes one RSA public key packet.
61293bf6008Sagc  * \param t Creation time
61393bf6008Sagc  * \param n RSA public modulus
61493bf6008Sagc  * \param e RSA public encryption exponent
61557324b9fSagc  * \param output Writer settings
61693bf6008Sagc  *
6174b3a3e18Sagc  * \return 1 if OK, otherwise 0
61893bf6008Sagc  */
61993bf6008Sagc 
6204b3a3e18Sagc unsigned
pgp_write_rsa_pubkey(time_t t,const BIGNUM * n,const BIGNUM * e,pgp_output_t * output)621fc1f8641Sagc pgp_write_rsa_pubkey(time_t t, const BIGNUM *n,
62293bf6008Sagc 			 const BIGNUM *e,
623fc1f8641Sagc 			 pgp_output_t *output)
62493bf6008Sagc {
625fc1f8641Sagc 	pgp_pubkey_t key;
62693bf6008Sagc 
627fc1f8641Sagc 	pgp_fast_create_rsa_pubkey(&key, t, __UNCONST(n), __UNCONST(e));
62857324b9fSagc 	return write_struct_pubkey(output, &key);
62993bf6008Sagc }
63093bf6008Sagc 
63193bf6008Sagc /**
63293bf6008Sagc  * \ingroup Core_Create
63393bf6008Sagc  * \param out
63493bf6008Sagc  * \param key
63593bf6008Sagc  * \param make_packet
63693bf6008Sagc  */
63793bf6008Sagc 
63893bf6008Sagc void
pgp_build_pubkey(pgp_memory_t * out,const pgp_pubkey_t * key,unsigned make_packet)639fc1f8641Sagc pgp_build_pubkey(pgp_memory_t *out, const pgp_pubkey_t *key,
6404b3a3e18Sagc 		     unsigned make_packet)
64193bf6008Sagc {
642fc1f8641Sagc 	pgp_output_t *output;
64393bf6008Sagc 
644fc1f8641Sagc 	output = pgp_output_new();
645fc1f8641Sagc 	pgp_memory_init(out, 128);
646fc1f8641Sagc 	pgp_writer_set_memory(output, out);
64757324b9fSagc 	write_pubkey_body(key, output);
648bcfd8565Sagc 	if (make_packet) {
649fc1f8641Sagc 		pgp_memory_make_packet(out, PGP_PTAG_CT_PUBLIC_KEY);
650bcfd8565Sagc 	}
651fc1f8641Sagc 	pgp_output_delete(output);
65293bf6008Sagc }
65393bf6008Sagc 
65493bf6008Sagc /**
65593bf6008Sagc  * \ingroup Core_Create
65693bf6008Sagc  *
65793bf6008Sagc  * Create an RSA secret key structure. If a parameter is marked as
65893bf6008Sagc  * [OPTIONAL], then it can be omitted and will be calculated from
65941335e2dSagc  * other params - or, in the case of e, will default to 0x10001.
66093bf6008Sagc  *
66193bf6008Sagc  * Parameters are _not_ copied, so will be freed if the structure is
66293bf6008Sagc  * freed.
66393bf6008Sagc  *
66493bf6008Sagc  * \param key The key structure to be initialised.
66593bf6008Sagc  * \param t
66693bf6008Sagc  * \param d The RSA parameter d (=e^-1 mod (p-1)(q-1)) [OPTIONAL]
66793bf6008Sagc  * \param p The RSA parameter p
66893bf6008Sagc  * \param q The RSA parameter q (q > p)
66993bf6008Sagc  * \param u The RSA parameter u (=p^-1 mod q) [OPTIONAL]
67093bf6008Sagc  * \param n The RSA public parameter n (=p*q) [OPTIONAL]
67193bf6008Sagc  * \param e The RSA public parameter e */
67293bf6008Sagc 
67393bf6008Sagc void
pgp_fast_create_rsa_seckey(pgp_seckey_t * key,time_t t,BIGNUM * d,BIGNUM * p,BIGNUM * q,BIGNUM * u,BIGNUM * n,BIGNUM * e)674fc1f8641Sagc pgp_fast_create_rsa_seckey(pgp_seckey_t *key, time_t t,
67593bf6008Sagc 			     BIGNUM *d, BIGNUM *p, BIGNUM *q, BIGNUM *u,
67693bf6008Sagc 			       BIGNUM *n, BIGNUM *e)
67793bf6008Sagc {
678fc1f8641Sagc 	pgp_fast_create_rsa_pubkey(&key->pubkey, t, n, e);
67993bf6008Sagc 
68093bf6008Sagc 	/* XXX: calculate optionals */
68193bf6008Sagc 	key->key.rsa.d = d;
68293bf6008Sagc 	key->key.rsa.p = p;
68393bf6008Sagc 	key->key.rsa.q = q;
68493bf6008Sagc 	key->key.rsa.u = u;
68593bf6008Sagc 
686fc1f8641Sagc 	key->s2k_usage = PGP_S2KU_NONE;
68793bf6008Sagc 
68893bf6008Sagc 	/* XXX: sanity check and add errors... */
68993bf6008Sagc }
69093bf6008Sagc 
69193bf6008Sagc /**
69293bf6008Sagc  * \ingroup Core_WritePackets
69393bf6008Sagc  * \brief Writes a Secret Key packet.
69493bf6008Sagc  * \param key The secret key
69593bf6008Sagc  * \param passphrase The passphrase
69693bf6008Sagc  * \param pplen Length of passphrase
69757324b9fSagc  * \param output
6984b3a3e18Sagc  * \return 1 if OK; else 0
69993bf6008Sagc  */
7004b3a3e18Sagc unsigned
pgp_write_struct_seckey(const pgp_seckey_t * key,const uint8_t * passphrase,const size_t pplen,pgp_output_t * output)701fc1f8641Sagc pgp_write_struct_seckey(const pgp_seckey_t *key,
702b15ec256Sagc 			    const uint8_t *passphrase,
70393bf6008Sagc 			    const size_t pplen,
704fc1f8641Sagc 			    pgp_output_t *output)
70593bf6008Sagc {
70693bf6008Sagc 	int             length = 0;
70793bf6008Sagc 
708ed0df671Sagc 	if (key->pubkey.version != 4) {
709ed0df671Sagc 		(void) fprintf(stderr,
710fc1f8641Sagc 			"pgp_write_struct_seckey: public key version\n");
7114b3a3e18Sagc 		return 0;
712ed0df671Sagc 	}
71393bf6008Sagc 
71493bf6008Sagc 	/* Ref: RFC4880 Section 5.5.3 */
71593bf6008Sagc 
716bcfd8565Sagc 	/* pubkey, excluding MPIs */
71793bf6008Sagc 	length += 1 + 4 + 1 + 1;
71893bf6008Sagc 
71993bf6008Sagc 	/* s2k usage */
72093bf6008Sagc 	length += 1;
72193bf6008Sagc 
72293bf6008Sagc 	switch (key->s2k_usage) {
723fc1f8641Sagc 	case PGP_S2KU_NONE:
72493bf6008Sagc 		/* nothing to add */
72593bf6008Sagc 		break;
72693bf6008Sagc 
727fc1f8641Sagc 	case PGP_S2KU_ENCRYPTED_AND_HASHED:	/* 254 */
728fc1f8641Sagc 	case PGP_S2KU_ENCRYPTED:	/* 255 */
72993bf6008Sagc 
73093bf6008Sagc 		/* Ref: RFC4880 Section 3.7 */
73193bf6008Sagc 		length += 1;	/* s2k_specifier */
73293bf6008Sagc 
73393bf6008Sagc 		switch (key->s2k_specifier) {
734fc1f8641Sagc 		case PGP_S2KS_SIMPLE:
73593bf6008Sagc 			length += 1;	/* hash algorithm */
73693bf6008Sagc 			break;
73793bf6008Sagc 
738fc1f8641Sagc 		case PGP_S2KS_SALTED:
73993bf6008Sagc 			length += 1 + 8;	/* hash algorithm + salt */
74093bf6008Sagc 			break;
74193bf6008Sagc 
742fc1f8641Sagc 		case PGP_S2KS_ITERATED_AND_SALTED:
74393bf6008Sagc 			length += 1 + 8 + 1;	/* hash algorithm, salt +
74493bf6008Sagc 						 * count */
74593bf6008Sagc 			break;
74693bf6008Sagc 
74793bf6008Sagc 		default:
748ed0df671Sagc 			(void) fprintf(stderr,
749fc1f8641Sagc 				"pgp_write_struct_seckey: s2k spec\n");
7504b3a3e18Sagc 			return 0;
75193bf6008Sagc 		}
75293bf6008Sagc 		break;
75393bf6008Sagc 
75493bf6008Sagc 	default:
755ed0df671Sagc 		(void) fprintf(stderr,
756fc1f8641Sagc 			"pgp_write_struct_seckey: s2k usage\n");
7574b3a3e18Sagc 		return 0;
75893bf6008Sagc 	}
75993bf6008Sagc 
76093bf6008Sagc 	/* IV */
7614b3a3e18Sagc 	if (key->s2k_usage) {
762fc1f8641Sagc 		length += pgp_block_size(key->alg);
76393bf6008Sagc 	}
76493bf6008Sagc 	/* checksum or hash */
76593bf6008Sagc 	switch (key->s2k_usage) {
766fc1f8641Sagc 	case PGP_S2KU_NONE:
767fc1f8641Sagc 	case PGP_S2KU_ENCRYPTED:
76893bf6008Sagc 		length += 2;
76993bf6008Sagc 		break;
77093bf6008Sagc 
771fc1f8641Sagc 	case PGP_S2KU_ENCRYPTED_AND_HASHED:
772fc1f8641Sagc 		length += PGP_CHECKHASH_SIZE;
77393bf6008Sagc 		break;
77493bf6008Sagc 
77593bf6008Sagc 	default:
776ed0df671Sagc 		(void) fprintf(stderr,
777fc1f8641Sagc 			"pgp_write_struct_seckey: s2k cksum usage\n");
7784b3a3e18Sagc 		return 0;
77993bf6008Sagc 	}
78093bf6008Sagc 
78193bf6008Sagc 	/* secret key and public key MPIs */
7825a83dba0Sagc 	length += (unsigned)seckey_length(key);
78393bf6008Sagc 
784fc1f8641Sagc 	return pgp_write_ptag(output, PGP_PTAG_CT_SECRET_KEY) &&
785fc1f8641Sagc 		/* pgp_write_length(output,1+4+1+1+seckey_length(key)+2) && */
786fc1f8641Sagc 		pgp_write_length(output, (unsigned)length) &&
78757324b9fSagc 		write_seckey_body(key, passphrase, pplen, output);
78893bf6008Sagc }
78993bf6008Sagc 
79093bf6008Sagc /**
79193bf6008Sagc  * \ingroup Core_Create
79293bf6008Sagc  *
793fc1f8641Sagc  * \brief Create a new pgp_output_t structure.
79493bf6008Sagc  *
79593bf6008Sagc  * \return the new structure.
796fc1f8641Sagc  * \note It is the responsiblity of the caller to call pgp_output_delete().
797fc1f8641Sagc  * \sa pgp_output_delete()
79893bf6008Sagc  */
799fc1f8641Sagc pgp_output_t *
pgp_output_new(void)800fc1f8641Sagc pgp_output_new(void)
80193bf6008Sagc {
802fc1f8641Sagc 	return calloc(1, sizeof(pgp_output_t));
80393bf6008Sagc }
80493bf6008Sagc 
80593bf6008Sagc /**
80693bf6008Sagc  * \ingroup Core_Create
807fc1f8641Sagc  * \brief Delete an pgp_output_t strucut and associated resources.
80893bf6008Sagc  *
809fc1f8641Sagc  * Delete an pgp_output_t structure. If a writer is active, then
81093bf6008Sagc  * that is also deleted.
81193bf6008Sagc  *
81293bf6008Sagc  * \param info the structure to be deleted.
81393bf6008Sagc  */
81493bf6008Sagc void
pgp_output_delete(pgp_output_t * output)815fc1f8641Sagc pgp_output_delete(pgp_output_t *output)
81693bf6008Sagc {
817fc1f8641Sagc 	pgp_writer_info_delete(&output->writer);
8185a83dba0Sagc 	free(output);
81993bf6008Sagc }
82093bf6008Sagc 
82193bf6008Sagc /**
82293bf6008Sagc  \ingroup Core_Create
82393bf6008Sagc  \brief Calculate the checksum for a session key
8242232f800Sagc  \param sesskey Session Key to use
82593bf6008Sagc  \param cs Checksum to be written
8264b3a3e18Sagc  \return 1 if OK; else 0
82793bf6008Sagc */
8284b3a3e18Sagc unsigned
pgp_calc_sesskey_checksum(pgp_pk_sesskey_t * sesskey,uint8_t cs[2])829fc1f8641Sagc pgp_calc_sesskey_checksum(pgp_pk_sesskey_t *sesskey, uint8_t cs[2])
83093bf6008Sagc {
831b15ec256Sagc 	uint32_t   checksum = 0;
832b15ec256Sagc 	unsigned    i;
83393bf6008Sagc 
834fc1f8641Sagc 	if (!pgp_is_sa_supported(sesskey->symm_alg)) {
8354b3a3e18Sagc 		return 0;
836bcfd8565Sagc 	}
83793bf6008Sagc 
838fc1f8641Sagc 	for (i = 0; i < pgp_key_size(sesskey->symm_alg); i++) {
8392232f800Sagc 		checksum += sesskey->key[i];
84093bf6008Sagc 	}
84193bf6008Sagc 	checksum = checksum % 65536;
84293bf6008Sagc 
843b15ec256Sagc 	cs[0] = (uint8_t)((checksum >> 8) & 0xff);
844b15ec256Sagc 	cs[1] = (uint8_t)(checksum & 0xff);
84593bf6008Sagc 
846fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
84747561e26Sagc 		hexdump(stderr, "nm buf checksum:", cs, 2);
848efdd9dbaSagc 	}
8494b3a3e18Sagc 	return 1;
85093bf6008Sagc }
85193bf6008Sagc 
8524b3a3e18Sagc static unsigned
create_unencoded_m_buf(pgp_pk_sesskey_t * sesskey,pgp_crypt_t * cipherinfo,uint8_t * m_buf)853fc1f8641Sagc create_unencoded_m_buf(pgp_pk_sesskey_t *sesskey, pgp_crypt_t *cipherinfo, uint8_t *m_buf)
85493bf6008Sagc {
855f7745f84Sagc 	unsigned	i;
85693bf6008Sagc 
857f7745f84Sagc 	/* m_buf is the buffer which will be encoded in PKCS#1 block
858f7745f84Sagc 	* encoding to form the "m" value used in the Public Key
859f7745f84Sagc 	* Encrypted Session Key Packet as defined in RFC Section 5.1
860f7745f84Sagc 	* "Public-Key Encrypted Session Key Packet"
86193bf6008Sagc 	 */
8622232f800Sagc 	m_buf[0] = sesskey->symm_alg;
863f7745f84Sagc 	for (i = 0; i < cipherinfo->keysize ; i++) {
8645a83dba0Sagc 		/* XXX - Flexelint - Warning 679: Suspicious Truncation in arithmetic expression combining with pointer */
8652232f800Sagc 		m_buf[1 + i] = sesskey->key[i];
86693bf6008Sagc 	}
86793bf6008Sagc 
868fc1f8641Sagc 	return pgp_calc_sesskey_checksum(sesskey,
869f7745f84Sagc 				m_buf + 1 + cipherinfo->keysize);
87093bf6008Sagc }
87193bf6008Sagc 
87293bf6008Sagc /**
87393bf6008Sagc \ingroup Core_Create
87493bf6008Sagc \brief implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC
87593bf6008Sagc \param M
87693bf6008Sagc \param mLen
8770c310959Sagc \param pubkey
87893bf6008Sagc \param EM
8794b3a3e18Sagc \return 1 if OK; else 0
88093bf6008Sagc */
8814b3a3e18Sagc unsigned
encode_m_buf(const uint8_t * M,size_t mLen,const pgp_pubkey_t * pubkey,uint8_t * EM)882fc1f8641Sagc encode_m_buf(const uint8_t *M, size_t mLen, const pgp_pubkey_t * pubkey,
883b15ec256Sagc 	     uint8_t *EM)
88493bf6008Sagc {
885b15ec256Sagc 	unsigned    k;
88693bf6008Sagc 	unsigned        i;
88793bf6008Sagc 
88893bf6008Sagc 	/* implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC */
889520c968fSagc 	switch (pubkey->alg) {
890fc1f8641Sagc 	case PGP_PKA_RSA:
8915a83dba0Sagc 		k = (unsigned)BN_num_bytes(pubkey->key.rsa.n);
89293bf6008Sagc 		if (mLen > k - 11) {
893ed0df671Sagc 			(void) fprintf(stderr, "encode_m_buf: message too long\n");
8944b3a3e18Sagc 			return 0;
89593bf6008Sagc 		}
89637d8b79bSagc 		break;
897fc1f8641Sagc 	case PGP_PKA_DSA:
898fc1f8641Sagc 	case PGP_PKA_ELGAMAL:
89937d8b79bSagc 		k = (unsigned)BN_num_bytes(pubkey->key.elgamal.p);
90037d8b79bSagc 		if (mLen > k - 11) {
90137d8b79bSagc 			(void) fprintf(stderr, "encode_m_buf: message too long\n");
90237d8b79bSagc 			return 0;
90337d8b79bSagc 		}
90437d8b79bSagc 		break;
90537d8b79bSagc 	default:
90637d8b79bSagc 		(void) fprintf(stderr, "encode_m_buf: pubkey algorithm\n");
90737d8b79bSagc 		return 0;
90837d8b79bSagc 	}
90993bf6008Sagc 	/* these two bytes defined by RFC */
91093bf6008Sagc 	EM[0] = 0x00;
91193bf6008Sagc 	EM[1] = 0x02;
91293bf6008Sagc 	/* add non-zero random bytes of length k - mLen -3 */
9135a83dba0Sagc 	for (i = 2; i < (k - mLen) - 1; ++i) {
914bcfd8565Sagc 		do {
915fc1f8641Sagc 			pgp_random(EM + i, 1);
916bcfd8565Sagc 		} while (EM[i] == 0);
917bcfd8565Sagc 	}
918ed0df671Sagc 	if (i < 8 + 2) {
919ed0df671Sagc 		(void) fprintf(stderr, "encode_m_buf: bad i len\n");
9204b3a3e18Sagc 		return 0;
921ed0df671Sagc 	}
92293bf6008Sagc 	EM[i++] = 0;
92393bf6008Sagc 	(void) memcpy(EM + i, M, mLen);
924fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
92547561e26Sagc 		hexdump(stderr, "Encoded Message:", EM, mLen);
92693bf6008Sagc 	}
9274b3a3e18Sagc 	return 1;
92893bf6008Sagc }
92993bf6008Sagc 
93093bf6008Sagc /**
93193bf6008Sagc  \ingroup Core_Create
932fc1f8641Sagc \brief Creates an pgp_pk_sesskey_t struct from keydata
93393bf6008Sagc \param key Keydata to use
934fc1f8641Sagc \return pgp_pk_sesskey_t struct
93593bf6008Sagc \note It is the caller's responsiblity to free the returned pointer
93693bf6008Sagc \note Currently hard-coded to use CAST5
93793bf6008Sagc \note Currently hard-coded to use RSA
93893bf6008Sagc */
939fc1f8641Sagc pgp_pk_sesskey_t *
pgp_create_pk_sesskey(const pgp_key_t * key,const char * ciphername)940fc1f8641Sagc pgp_create_pk_sesskey(const pgp_key_t *key, const char *ciphername)
94193bf6008Sagc {
94293bf6008Sagc 	/*
94393bf6008Sagc          * Creates a random session key and encrypts it for the given key
94493bf6008Sagc          *
94593bf6008Sagc          * Encryption used is PK,
94693bf6008Sagc          * can be any, we're hardcoding RSA for now
94793bf6008Sagc          */
94893bf6008Sagc 
949fc1f8641Sagc 	const pgp_pubkey_t	*pubkey;
950fc1f8641Sagc 	pgp_pk_sesskey_t	*sesskey;
951fc1f8641Sagc 	pgp_symm_alg_t	 cipher;
9529b987001Sagc 	const uint8_t		*id;
953fc1f8641Sagc 	pgp_crypt_t		 cipherinfo;
954f7745f84Sagc 	uint8_t			*unencoded_m_buf;
955b15ec256Sagc 	uint8_t			*encoded_m_buf;
9565a83dba0Sagc 	size_t			 sz_encoded_m_buf;
9575a83dba0Sagc 
9589b987001Sagc 	if (memcmp(key->encid, "\0\0\0\0\0\0\0\0", 8) == 0) {
959fc1f8641Sagc 		pubkey = pgp_get_pubkey(key);
9609b987001Sagc 		id = key->sigid;
9619b987001Sagc 	} else {
9629b987001Sagc 		pubkey = &key->enckey;
9639b987001Sagc 		id = key->encid;
9649b987001Sagc 	}
965f7745f84Sagc 	/* allocate unencoded_m_buf here */
966f7745f84Sagc 	(void) memset(&cipherinfo, 0x0, sizeof(cipherinfo));
967fc1f8641Sagc 	pgp_crypt_any(&cipherinfo,
968fc1f8641Sagc 		cipher = pgp_str_to_cipher((ciphername) ? ciphername : "cast5"));
969f7745f84Sagc 	unencoded_m_buf = calloc(1, cipherinfo.keysize + 1 + 2);
970f7745f84Sagc 	if (unencoded_m_buf == NULL) {
971f7745f84Sagc 		(void) fprintf(stderr,
972fc1f8641Sagc 			"pgp_create_pk_sesskey: can't allocate\n");
973f7745f84Sagc 		return NULL;
974f7745f84Sagc 	}
97537d8b79bSagc 	switch(pubkey->alg) {
976fc1f8641Sagc 	case PGP_PKA_RSA:
9775a83dba0Sagc 		sz_encoded_m_buf = BN_num_bytes(pubkey->key.rsa.n);
97837d8b79bSagc 		break;
979fc1f8641Sagc 	case PGP_PKA_DSA:
980fc1f8641Sagc 	case PGP_PKA_ELGAMAL:
98137d8b79bSagc 		sz_encoded_m_buf = BN_num_bytes(pubkey->key.elgamal.p);
98237d8b79bSagc 		break;
98337d8b79bSagc 	default:
98437d8b79bSagc 		sz_encoded_m_buf = 0;
98537d8b79bSagc 		break;
98637d8b79bSagc 	}
9875a83dba0Sagc 	if ((encoded_m_buf = calloc(1, sz_encoded_m_buf)) == NULL) {
9885a83dba0Sagc 		(void) fprintf(stderr,
989fc1f8641Sagc 			"pgp_create_pk_sesskey: can't allocate\n");
990f7745f84Sagc 		free(unencoded_m_buf);
9915a83dba0Sagc 		return NULL;
9925a83dba0Sagc 	}
9935a83dba0Sagc 	if ((sesskey = calloc(1, sizeof(*sesskey))) == NULL) {
9945a83dba0Sagc 		(void) fprintf(stderr,
995fc1f8641Sagc 			"pgp_create_pk_sesskey: can't allocate\n");
996f7745f84Sagc 		free(unencoded_m_buf);
9970aa60872Sagc 		free(encoded_m_buf);
9985a83dba0Sagc 		return NULL;
9995a83dba0Sagc 	}
1000fc1f8641Sagc 	if (key->type != PGP_PTAG_CT_PUBLIC_KEY) {
1001ed0df671Sagc 		(void) fprintf(stderr,
1002fc1f8641Sagc 			"pgp_create_pk_sesskey: bad type\n");
1003f7745f84Sagc 		free(unencoded_m_buf);
10040aa60872Sagc 		free(encoded_m_buf);
10050aa60872Sagc 		free(sesskey);
1006ed0df671Sagc 		return NULL;
1007ed0df671Sagc 	}
1008fc1f8641Sagc 	sesskey->version = PGP_PKSK_V3;
10099b987001Sagc 	(void) memcpy(sesskey->key_id, id, sizeof(sesskey->key_id));
101093bf6008Sagc 
1011fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
101237d8b79bSagc 		hexdump(stderr, "Encrypting for keyid", id, sizeof(sesskey->key_id));
101393bf6008Sagc 	}
10149b987001Sagc 	switch (pubkey->alg) {
1015fc1f8641Sagc 	case PGP_PKA_RSA:
1016fc1f8641Sagc 	case PGP_PKA_DSA:
1017fc1f8641Sagc 	case PGP_PKA_ELGAMAL:
1018520c968fSagc 		break;
1019520c968fSagc 	default:
1020ed0df671Sagc 		(void) fprintf(stderr,
1021fc1f8641Sagc 			"pgp_create_pk_sesskey: bad pubkey algorithm\n");
1022f7745f84Sagc 		free(unencoded_m_buf);
10230aa60872Sagc 		free(encoded_m_buf);
10240aa60872Sagc 		free(sesskey);
1025ed0df671Sagc 		return NULL;
1026ed0df671Sagc 	}
10279b987001Sagc 	sesskey->alg = pubkey->alg;
102893bf6008Sagc 
1029f7745f84Sagc 	sesskey->symm_alg = cipher;
1030fc1f8641Sagc 	pgp_random(sesskey->key, cipherinfo.keysize);
103193bf6008Sagc 
1032fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
1033f7745f84Sagc 		hexdump(stderr, "sesskey created", sesskey->key,
1034f7745f84Sagc 			cipherinfo.keysize + 1 + 2);
103593bf6008Sagc 	}
1036f7745f84Sagc 	if (create_unencoded_m_buf(sesskey, &cipherinfo, &unencoded_m_buf[0]) == 0) {
1037f7745f84Sagc 		free(unencoded_m_buf);
10385a83dba0Sagc 		free(encoded_m_buf);
10390aa60872Sagc 		free(sesskey);
104093bf6008Sagc 		return NULL;
104193bf6008Sagc 	}
1042fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
1043f7745f84Sagc 		hexdump(stderr, "uuencoded m buf", unencoded_m_buf, cipherinfo.keysize + 1 + 2);
1044bcfd8565Sagc 	}
1045f7745f84Sagc 	encode_m_buf(unencoded_m_buf, cipherinfo.keysize + 1 + 2, pubkey, encoded_m_buf);
104693bf6008Sagc 
104793bf6008Sagc 	/* and encrypt it */
1048520c968fSagc 	switch (key->key.pubkey.alg) {
1049fc1f8641Sagc 	case PGP_PKA_RSA:
1050fc1f8641Sagc 		if (!pgp_rsa_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey,
105141335e2dSagc 				&sesskey->params)) {
1052f7745f84Sagc 			free(unencoded_m_buf);
10535a83dba0Sagc 			free(encoded_m_buf);
10540aa60872Sagc 			free(sesskey);
105593bf6008Sagc 			return NULL;
105693bf6008Sagc 		}
1057520c968fSagc 		break;
1058fc1f8641Sagc 	case PGP_PKA_DSA:
1059fc1f8641Sagc 	case PGP_PKA_ELGAMAL:
1060fc1f8641Sagc 		if (!pgp_elgamal_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey,
106137d8b79bSagc 				&sesskey->params)) {
1062f7745f84Sagc 			free(unencoded_m_buf);
1063520c968fSagc 			free(encoded_m_buf);
1064520c968fSagc 			free(sesskey);
1065520c968fSagc 			return NULL;
106637d8b79bSagc 		}
106737d8b79bSagc 		break;
1068520c968fSagc 	default:
1069520c968fSagc 		/* will not get here - for lint only */
1070520c968fSagc 		break;
1071520c968fSagc 	}
1072f7745f84Sagc 	free(unencoded_m_buf);
10735a83dba0Sagc 	free(encoded_m_buf);
10742232f800Sagc 	return sesskey;
107593bf6008Sagc }
107693bf6008Sagc 
107793bf6008Sagc /**
107893bf6008Sagc \ingroup Core_WritePackets
107993bf6008Sagc \brief Writes Public Key Session Key packet
108093bf6008Sagc \param info Write settings
108193bf6008Sagc \param pksk Public Key Session Key to write out
10824b3a3e18Sagc \return 1 if OK; else 0
108393bf6008Sagc */
10844b3a3e18Sagc unsigned
pgp_write_pk_sesskey(pgp_output_t * output,pgp_pk_sesskey_t * pksk)1085fc1f8641Sagc pgp_write_pk_sesskey(pgp_output_t *output, pgp_pk_sesskey_t *pksk)
108693bf6008Sagc {
10875a83dba0Sagc 	/* XXX - Flexelint - Pointer parameter 'pksk' (line 1076) could be declared as pointing to const */
1088ed0df671Sagc 	if (pksk == NULL) {
1089ed0df671Sagc 		(void) fprintf(stderr,
1090fc1f8641Sagc 			"pgp_write_pk_sesskey: NULL pksk\n");
10914b3a3e18Sagc 		return 0;
1092ed0df671Sagc 	}
1093520c968fSagc 	switch (pksk->alg) {
1094fc1f8641Sagc 	case PGP_PKA_RSA:
1095fc1f8641Sagc 		return pgp_write_ptag(output, PGP_PTAG_CT_PK_SESSION_KEY) &&
1096fc1f8641Sagc 			pgp_write_length(output, (unsigned)(1 + 8 + 1 +
109741335e2dSagc 				BN_num_bytes(pksk->params.rsa.encrypted_m) + 2)) &&
1098fc1f8641Sagc 			pgp_write_scalar(output, (unsigned)pksk->version, 1) &&
1099fc1f8641Sagc 			pgp_write(output, pksk->key_id, 8) &&
1100fc1f8641Sagc 			pgp_write_scalar(output, (unsigned)pksk->alg, 1) &&
1101fc1f8641Sagc 			pgp_write_mpi(output, pksk->params.rsa.encrypted_m)
1102fc1f8641Sagc 			/* ??	&& pgp_write_scalar(output, 0, 2); */
110393bf6008Sagc 			;
1104fc1f8641Sagc 	case PGP_PKA_DSA:
1105fc1f8641Sagc 	case PGP_PKA_ELGAMAL:
1106fc1f8641Sagc 		return pgp_write_ptag(output, PGP_PTAG_CT_PK_SESSION_KEY) &&
1107fc1f8641Sagc 			pgp_write_length(output, (unsigned)(1 + 8 + 1 +
110837d8b79bSagc 				BN_num_bytes(pksk->params.elgamal.g_to_k) + 2 +
110937d8b79bSagc 				BN_num_bytes(pksk->params.elgamal.encrypted_m) + 2)) &&
1110fc1f8641Sagc 			pgp_write_scalar(output, (unsigned)pksk->version, 1) &&
1111fc1f8641Sagc 			pgp_write(output, pksk->key_id, 8) &&
1112fc1f8641Sagc 			pgp_write_scalar(output, (unsigned)pksk->alg, 1) &&
1113fc1f8641Sagc 			pgp_write_mpi(output, pksk->params.elgamal.g_to_k) &&
1114fc1f8641Sagc 			pgp_write_mpi(output, pksk->params.elgamal.encrypted_m)
1115fc1f8641Sagc 			/* ??	&& pgp_write_scalar(output, 0, 2); */
111637d8b79bSagc 			;
1117520c968fSagc 	default:
1118520c968fSagc 		(void) fprintf(stderr,
1119fc1f8641Sagc 			"pgp_write_pk_sesskey: bad algorithm\n");
1120520c968fSagc 		return 0;
1121520c968fSagc 	}
112293bf6008Sagc }
112393bf6008Sagc 
112493bf6008Sagc /**
112593bf6008Sagc \ingroup Core_WritePackets
112693bf6008Sagc \brief Writes MDC packet
112793bf6008Sagc \param hashed Hash for MDC
112857324b9fSagc \param output Write settings
11294b3a3e18Sagc \return 1 if OK; else 0
113093bf6008Sagc */
113193bf6008Sagc 
11324b3a3e18Sagc unsigned
pgp_write_mdc(pgp_output_t * output,const uint8_t * hashed)1133fc1f8641Sagc pgp_write_mdc(pgp_output_t *output, const uint8_t *hashed)
113493bf6008Sagc {
113593bf6008Sagc 	/* write it out */
1136fc1f8641Sagc 	return pgp_write_ptag(output, PGP_PTAG_CT_MDC) &&
1137fc1f8641Sagc 		pgp_write_length(output, PGP_SHA1_HASH_SIZE) &&
1138fc1f8641Sagc 		pgp_write(output, hashed, PGP_SHA1_HASH_SIZE);
113993bf6008Sagc }
114093bf6008Sagc 
114193bf6008Sagc /**
114293bf6008Sagc \ingroup Core_WritePackets
114393bf6008Sagc \brief Writes Literal Data packet from buffer
114493bf6008Sagc \param data Buffer to write out
114593bf6008Sagc \param maxlen Max length of buffer
114693bf6008Sagc \param type Literal Data Type
114757324b9fSagc \param output Write settings
11484b3a3e18Sagc \return 1 if OK; else 0
114993bf6008Sagc */
11504b3a3e18Sagc unsigned
pgp_write_litdata(pgp_output_t * output,const uint8_t * data,const int maxlen,const pgp_litdata_enum type)1151fc1f8641Sagc pgp_write_litdata(pgp_output_t *output,
1152b15ec256Sagc 			const uint8_t *data,
115393bf6008Sagc 			const int maxlen,
1154fc1f8641Sagc 			const pgp_litdata_enum type)
115593bf6008Sagc {
115693bf6008Sagc 	/*
115793bf6008Sagc          * RFC4880 does not specify a meaning for filename or date.
115893bf6008Sagc          * It is implementation-dependent.
115993bf6008Sagc          * We will not implement them.
116093bf6008Sagc          */
116193bf6008Sagc 	/* \todo do we need to check text data for <cr><lf> line endings ? */
1162fc1f8641Sagc 	return pgp_write_ptag(output, PGP_PTAG_CT_LITDATA) &&
1163fc1f8641Sagc 		pgp_write_length(output, (unsigned)(1 + 1 + 4 + maxlen)) &&
1164fc1f8641Sagc 		pgp_write_scalar(output, (unsigned)type, 1) &&
1165fc1f8641Sagc 		pgp_write_scalar(output, 0, 1) &&
1166fc1f8641Sagc 		pgp_write_scalar(output, 0, 4) &&
1167fc1f8641Sagc 		pgp_write(output, data, (unsigned)maxlen);
116893bf6008Sagc }
116993bf6008Sagc 
117093bf6008Sagc /**
117193bf6008Sagc \ingroup Core_WritePackets
117293bf6008Sagc \brief Writes Literal Data packet from contents of file
117393bf6008Sagc \param filename Name of file to read from
117493bf6008Sagc \param type Literal Data Type
117557324b9fSagc \param output Write settings
11764b3a3e18Sagc \return 1 if OK; else 0
117793bf6008Sagc */
117893bf6008Sagc 
11794b3a3e18Sagc unsigned
pgp_fileread_litdata(const char * filename,const pgp_litdata_enum type,pgp_output_t * output)1180fc1f8641Sagc pgp_fileread_litdata(const char *filename,
1181fc1f8641Sagc 				 const pgp_litdata_enum type,
1182fc1f8641Sagc 				 pgp_output_t *output)
118393bf6008Sagc {
1184fc1f8641Sagc 	pgp_memory_t	*mem;
118557324b9fSagc 	unsigned   	 ret;
118638beab94Sagc 	int		 len;
118793bf6008Sagc 
1188fc1f8641Sagc 	mem = pgp_memory_new();
1189fc1f8641Sagc 	if (!pgp_mem_readfile(mem, filename)) {
1190fc1f8641Sagc 		(void) fprintf(stderr, "pgp_mem_readfile of '%s' failed\n", filename);
11910df5e957Sagc 		return 0;
119285073018Sagc 	}
1193fc1f8641Sagc 	len = (int)pgp_mem_len(mem);
1194fc1f8641Sagc 	ret = pgp_write_litdata(output, pgp_mem_data(mem), len, type);
1195fc1f8641Sagc 	pgp_memory_free(mem);
119657324b9fSagc 	return ret;
119793bf6008Sagc }
119893bf6008Sagc 
119993bf6008Sagc /**
120093bf6008Sagc    \ingroup HighLevel_General
120193bf6008Sagc 
1202efdd9dbaSagc    \brief Writes contents of buffer into file
120393bf6008Sagc 
120493bf6008Sagc    \param filename Filename to write to
120593bf6008Sagc    \param buf Buffer to write to file
120693bf6008Sagc    \param len Size of buffer
120793bf6008Sagc    \param overwrite Flag to set whether to overwrite an existing file
120893bf6008Sagc    \return 1 if OK; 0 if error
120993bf6008Sagc */
121093bf6008Sagc 
121193bf6008Sagc int
pgp_filewrite(const char * filename,const char * buf,const size_t len,const unsigned overwrite)1212fc1f8641Sagc pgp_filewrite(const char *filename, const char *buf,
12134b3a3e18Sagc 			const size_t len, const unsigned overwrite)
121493bf6008Sagc {
12155a83dba0Sagc 	int		flags;
12165a83dba0Sagc 	int		fd;
121793bf6008Sagc 
121893bf6008Sagc 	flags = O_WRONLY | O_CREAT;
12194b3a3e18Sagc 	if (overwrite) {
122093bf6008Sagc 		flags |= O_TRUNC;
1221de704779Sagc 	} else {
122293bf6008Sagc 		flags |= O_EXCL;
1223de704779Sagc 	}
122493bf6008Sagc #ifdef O_BINARY
122593bf6008Sagc 	flags |= O_BINARY;
122693bf6008Sagc #endif
122793bf6008Sagc 	fd = open(filename, flags, 0600);
122893bf6008Sagc 	if (fd < 0) {
12295a83dba0Sagc 		(void) fprintf(stderr, "can't open '%s'\n", filename);
123093bf6008Sagc 		return 0;
123193bf6008Sagc 	}
12323326c4c5Sagc 	if (write(fd, buf, len) != (int)len) {
12330aa60872Sagc 		(void) close(fd);
123493bf6008Sagc 		return 0;
1235bcfd8565Sagc 	}
123693bf6008Sagc 
12373326c4c5Sagc 	return (close(fd) == 0);
123893bf6008Sagc }
123993bf6008Sagc 
124093bf6008Sagc /**
124193bf6008Sagc \ingroup Core_WritePackets
124293bf6008Sagc \brief Write Symmetrically Encrypted packet
124393bf6008Sagc \param data Data to encrypt
124493bf6008Sagc \param len Length of data
124557324b9fSagc \param output Write settings
12464b3a3e18Sagc \return 1 if OK; else 0
124793bf6008Sagc \note Hard-coded to use AES256
124893bf6008Sagc */
12494b3a3e18Sagc unsigned
pgp_write_symm_enc_data(const uint8_t * data,const int len,pgp_output_t * output)1250fc1f8641Sagc pgp_write_symm_enc_data(const uint8_t *data,
125193bf6008Sagc 				       const int len,
1252fc1f8641Sagc 				       pgp_output_t * output)
125393bf6008Sagc {
1254fc1f8641Sagc 	pgp_crypt_t	crypt_info;
1255b15ec256Sagc 	uint8_t		*encrypted = (uint8_t *) NULL;
1256b15ec256Sagc 	size_t		encrypted_sz;
1257efdd9dbaSagc 	int             done = 0;
125893bf6008Sagc 
125993bf6008Sagc 	/* \todo assume AES256 for now */
1260fc1f8641Sagc 	pgp_crypt_any(&crypt_info, PGP_SA_AES_256);
1261fc1f8641Sagc 	pgp_encrypt_init(&crypt_info);
126293bf6008Sagc 
12635a83dba0Sagc 	encrypted_sz = (size_t)(len + crypt_info.blocksize + 2);
12645a83dba0Sagc 	if ((encrypted = calloc(1, encrypted_sz)) == NULL) {
12655a83dba0Sagc 		(void) fprintf(stderr, "can't allocate %" PRIsize "d\n",
12665a83dba0Sagc 			encrypted_sz);
12675a83dba0Sagc 		return 0;
12685a83dba0Sagc 	}
126993bf6008Sagc 
1270fc1f8641Sagc 	done = (int)pgp_encrypt_se(&crypt_info, encrypted, data, (unsigned)len);
1271ed0df671Sagc 	if (done != len) {
1272ed0df671Sagc 		(void) fprintf(stderr,
1273fc1f8641Sagc 			"pgp_write_symm_enc_data: done != len\n");
12744b3a3e18Sagc 		return 0;
1275ed0df671Sagc 	}
127693bf6008Sagc 
1277fc1f8641Sagc 	return pgp_write_ptag(output, PGP_PTAG_CT_SE_DATA) &&
1278fc1f8641Sagc 		pgp_write_length(output, (unsigned)(1 + encrypted_sz)) &&
1279fc1f8641Sagc 		pgp_write(output, data, (unsigned)len);
128093bf6008Sagc }
128193bf6008Sagc 
128293bf6008Sagc /**
128393bf6008Sagc \ingroup Core_WritePackets
128493bf6008Sagc \brief Write a One Pass Signature packet
12850c310959Sagc \param seckey Secret Key to use
128693bf6008Sagc \param hash_alg Hash Algorithm to use
128793bf6008Sagc \param sig_type Signature type
128857324b9fSagc \param output Write settings
12894b3a3e18Sagc \return 1 if OK; else 0
129093bf6008Sagc */
12914b3a3e18Sagc unsigned
pgp_write_one_pass_sig(pgp_output_t * output,const pgp_seckey_t * seckey,const pgp_hash_alg_t hash_alg,const pgp_sig_type_t sig_type)1292fc1f8641Sagc pgp_write_one_pass_sig(pgp_output_t *output,
1293fc1f8641Sagc 			const pgp_seckey_t *seckey,
1294fc1f8641Sagc 			const pgp_hash_alg_t hash_alg,
1295fc1f8641Sagc 			const pgp_sig_type_t sig_type)
129693bf6008Sagc {
1297fc1f8641Sagc 	uint8_t   keyid[PGP_KEY_ID_SIZE];
129885073018Sagc 
1299fc1f8641Sagc 	pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, PGP_HASH_SHA1); /* XXX - hardcoded */
1300fc1f8641Sagc 	return pgp_write_ptag(output, PGP_PTAG_CT_1_PASS_SIG) &&
1301fc1f8641Sagc 		pgp_write_length(output, 1 + 1 + 1 + 1 + 8 + 1) &&
1302fc1f8641Sagc 		pgp_write_scalar(output, 3, 1)	/* version */ &&
1303fc1f8641Sagc 		pgp_write_scalar(output, (unsigned)sig_type, 1) &&
1304fc1f8641Sagc 		pgp_write_scalar(output, (unsigned)hash_alg, 1) &&
1305fc1f8641Sagc 		pgp_write_scalar(output, (unsigned)seckey->pubkey.alg, 1) &&
1306fc1f8641Sagc 		pgp_write(output, keyid, 8) &&
1307fc1f8641Sagc 		pgp_write_scalar(output, 1, 1);
130893bf6008Sagc }
1309