xref: /minix3/crypto/external/bsd/netpgp/dist/src/lib/create.c (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1*ebfedea0SLionel Sambuc /*-
2*ebfedea0SLionel Sambuc  * Copyright (c) 2009 The NetBSD Foundation, Inc.
3*ebfedea0SLionel Sambuc  * All rights reserved.
4*ebfedea0SLionel Sambuc  *
5*ebfedea0SLionel Sambuc  * This code is derived from software contributed to The NetBSD Foundation
6*ebfedea0SLionel Sambuc  * by Alistair Crooks (agc@NetBSD.org)
7*ebfedea0SLionel Sambuc  *
8*ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9*ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10*ebfedea0SLionel Sambuc  * are met:
11*ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
12*ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
13*ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
14*ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
15*ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
16*ebfedea0SLionel Sambuc  *
17*ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18*ebfedea0SLionel Sambuc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19*ebfedea0SLionel Sambuc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20*ebfedea0SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21*ebfedea0SLionel Sambuc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*ebfedea0SLionel Sambuc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*ebfedea0SLionel Sambuc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*ebfedea0SLionel Sambuc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*ebfedea0SLionel Sambuc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*ebfedea0SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*ebfedea0SLionel Sambuc  * POSSIBILITY OF SUCH DAMAGE.
28*ebfedea0SLionel Sambuc  */
29*ebfedea0SLionel Sambuc /*
30*ebfedea0SLionel Sambuc  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31*ebfedea0SLionel Sambuc  * All rights reserved.
32*ebfedea0SLionel Sambuc  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33*ebfedea0SLionel Sambuc  * their moral rights under the UK Copyright Design and Patents Act 1988 to
34*ebfedea0SLionel Sambuc  * be recorded as the authors of this copyright work.
35*ebfedea0SLionel Sambuc  *
36*ebfedea0SLionel Sambuc  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37*ebfedea0SLionel Sambuc  * use this file except in compliance with the License.
38*ebfedea0SLionel Sambuc  *
39*ebfedea0SLionel Sambuc  * You may obtain a copy of the License at
40*ebfedea0SLionel Sambuc  *     http://www.apache.org/licenses/LICENSE-2.0
41*ebfedea0SLionel Sambuc  *
42*ebfedea0SLionel Sambuc  * Unless required by applicable law or agreed to in writing, software
43*ebfedea0SLionel Sambuc  * distributed under the License is distributed on an "AS IS" BASIS,
44*ebfedea0SLionel Sambuc  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45*ebfedea0SLionel Sambuc  *
46*ebfedea0SLionel Sambuc  * See the License for the specific language governing permissions and
47*ebfedea0SLionel Sambuc  * limitations under the License.
48*ebfedea0SLionel Sambuc  */
49*ebfedea0SLionel Sambuc 
50*ebfedea0SLionel Sambuc /** \file
51*ebfedea0SLionel Sambuc  */
52*ebfedea0SLionel Sambuc #include "config.h"
53*ebfedea0SLionel Sambuc 
54*ebfedea0SLionel Sambuc #ifdef HAVE_SYS_CDEFS_H
55*ebfedea0SLionel Sambuc #include <sys/cdefs.h>
56*ebfedea0SLionel Sambuc #endif
57*ebfedea0SLionel Sambuc 
58*ebfedea0SLionel Sambuc #if defined(__NetBSD__)
59*ebfedea0SLionel Sambuc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60*ebfedea0SLionel Sambuc __RCSID("$NetBSD: create.c,v 1.38 2010/11/15 08:03:39 agc Exp $");
61*ebfedea0SLionel Sambuc #endif
62*ebfedea0SLionel Sambuc 
63*ebfedea0SLionel Sambuc #include <sys/types.h>
64*ebfedea0SLionel Sambuc #include <sys/param.h>
65*ebfedea0SLionel Sambuc #include <sys/stat.h>
66*ebfedea0SLionel Sambuc 
67*ebfedea0SLionel Sambuc #ifdef HAVE_FCNTL_H
68*ebfedea0SLionel Sambuc #include <fcntl.h>
69*ebfedea0SLionel Sambuc #endif
70*ebfedea0SLionel Sambuc 
71*ebfedea0SLionel Sambuc #include <string.h>
72*ebfedea0SLionel Sambuc 
73*ebfedea0SLionel Sambuc #ifdef HAVE_UNISTD_H
74*ebfedea0SLionel Sambuc #include <unistd.h>
75*ebfedea0SLionel Sambuc #endif
76*ebfedea0SLionel Sambuc 
77*ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL_CAST_H
78*ebfedea0SLionel Sambuc #include <openssl/cast.h>
79*ebfedea0SLionel Sambuc #endif
80*ebfedea0SLionel Sambuc 
81*ebfedea0SLionel Sambuc #include "create.h"
82*ebfedea0SLionel Sambuc #include "keyring.h"
83*ebfedea0SLionel Sambuc #include "packet.h"
84*ebfedea0SLionel Sambuc #include "signature.h"
85*ebfedea0SLionel Sambuc #include "writer.h"
86*ebfedea0SLionel Sambuc #include "readerwriter.h"
87*ebfedea0SLionel Sambuc #include "memory.h"
88*ebfedea0SLionel Sambuc #include "netpgpdefs.h"
89*ebfedea0SLionel Sambuc #include "netpgpdigest.h"
90*ebfedea0SLionel Sambuc 
91*ebfedea0SLionel Sambuc /**
92*ebfedea0SLionel Sambuc  * \ingroup Core_Create
93*ebfedea0SLionel Sambuc  * \param length
94*ebfedea0SLionel Sambuc  * \param type
95*ebfedea0SLionel Sambuc  * \param output
96*ebfedea0SLionel Sambuc  * \return 1 if OK, otherwise 0
97*ebfedea0SLionel Sambuc  */
98*ebfedea0SLionel Sambuc 
99*ebfedea0SLionel Sambuc unsigned
pgp_write_ss_header(pgp_output_t * output,unsigned length,pgp_content_enum type)100*ebfedea0SLionel Sambuc pgp_write_ss_header(pgp_output_t *output,
101*ebfedea0SLionel Sambuc 			unsigned length,
102*ebfedea0SLionel Sambuc 			pgp_content_enum type)
103*ebfedea0SLionel Sambuc {
104*ebfedea0SLionel Sambuc 	return pgp_write_length(output, length) &&
105*ebfedea0SLionel Sambuc 		pgp_write_scalar(output, (unsigned)(type -
106*ebfedea0SLionel Sambuc 				(unsigned)PGP_PTAG_SIG_SUBPKT_BASE), 1);
107*ebfedea0SLionel Sambuc }
108*ebfedea0SLionel Sambuc 
109*ebfedea0SLionel Sambuc /*
110*ebfedea0SLionel Sambuc  * XXX: the general idea of _fast_ is that it doesn't copy stuff the safe
111*ebfedea0SLionel Sambuc  * (i.e. non _fast_) version will, and so will also need to be freed.
112*ebfedea0SLionel Sambuc  */
113*ebfedea0SLionel Sambuc 
114*ebfedea0SLionel Sambuc /**
115*ebfedea0SLionel Sambuc  * \ingroup Core_Create
116*ebfedea0SLionel Sambuc  *
117*ebfedea0SLionel Sambuc  * pgp_fast_create_userid() sets id->userid to the given userid.
118*ebfedea0SLionel Sambuc  * This is fast because it is only copying a char*. However, if userid
119*ebfedea0SLionel Sambuc  * is changed or freed in the future, this could have injurious results.
120*ebfedea0SLionel Sambuc  * \param id
121*ebfedea0SLionel Sambuc  * \param userid
122*ebfedea0SLionel Sambuc  */
123*ebfedea0SLionel Sambuc 
124*ebfedea0SLionel Sambuc void
pgp_fast_create_userid(uint8_t ** id,uint8_t * userid)125*ebfedea0SLionel Sambuc pgp_fast_create_userid(uint8_t **id, uint8_t *userid)
126*ebfedea0SLionel Sambuc {
127*ebfedea0SLionel Sambuc 	*id = userid;
128*ebfedea0SLionel Sambuc }
129*ebfedea0SLionel Sambuc 
130*ebfedea0SLionel Sambuc /**
131*ebfedea0SLionel Sambuc  * \ingroup Core_WritePackets
132*ebfedea0SLionel Sambuc  * \brief Writes a User Id packet
133*ebfedea0SLionel Sambuc  * \param id
134*ebfedea0SLionel Sambuc  * \param output
135*ebfedea0SLionel Sambuc  * \return 1 if OK, otherwise 0
136*ebfedea0SLionel Sambuc  */
137*ebfedea0SLionel Sambuc unsigned
pgp_write_struct_userid(pgp_output_t * output,const uint8_t * id)138*ebfedea0SLionel Sambuc pgp_write_struct_userid(pgp_output_t *output, const uint8_t *id)
139*ebfedea0SLionel Sambuc {
140*ebfedea0SLionel Sambuc 	return pgp_write_ptag(output, PGP_PTAG_CT_USER_ID) &&
141*ebfedea0SLionel Sambuc 		pgp_write_length(output, (unsigned)strlen((const char *) id)) &&
142*ebfedea0SLionel Sambuc 		pgp_write(output, id, (unsigned)strlen((const char *) id));
143*ebfedea0SLionel Sambuc }
144*ebfedea0SLionel Sambuc 
145*ebfedea0SLionel Sambuc /**
146*ebfedea0SLionel Sambuc  * \ingroup Core_WritePackets
147*ebfedea0SLionel Sambuc  * \brief Write a User Id packet.
148*ebfedea0SLionel Sambuc  * \param userid
149*ebfedea0SLionel Sambuc  * \param output
150*ebfedea0SLionel Sambuc  *
151*ebfedea0SLionel Sambuc  * \return return value from pgp_write_struct_userid()
152*ebfedea0SLionel Sambuc  */
153*ebfedea0SLionel Sambuc unsigned
pgp_write_userid(const uint8_t * userid,pgp_output_t * output)154*ebfedea0SLionel Sambuc pgp_write_userid(const uint8_t *userid, pgp_output_t *output)
155*ebfedea0SLionel Sambuc {
156*ebfedea0SLionel Sambuc 	return pgp_write_struct_userid(output, userid);
157*ebfedea0SLionel Sambuc }
158*ebfedea0SLionel Sambuc 
159*ebfedea0SLionel Sambuc /**
160*ebfedea0SLionel Sambuc \ingroup Core_MPI
161*ebfedea0SLionel Sambuc */
162*ebfedea0SLionel Sambuc static unsigned
mpi_length(const BIGNUM * bn)163*ebfedea0SLionel Sambuc mpi_length(const BIGNUM *bn)
164*ebfedea0SLionel Sambuc {
165*ebfedea0SLionel Sambuc 	return (unsigned)(2 + (BN_num_bits(bn) + 7) / 8);
166*ebfedea0SLionel Sambuc }
167*ebfedea0SLionel Sambuc 
168*ebfedea0SLionel Sambuc static unsigned
pubkey_length(const pgp_pubkey_t * key)169*ebfedea0SLionel Sambuc pubkey_length(const pgp_pubkey_t *key)
170*ebfedea0SLionel Sambuc {
171*ebfedea0SLionel Sambuc 	switch (key->alg) {
172*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
173*ebfedea0SLionel Sambuc 		return mpi_length(key->key.dsa.p) + mpi_length(key->key.dsa.q) +
174*ebfedea0SLionel Sambuc 			mpi_length(key->key.dsa.g) + mpi_length(key->key.dsa.y);
175*ebfedea0SLionel Sambuc 
176*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
177*ebfedea0SLionel Sambuc 		return mpi_length(key->key.rsa.n) + mpi_length(key->key.rsa.e);
178*ebfedea0SLionel Sambuc 
179*ebfedea0SLionel Sambuc 	default:
180*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
181*ebfedea0SLionel Sambuc 			"pubkey_length: unknown key algorithm\n");
182*ebfedea0SLionel Sambuc 	}
183*ebfedea0SLionel Sambuc 	return 0;
184*ebfedea0SLionel Sambuc }
185*ebfedea0SLionel Sambuc 
186*ebfedea0SLionel Sambuc static unsigned
seckey_length(const pgp_seckey_t * key)187*ebfedea0SLionel Sambuc seckey_length(const pgp_seckey_t *key)
188*ebfedea0SLionel Sambuc {
189*ebfedea0SLionel Sambuc 	int             len;
190*ebfedea0SLionel Sambuc 
191*ebfedea0SLionel Sambuc 	len = 0;
192*ebfedea0SLionel Sambuc 	switch (key->pubkey.alg) {
193*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
194*ebfedea0SLionel Sambuc 		return (unsigned)(mpi_length(key->key.dsa.x) + pubkey_length(&key->pubkey));
195*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
196*ebfedea0SLionel Sambuc 		len = mpi_length(key->key.rsa.d) + mpi_length(key->key.rsa.p) +
197*ebfedea0SLionel Sambuc 			mpi_length(key->key.rsa.q) + mpi_length(key->key.rsa.u);
198*ebfedea0SLionel Sambuc 
199*ebfedea0SLionel Sambuc 		return (unsigned)(len + pubkey_length(&key->pubkey));
200*ebfedea0SLionel Sambuc 	default:
201*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
202*ebfedea0SLionel Sambuc 			"seckey_length: unknown key algorithm\n");
203*ebfedea0SLionel Sambuc 	}
204*ebfedea0SLionel Sambuc 	return 0;
205*ebfedea0SLionel Sambuc }
206*ebfedea0SLionel Sambuc 
207*ebfedea0SLionel Sambuc /**
208*ebfedea0SLionel Sambuc  * \ingroup Core_Create
209*ebfedea0SLionel Sambuc  * \param key
210*ebfedea0SLionel Sambuc  * \param t
211*ebfedea0SLionel Sambuc  * \param n
212*ebfedea0SLionel Sambuc  * \param e
213*ebfedea0SLionel Sambuc */
214*ebfedea0SLionel Sambuc void
pgp_fast_create_rsa_pubkey(pgp_pubkey_t * key,time_t t,BIGNUM * n,BIGNUM * e)215*ebfedea0SLionel Sambuc pgp_fast_create_rsa_pubkey(pgp_pubkey_t *key, time_t t,
216*ebfedea0SLionel Sambuc 			       BIGNUM *n, BIGNUM *e)
217*ebfedea0SLionel Sambuc {
218*ebfedea0SLionel Sambuc 	key->version = PGP_V4;
219*ebfedea0SLionel Sambuc 	key->birthtime = t;
220*ebfedea0SLionel Sambuc 	key->alg = PGP_PKA_RSA;
221*ebfedea0SLionel Sambuc 	key->key.rsa.n = n;
222*ebfedea0SLionel Sambuc 	key->key.rsa.e = e;
223*ebfedea0SLionel Sambuc }
224*ebfedea0SLionel Sambuc 
225*ebfedea0SLionel Sambuc /*
226*ebfedea0SLionel Sambuc  * Note that we support v3 keys here because they're needed for for
227*ebfedea0SLionel Sambuc  * verification - the writer doesn't allow them, though
228*ebfedea0SLionel Sambuc  */
229*ebfedea0SLionel Sambuc static unsigned
write_pubkey_body(const pgp_pubkey_t * key,pgp_output_t * output)230*ebfedea0SLionel Sambuc write_pubkey_body(const pgp_pubkey_t *key, pgp_output_t *output)
231*ebfedea0SLionel Sambuc {
232*ebfedea0SLionel Sambuc 	if (!(pgp_write_scalar(output, (unsigned)key->version, 1) &&
233*ebfedea0SLionel Sambuc 	      pgp_write_scalar(output, (unsigned)key->birthtime, 4))) {
234*ebfedea0SLionel Sambuc 		return 0;
235*ebfedea0SLionel Sambuc 	}
236*ebfedea0SLionel Sambuc 
237*ebfedea0SLionel Sambuc 	if (key->version != 4 &&
238*ebfedea0SLionel Sambuc 	    !pgp_write_scalar(output, key->days_valid, 2)) {
239*ebfedea0SLionel Sambuc 		return 0;
240*ebfedea0SLionel Sambuc 	}
241*ebfedea0SLionel Sambuc 
242*ebfedea0SLionel Sambuc 	if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) {
243*ebfedea0SLionel Sambuc 		return 0;
244*ebfedea0SLionel Sambuc 	}
245*ebfedea0SLionel Sambuc 
246*ebfedea0SLionel Sambuc 	switch (key->alg) {
247*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
248*ebfedea0SLionel Sambuc 		return pgp_write_mpi(output, key->key.dsa.p) &&
249*ebfedea0SLionel Sambuc 			pgp_write_mpi(output, key->key.dsa.q) &&
250*ebfedea0SLionel Sambuc 			pgp_write_mpi(output, key->key.dsa.g) &&
251*ebfedea0SLionel Sambuc 			pgp_write_mpi(output, key->key.dsa.y);
252*ebfedea0SLionel Sambuc 
253*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
254*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA_ENCRYPT_ONLY:
255*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA_SIGN_ONLY:
256*ebfedea0SLionel Sambuc 		return pgp_write_mpi(output, key->key.rsa.n) &&
257*ebfedea0SLionel Sambuc 			pgp_write_mpi(output, key->key.rsa.e);
258*ebfedea0SLionel Sambuc 
259*ebfedea0SLionel Sambuc 	case PGP_PKA_ELGAMAL:
260*ebfedea0SLionel Sambuc 		return pgp_write_mpi(output, key->key.elgamal.p) &&
261*ebfedea0SLionel Sambuc 			pgp_write_mpi(output, key->key.elgamal.g) &&
262*ebfedea0SLionel Sambuc 			pgp_write_mpi(output, key->key.elgamal.y);
263*ebfedea0SLionel Sambuc 
264*ebfedea0SLionel Sambuc 	default:
265*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
266*ebfedea0SLionel Sambuc 			"write_pubkey_body: bad algorithm\n");
267*ebfedea0SLionel Sambuc 		break;
268*ebfedea0SLionel Sambuc 	}
269*ebfedea0SLionel Sambuc 	return 0;
270*ebfedea0SLionel Sambuc }
271*ebfedea0SLionel Sambuc 
272*ebfedea0SLionel Sambuc /*
273*ebfedea0SLionel Sambuc  * Note that we support v3 keys here because they're needed for
274*ebfedea0SLionel Sambuc  * verification.
275*ebfedea0SLionel Sambuc  */
276*ebfedea0SLionel Sambuc static unsigned
write_seckey_body(const pgp_seckey_t * key,const uint8_t * passphrase,const size_t pplen,pgp_output_t * output)277*ebfedea0SLionel Sambuc write_seckey_body(const pgp_seckey_t *key,
278*ebfedea0SLionel Sambuc 		      const uint8_t *passphrase,
279*ebfedea0SLionel Sambuc 		      const size_t pplen,
280*ebfedea0SLionel Sambuc 		      pgp_output_t *output)
281*ebfedea0SLionel Sambuc {
282*ebfedea0SLionel Sambuc 	/* RFC4880 Section 5.5.3 Secret-Key Packet Formats */
283*ebfedea0SLionel Sambuc 
284*ebfedea0SLionel Sambuc 	pgp_crypt_t   crypted;
285*ebfedea0SLionel Sambuc 	pgp_hash_t    hash;
286*ebfedea0SLionel Sambuc 	unsigned	done = 0;
287*ebfedea0SLionel Sambuc 	unsigned	i = 0;
288*ebfedea0SLionel Sambuc 	uint8_t		*hashed;
289*ebfedea0SLionel Sambuc 	uint8_t		sesskey[CAST_KEY_LENGTH];
290*ebfedea0SLionel Sambuc 
291*ebfedea0SLionel Sambuc 	if (!write_pubkey_body(&key->pubkey, output)) {
292*ebfedea0SLionel Sambuc 		return 0;
293*ebfedea0SLionel Sambuc 	}
294*ebfedea0SLionel Sambuc 	if (key->s2k_usage != PGP_S2KU_ENCRYPTED_AND_HASHED) {
295*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "write_seckey_body: s2k usage\n");
296*ebfedea0SLionel Sambuc 		return 0;
297*ebfedea0SLionel Sambuc 	}
298*ebfedea0SLionel Sambuc 	if (!pgp_write_scalar(output, (unsigned)key->s2k_usage, 1)) {
299*ebfedea0SLionel Sambuc 		return 0;
300*ebfedea0SLionel Sambuc 	}
301*ebfedea0SLionel Sambuc 
302*ebfedea0SLionel Sambuc 	if (key->alg != PGP_SA_CAST5) {
303*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "write_seckey_body: algorithm\n");
304*ebfedea0SLionel Sambuc 		return 0;
305*ebfedea0SLionel Sambuc 	}
306*ebfedea0SLionel Sambuc 	if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) {
307*ebfedea0SLionel Sambuc 		return 0;
308*ebfedea0SLionel Sambuc 	}
309*ebfedea0SLionel Sambuc 
310*ebfedea0SLionel Sambuc 	if (key->s2k_specifier != PGP_S2KS_SIMPLE &&
311*ebfedea0SLionel Sambuc 	    key->s2k_specifier != PGP_S2KS_SALTED) {
312*ebfedea0SLionel Sambuc 		/* = 1 \todo could also be iterated-and-salted */
313*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "write_seckey_body: s2k spec\n");
314*ebfedea0SLionel Sambuc 		return 0;
315*ebfedea0SLionel Sambuc 	}
316*ebfedea0SLionel Sambuc 	if (!pgp_write_scalar(output, (unsigned)key->s2k_specifier, 1)) {
317*ebfedea0SLionel Sambuc 		return 0;
318*ebfedea0SLionel Sambuc 	}
319*ebfedea0SLionel Sambuc 	if (!pgp_write_scalar(output, (unsigned)key->hash_alg, 1)) {
320*ebfedea0SLionel Sambuc 		return 0;
321*ebfedea0SLionel Sambuc 	}
322*ebfedea0SLionel Sambuc 
323*ebfedea0SLionel Sambuc 	switch (key->s2k_specifier) {
324*ebfedea0SLionel Sambuc 	case PGP_S2KS_SIMPLE:
325*ebfedea0SLionel Sambuc 		/* nothing more to do */
326*ebfedea0SLionel Sambuc 		break;
327*ebfedea0SLionel Sambuc 
328*ebfedea0SLionel Sambuc 	case PGP_S2KS_SALTED:
329*ebfedea0SLionel Sambuc 		/* 8-octet salt value */
330*ebfedea0SLionel Sambuc 		pgp_random(__UNCONST(&key->salt[0]), PGP_SALT_SIZE);
331*ebfedea0SLionel Sambuc 		if (!pgp_write(output, key->salt, PGP_SALT_SIZE)) {
332*ebfedea0SLionel Sambuc 			return 0;
333*ebfedea0SLionel Sambuc 		}
334*ebfedea0SLionel Sambuc 		break;
335*ebfedea0SLionel Sambuc 
336*ebfedea0SLionel Sambuc 		/*
337*ebfedea0SLionel Sambuc 		 * \todo case PGP_S2KS_ITERATED_AND_SALTED: // 8-octet salt
338*ebfedea0SLionel Sambuc 		 * value // 1-octet count break;
339*ebfedea0SLionel Sambuc 		 */
340*ebfedea0SLionel Sambuc 
341*ebfedea0SLionel Sambuc 	default:
342*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
343*ebfedea0SLionel Sambuc 			"invalid/unsupported s2k specifier %d\n",
344*ebfedea0SLionel Sambuc 			key->s2k_specifier);
345*ebfedea0SLionel Sambuc 		return 0;
346*ebfedea0SLionel Sambuc 	}
347*ebfedea0SLionel Sambuc 
348*ebfedea0SLionel Sambuc 	if (!pgp_write(output, &key->iv[0], pgp_block_size(key->alg))) {
349*ebfedea0SLionel Sambuc 		return 0;
350*ebfedea0SLionel Sambuc 	}
351*ebfedea0SLionel Sambuc 
352*ebfedea0SLionel Sambuc 	/*
353*ebfedea0SLionel Sambuc 	 * create the session key for encrypting the algorithm-specific
354*ebfedea0SLionel Sambuc 	 * fields
355*ebfedea0SLionel Sambuc 	 */
356*ebfedea0SLionel Sambuc 
357*ebfedea0SLionel Sambuc 	switch (key->s2k_specifier) {
358*ebfedea0SLionel Sambuc 	case PGP_S2KS_SIMPLE:
359*ebfedea0SLionel Sambuc 	case PGP_S2KS_SALTED:
360*ebfedea0SLionel Sambuc 		/* RFC4880: section 3.7.1.1 and 3.7.1.2 */
361*ebfedea0SLionel Sambuc 
362*ebfedea0SLionel Sambuc 		for (done = 0, i = 0; done < CAST_KEY_LENGTH; i++) {
363*ebfedea0SLionel Sambuc 			unsigned 	hashsize;
364*ebfedea0SLionel Sambuc 			unsigned 	j;
365*ebfedea0SLionel Sambuc 			unsigned	needed;
366*ebfedea0SLionel Sambuc 			unsigned	size;
367*ebfedea0SLionel Sambuc 			uint8_t		zero = 0;
368*ebfedea0SLionel Sambuc 
369*ebfedea0SLionel Sambuc 			/* Hard-coded SHA1 for session key */
370*ebfedea0SLionel Sambuc 			pgp_hash_any(&hash, PGP_HASH_SHA1);
371*ebfedea0SLionel Sambuc 			hashsize = pgp_hash_size(key->hash_alg);
372*ebfedea0SLionel Sambuc 			needed = CAST_KEY_LENGTH - done;
373*ebfedea0SLionel Sambuc 			size = MIN(needed, hashsize);
374*ebfedea0SLionel Sambuc 			if ((hashed = calloc(1, hashsize)) == NULL) {
375*ebfedea0SLionel Sambuc 				(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
376*ebfedea0SLionel Sambuc 				return 0;
377*ebfedea0SLionel Sambuc 			}
378*ebfedea0SLionel Sambuc 			if (!hash.init(&hash)) {
379*ebfedea0SLionel Sambuc 				(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
380*ebfedea0SLionel Sambuc 				return 0;
381*ebfedea0SLionel Sambuc 			}
382*ebfedea0SLionel Sambuc 
383*ebfedea0SLionel Sambuc 			/* preload if iterating  */
384*ebfedea0SLionel Sambuc 			for (j = 0; j < i; j++) {
385*ebfedea0SLionel Sambuc 				/*
386*ebfedea0SLionel Sambuc 				 * Coverity shows a DEADCODE error on this
387*ebfedea0SLionel Sambuc 				 * line. This is expected since the hardcoded
388*ebfedea0SLionel Sambuc 				 * use of SHA1 and CAST5 means that it will
389*ebfedea0SLionel Sambuc 				 * not used. This will change however when
390*ebfedea0SLionel Sambuc 				 * other algorithms are supported.
391*ebfedea0SLionel Sambuc 				 */
392*ebfedea0SLionel Sambuc 				hash.add(&hash, &zero, 1);
393*ebfedea0SLionel Sambuc 			}
394*ebfedea0SLionel Sambuc 
395*ebfedea0SLionel Sambuc 			if (key->s2k_specifier == PGP_S2KS_SALTED) {
396*ebfedea0SLionel Sambuc 				hash.add(&hash, key->salt, PGP_SALT_SIZE);
397*ebfedea0SLionel Sambuc 			}
398*ebfedea0SLionel Sambuc 			hash.add(&hash, passphrase, (unsigned)pplen);
399*ebfedea0SLionel Sambuc 			hash.finish(&hash, hashed);
400*ebfedea0SLionel Sambuc 
401*ebfedea0SLionel Sambuc 			/*
402*ebfedea0SLionel Sambuc 			 * if more in hash than is needed by session key, use
403*ebfedea0SLionel Sambuc 			 * the leftmost octets
404*ebfedea0SLionel Sambuc 			 */
405*ebfedea0SLionel Sambuc 			(void) memcpy(&sesskey[i * hashsize],
406*ebfedea0SLionel Sambuc 					hashed, (unsigned)size);
407*ebfedea0SLionel Sambuc 			done += (unsigned)size;
408*ebfedea0SLionel Sambuc 			if (done > CAST_KEY_LENGTH) {
409*ebfedea0SLionel Sambuc 				(void) fprintf(stderr,
410*ebfedea0SLionel Sambuc 					"write_seckey_body: short add\n");
411*ebfedea0SLionel Sambuc 				return 0;
412*ebfedea0SLionel Sambuc 			}
413*ebfedea0SLionel Sambuc 		}
414*ebfedea0SLionel Sambuc 
415*ebfedea0SLionel Sambuc 		break;
416*ebfedea0SLionel Sambuc 
417*ebfedea0SLionel Sambuc 		/*
418*ebfedea0SLionel Sambuc 		 * \todo case PGP_S2KS_ITERATED_AND_SALTED: * 8-octet salt
419*ebfedea0SLionel Sambuc 		 * value * 1-octet count break;
420*ebfedea0SLionel Sambuc 		 */
421*ebfedea0SLionel Sambuc 
422*ebfedea0SLionel Sambuc 	default:
423*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
424*ebfedea0SLionel Sambuc 			"invalid/unsupported s2k specifier %d\n",
425*ebfedea0SLionel Sambuc 			key->s2k_specifier);
426*ebfedea0SLionel Sambuc 		return 0;
427*ebfedea0SLionel Sambuc 	}
428*ebfedea0SLionel Sambuc 
429*ebfedea0SLionel Sambuc 	/* use this session key to encrypt */
430*ebfedea0SLionel Sambuc 
431*ebfedea0SLionel Sambuc 	pgp_crypt_any(&crypted, key->alg);
432*ebfedea0SLionel Sambuc 	crypted.set_iv(&crypted, key->iv);
433*ebfedea0SLionel Sambuc 	crypted.set_crypt_key(&crypted, sesskey);
434*ebfedea0SLionel Sambuc 	pgp_encrypt_init(&crypted);
435*ebfedea0SLionel Sambuc 
436*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
437*ebfedea0SLionel Sambuc 		hexdump(stderr, "writing: iv=", key->iv, pgp_block_size(key->alg));
438*ebfedea0SLionel Sambuc 		hexdump(stderr, "key= ", sesskey, CAST_KEY_LENGTH);
439*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "\nturning encryption on...\n");
440*ebfedea0SLionel Sambuc 	}
441*ebfedea0SLionel Sambuc 	pgp_push_enc_crypt(output, &crypted);
442*ebfedea0SLionel Sambuc 
443*ebfedea0SLionel Sambuc 	switch (key->pubkey.alg) {
444*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
445*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA_ENCRYPT_ONLY:
446*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA_SIGN_ONLY:
447*ebfedea0SLionel Sambuc 		if (!pgp_write_mpi(output, key->key.rsa.d) ||
448*ebfedea0SLionel Sambuc 		    !pgp_write_mpi(output, key->key.rsa.p) ||
449*ebfedea0SLionel Sambuc 		    !pgp_write_mpi(output, key->key.rsa.q) ||
450*ebfedea0SLionel Sambuc 		    !pgp_write_mpi(output, key->key.rsa.u)) {
451*ebfedea0SLionel Sambuc 			if (pgp_get_debug_level(__FILE__)) {
452*ebfedea0SLionel Sambuc 				(void) fprintf(stderr,
453*ebfedea0SLionel Sambuc 					"4 x mpi not written - problem\n");
454*ebfedea0SLionel Sambuc 			}
455*ebfedea0SLionel Sambuc 			return 0;
456*ebfedea0SLionel Sambuc 		}
457*ebfedea0SLionel Sambuc 		break;
458*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
459*ebfedea0SLionel Sambuc 		return pgp_write_mpi(output, key->key.dsa.x);
460*ebfedea0SLionel Sambuc 	case PGP_PKA_ELGAMAL:
461*ebfedea0SLionel Sambuc 		return pgp_write_mpi(output, key->key.elgamal.x);
462*ebfedea0SLionel Sambuc 	default:
463*ebfedea0SLionel Sambuc 		return 0;
464*ebfedea0SLionel Sambuc 	}
465*ebfedea0SLionel Sambuc 
466*ebfedea0SLionel Sambuc 	if (!pgp_write(output, key->checkhash, PGP_CHECKHASH_SIZE)) {
467*ebfedea0SLionel Sambuc 		return 0;
468*ebfedea0SLionel Sambuc 	}
469*ebfedea0SLionel Sambuc 
470*ebfedea0SLionel Sambuc 	pgp_writer_pop(output);
471*ebfedea0SLionel Sambuc 
472*ebfedea0SLionel Sambuc 	return 1;
473*ebfedea0SLionel Sambuc }
474*ebfedea0SLionel Sambuc 
475*ebfedea0SLionel Sambuc /**
476*ebfedea0SLionel Sambuc  * \ingroup Core_WritePackets
477*ebfedea0SLionel Sambuc  * \brief Writes a Public Key packet
478*ebfedea0SLionel Sambuc  * \param key
479*ebfedea0SLionel Sambuc  * \param output
480*ebfedea0SLionel Sambuc  * \return 1 if OK, otherwise 0
481*ebfedea0SLionel Sambuc  */
482*ebfedea0SLionel Sambuc static unsigned
write_struct_pubkey(pgp_output_t * output,const pgp_pubkey_t * key)483*ebfedea0SLionel Sambuc write_struct_pubkey(pgp_output_t *output, const pgp_pubkey_t *key)
484*ebfedea0SLionel Sambuc {
485*ebfedea0SLionel Sambuc 	return pgp_write_ptag(output, PGP_PTAG_CT_PUBLIC_KEY) &&
486*ebfedea0SLionel Sambuc 		pgp_write_length(output, 1 + 4 + 1 + pubkey_length(key)) &&
487*ebfedea0SLionel Sambuc 		write_pubkey_body(key, output);
488*ebfedea0SLionel Sambuc }
489*ebfedea0SLionel Sambuc 
490*ebfedea0SLionel Sambuc 
491*ebfedea0SLionel Sambuc /**
492*ebfedea0SLionel Sambuc    \ingroup HighLevel_KeyWrite
493*ebfedea0SLionel Sambuc 
494*ebfedea0SLionel Sambuc    \brief Writes a transferable PGP public key to the given output stream.
495*ebfedea0SLionel Sambuc 
496*ebfedea0SLionel Sambuc    \param keydata Key to be written
497*ebfedea0SLionel Sambuc    \param armoured Flag is set for armoured output
498*ebfedea0SLionel Sambuc    \param output Output stream
499*ebfedea0SLionel Sambuc 
500*ebfedea0SLionel Sambuc */
501*ebfedea0SLionel Sambuc 
502*ebfedea0SLionel Sambuc unsigned
pgp_write_xfer_pubkey(pgp_output_t * output,const pgp_key_t * key,const unsigned armoured)503*ebfedea0SLionel Sambuc pgp_write_xfer_pubkey(pgp_output_t *output,
504*ebfedea0SLionel Sambuc 			const pgp_key_t *key,
505*ebfedea0SLionel Sambuc 			const unsigned armoured)
506*ebfedea0SLionel Sambuc {
507*ebfedea0SLionel Sambuc 	unsigned    i, j;
508*ebfedea0SLionel Sambuc 
509*ebfedea0SLionel Sambuc 	if (armoured) {
510*ebfedea0SLionel Sambuc 		pgp_writer_push_armoured(output, PGP_PGP_PUBLIC_KEY_BLOCK);
511*ebfedea0SLionel Sambuc 	}
512*ebfedea0SLionel Sambuc 	/* public key */
513*ebfedea0SLionel Sambuc 	if (!write_struct_pubkey(output, &key->key.pubkey)) {
514*ebfedea0SLionel Sambuc 		return 0;
515*ebfedea0SLionel Sambuc 	}
516*ebfedea0SLionel Sambuc 
517*ebfedea0SLionel Sambuc 	/* TODO: revocation signatures go here */
518*ebfedea0SLionel Sambuc 
519*ebfedea0SLionel Sambuc 	/* user ids and corresponding signatures */
520*ebfedea0SLionel Sambuc 	for (i = 0; i < key->uidc; i++) {
521*ebfedea0SLionel Sambuc 		if (!pgp_write_struct_userid(output, key->uids[i])) {
522*ebfedea0SLionel Sambuc 			return 0;
523*ebfedea0SLionel Sambuc 		}
524*ebfedea0SLionel Sambuc 		for (j = 0; j < key->packetc; j++) {
525*ebfedea0SLionel Sambuc 			if (!pgp_write(output, key->packets[j].raw, (unsigned)key->packets[j].length)) {
526*ebfedea0SLionel Sambuc 				return 0;
527*ebfedea0SLionel Sambuc 			}
528*ebfedea0SLionel Sambuc 		}
529*ebfedea0SLionel Sambuc 	}
530*ebfedea0SLionel Sambuc 
531*ebfedea0SLionel Sambuc 	/* TODO: user attributes and corresponding signatures */
532*ebfedea0SLionel Sambuc 
533*ebfedea0SLionel Sambuc 	/*
534*ebfedea0SLionel Sambuc 	 * subkey packets and corresponding signatures and optional
535*ebfedea0SLionel Sambuc 	 * revocation
536*ebfedea0SLionel Sambuc 	 */
537*ebfedea0SLionel Sambuc 
538*ebfedea0SLionel Sambuc 	if (armoured) {
539*ebfedea0SLionel Sambuc 		pgp_writer_info_finalise(&output->errors, &output->writer);
540*ebfedea0SLionel Sambuc 		pgp_writer_pop(output);
541*ebfedea0SLionel Sambuc 	}
542*ebfedea0SLionel Sambuc 	return 1;
543*ebfedea0SLionel Sambuc }
544*ebfedea0SLionel Sambuc 
545*ebfedea0SLionel Sambuc /**
546*ebfedea0SLionel Sambuc    \ingroup HighLevel_KeyWrite
547*ebfedea0SLionel Sambuc 
548*ebfedea0SLionel Sambuc    \brief Writes a transferable PGP secret key to the given output stream.
549*ebfedea0SLionel Sambuc 
550*ebfedea0SLionel Sambuc    \param keydata Key to be written
551*ebfedea0SLionel Sambuc    \param passphrase
552*ebfedea0SLionel Sambuc    \param pplen
553*ebfedea0SLionel Sambuc    \param armoured Flag is set for armoured output
554*ebfedea0SLionel Sambuc    \param output Output stream
555*ebfedea0SLionel Sambuc 
556*ebfedea0SLionel Sambuc */
557*ebfedea0SLionel Sambuc 
558*ebfedea0SLionel Sambuc unsigned
pgp_write_xfer_seckey(pgp_output_t * output,const pgp_key_t * key,const uint8_t * passphrase,const size_t pplen,unsigned armoured)559*ebfedea0SLionel Sambuc pgp_write_xfer_seckey(pgp_output_t *output,
560*ebfedea0SLionel Sambuc 				const pgp_key_t *key,
561*ebfedea0SLionel Sambuc 				const uint8_t *passphrase,
562*ebfedea0SLionel Sambuc 				const size_t pplen,
563*ebfedea0SLionel Sambuc 				unsigned armoured)
564*ebfedea0SLionel Sambuc {
565*ebfedea0SLionel Sambuc 	unsigned	i, j;
566*ebfedea0SLionel Sambuc 
567*ebfedea0SLionel Sambuc 	if (armoured) {
568*ebfedea0SLionel Sambuc 		pgp_writer_push_armoured(output, PGP_PGP_PRIVATE_KEY_BLOCK);
569*ebfedea0SLionel Sambuc 	}
570*ebfedea0SLionel Sambuc 	/* public key */
571*ebfedea0SLionel Sambuc 	if (!pgp_write_struct_seckey(&key->key.seckey, passphrase,
572*ebfedea0SLionel Sambuc 			pplen, output)) {
573*ebfedea0SLionel Sambuc 		return 0;
574*ebfedea0SLionel Sambuc 	}
575*ebfedea0SLionel Sambuc 
576*ebfedea0SLionel Sambuc 	/* TODO: revocation signatures go here */
577*ebfedea0SLionel Sambuc 
578*ebfedea0SLionel Sambuc 	/* user ids and corresponding signatures */
579*ebfedea0SLionel Sambuc 	for (i = 0; i < key->uidc; i++) {
580*ebfedea0SLionel Sambuc 		if (!pgp_write_struct_userid(output, key->uids[i])) {
581*ebfedea0SLionel Sambuc 			return 0;
582*ebfedea0SLionel Sambuc 		}
583*ebfedea0SLionel Sambuc 		for (j = 0; j < key->packetc; j++) {
584*ebfedea0SLionel Sambuc 			if (!pgp_write(output, key->packets[j].raw, (unsigned)key->packets[j].length)) {
585*ebfedea0SLionel Sambuc 				return 0;
586*ebfedea0SLionel Sambuc 			}
587*ebfedea0SLionel Sambuc 		}
588*ebfedea0SLionel Sambuc 	}
589*ebfedea0SLionel Sambuc 
590*ebfedea0SLionel Sambuc 	/* TODO: user attributes and corresponding signatures */
591*ebfedea0SLionel Sambuc 
592*ebfedea0SLionel Sambuc 	/*
593*ebfedea0SLionel Sambuc 	 * subkey packets and corresponding signatures and optional
594*ebfedea0SLionel Sambuc 	 * revocation
595*ebfedea0SLionel Sambuc 	 */
596*ebfedea0SLionel Sambuc 
597*ebfedea0SLionel Sambuc 	if (armoured) {
598*ebfedea0SLionel Sambuc 		pgp_writer_info_finalise(&output->errors, &output->writer);
599*ebfedea0SLionel Sambuc 		pgp_writer_pop(output);
600*ebfedea0SLionel Sambuc 	}
601*ebfedea0SLionel Sambuc 	return 1;
602*ebfedea0SLionel Sambuc }
603*ebfedea0SLionel Sambuc 
604*ebfedea0SLionel Sambuc /**
605*ebfedea0SLionel Sambuc  * \ingroup Core_WritePackets
606*ebfedea0SLionel Sambuc  * \brief Writes one RSA public key packet.
607*ebfedea0SLionel Sambuc  * \param t Creation time
608*ebfedea0SLionel Sambuc  * \param n RSA public modulus
609*ebfedea0SLionel Sambuc  * \param e RSA public encryption exponent
610*ebfedea0SLionel Sambuc  * \param output Writer settings
611*ebfedea0SLionel Sambuc  *
612*ebfedea0SLionel Sambuc  * \return 1 if OK, otherwise 0
613*ebfedea0SLionel Sambuc  */
614*ebfedea0SLionel Sambuc 
615*ebfedea0SLionel Sambuc unsigned
pgp_write_rsa_pubkey(time_t t,const BIGNUM * n,const BIGNUM * e,pgp_output_t * output)616*ebfedea0SLionel Sambuc pgp_write_rsa_pubkey(time_t t, const BIGNUM *n,
617*ebfedea0SLionel Sambuc 			 const BIGNUM *e,
618*ebfedea0SLionel Sambuc 			 pgp_output_t *output)
619*ebfedea0SLionel Sambuc {
620*ebfedea0SLionel Sambuc 	pgp_pubkey_t key;
621*ebfedea0SLionel Sambuc 
622*ebfedea0SLionel Sambuc 	pgp_fast_create_rsa_pubkey(&key, t, __UNCONST(n), __UNCONST(e));
623*ebfedea0SLionel Sambuc 	return write_struct_pubkey(output, &key);
624*ebfedea0SLionel Sambuc }
625*ebfedea0SLionel Sambuc 
626*ebfedea0SLionel Sambuc /**
627*ebfedea0SLionel Sambuc  * \ingroup Core_Create
628*ebfedea0SLionel Sambuc  * \param out
629*ebfedea0SLionel Sambuc  * \param key
630*ebfedea0SLionel Sambuc  * \param make_packet
631*ebfedea0SLionel Sambuc  */
632*ebfedea0SLionel Sambuc 
633*ebfedea0SLionel Sambuc void
pgp_build_pubkey(pgp_memory_t * out,const pgp_pubkey_t * key,unsigned make_packet)634*ebfedea0SLionel Sambuc pgp_build_pubkey(pgp_memory_t *out, const pgp_pubkey_t *key,
635*ebfedea0SLionel Sambuc 		     unsigned make_packet)
636*ebfedea0SLionel Sambuc {
637*ebfedea0SLionel Sambuc 	pgp_output_t *output;
638*ebfedea0SLionel Sambuc 
639*ebfedea0SLionel Sambuc 	output = pgp_output_new();
640*ebfedea0SLionel Sambuc 	pgp_memory_init(out, 128);
641*ebfedea0SLionel Sambuc 	pgp_writer_set_memory(output, out);
642*ebfedea0SLionel Sambuc 	write_pubkey_body(key, output);
643*ebfedea0SLionel Sambuc 	if (make_packet) {
644*ebfedea0SLionel Sambuc 		pgp_memory_make_packet(out, PGP_PTAG_CT_PUBLIC_KEY);
645*ebfedea0SLionel Sambuc 	}
646*ebfedea0SLionel Sambuc 	pgp_output_delete(output);
647*ebfedea0SLionel Sambuc }
648*ebfedea0SLionel Sambuc 
649*ebfedea0SLionel Sambuc /**
650*ebfedea0SLionel Sambuc  * \ingroup Core_Create
651*ebfedea0SLionel Sambuc  *
652*ebfedea0SLionel Sambuc  * Create an RSA secret key structure. If a parameter is marked as
653*ebfedea0SLionel Sambuc  * [OPTIONAL], then it can be omitted and will be calculated from
654*ebfedea0SLionel Sambuc  * other params - or, in the case of e, will default to 0x10001.
655*ebfedea0SLionel Sambuc  *
656*ebfedea0SLionel Sambuc  * Parameters are _not_ copied, so will be freed if the structure is
657*ebfedea0SLionel Sambuc  * freed.
658*ebfedea0SLionel Sambuc  *
659*ebfedea0SLionel Sambuc  * \param key The key structure to be initialised.
660*ebfedea0SLionel Sambuc  * \param t
661*ebfedea0SLionel Sambuc  * \param d The RSA parameter d (=e^-1 mod (p-1)(q-1)) [OPTIONAL]
662*ebfedea0SLionel Sambuc  * \param p The RSA parameter p
663*ebfedea0SLionel Sambuc  * \param q The RSA parameter q (q > p)
664*ebfedea0SLionel Sambuc  * \param u The RSA parameter u (=p^-1 mod q) [OPTIONAL]
665*ebfedea0SLionel Sambuc  * \param n The RSA public parameter n (=p*q) [OPTIONAL]
666*ebfedea0SLionel Sambuc  * \param e The RSA public parameter e */
667*ebfedea0SLionel Sambuc 
668*ebfedea0SLionel Sambuc 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)669*ebfedea0SLionel Sambuc pgp_fast_create_rsa_seckey(pgp_seckey_t *key, time_t t,
670*ebfedea0SLionel Sambuc 			     BIGNUM *d, BIGNUM *p, BIGNUM *q, BIGNUM *u,
671*ebfedea0SLionel Sambuc 			       BIGNUM *n, BIGNUM *e)
672*ebfedea0SLionel Sambuc {
673*ebfedea0SLionel Sambuc 	pgp_fast_create_rsa_pubkey(&key->pubkey, t, n, e);
674*ebfedea0SLionel Sambuc 
675*ebfedea0SLionel Sambuc 	/* XXX: calculate optionals */
676*ebfedea0SLionel Sambuc 	key->key.rsa.d = d;
677*ebfedea0SLionel Sambuc 	key->key.rsa.p = p;
678*ebfedea0SLionel Sambuc 	key->key.rsa.q = q;
679*ebfedea0SLionel Sambuc 	key->key.rsa.u = u;
680*ebfedea0SLionel Sambuc 
681*ebfedea0SLionel Sambuc 	key->s2k_usage = PGP_S2KU_NONE;
682*ebfedea0SLionel Sambuc 
683*ebfedea0SLionel Sambuc 	/* XXX: sanity check and add errors... */
684*ebfedea0SLionel Sambuc }
685*ebfedea0SLionel Sambuc 
686*ebfedea0SLionel Sambuc /**
687*ebfedea0SLionel Sambuc  * \ingroup Core_WritePackets
688*ebfedea0SLionel Sambuc  * \brief Writes a Secret Key packet.
689*ebfedea0SLionel Sambuc  * \param key The secret key
690*ebfedea0SLionel Sambuc  * \param passphrase The passphrase
691*ebfedea0SLionel Sambuc  * \param pplen Length of passphrase
692*ebfedea0SLionel Sambuc  * \param output
693*ebfedea0SLionel Sambuc  * \return 1 if OK; else 0
694*ebfedea0SLionel Sambuc  */
695*ebfedea0SLionel Sambuc unsigned
pgp_write_struct_seckey(const pgp_seckey_t * key,const uint8_t * passphrase,const size_t pplen,pgp_output_t * output)696*ebfedea0SLionel Sambuc pgp_write_struct_seckey(const pgp_seckey_t *key,
697*ebfedea0SLionel Sambuc 			    const uint8_t *passphrase,
698*ebfedea0SLionel Sambuc 			    const size_t pplen,
699*ebfedea0SLionel Sambuc 			    pgp_output_t *output)
700*ebfedea0SLionel Sambuc {
701*ebfedea0SLionel Sambuc 	int             length = 0;
702*ebfedea0SLionel Sambuc 
703*ebfedea0SLionel Sambuc 	if (key->pubkey.version != 4) {
704*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
705*ebfedea0SLionel Sambuc 			"pgp_write_struct_seckey: public key version\n");
706*ebfedea0SLionel Sambuc 		return 0;
707*ebfedea0SLionel Sambuc 	}
708*ebfedea0SLionel Sambuc 
709*ebfedea0SLionel Sambuc 	/* Ref: RFC4880 Section 5.5.3 */
710*ebfedea0SLionel Sambuc 
711*ebfedea0SLionel Sambuc 	/* pubkey, excluding MPIs */
712*ebfedea0SLionel Sambuc 	length += 1 + 4 + 1 + 1;
713*ebfedea0SLionel Sambuc 
714*ebfedea0SLionel Sambuc 	/* s2k usage */
715*ebfedea0SLionel Sambuc 	length += 1;
716*ebfedea0SLionel Sambuc 
717*ebfedea0SLionel Sambuc 	switch (key->s2k_usage) {
718*ebfedea0SLionel Sambuc 	case PGP_S2KU_NONE:
719*ebfedea0SLionel Sambuc 		/* nothing to add */
720*ebfedea0SLionel Sambuc 		break;
721*ebfedea0SLionel Sambuc 
722*ebfedea0SLionel Sambuc 	case PGP_S2KU_ENCRYPTED_AND_HASHED:	/* 254 */
723*ebfedea0SLionel Sambuc 	case PGP_S2KU_ENCRYPTED:	/* 255 */
724*ebfedea0SLionel Sambuc 
725*ebfedea0SLionel Sambuc 		/* Ref: RFC4880 Section 3.7 */
726*ebfedea0SLionel Sambuc 		length += 1;	/* s2k_specifier */
727*ebfedea0SLionel Sambuc 
728*ebfedea0SLionel Sambuc 		switch (key->s2k_specifier) {
729*ebfedea0SLionel Sambuc 		case PGP_S2KS_SIMPLE:
730*ebfedea0SLionel Sambuc 			length += 1;	/* hash algorithm */
731*ebfedea0SLionel Sambuc 			break;
732*ebfedea0SLionel Sambuc 
733*ebfedea0SLionel Sambuc 		case PGP_S2KS_SALTED:
734*ebfedea0SLionel Sambuc 			length += 1 + 8;	/* hash algorithm + salt */
735*ebfedea0SLionel Sambuc 			break;
736*ebfedea0SLionel Sambuc 
737*ebfedea0SLionel Sambuc 		case PGP_S2KS_ITERATED_AND_SALTED:
738*ebfedea0SLionel Sambuc 			length += 1 + 8 + 1;	/* hash algorithm, salt +
739*ebfedea0SLionel Sambuc 						 * count */
740*ebfedea0SLionel Sambuc 			break;
741*ebfedea0SLionel Sambuc 
742*ebfedea0SLionel Sambuc 		default:
743*ebfedea0SLionel Sambuc 			(void) fprintf(stderr,
744*ebfedea0SLionel Sambuc 				"pgp_write_struct_seckey: s2k spec\n");
745*ebfedea0SLionel Sambuc 			return 0;
746*ebfedea0SLionel Sambuc 		}
747*ebfedea0SLionel Sambuc 		break;
748*ebfedea0SLionel Sambuc 
749*ebfedea0SLionel Sambuc 	default:
750*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
751*ebfedea0SLionel Sambuc 			"pgp_write_struct_seckey: s2k usage\n");
752*ebfedea0SLionel Sambuc 		return 0;
753*ebfedea0SLionel Sambuc 	}
754*ebfedea0SLionel Sambuc 
755*ebfedea0SLionel Sambuc 	/* IV */
756*ebfedea0SLionel Sambuc 	if (key->s2k_usage) {
757*ebfedea0SLionel Sambuc 		length += pgp_block_size(key->alg);
758*ebfedea0SLionel Sambuc 	}
759*ebfedea0SLionel Sambuc 	/* checksum or hash */
760*ebfedea0SLionel Sambuc 	switch (key->s2k_usage) {
761*ebfedea0SLionel Sambuc 	case PGP_S2KU_NONE:
762*ebfedea0SLionel Sambuc 	case PGP_S2KU_ENCRYPTED:
763*ebfedea0SLionel Sambuc 		length += 2;
764*ebfedea0SLionel Sambuc 		break;
765*ebfedea0SLionel Sambuc 
766*ebfedea0SLionel Sambuc 	case PGP_S2KU_ENCRYPTED_AND_HASHED:
767*ebfedea0SLionel Sambuc 		length += PGP_CHECKHASH_SIZE;
768*ebfedea0SLionel Sambuc 		break;
769*ebfedea0SLionel Sambuc 
770*ebfedea0SLionel Sambuc 	default:
771*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
772*ebfedea0SLionel Sambuc 			"pgp_write_struct_seckey: s2k cksum usage\n");
773*ebfedea0SLionel Sambuc 		return 0;
774*ebfedea0SLionel Sambuc 	}
775*ebfedea0SLionel Sambuc 
776*ebfedea0SLionel Sambuc 	/* secret key and public key MPIs */
777*ebfedea0SLionel Sambuc 	length += (unsigned)seckey_length(key);
778*ebfedea0SLionel Sambuc 
779*ebfedea0SLionel Sambuc 	return pgp_write_ptag(output, PGP_PTAG_CT_SECRET_KEY) &&
780*ebfedea0SLionel Sambuc 		/* pgp_write_length(output,1+4+1+1+seckey_length(key)+2) && */
781*ebfedea0SLionel Sambuc 		pgp_write_length(output, (unsigned)length) &&
782*ebfedea0SLionel Sambuc 		write_seckey_body(key, passphrase, pplen, output);
783*ebfedea0SLionel Sambuc }
784*ebfedea0SLionel Sambuc 
785*ebfedea0SLionel Sambuc /**
786*ebfedea0SLionel Sambuc  * \ingroup Core_Create
787*ebfedea0SLionel Sambuc  *
788*ebfedea0SLionel Sambuc  * \brief Create a new pgp_output_t structure.
789*ebfedea0SLionel Sambuc  *
790*ebfedea0SLionel Sambuc  * \return the new structure.
791*ebfedea0SLionel Sambuc  * \note It is the responsiblity of the caller to call pgp_output_delete().
792*ebfedea0SLionel Sambuc  * \sa pgp_output_delete()
793*ebfedea0SLionel Sambuc  */
794*ebfedea0SLionel Sambuc pgp_output_t *
pgp_output_new(void)795*ebfedea0SLionel Sambuc pgp_output_new(void)
796*ebfedea0SLionel Sambuc {
797*ebfedea0SLionel Sambuc 	return calloc(1, sizeof(pgp_output_t));
798*ebfedea0SLionel Sambuc }
799*ebfedea0SLionel Sambuc 
800*ebfedea0SLionel Sambuc /**
801*ebfedea0SLionel Sambuc  * \ingroup Core_Create
802*ebfedea0SLionel Sambuc  * \brief Delete an pgp_output_t strucut and associated resources.
803*ebfedea0SLionel Sambuc  *
804*ebfedea0SLionel Sambuc  * Delete an pgp_output_t structure. If a writer is active, then
805*ebfedea0SLionel Sambuc  * that is also deleted.
806*ebfedea0SLionel Sambuc  *
807*ebfedea0SLionel Sambuc  * \param info the structure to be deleted.
808*ebfedea0SLionel Sambuc  */
809*ebfedea0SLionel Sambuc void
pgp_output_delete(pgp_output_t * output)810*ebfedea0SLionel Sambuc pgp_output_delete(pgp_output_t *output)
811*ebfedea0SLionel Sambuc {
812*ebfedea0SLionel Sambuc 	pgp_writer_info_delete(&output->writer);
813*ebfedea0SLionel Sambuc 	free(output);
814*ebfedea0SLionel Sambuc }
815*ebfedea0SLionel Sambuc 
816*ebfedea0SLionel Sambuc /**
817*ebfedea0SLionel Sambuc  \ingroup Core_Create
818*ebfedea0SLionel Sambuc  \brief Calculate the checksum for a session key
819*ebfedea0SLionel Sambuc  \param sesskey Session Key to use
820*ebfedea0SLionel Sambuc  \param cs Checksum to be written
821*ebfedea0SLionel Sambuc  \return 1 if OK; else 0
822*ebfedea0SLionel Sambuc */
823*ebfedea0SLionel Sambuc unsigned
pgp_calc_sesskey_checksum(pgp_pk_sesskey_t * sesskey,uint8_t cs[2])824*ebfedea0SLionel Sambuc pgp_calc_sesskey_checksum(pgp_pk_sesskey_t *sesskey, uint8_t cs[2])
825*ebfedea0SLionel Sambuc {
826*ebfedea0SLionel Sambuc 	uint32_t   checksum = 0;
827*ebfedea0SLionel Sambuc 	unsigned    i;
828*ebfedea0SLionel Sambuc 
829*ebfedea0SLionel Sambuc 	if (!pgp_is_sa_supported(sesskey->symm_alg)) {
830*ebfedea0SLionel Sambuc 		return 0;
831*ebfedea0SLionel Sambuc 	}
832*ebfedea0SLionel Sambuc 
833*ebfedea0SLionel Sambuc 	for (i = 0; i < pgp_key_size(sesskey->symm_alg); i++) {
834*ebfedea0SLionel Sambuc 		checksum += sesskey->key[i];
835*ebfedea0SLionel Sambuc 	}
836*ebfedea0SLionel Sambuc 	checksum = checksum % 65536;
837*ebfedea0SLionel Sambuc 
838*ebfedea0SLionel Sambuc 	cs[0] = (uint8_t)((checksum >> 8) & 0xff);
839*ebfedea0SLionel Sambuc 	cs[1] = (uint8_t)(checksum & 0xff);
840*ebfedea0SLionel Sambuc 
841*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
842*ebfedea0SLionel Sambuc 		hexdump(stderr, "nm buf checksum:", cs, 2);
843*ebfedea0SLionel Sambuc 	}
844*ebfedea0SLionel Sambuc 	return 1;
845*ebfedea0SLionel Sambuc }
846*ebfedea0SLionel Sambuc 
847*ebfedea0SLionel Sambuc static unsigned
create_unencoded_m_buf(pgp_pk_sesskey_t * sesskey,pgp_crypt_t * cipherinfo,uint8_t * m_buf)848*ebfedea0SLionel Sambuc create_unencoded_m_buf(pgp_pk_sesskey_t *sesskey, pgp_crypt_t *cipherinfo, uint8_t *m_buf)
849*ebfedea0SLionel Sambuc {
850*ebfedea0SLionel Sambuc 	unsigned	i;
851*ebfedea0SLionel Sambuc 
852*ebfedea0SLionel Sambuc 	/* m_buf is the buffer which will be encoded in PKCS#1 block
853*ebfedea0SLionel Sambuc 	* encoding to form the "m" value used in the Public Key
854*ebfedea0SLionel Sambuc 	* Encrypted Session Key Packet as defined in RFC Section 5.1
855*ebfedea0SLionel Sambuc 	* "Public-Key Encrypted Session Key Packet"
856*ebfedea0SLionel Sambuc 	 */
857*ebfedea0SLionel Sambuc 	m_buf[0] = sesskey->symm_alg;
858*ebfedea0SLionel Sambuc 	for (i = 0; i < cipherinfo->keysize ; i++) {
859*ebfedea0SLionel Sambuc 		/* XXX - Flexelint - Warning 679: Suspicious Truncation in arithmetic expression combining with pointer */
860*ebfedea0SLionel Sambuc 		m_buf[1 + i] = sesskey->key[i];
861*ebfedea0SLionel Sambuc 	}
862*ebfedea0SLionel Sambuc 
863*ebfedea0SLionel Sambuc 	return pgp_calc_sesskey_checksum(sesskey,
864*ebfedea0SLionel Sambuc 				m_buf + 1 + cipherinfo->keysize);
865*ebfedea0SLionel Sambuc }
866*ebfedea0SLionel Sambuc 
867*ebfedea0SLionel Sambuc /**
868*ebfedea0SLionel Sambuc \ingroup Core_Create
869*ebfedea0SLionel Sambuc \brief implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC
870*ebfedea0SLionel Sambuc \param M
871*ebfedea0SLionel Sambuc \param mLen
872*ebfedea0SLionel Sambuc \param pubkey
873*ebfedea0SLionel Sambuc \param EM
874*ebfedea0SLionel Sambuc \return 1 if OK; else 0
875*ebfedea0SLionel Sambuc */
876*ebfedea0SLionel Sambuc unsigned
encode_m_buf(const uint8_t * M,size_t mLen,const pgp_pubkey_t * pubkey,uint8_t * EM)877*ebfedea0SLionel Sambuc encode_m_buf(const uint8_t *M, size_t mLen, const pgp_pubkey_t * pubkey,
878*ebfedea0SLionel Sambuc 	     uint8_t *EM)
879*ebfedea0SLionel Sambuc {
880*ebfedea0SLionel Sambuc 	unsigned    k;
881*ebfedea0SLionel Sambuc 	unsigned        i;
882*ebfedea0SLionel Sambuc 
883*ebfedea0SLionel Sambuc 	/* implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC */
884*ebfedea0SLionel Sambuc 	switch (pubkey->alg) {
885*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
886*ebfedea0SLionel Sambuc 		k = (unsigned)BN_num_bytes(pubkey->key.rsa.n);
887*ebfedea0SLionel Sambuc 		if (mLen > k - 11) {
888*ebfedea0SLionel Sambuc 			(void) fprintf(stderr, "encode_m_buf: message too long\n");
889*ebfedea0SLionel Sambuc 			return 0;
890*ebfedea0SLionel Sambuc 		}
891*ebfedea0SLionel Sambuc 		break;
892*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
893*ebfedea0SLionel Sambuc 	case PGP_PKA_ELGAMAL:
894*ebfedea0SLionel Sambuc 		k = (unsigned)BN_num_bytes(pubkey->key.elgamal.p);
895*ebfedea0SLionel Sambuc 		if (mLen > k - 11) {
896*ebfedea0SLionel Sambuc 			(void) fprintf(stderr, "encode_m_buf: message too long\n");
897*ebfedea0SLionel Sambuc 			return 0;
898*ebfedea0SLionel Sambuc 		}
899*ebfedea0SLionel Sambuc 		break;
900*ebfedea0SLionel Sambuc 	default:
901*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "encode_m_buf: pubkey algorithm\n");
902*ebfedea0SLionel Sambuc 		return 0;
903*ebfedea0SLionel Sambuc 	}
904*ebfedea0SLionel Sambuc 	/* these two bytes defined by RFC */
905*ebfedea0SLionel Sambuc 	EM[0] = 0x00;
906*ebfedea0SLionel Sambuc 	EM[1] = 0x02;
907*ebfedea0SLionel Sambuc 	/* add non-zero random bytes of length k - mLen -3 */
908*ebfedea0SLionel Sambuc 	for (i = 2; i < (k - mLen) - 1; ++i) {
909*ebfedea0SLionel Sambuc 		do {
910*ebfedea0SLionel Sambuc 			pgp_random(EM + i, 1);
911*ebfedea0SLionel Sambuc 		} while (EM[i] == 0);
912*ebfedea0SLionel Sambuc 	}
913*ebfedea0SLionel Sambuc 	if (i < 8 + 2) {
914*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "encode_m_buf: bad i len\n");
915*ebfedea0SLionel Sambuc 		return 0;
916*ebfedea0SLionel Sambuc 	}
917*ebfedea0SLionel Sambuc 	EM[i++] = 0;
918*ebfedea0SLionel Sambuc 	(void) memcpy(EM + i, M, mLen);
919*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
920*ebfedea0SLionel Sambuc 		hexdump(stderr, "Encoded Message:", EM, mLen);
921*ebfedea0SLionel Sambuc 	}
922*ebfedea0SLionel Sambuc 	return 1;
923*ebfedea0SLionel Sambuc }
924*ebfedea0SLionel Sambuc 
925*ebfedea0SLionel Sambuc /**
926*ebfedea0SLionel Sambuc  \ingroup Core_Create
927*ebfedea0SLionel Sambuc \brief Creates an pgp_pk_sesskey_t struct from keydata
928*ebfedea0SLionel Sambuc \param key Keydata to use
929*ebfedea0SLionel Sambuc \return pgp_pk_sesskey_t struct
930*ebfedea0SLionel Sambuc \note It is the caller's responsiblity to free the returned pointer
931*ebfedea0SLionel Sambuc \note Currently hard-coded to use CAST5
932*ebfedea0SLionel Sambuc \note Currently hard-coded to use RSA
933*ebfedea0SLionel Sambuc */
934*ebfedea0SLionel Sambuc pgp_pk_sesskey_t *
pgp_create_pk_sesskey(const pgp_key_t * key,const char * ciphername)935*ebfedea0SLionel Sambuc pgp_create_pk_sesskey(const pgp_key_t *key, const char *ciphername)
936*ebfedea0SLionel Sambuc {
937*ebfedea0SLionel Sambuc 	/*
938*ebfedea0SLionel Sambuc          * Creates a random session key and encrypts it for the given key
939*ebfedea0SLionel Sambuc          *
940*ebfedea0SLionel Sambuc          * Encryption used is PK,
941*ebfedea0SLionel Sambuc          * can be any, we're hardcoding RSA for now
942*ebfedea0SLionel Sambuc          */
943*ebfedea0SLionel Sambuc 
944*ebfedea0SLionel Sambuc 	const pgp_pubkey_t	*pubkey;
945*ebfedea0SLionel Sambuc 	pgp_pk_sesskey_t	*sesskey;
946*ebfedea0SLionel Sambuc 	pgp_symm_alg_t	 cipher;
947*ebfedea0SLionel Sambuc 	const uint8_t		*id;
948*ebfedea0SLionel Sambuc 	pgp_crypt_t		 cipherinfo;
949*ebfedea0SLionel Sambuc 	uint8_t			*unencoded_m_buf;
950*ebfedea0SLionel Sambuc 	uint8_t			*encoded_m_buf;
951*ebfedea0SLionel Sambuc 	size_t			 sz_encoded_m_buf;
952*ebfedea0SLionel Sambuc 
953*ebfedea0SLionel Sambuc 	if (memcmp(key->encid, "\0\0\0\0\0\0\0\0", 8) == 0) {
954*ebfedea0SLionel Sambuc 		pubkey = pgp_get_pubkey(key);
955*ebfedea0SLionel Sambuc 		id = key->sigid;
956*ebfedea0SLionel Sambuc 	} else {
957*ebfedea0SLionel Sambuc 		pubkey = &key->enckey;
958*ebfedea0SLionel Sambuc 		id = key->encid;
959*ebfedea0SLionel Sambuc 	}
960*ebfedea0SLionel Sambuc 	/* allocate unencoded_m_buf here */
961*ebfedea0SLionel Sambuc 	(void) memset(&cipherinfo, 0x0, sizeof(cipherinfo));
962*ebfedea0SLionel Sambuc 	pgp_crypt_any(&cipherinfo,
963*ebfedea0SLionel Sambuc 		cipher = pgp_str_to_cipher((ciphername) ? ciphername : "cast5"));
964*ebfedea0SLionel Sambuc 	unencoded_m_buf = calloc(1, cipherinfo.keysize + 1 + 2);
965*ebfedea0SLionel Sambuc 	if (unencoded_m_buf == NULL) {
966*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
967*ebfedea0SLionel Sambuc 			"pgp_create_pk_sesskey: can't allocate\n");
968*ebfedea0SLionel Sambuc 		return NULL;
969*ebfedea0SLionel Sambuc 	}
970*ebfedea0SLionel Sambuc 	switch(pubkey->alg) {
971*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
972*ebfedea0SLionel Sambuc 		sz_encoded_m_buf = BN_num_bytes(pubkey->key.rsa.n);
973*ebfedea0SLionel Sambuc 		break;
974*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
975*ebfedea0SLionel Sambuc 	case PGP_PKA_ELGAMAL:
976*ebfedea0SLionel Sambuc 		sz_encoded_m_buf = BN_num_bytes(pubkey->key.elgamal.p);
977*ebfedea0SLionel Sambuc 		break;
978*ebfedea0SLionel Sambuc 	default:
979*ebfedea0SLionel Sambuc 		sz_encoded_m_buf = 0;
980*ebfedea0SLionel Sambuc 		break;
981*ebfedea0SLionel Sambuc 	}
982*ebfedea0SLionel Sambuc 	if ((encoded_m_buf = calloc(1, sz_encoded_m_buf)) == NULL) {
983*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
984*ebfedea0SLionel Sambuc 			"pgp_create_pk_sesskey: can't allocate\n");
985*ebfedea0SLionel Sambuc 		free(unencoded_m_buf);
986*ebfedea0SLionel Sambuc 		return NULL;
987*ebfedea0SLionel Sambuc 	}
988*ebfedea0SLionel Sambuc 	if ((sesskey = calloc(1, sizeof(*sesskey))) == NULL) {
989*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
990*ebfedea0SLionel Sambuc 			"pgp_create_pk_sesskey: can't allocate\n");
991*ebfedea0SLionel Sambuc 		free(unencoded_m_buf);
992*ebfedea0SLionel Sambuc 		free(encoded_m_buf);
993*ebfedea0SLionel Sambuc 		return NULL;
994*ebfedea0SLionel Sambuc 	}
995*ebfedea0SLionel Sambuc 	if (key->type != PGP_PTAG_CT_PUBLIC_KEY) {
996*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
997*ebfedea0SLionel Sambuc 			"pgp_create_pk_sesskey: bad type\n");
998*ebfedea0SLionel Sambuc 		free(unencoded_m_buf);
999*ebfedea0SLionel Sambuc 		free(encoded_m_buf);
1000*ebfedea0SLionel Sambuc 		free(sesskey);
1001*ebfedea0SLionel Sambuc 		return NULL;
1002*ebfedea0SLionel Sambuc 	}
1003*ebfedea0SLionel Sambuc 	sesskey->version = PGP_PKSK_V3;
1004*ebfedea0SLionel Sambuc 	(void) memcpy(sesskey->key_id, id, sizeof(sesskey->key_id));
1005*ebfedea0SLionel Sambuc 
1006*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
1007*ebfedea0SLionel Sambuc 		hexdump(stderr, "Encrypting for keyid", id, sizeof(sesskey->key_id));
1008*ebfedea0SLionel Sambuc 	}
1009*ebfedea0SLionel Sambuc 	switch (pubkey->alg) {
1010*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
1011*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
1012*ebfedea0SLionel Sambuc 	case PGP_PKA_ELGAMAL:
1013*ebfedea0SLionel Sambuc 		break;
1014*ebfedea0SLionel Sambuc 	default:
1015*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
1016*ebfedea0SLionel Sambuc 			"pgp_create_pk_sesskey: bad pubkey algorithm\n");
1017*ebfedea0SLionel Sambuc 		free(unencoded_m_buf);
1018*ebfedea0SLionel Sambuc 		free(encoded_m_buf);
1019*ebfedea0SLionel Sambuc 		free(sesskey);
1020*ebfedea0SLionel Sambuc 		return NULL;
1021*ebfedea0SLionel Sambuc 	}
1022*ebfedea0SLionel Sambuc 	sesskey->alg = pubkey->alg;
1023*ebfedea0SLionel Sambuc 
1024*ebfedea0SLionel Sambuc 	sesskey->symm_alg = cipher;
1025*ebfedea0SLionel Sambuc 	pgp_random(sesskey->key, cipherinfo.keysize);
1026*ebfedea0SLionel Sambuc 
1027*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
1028*ebfedea0SLionel Sambuc 		hexdump(stderr, "sesskey created", sesskey->key,
1029*ebfedea0SLionel Sambuc 			cipherinfo.keysize + 1 + 2);
1030*ebfedea0SLionel Sambuc 	}
1031*ebfedea0SLionel Sambuc 	if (create_unencoded_m_buf(sesskey, &cipherinfo, &unencoded_m_buf[0]) == 0) {
1032*ebfedea0SLionel Sambuc 		free(unencoded_m_buf);
1033*ebfedea0SLionel Sambuc 		free(encoded_m_buf);
1034*ebfedea0SLionel Sambuc 		free(sesskey);
1035*ebfedea0SLionel Sambuc 		return NULL;
1036*ebfedea0SLionel Sambuc 	}
1037*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
1038*ebfedea0SLionel Sambuc 		hexdump(stderr, "uuencoded m buf", unencoded_m_buf, cipherinfo.keysize + 1 + 2);
1039*ebfedea0SLionel Sambuc 	}
1040*ebfedea0SLionel Sambuc 	encode_m_buf(unencoded_m_buf, cipherinfo.keysize + 1 + 2, pubkey, encoded_m_buf);
1041*ebfedea0SLionel Sambuc 
1042*ebfedea0SLionel Sambuc 	/* and encrypt it */
1043*ebfedea0SLionel Sambuc 	switch (key->key.pubkey.alg) {
1044*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
1045*ebfedea0SLionel Sambuc 		if (!pgp_rsa_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey,
1046*ebfedea0SLionel Sambuc 				&sesskey->params)) {
1047*ebfedea0SLionel Sambuc 			free(unencoded_m_buf);
1048*ebfedea0SLionel Sambuc 			free(encoded_m_buf);
1049*ebfedea0SLionel Sambuc 			free(sesskey);
1050*ebfedea0SLionel Sambuc 			return NULL;
1051*ebfedea0SLionel Sambuc 		}
1052*ebfedea0SLionel Sambuc 		break;
1053*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
1054*ebfedea0SLionel Sambuc 	case PGP_PKA_ELGAMAL:
1055*ebfedea0SLionel Sambuc 		if (!pgp_elgamal_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey,
1056*ebfedea0SLionel Sambuc 				&sesskey->params)) {
1057*ebfedea0SLionel Sambuc 			free(unencoded_m_buf);
1058*ebfedea0SLionel Sambuc 			free(encoded_m_buf);
1059*ebfedea0SLionel Sambuc 			free(sesskey);
1060*ebfedea0SLionel Sambuc 			return NULL;
1061*ebfedea0SLionel Sambuc 		}
1062*ebfedea0SLionel Sambuc 		break;
1063*ebfedea0SLionel Sambuc 	default:
1064*ebfedea0SLionel Sambuc 		/* will not get here - for lint only */
1065*ebfedea0SLionel Sambuc 		break;
1066*ebfedea0SLionel Sambuc 	}
1067*ebfedea0SLionel Sambuc 	free(unencoded_m_buf);
1068*ebfedea0SLionel Sambuc 	free(encoded_m_buf);
1069*ebfedea0SLionel Sambuc 	return sesskey;
1070*ebfedea0SLionel Sambuc }
1071*ebfedea0SLionel Sambuc 
1072*ebfedea0SLionel Sambuc /**
1073*ebfedea0SLionel Sambuc \ingroup Core_WritePackets
1074*ebfedea0SLionel Sambuc \brief Writes Public Key Session Key packet
1075*ebfedea0SLionel Sambuc \param info Write settings
1076*ebfedea0SLionel Sambuc \param pksk Public Key Session Key to write out
1077*ebfedea0SLionel Sambuc \return 1 if OK; else 0
1078*ebfedea0SLionel Sambuc */
1079*ebfedea0SLionel Sambuc unsigned
pgp_write_pk_sesskey(pgp_output_t * output,pgp_pk_sesskey_t * pksk)1080*ebfedea0SLionel Sambuc pgp_write_pk_sesskey(pgp_output_t *output, pgp_pk_sesskey_t *pksk)
1081*ebfedea0SLionel Sambuc {
1082*ebfedea0SLionel Sambuc 	/* XXX - Flexelint - Pointer parameter 'pksk' (line 1076) could be declared as pointing to const */
1083*ebfedea0SLionel Sambuc 	if (pksk == NULL) {
1084*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
1085*ebfedea0SLionel Sambuc 			"pgp_write_pk_sesskey: NULL pksk\n");
1086*ebfedea0SLionel Sambuc 		return 0;
1087*ebfedea0SLionel Sambuc 	}
1088*ebfedea0SLionel Sambuc 	switch (pksk->alg) {
1089*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
1090*ebfedea0SLionel Sambuc 		return pgp_write_ptag(output, PGP_PTAG_CT_PK_SESSION_KEY) &&
1091*ebfedea0SLionel Sambuc 			pgp_write_length(output, (unsigned)(1 + 8 + 1 +
1092*ebfedea0SLionel Sambuc 				BN_num_bytes(pksk->params.rsa.encrypted_m) + 2)) &&
1093*ebfedea0SLionel Sambuc 			pgp_write_scalar(output, (unsigned)pksk->version, 1) &&
1094*ebfedea0SLionel Sambuc 			pgp_write(output, pksk->key_id, 8) &&
1095*ebfedea0SLionel Sambuc 			pgp_write_scalar(output, (unsigned)pksk->alg, 1) &&
1096*ebfedea0SLionel Sambuc 			pgp_write_mpi(output, pksk->params.rsa.encrypted_m)
1097*ebfedea0SLionel Sambuc 			/* ??	&& pgp_write_scalar(output, 0, 2); */
1098*ebfedea0SLionel Sambuc 			;
1099*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
1100*ebfedea0SLionel Sambuc 	case PGP_PKA_ELGAMAL:
1101*ebfedea0SLionel Sambuc 		return pgp_write_ptag(output, PGP_PTAG_CT_PK_SESSION_KEY) &&
1102*ebfedea0SLionel Sambuc 			pgp_write_length(output, (unsigned)(1 + 8 + 1 +
1103*ebfedea0SLionel Sambuc 				BN_num_bytes(pksk->params.elgamal.g_to_k) + 2 +
1104*ebfedea0SLionel Sambuc 				BN_num_bytes(pksk->params.elgamal.encrypted_m) + 2)) &&
1105*ebfedea0SLionel Sambuc 			pgp_write_scalar(output, (unsigned)pksk->version, 1) &&
1106*ebfedea0SLionel Sambuc 			pgp_write(output, pksk->key_id, 8) &&
1107*ebfedea0SLionel Sambuc 			pgp_write_scalar(output, (unsigned)pksk->alg, 1) &&
1108*ebfedea0SLionel Sambuc 			pgp_write_mpi(output, pksk->params.elgamal.g_to_k) &&
1109*ebfedea0SLionel Sambuc 			pgp_write_mpi(output, pksk->params.elgamal.encrypted_m)
1110*ebfedea0SLionel Sambuc 			/* ??	&& pgp_write_scalar(output, 0, 2); */
1111*ebfedea0SLionel Sambuc 			;
1112*ebfedea0SLionel Sambuc 	default:
1113*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
1114*ebfedea0SLionel Sambuc 			"pgp_write_pk_sesskey: bad algorithm\n");
1115*ebfedea0SLionel Sambuc 		return 0;
1116*ebfedea0SLionel Sambuc 	}
1117*ebfedea0SLionel Sambuc }
1118*ebfedea0SLionel Sambuc 
1119*ebfedea0SLionel Sambuc /**
1120*ebfedea0SLionel Sambuc \ingroup Core_WritePackets
1121*ebfedea0SLionel Sambuc \brief Writes MDC packet
1122*ebfedea0SLionel Sambuc \param hashed Hash for MDC
1123*ebfedea0SLionel Sambuc \param output Write settings
1124*ebfedea0SLionel Sambuc \return 1 if OK; else 0
1125*ebfedea0SLionel Sambuc */
1126*ebfedea0SLionel Sambuc 
1127*ebfedea0SLionel Sambuc unsigned
pgp_write_mdc(pgp_output_t * output,const uint8_t * hashed)1128*ebfedea0SLionel Sambuc pgp_write_mdc(pgp_output_t *output, const uint8_t *hashed)
1129*ebfedea0SLionel Sambuc {
1130*ebfedea0SLionel Sambuc 	/* write it out */
1131*ebfedea0SLionel Sambuc 	return pgp_write_ptag(output, PGP_PTAG_CT_MDC) &&
1132*ebfedea0SLionel Sambuc 		pgp_write_length(output, PGP_SHA1_HASH_SIZE) &&
1133*ebfedea0SLionel Sambuc 		pgp_write(output, hashed, PGP_SHA1_HASH_SIZE);
1134*ebfedea0SLionel Sambuc }
1135*ebfedea0SLionel Sambuc 
1136*ebfedea0SLionel Sambuc /**
1137*ebfedea0SLionel Sambuc \ingroup Core_WritePackets
1138*ebfedea0SLionel Sambuc \brief Writes Literal Data packet from buffer
1139*ebfedea0SLionel Sambuc \param data Buffer to write out
1140*ebfedea0SLionel Sambuc \param maxlen Max length of buffer
1141*ebfedea0SLionel Sambuc \param type Literal Data Type
1142*ebfedea0SLionel Sambuc \param output Write settings
1143*ebfedea0SLionel Sambuc \return 1 if OK; else 0
1144*ebfedea0SLionel Sambuc */
1145*ebfedea0SLionel Sambuc unsigned
pgp_write_litdata(pgp_output_t * output,const uint8_t * data,const int maxlen,const pgp_litdata_enum type)1146*ebfedea0SLionel Sambuc pgp_write_litdata(pgp_output_t *output,
1147*ebfedea0SLionel Sambuc 			const uint8_t *data,
1148*ebfedea0SLionel Sambuc 			const int maxlen,
1149*ebfedea0SLionel Sambuc 			const pgp_litdata_enum type)
1150*ebfedea0SLionel Sambuc {
1151*ebfedea0SLionel Sambuc 	/*
1152*ebfedea0SLionel Sambuc          * RFC4880 does not specify a meaning for filename or date.
1153*ebfedea0SLionel Sambuc          * It is implementation-dependent.
1154*ebfedea0SLionel Sambuc          * We will not implement them.
1155*ebfedea0SLionel Sambuc          */
1156*ebfedea0SLionel Sambuc 	/* \todo do we need to check text data for <cr><lf> line endings ? */
1157*ebfedea0SLionel Sambuc 	return pgp_write_ptag(output, PGP_PTAG_CT_LITDATA) &&
1158*ebfedea0SLionel Sambuc 		pgp_write_length(output, (unsigned)(1 + 1 + 4 + maxlen)) &&
1159*ebfedea0SLionel Sambuc 		pgp_write_scalar(output, (unsigned)type, 1) &&
1160*ebfedea0SLionel Sambuc 		pgp_write_scalar(output, 0, 1) &&
1161*ebfedea0SLionel Sambuc 		pgp_write_scalar(output, 0, 4) &&
1162*ebfedea0SLionel Sambuc 		pgp_write(output, data, (unsigned)maxlen);
1163*ebfedea0SLionel Sambuc }
1164*ebfedea0SLionel Sambuc 
1165*ebfedea0SLionel Sambuc /**
1166*ebfedea0SLionel Sambuc \ingroup Core_WritePackets
1167*ebfedea0SLionel Sambuc \brief Writes Literal Data packet from contents of file
1168*ebfedea0SLionel Sambuc \param filename Name of file to read from
1169*ebfedea0SLionel Sambuc \param type Literal Data Type
1170*ebfedea0SLionel Sambuc \param output Write settings
1171*ebfedea0SLionel Sambuc \return 1 if OK; else 0
1172*ebfedea0SLionel Sambuc */
1173*ebfedea0SLionel Sambuc 
1174*ebfedea0SLionel Sambuc unsigned
pgp_fileread_litdata(const char * filename,const pgp_litdata_enum type,pgp_output_t * output)1175*ebfedea0SLionel Sambuc pgp_fileread_litdata(const char *filename,
1176*ebfedea0SLionel Sambuc 				 const pgp_litdata_enum type,
1177*ebfedea0SLionel Sambuc 				 pgp_output_t *output)
1178*ebfedea0SLionel Sambuc {
1179*ebfedea0SLionel Sambuc 	pgp_memory_t	*mem;
1180*ebfedea0SLionel Sambuc 	unsigned   	 ret;
1181*ebfedea0SLionel Sambuc 	int		 len;
1182*ebfedea0SLionel Sambuc 
1183*ebfedea0SLionel Sambuc 	mem = pgp_memory_new();
1184*ebfedea0SLionel Sambuc 	if (!pgp_mem_readfile(mem, filename)) {
1185*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "pgp_mem_readfile of '%s' failed\n", filename);
1186*ebfedea0SLionel Sambuc 		return 0;
1187*ebfedea0SLionel Sambuc 	}
1188*ebfedea0SLionel Sambuc 	len = (int)pgp_mem_len(mem);
1189*ebfedea0SLionel Sambuc 	ret = pgp_write_litdata(output, pgp_mem_data(mem), len, type);
1190*ebfedea0SLionel Sambuc 	pgp_memory_free(mem);
1191*ebfedea0SLionel Sambuc 	return ret;
1192*ebfedea0SLionel Sambuc }
1193*ebfedea0SLionel Sambuc 
1194*ebfedea0SLionel Sambuc /**
1195*ebfedea0SLionel Sambuc    \ingroup HighLevel_General
1196*ebfedea0SLionel Sambuc 
1197*ebfedea0SLionel Sambuc    \brief Writes contents of buffer into file
1198*ebfedea0SLionel Sambuc 
1199*ebfedea0SLionel Sambuc    \param filename Filename to write to
1200*ebfedea0SLionel Sambuc    \param buf Buffer to write to file
1201*ebfedea0SLionel Sambuc    \param len Size of buffer
1202*ebfedea0SLionel Sambuc    \param overwrite Flag to set whether to overwrite an existing file
1203*ebfedea0SLionel Sambuc    \return 1 if OK; 0 if error
1204*ebfedea0SLionel Sambuc */
1205*ebfedea0SLionel Sambuc 
1206*ebfedea0SLionel Sambuc int
pgp_filewrite(const char * filename,const char * buf,const size_t len,const unsigned overwrite)1207*ebfedea0SLionel Sambuc pgp_filewrite(const char *filename, const char *buf,
1208*ebfedea0SLionel Sambuc 			const size_t len, const unsigned overwrite)
1209*ebfedea0SLionel Sambuc {
1210*ebfedea0SLionel Sambuc 	int		flags;
1211*ebfedea0SLionel Sambuc 	int		fd;
1212*ebfedea0SLionel Sambuc 
1213*ebfedea0SLionel Sambuc 	flags = O_WRONLY | O_CREAT;
1214*ebfedea0SLionel Sambuc 	if (overwrite) {
1215*ebfedea0SLionel Sambuc 		flags |= O_TRUNC;
1216*ebfedea0SLionel Sambuc 	} else {
1217*ebfedea0SLionel Sambuc 		flags |= O_EXCL;
1218*ebfedea0SLionel Sambuc 	}
1219*ebfedea0SLionel Sambuc #ifdef O_BINARY
1220*ebfedea0SLionel Sambuc 	flags |= O_BINARY;
1221*ebfedea0SLionel Sambuc #endif
1222*ebfedea0SLionel Sambuc 	fd = open(filename, flags, 0600);
1223*ebfedea0SLionel Sambuc 	if (fd < 0) {
1224*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "can't open '%s'\n", filename);
1225*ebfedea0SLionel Sambuc 		return 0;
1226*ebfedea0SLionel Sambuc 	}
1227*ebfedea0SLionel Sambuc 	if (write(fd, buf, len) != (int)len) {
1228*ebfedea0SLionel Sambuc 		(void) close(fd);
1229*ebfedea0SLionel Sambuc 		return 0;
1230*ebfedea0SLionel Sambuc 	}
1231*ebfedea0SLionel Sambuc 
1232*ebfedea0SLionel Sambuc 	return (close(fd) == 0);
1233*ebfedea0SLionel Sambuc }
1234*ebfedea0SLionel Sambuc 
1235*ebfedea0SLionel Sambuc /**
1236*ebfedea0SLionel Sambuc \ingroup Core_WritePackets
1237*ebfedea0SLionel Sambuc \brief Write Symmetrically Encrypted packet
1238*ebfedea0SLionel Sambuc \param data Data to encrypt
1239*ebfedea0SLionel Sambuc \param len Length of data
1240*ebfedea0SLionel Sambuc \param output Write settings
1241*ebfedea0SLionel Sambuc \return 1 if OK; else 0
1242*ebfedea0SLionel Sambuc \note Hard-coded to use AES256
1243*ebfedea0SLionel Sambuc */
1244*ebfedea0SLionel Sambuc unsigned
pgp_write_symm_enc_data(const uint8_t * data,const int len,pgp_output_t * output)1245*ebfedea0SLionel Sambuc pgp_write_symm_enc_data(const uint8_t *data,
1246*ebfedea0SLionel Sambuc 				       const int len,
1247*ebfedea0SLionel Sambuc 				       pgp_output_t * output)
1248*ebfedea0SLionel Sambuc {
1249*ebfedea0SLionel Sambuc 	pgp_crypt_t	crypt_info;
1250*ebfedea0SLionel Sambuc 	uint8_t		*encrypted = (uint8_t *) NULL;
1251*ebfedea0SLionel Sambuc 	size_t		encrypted_sz;
1252*ebfedea0SLionel Sambuc 	int             done = 0;
1253*ebfedea0SLionel Sambuc 
1254*ebfedea0SLionel Sambuc 	/* \todo assume AES256 for now */
1255*ebfedea0SLionel Sambuc 	pgp_crypt_any(&crypt_info, PGP_SA_AES_256);
1256*ebfedea0SLionel Sambuc 	pgp_encrypt_init(&crypt_info);
1257*ebfedea0SLionel Sambuc 
1258*ebfedea0SLionel Sambuc 	encrypted_sz = (size_t)(len + crypt_info.blocksize + 2);
1259*ebfedea0SLionel Sambuc 	if ((encrypted = calloc(1, encrypted_sz)) == NULL) {
1260*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "can't allocate %" PRIsize "d\n",
1261*ebfedea0SLionel Sambuc 			encrypted_sz);
1262*ebfedea0SLionel Sambuc 		return 0;
1263*ebfedea0SLionel Sambuc 	}
1264*ebfedea0SLionel Sambuc 
1265*ebfedea0SLionel Sambuc 	done = (int)pgp_encrypt_se(&crypt_info, encrypted, data, (unsigned)len);
1266*ebfedea0SLionel Sambuc 	if (done != len) {
1267*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
1268*ebfedea0SLionel Sambuc 			"pgp_write_symm_enc_data: done != len\n");
1269*ebfedea0SLionel Sambuc 		return 0;
1270*ebfedea0SLionel Sambuc 	}
1271*ebfedea0SLionel Sambuc 
1272*ebfedea0SLionel Sambuc 	return pgp_write_ptag(output, PGP_PTAG_CT_SE_DATA) &&
1273*ebfedea0SLionel Sambuc 		pgp_write_length(output, (unsigned)(1 + encrypted_sz)) &&
1274*ebfedea0SLionel Sambuc 		pgp_write(output, data, (unsigned)len);
1275*ebfedea0SLionel Sambuc }
1276*ebfedea0SLionel Sambuc 
1277*ebfedea0SLionel Sambuc /**
1278*ebfedea0SLionel Sambuc \ingroup Core_WritePackets
1279*ebfedea0SLionel Sambuc \brief Write a One Pass Signature packet
1280*ebfedea0SLionel Sambuc \param seckey Secret Key to use
1281*ebfedea0SLionel Sambuc \param hash_alg Hash Algorithm to use
1282*ebfedea0SLionel Sambuc \param sig_type Signature type
1283*ebfedea0SLionel Sambuc \param output Write settings
1284*ebfedea0SLionel Sambuc \return 1 if OK; else 0
1285*ebfedea0SLionel Sambuc */
1286*ebfedea0SLionel Sambuc 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)1287*ebfedea0SLionel Sambuc pgp_write_one_pass_sig(pgp_output_t *output,
1288*ebfedea0SLionel Sambuc 			const pgp_seckey_t *seckey,
1289*ebfedea0SLionel Sambuc 			const pgp_hash_alg_t hash_alg,
1290*ebfedea0SLionel Sambuc 			const pgp_sig_type_t sig_type)
1291*ebfedea0SLionel Sambuc {
1292*ebfedea0SLionel Sambuc 	uint8_t   keyid[PGP_KEY_ID_SIZE];
1293*ebfedea0SLionel Sambuc 
1294*ebfedea0SLionel Sambuc 	pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, PGP_HASH_SHA1); /* XXX - hardcoded */
1295*ebfedea0SLionel Sambuc 	return pgp_write_ptag(output, PGP_PTAG_CT_1_PASS_SIG) &&
1296*ebfedea0SLionel Sambuc 		pgp_write_length(output, 1 + 1 + 1 + 1 + 8 + 1) &&
1297*ebfedea0SLionel Sambuc 		pgp_write_scalar(output, 3, 1)	/* version */ &&
1298*ebfedea0SLionel Sambuc 		pgp_write_scalar(output, (unsigned)sig_type, 1) &&
1299*ebfedea0SLionel Sambuc 		pgp_write_scalar(output, (unsigned)hash_alg, 1) &&
1300*ebfedea0SLionel Sambuc 		pgp_write_scalar(output, (unsigned)seckey->pubkey.alg, 1) &&
1301*ebfedea0SLionel Sambuc 		pgp_write(output, keyid, 8) &&
1302*ebfedea0SLionel Sambuc 		pgp_write_scalar(output, 1, 1);
1303*ebfedea0SLionel Sambuc }
1304