xref: /minix3/crypto/external/bsd/netpgp/dist/src/lib/signature.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: signature.c,v 1.34 2012/03/05 02:20:18 christos 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 
66*ebfedea0SLionel Sambuc #ifdef HAVE_FCNTL_H
67*ebfedea0SLionel Sambuc #include <fcntl.h>
68*ebfedea0SLionel Sambuc #endif
69*ebfedea0SLionel Sambuc 
70*ebfedea0SLionel Sambuc #include <string.h>
71*ebfedea0SLionel Sambuc 
72*ebfedea0SLionel Sambuc #ifdef HAVE_UNISTD_H
73*ebfedea0SLionel Sambuc #include <unistd.h>
74*ebfedea0SLionel Sambuc #endif
75*ebfedea0SLionel Sambuc 
76*ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL_DSA_H
77*ebfedea0SLionel Sambuc #include <openssl/dsa.h>
78*ebfedea0SLionel Sambuc #endif
79*ebfedea0SLionel Sambuc 
80*ebfedea0SLionel Sambuc #include "signature.h"
81*ebfedea0SLionel Sambuc #include "crypto.h"
82*ebfedea0SLionel Sambuc #include "create.h"
83*ebfedea0SLionel Sambuc #include "netpgpsdk.h"
84*ebfedea0SLionel Sambuc #include "readerwriter.h"
85*ebfedea0SLionel Sambuc #include "validate.h"
86*ebfedea0SLionel Sambuc #include "netpgpdefs.h"
87*ebfedea0SLionel Sambuc #include "netpgpdigest.h"
88*ebfedea0SLionel Sambuc 
89*ebfedea0SLionel Sambuc 
90*ebfedea0SLionel Sambuc /** \ingroup Core_Create
91*ebfedea0SLionel Sambuc  * needed for signature creation
92*ebfedea0SLionel Sambuc  */
93*ebfedea0SLionel Sambuc struct pgp_create_sig_t {
94*ebfedea0SLionel Sambuc 	pgp_hash_t		 hash;
95*ebfedea0SLionel Sambuc 	pgp_sig_t		 sig;
96*ebfedea0SLionel Sambuc 	pgp_memory_t		*mem;
97*ebfedea0SLionel Sambuc 	pgp_output_t		*output;	/* how to do the writing */
98*ebfedea0SLionel Sambuc 	unsigned		 hashoff;	/* hashed count offset */
99*ebfedea0SLionel Sambuc 	unsigned		 hashlen;
100*ebfedea0SLionel Sambuc 	unsigned 		 unhashoff;
101*ebfedea0SLionel Sambuc };
102*ebfedea0SLionel Sambuc 
103*ebfedea0SLionel Sambuc /**
104*ebfedea0SLionel Sambuc    \ingroup Core_Signature
105*ebfedea0SLionel Sambuc    Creates new pgp_create_sig_t
106*ebfedea0SLionel Sambuc    \return new pgp_create_sig_t
107*ebfedea0SLionel Sambuc    \note It is the caller's responsibility to call pgp_create_sig_delete()
108*ebfedea0SLionel Sambuc    \sa pgp_create_sig_delete()
109*ebfedea0SLionel Sambuc */
110*ebfedea0SLionel Sambuc pgp_create_sig_t *
pgp_create_sig_new(void)111*ebfedea0SLionel Sambuc pgp_create_sig_new(void)
112*ebfedea0SLionel Sambuc {
113*ebfedea0SLionel Sambuc 	return calloc(1, sizeof(pgp_create_sig_t));
114*ebfedea0SLionel Sambuc }
115*ebfedea0SLionel Sambuc 
116*ebfedea0SLionel Sambuc /**
117*ebfedea0SLionel Sambuc    \ingroup Core_Signature
118*ebfedea0SLionel Sambuc    Free signature and memory associated with it
119*ebfedea0SLionel Sambuc    \param sig struct to free
120*ebfedea0SLionel Sambuc    \sa pgp_create_sig_new()
121*ebfedea0SLionel Sambuc */
122*ebfedea0SLionel Sambuc void
pgp_create_sig_delete(pgp_create_sig_t * sig)123*ebfedea0SLionel Sambuc pgp_create_sig_delete(pgp_create_sig_t *sig)
124*ebfedea0SLionel Sambuc {
125*ebfedea0SLionel Sambuc 	pgp_output_delete(sig->output);
126*ebfedea0SLionel Sambuc 	sig->output = NULL;
127*ebfedea0SLionel Sambuc 	free(sig);
128*ebfedea0SLionel Sambuc }
129*ebfedea0SLionel Sambuc 
130*ebfedea0SLionel Sambuc #if 0
131*ebfedea0SLionel Sambuc void
pgp_dump_sig(pgp_sig_t * sig)132*ebfedea0SLionel Sambuc pgp_dump_sig(pgp_sig_t *sig)
133*ebfedea0SLionel Sambuc {
134*ebfedea0SLionel Sambuc }
135*ebfedea0SLionel Sambuc #endif
136*ebfedea0SLionel Sambuc 
137*ebfedea0SLionel Sambuc static uint8_t prefix_md5[] = {
138*ebfedea0SLionel Sambuc 	0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
139*ebfedea0SLionel Sambuc 	0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
140*ebfedea0SLionel Sambuc };
141*ebfedea0SLionel Sambuc 
142*ebfedea0SLionel Sambuc static uint8_t prefix_sha1[] = {
143*ebfedea0SLionel Sambuc 	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02,
144*ebfedea0SLionel Sambuc 	0x1A, 0x05, 0x00, 0x04, 0x14
145*ebfedea0SLionel Sambuc };
146*ebfedea0SLionel Sambuc 
147*ebfedea0SLionel Sambuc static uint8_t prefix_sha256[] = {
148*ebfedea0SLionel Sambuc 	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
149*ebfedea0SLionel Sambuc 	0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
150*ebfedea0SLionel Sambuc };
151*ebfedea0SLionel Sambuc 
152*ebfedea0SLionel Sambuc 
153*ebfedea0SLionel Sambuc /* XXX: both this and verify would be clearer if the signature were */
154*ebfedea0SLionel Sambuc /* treated as an MPI. */
155*ebfedea0SLionel Sambuc static int
rsa_sign(pgp_hash_t * hash,const pgp_rsa_pubkey_t * pubrsa,const pgp_rsa_seckey_t * secrsa,pgp_output_t * out)156*ebfedea0SLionel Sambuc rsa_sign(pgp_hash_t *hash,
157*ebfedea0SLionel Sambuc 	const pgp_rsa_pubkey_t *pubrsa,
158*ebfedea0SLionel Sambuc 	const pgp_rsa_seckey_t *secrsa,
159*ebfedea0SLionel Sambuc 	pgp_output_t *out)
160*ebfedea0SLionel Sambuc {
161*ebfedea0SLionel Sambuc 	unsigned        prefixsize;
162*ebfedea0SLionel Sambuc 	unsigned        expected;
163*ebfedea0SLionel Sambuc 	unsigned        hashsize;
164*ebfedea0SLionel Sambuc 	unsigned        keysize;
165*ebfedea0SLionel Sambuc 	unsigned        n;
166*ebfedea0SLionel Sambuc 	unsigned        t;
167*ebfedea0SLionel Sambuc 	uint8_t		hashbuf[NETPGP_BUFSIZ];
168*ebfedea0SLionel Sambuc 	uint8_t		sigbuf[NETPGP_BUFSIZ];
169*ebfedea0SLionel Sambuc 	uint8_t		*prefix;
170*ebfedea0SLionel Sambuc 	BIGNUM         *bn;
171*ebfedea0SLionel Sambuc 
172*ebfedea0SLionel Sambuc 	if (strcmp(hash->name, "SHA1") == 0) {
173*ebfedea0SLionel Sambuc 		hashsize = PGP_SHA1_HASH_SIZE + sizeof(prefix_sha1);
174*ebfedea0SLionel Sambuc 		prefix = prefix_sha1;
175*ebfedea0SLionel Sambuc 		prefixsize = sizeof(prefix_sha1);
176*ebfedea0SLionel Sambuc 		expected = PGP_SHA1_HASH_SIZE;
177*ebfedea0SLionel Sambuc 	} else {
178*ebfedea0SLionel Sambuc 		hashsize = PGP_SHA256_HASH_SIZE + sizeof(prefix_sha256);
179*ebfedea0SLionel Sambuc 		prefix = prefix_sha256;
180*ebfedea0SLionel Sambuc 		prefixsize = sizeof(prefix_sha256);
181*ebfedea0SLionel Sambuc 		expected = PGP_SHA256_HASH_SIZE;
182*ebfedea0SLionel Sambuc 	}
183*ebfedea0SLionel Sambuc 	keysize = (BN_num_bits(pubrsa->n) + 7) / 8;
184*ebfedea0SLionel Sambuc 	if (keysize > sizeof(hashbuf)) {
185*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "rsa_sign: keysize too big\n");
186*ebfedea0SLionel Sambuc 		return 0;
187*ebfedea0SLionel Sambuc 	}
188*ebfedea0SLionel Sambuc 	if (10 + hashsize > keysize) {
189*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "rsa_sign: hashsize too big\n");
190*ebfedea0SLionel Sambuc 		return 0;
191*ebfedea0SLionel Sambuc 	}
192*ebfedea0SLionel Sambuc 
193*ebfedea0SLionel Sambuc 	hashbuf[0] = 0;
194*ebfedea0SLionel Sambuc 	hashbuf[1] = 1;
195*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
196*ebfedea0SLionel Sambuc 		printf("rsa_sign: PS is %d\n", keysize - hashsize - 1 - 2);
197*ebfedea0SLionel Sambuc 	}
198*ebfedea0SLionel Sambuc 	for (n = 2; n < keysize - hashsize - 1; ++n) {
199*ebfedea0SLionel Sambuc 		hashbuf[n] = 0xff;
200*ebfedea0SLionel Sambuc 	}
201*ebfedea0SLionel Sambuc 	hashbuf[n++] = 0;
202*ebfedea0SLionel Sambuc 
203*ebfedea0SLionel Sambuc 	(void) memcpy(&hashbuf[n], prefix, prefixsize);
204*ebfedea0SLionel Sambuc 	n += prefixsize;
205*ebfedea0SLionel Sambuc 	if ((t = hash->finish(hash, &hashbuf[n])) != expected) {
206*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "rsa_sign: short %s hash\n", hash->name);
207*ebfedea0SLionel Sambuc 		return 0;
208*ebfedea0SLionel Sambuc 	}
209*ebfedea0SLionel Sambuc 
210*ebfedea0SLionel Sambuc 	pgp_write(out, &hashbuf[n], 2);
211*ebfedea0SLionel Sambuc 
212*ebfedea0SLionel Sambuc 	n += t;
213*ebfedea0SLionel Sambuc 	if (n != keysize) {
214*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "rsa_sign: n != keysize\n");
215*ebfedea0SLionel Sambuc 		return 0;
216*ebfedea0SLionel Sambuc 	}
217*ebfedea0SLionel Sambuc 
218*ebfedea0SLionel Sambuc 	t = pgp_rsa_private_encrypt(sigbuf, hashbuf, keysize, secrsa, pubrsa);
219*ebfedea0SLionel Sambuc 	bn = BN_bin2bn(sigbuf, (int)t, NULL);
220*ebfedea0SLionel Sambuc 	pgp_write_mpi(out, bn);
221*ebfedea0SLionel Sambuc 	BN_free(bn);
222*ebfedea0SLionel Sambuc 	return 1;
223*ebfedea0SLionel Sambuc }
224*ebfedea0SLionel Sambuc 
225*ebfedea0SLionel Sambuc static int
dsa_sign(pgp_hash_t * hash,const pgp_dsa_pubkey_t * dsa,const pgp_dsa_seckey_t * sdsa,pgp_output_t * output)226*ebfedea0SLionel Sambuc dsa_sign(pgp_hash_t *hash,
227*ebfedea0SLionel Sambuc 	 const pgp_dsa_pubkey_t *dsa,
228*ebfedea0SLionel Sambuc 	 const pgp_dsa_seckey_t *sdsa,
229*ebfedea0SLionel Sambuc 	 pgp_output_t *output)
230*ebfedea0SLionel Sambuc {
231*ebfedea0SLionel Sambuc 	unsigned        hashsize;
232*ebfedea0SLionel Sambuc 	unsigned        t;
233*ebfedea0SLionel Sambuc 	uint8_t		hashbuf[NETPGP_BUFSIZ];
234*ebfedea0SLionel Sambuc 	DSA_SIG        *dsasig;
235*ebfedea0SLionel Sambuc 
236*ebfedea0SLionel Sambuc 	/* hashsize must be "equal in size to the number of bits of q,  */
237*ebfedea0SLionel Sambuc 	/* the group generated by the DSA key's generator value */
238*ebfedea0SLionel Sambuc 	/* 160/8 = 20 */
239*ebfedea0SLionel Sambuc 
240*ebfedea0SLionel Sambuc 	hashsize = 20;
241*ebfedea0SLionel Sambuc 
242*ebfedea0SLionel Sambuc 	/* finalise hash */
243*ebfedea0SLionel Sambuc 	t = hash->finish(hash, &hashbuf[0]);
244*ebfedea0SLionel Sambuc 	if (t != 20) {
245*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "dsa_sign: hashfinish not 20\n");
246*ebfedea0SLionel Sambuc 		return 0;
247*ebfedea0SLionel Sambuc 	}
248*ebfedea0SLionel Sambuc 
249*ebfedea0SLionel Sambuc 	pgp_write(output, &hashbuf[0], 2);
250*ebfedea0SLionel Sambuc 
251*ebfedea0SLionel Sambuc 	/* write signature to buf */
252*ebfedea0SLionel Sambuc 	dsasig = pgp_dsa_sign(hashbuf, hashsize, sdsa, dsa);
253*ebfedea0SLionel Sambuc 
254*ebfedea0SLionel Sambuc 	/* convert and write the sig out to memory */
255*ebfedea0SLionel Sambuc 	pgp_write_mpi(output, dsasig->r);
256*ebfedea0SLionel Sambuc 	pgp_write_mpi(output, dsasig->s);
257*ebfedea0SLionel Sambuc 	DSA_SIG_free(dsasig);
258*ebfedea0SLionel Sambuc 	return 1;
259*ebfedea0SLionel Sambuc }
260*ebfedea0SLionel Sambuc 
261*ebfedea0SLionel Sambuc static unsigned
rsa_verify(pgp_hash_alg_t type,const uint8_t * hash,size_t hash_length,const pgp_rsa_sig_t * sig,const pgp_rsa_pubkey_t * pubrsa)262*ebfedea0SLionel Sambuc rsa_verify(pgp_hash_alg_t type,
263*ebfedea0SLionel Sambuc 	   const uint8_t *hash,
264*ebfedea0SLionel Sambuc 	   size_t hash_length,
265*ebfedea0SLionel Sambuc 	   const pgp_rsa_sig_t *sig,
266*ebfedea0SLionel Sambuc 	   const pgp_rsa_pubkey_t *pubrsa)
267*ebfedea0SLionel Sambuc {
268*ebfedea0SLionel Sambuc 	const uint8_t	*prefix;
269*ebfedea0SLionel Sambuc 	unsigned       	 n;
270*ebfedea0SLionel Sambuc 	unsigned       	 keysize;
271*ebfedea0SLionel Sambuc 	unsigned	 plen;
272*ebfedea0SLionel Sambuc 	unsigned	 debug_len_decrypted;
273*ebfedea0SLionel Sambuc 	uint8_t   	 sigbuf[NETPGP_BUFSIZ];
274*ebfedea0SLionel Sambuc 	uint8_t   	 hashbuf_from_sig[NETPGP_BUFSIZ];
275*ebfedea0SLionel Sambuc 
276*ebfedea0SLionel Sambuc 	plen = 0;
277*ebfedea0SLionel Sambuc 	prefix = (const uint8_t *) "";
278*ebfedea0SLionel Sambuc 	keysize = BN_num_bytes(pubrsa->n);
279*ebfedea0SLionel Sambuc 	/* RSA key can't be bigger than 65535 bits, so... */
280*ebfedea0SLionel Sambuc 	if (keysize > sizeof(hashbuf_from_sig)) {
281*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "rsa_verify: keysize too big\n");
282*ebfedea0SLionel Sambuc 		return 0;
283*ebfedea0SLionel Sambuc 	}
284*ebfedea0SLionel Sambuc 	if ((unsigned) BN_num_bits(sig->sig) > 8 * sizeof(sigbuf)) {
285*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "rsa_verify: BN_numbits too big\n");
286*ebfedea0SLionel Sambuc 		return 0;
287*ebfedea0SLionel Sambuc 	}
288*ebfedea0SLionel Sambuc 	BN_bn2bin(sig->sig, sigbuf);
289*ebfedea0SLionel Sambuc 
290*ebfedea0SLionel Sambuc 	n = pgp_rsa_public_decrypt(hashbuf_from_sig, sigbuf,
291*ebfedea0SLionel Sambuc 		(unsigned)(BN_num_bits(sig->sig) + 7) / 8, pubrsa);
292*ebfedea0SLionel Sambuc 	debug_len_decrypted = n;
293*ebfedea0SLionel Sambuc 
294*ebfedea0SLionel Sambuc 	if (n != keysize) {
295*ebfedea0SLionel Sambuc 		/* obviously, this includes error returns */
296*ebfedea0SLionel Sambuc 		return 0;
297*ebfedea0SLionel Sambuc 	}
298*ebfedea0SLionel Sambuc 
299*ebfedea0SLionel Sambuc 	/* XXX: why is there a leading 0? The first byte should be 1... */
300*ebfedea0SLionel Sambuc 	/* XXX: because the decrypt should use keysize and not sigsize? */
301*ebfedea0SLionel Sambuc 	if (hashbuf_from_sig[0] != 0 || hashbuf_from_sig[1] != 1) {
302*ebfedea0SLionel Sambuc 		return 0;
303*ebfedea0SLionel Sambuc 	}
304*ebfedea0SLionel Sambuc 
305*ebfedea0SLionel Sambuc 	switch (type) {
306*ebfedea0SLionel Sambuc 	case PGP_HASH_MD5:
307*ebfedea0SLionel Sambuc 		prefix = prefix_md5;
308*ebfedea0SLionel Sambuc 		plen = sizeof(prefix_md5);
309*ebfedea0SLionel Sambuc 		break;
310*ebfedea0SLionel Sambuc 	case PGP_HASH_SHA1:
311*ebfedea0SLionel Sambuc 		prefix = prefix_sha1;
312*ebfedea0SLionel Sambuc 		plen = sizeof(prefix_sha1);
313*ebfedea0SLionel Sambuc 		break;
314*ebfedea0SLionel Sambuc 	case PGP_HASH_SHA256:
315*ebfedea0SLionel Sambuc 		prefix = prefix_sha256;
316*ebfedea0SLionel Sambuc 		plen = sizeof(prefix_sha256);
317*ebfedea0SLionel Sambuc 		break;
318*ebfedea0SLionel Sambuc 	default:
319*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "Unknown hash algorithm: %d\n", type);
320*ebfedea0SLionel Sambuc 		return 0;
321*ebfedea0SLionel Sambuc 	}
322*ebfedea0SLionel Sambuc 
323*ebfedea0SLionel Sambuc 	if (keysize - plen - hash_length < 10) {
324*ebfedea0SLionel Sambuc 		return 0;
325*ebfedea0SLionel Sambuc 	}
326*ebfedea0SLionel Sambuc 
327*ebfedea0SLionel Sambuc 	for (n = 2; n < keysize - plen - hash_length - 1; ++n) {
328*ebfedea0SLionel Sambuc 		if (hashbuf_from_sig[n] != 0xff) {
329*ebfedea0SLionel Sambuc 			return 0;
330*ebfedea0SLionel Sambuc 		}
331*ebfedea0SLionel Sambuc 	}
332*ebfedea0SLionel Sambuc 
333*ebfedea0SLionel Sambuc 	if (hashbuf_from_sig[n++] != 0) {
334*ebfedea0SLionel Sambuc 		return 0;
335*ebfedea0SLionel Sambuc 	}
336*ebfedea0SLionel Sambuc 
337*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
338*ebfedea0SLionel Sambuc 		hexdump(stderr, "sig hashbuf", hashbuf_from_sig, debug_len_decrypted);
339*ebfedea0SLionel Sambuc 		hexdump(stderr, "prefix", prefix, plen);
340*ebfedea0SLionel Sambuc 		hexdump(stderr, "sig hash", &hashbuf_from_sig[n + plen], hash_length);
341*ebfedea0SLionel Sambuc 		hexdump(stderr, "input hash", hash, hash_length);
342*ebfedea0SLionel Sambuc 	}
343*ebfedea0SLionel Sambuc 	return (memcmp(&hashbuf_from_sig[n], prefix, plen) == 0 &&
344*ebfedea0SLionel Sambuc 	        memcmp(&hashbuf_from_sig[n + plen], hash, hash_length) == 0);
345*ebfedea0SLionel Sambuc }
346*ebfedea0SLionel Sambuc 
347*ebfedea0SLionel Sambuc static void
hash_add_key(pgp_hash_t * hash,const pgp_pubkey_t * key)348*ebfedea0SLionel Sambuc hash_add_key(pgp_hash_t *hash, const pgp_pubkey_t *key)
349*ebfedea0SLionel Sambuc {
350*ebfedea0SLionel Sambuc 	pgp_memory_t	*mem = pgp_memory_new();
351*ebfedea0SLionel Sambuc 	const unsigned 	 dontmakepacket = 0;
352*ebfedea0SLionel Sambuc 	size_t		 len;
353*ebfedea0SLionel Sambuc 
354*ebfedea0SLionel Sambuc 	pgp_build_pubkey(mem, key, dontmakepacket);
355*ebfedea0SLionel Sambuc 	len = pgp_mem_len(mem);
356*ebfedea0SLionel Sambuc 	pgp_hash_add_int(hash, 0x99, 1);
357*ebfedea0SLionel Sambuc 	pgp_hash_add_int(hash, (unsigned)len, 2);
358*ebfedea0SLionel Sambuc 	hash->add(hash, pgp_mem_data(mem), (unsigned)len);
359*ebfedea0SLionel Sambuc 	pgp_memory_free(mem);
360*ebfedea0SLionel Sambuc }
361*ebfedea0SLionel Sambuc 
362*ebfedea0SLionel Sambuc static void
initialise_hash(pgp_hash_t * hash,const pgp_sig_t * sig)363*ebfedea0SLionel Sambuc initialise_hash(pgp_hash_t *hash, const pgp_sig_t *sig)
364*ebfedea0SLionel Sambuc {
365*ebfedea0SLionel Sambuc 	pgp_hash_any(hash, sig->info.hash_alg);
366*ebfedea0SLionel Sambuc 	if (!hash->init(hash)) {
367*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
368*ebfedea0SLionel Sambuc 			"initialise_hash: bad hash init\n");
369*ebfedea0SLionel Sambuc 		/* just continue and die */
370*ebfedea0SLionel Sambuc 		/* XXX - agc - no way to return failure */
371*ebfedea0SLionel Sambuc 	}
372*ebfedea0SLionel Sambuc }
373*ebfedea0SLionel Sambuc 
374*ebfedea0SLionel Sambuc static void
init_key_sig(pgp_hash_t * hash,const pgp_sig_t * sig,const pgp_pubkey_t * key)375*ebfedea0SLionel Sambuc init_key_sig(pgp_hash_t *hash, const pgp_sig_t *sig,
376*ebfedea0SLionel Sambuc 		   const pgp_pubkey_t *key)
377*ebfedea0SLionel Sambuc {
378*ebfedea0SLionel Sambuc 	initialise_hash(hash, sig);
379*ebfedea0SLionel Sambuc 	hash_add_key(hash, key);
380*ebfedea0SLionel Sambuc }
381*ebfedea0SLionel Sambuc 
382*ebfedea0SLionel Sambuc static void
hash_add_trailer(pgp_hash_t * hash,const pgp_sig_t * sig,const uint8_t * raw_packet)383*ebfedea0SLionel Sambuc hash_add_trailer(pgp_hash_t *hash, const pgp_sig_t *sig,
384*ebfedea0SLionel Sambuc 		 const uint8_t *raw_packet)
385*ebfedea0SLionel Sambuc {
386*ebfedea0SLionel Sambuc 	if (sig->info.version == PGP_V4) {
387*ebfedea0SLionel Sambuc 		if (raw_packet) {
388*ebfedea0SLionel Sambuc 			hash->add(hash, raw_packet + sig->v4_hashstart,
389*ebfedea0SLionel Sambuc 				  (unsigned)sig->info.v4_hashlen);
390*ebfedea0SLionel Sambuc 		}
391*ebfedea0SLionel Sambuc 		pgp_hash_add_int(hash, (unsigned)sig->info.version, 1);
392*ebfedea0SLionel Sambuc 		pgp_hash_add_int(hash, 0xff, 1);
393*ebfedea0SLionel Sambuc 		pgp_hash_add_int(hash, (unsigned)sig->info.v4_hashlen, 4);
394*ebfedea0SLionel Sambuc 	} else {
395*ebfedea0SLionel Sambuc 		pgp_hash_add_int(hash, (unsigned)sig->info.type, 1);
396*ebfedea0SLionel Sambuc 		pgp_hash_add_int(hash, (unsigned)sig->info.birthtime, 4);
397*ebfedea0SLionel Sambuc 	}
398*ebfedea0SLionel Sambuc }
399*ebfedea0SLionel Sambuc 
400*ebfedea0SLionel Sambuc /**
401*ebfedea0SLionel Sambuc    \ingroup Core_Signature
402*ebfedea0SLionel Sambuc    \brief Checks a signature
403*ebfedea0SLionel Sambuc    \param hash Signature Hash to be checked
404*ebfedea0SLionel Sambuc    \param length Signature Length
405*ebfedea0SLionel Sambuc    \param sig The Signature to be checked
406*ebfedea0SLionel Sambuc    \param signer The signer's public key
407*ebfedea0SLionel Sambuc    \return 1 if good; else 0
408*ebfedea0SLionel Sambuc */
409*ebfedea0SLionel Sambuc unsigned
pgp_check_sig(const uint8_t * hash,unsigned length,const pgp_sig_t * sig,const pgp_pubkey_t * signer)410*ebfedea0SLionel Sambuc pgp_check_sig(const uint8_t *hash, unsigned length,
411*ebfedea0SLionel Sambuc 		    const pgp_sig_t * sig,
412*ebfedea0SLionel Sambuc 		    const pgp_pubkey_t * signer)
413*ebfedea0SLionel Sambuc {
414*ebfedea0SLionel Sambuc 	unsigned   ret;
415*ebfedea0SLionel Sambuc 
416*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
417*ebfedea0SLionel Sambuc 		hexdump(stdout, "hash", hash, length);
418*ebfedea0SLionel Sambuc 	}
419*ebfedea0SLionel Sambuc 	ret = 0;
420*ebfedea0SLionel Sambuc 	switch (sig->info.key_alg) {
421*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
422*ebfedea0SLionel Sambuc 		ret = pgp_dsa_verify(hash, length, &sig->info.sig.dsa,
423*ebfedea0SLionel Sambuc 				&signer->key.dsa);
424*ebfedea0SLionel Sambuc 		break;
425*ebfedea0SLionel Sambuc 
426*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
427*ebfedea0SLionel Sambuc 		ret = rsa_verify(sig->info.hash_alg, hash, length,
428*ebfedea0SLionel Sambuc 				&sig->info.sig.rsa,
429*ebfedea0SLionel Sambuc 				&signer->key.rsa);
430*ebfedea0SLionel Sambuc 		break;
431*ebfedea0SLionel Sambuc 
432*ebfedea0SLionel Sambuc 	default:
433*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "pgp_check_sig: unusual alg\n");
434*ebfedea0SLionel Sambuc 		ret = 0;
435*ebfedea0SLionel Sambuc 	}
436*ebfedea0SLionel Sambuc 
437*ebfedea0SLionel Sambuc 	return ret;
438*ebfedea0SLionel Sambuc }
439*ebfedea0SLionel Sambuc 
440*ebfedea0SLionel Sambuc static unsigned
hash_and_check_sig(pgp_hash_t * hash,const pgp_sig_t * sig,const pgp_pubkey_t * signer)441*ebfedea0SLionel Sambuc hash_and_check_sig(pgp_hash_t *hash,
442*ebfedea0SLionel Sambuc 			 const pgp_sig_t *sig,
443*ebfedea0SLionel Sambuc 			 const pgp_pubkey_t *signer)
444*ebfedea0SLionel Sambuc {
445*ebfedea0SLionel Sambuc 	uint8_t   hashout[PGP_MAX_HASH_SIZE];
446*ebfedea0SLionel Sambuc 	unsigned	n;
447*ebfedea0SLionel Sambuc 
448*ebfedea0SLionel Sambuc 	n = hash->finish(hash, hashout);
449*ebfedea0SLionel Sambuc 	return pgp_check_sig(hashout, n, sig, signer);
450*ebfedea0SLionel Sambuc }
451*ebfedea0SLionel Sambuc 
452*ebfedea0SLionel Sambuc static unsigned
finalise_sig(pgp_hash_t * hash,const pgp_sig_t * sig,const pgp_pubkey_t * signer,const uint8_t * raw_packet)453*ebfedea0SLionel Sambuc finalise_sig(pgp_hash_t *hash,
454*ebfedea0SLionel Sambuc 		   const pgp_sig_t *sig,
455*ebfedea0SLionel Sambuc 		   const pgp_pubkey_t *signer,
456*ebfedea0SLionel Sambuc 		   const uint8_t *raw_packet)
457*ebfedea0SLionel Sambuc {
458*ebfedea0SLionel Sambuc 	hash_add_trailer(hash, sig, raw_packet);
459*ebfedea0SLionel Sambuc 	return hash_and_check_sig(hash, sig, signer);
460*ebfedea0SLionel Sambuc }
461*ebfedea0SLionel Sambuc 
462*ebfedea0SLionel Sambuc /**
463*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
464*ebfedea0SLionel Sambuc  *
465*ebfedea0SLionel Sambuc  * \brief Verify a certification signature.
466*ebfedea0SLionel Sambuc  *
467*ebfedea0SLionel Sambuc  * \param key The public key that was signed.
468*ebfedea0SLionel Sambuc  * \param id The user ID that was signed
469*ebfedea0SLionel Sambuc  * \param sig The signature.
470*ebfedea0SLionel Sambuc  * \param signer The public key of the signer.
471*ebfedea0SLionel Sambuc  * \param raw_packet The raw signature packet.
472*ebfedea0SLionel Sambuc  * \return 1 if OK; else 0
473*ebfedea0SLionel Sambuc  */
474*ebfedea0SLionel Sambuc unsigned
pgp_check_useridcert_sig(const pgp_pubkey_t * key,const uint8_t * id,const pgp_sig_t * sig,const pgp_pubkey_t * signer,const uint8_t * raw_packet)475*ebfedea0SLionel Sambuc pgp_check_useridcert_sig(const pgp_pubkey_t *key,
476*ebfedea0SLionel Sambuc 			  const uint8_t *id,
477*ebfedea0SLionel Sambuc 			  const pgp_sig_t *sig,
478*ebfedea0SLionel Sambuc 			  const pgp_pubkey_t *signer,
479*ebfedea0SLionel Sambuc 			  const uint8_t *raw_packet)
480*ebfedea0SLionel Sambuc {
481*ebfedea0SLionel Sambuc 	pgp_hash_t	hash;
482*ebfedea0SLionel Sambuc 	size_t          userid_len;
483*ebfedea0SLionel Sambuc 
484*ebfedea0SLionel Sambuc 	userid_len = strlen((const char *) id);
485*ebfedea0SLionel Sambuc 	init_key_sig(&hash, sig, key);
486*ebfedea0SLionel Sambuc 	if (sig->info.version == PGP_V4) {
487*ebfedea0SLionel Sambuc 		pgp_hash_add_int(&hash, 0xb4, 1);
488*ebfedea0SLionel Sambuc 		pgp_hash_add_int(&hash, (unsigned)userid_len, 4);
489*ebfedea0SLionel Sambuc 	}
490*ebfedea0SLionel Sambuc 	hash.add(&hash, id, (unsigned)userid_len);
491*ebfedea0SLionel Sambuc 	return finalise_sig(&hash, sig, signer, raw_packet);
492*ebfedea0SLionel Sambuc }
493*ebfedea0SLionel Sambuc 
494*ebfedea0SLionel Sambuc /**
495*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
496*ebfedea0SLionel Sambuc  *
497*ebfedea0SLionel Sambuc  * Verify a certification signature.
498*ebfedea0SLionel Sambuc  *
499*ebfedea0SLionel Sambuc  * \param key The public key that was signed.
500*ebfedea0SLionel Sambuc  * \param attribute The user attribute that was signed
501*ebfedea0SLionel Sambuc  * \param sig The signature.
502*ebfedea0SLionel Sambuc  * \param signer The public key of the signer.
503*ebfedea0SLionel Sambuc  * \param raw_packet The raw signature packet.
504*ebfedea0SLionel Sambuc  * \return 1 if OK; else 0
505*ebfedea0SLionel Sambuc  */
506*ebfedea0SLionel Sambuc unsigned
pgp_check_userattrcert_sig(const pgp_pubkey_t * key,const pgp_data_t * attribute,const pgp_sig_t * sig,const pgp_pubkey_t * signer,const uint8_t * raw_packet)507*ebfedea0SLionel Sambuc pgp_check_userattrcert_sig(const pgp_pubkey_t *key,
508*ebfedea0SLionel Sambuc 				const pgp_data_t *attribute,
509*ebfedea0SLionel Sambuc 				const pgp_sig_t *sig,
510*ebfedea0SLionel Sambuc 				const pgp_pubkey_t *signer,
511*ebfedea0SLionel Sambuc 				const uint8_t *raw_packet)
512*ebfedea0SLionel Sambuc {
513*ebfedea0SLionel Sambuc 	pgp_hash_t      hash;
514*ebfedea0SLionel Sambuc 
515*ebfedea0SLionel Sambuc 	init_key_sig(&hash, sig, key);
516*ebfedea0SLionel Sambuc 	if (sig->info.version == PGP_V4) {
517*ebfedea0SLionel Sambuc 		pgp_hash_add_int(&hash, 0xd1, 1);
518*ebfedea0SLionel Sambuc 		pgp_hash_add_int(&hash, (unsigned)attribute->len, 4);
519*ebfedea0SLionel Sambuc 	}
520*ebfedea0SLionel Sambuc 	hash.add(&hash, attribute->contents, (unsigned)attribute->len);
521*ebfedea0SLionel Sambuc 	return finalise_sig(&hash, sig, signer, raw_packet);
522*ebfedea0SLionel Sambuc }
523*ebfedea0SLionel Sambuc 
524*ebfedea0SLionel Sambuc /**
525*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
526*ebfedea0SLionel Sambuc  *
527*ebfedea0SLionel Sambuc  * Verify a subkey signature.
528*ebfedea0SLionel Sambuc  *
529*ebfedea0SLionel Sambuc  * \param key The public key whose subkey was signed.
530*ebfedea0SLionel Sambuc  * \param subkey The subkey of the public key that was signed.
531*ebfedea0SLionel Sambuc  * \param sig The signature.
532*ebfedea0SLionel Sambuc  * \param signer The public key of the signer.
533*ebfedea0SLionel Sambuc  * \param raw_packet The raw signature packet.
534*ebfedea0SLionel Sambuc  * \return 1 if OK; else 0
535*ebfedea0SLionel Sambuc  */
536*ebfedea0SLionel Sambuc unsigned
pgp_check_subkey_sig(const pgp_pubkey_t * key,const pgp_pubkey_t * subkey,const pgp_sig_t * sig,const pgp_pubkey_t * signer,const uint8_t * raw_packet)537*ebfedea0SLionel Sambuc pgp_check_subkey_sig(const pgp_pubkey_t *key,
538*ebfedea0SLionel Sambuc 			   const pgp_pubkey_t *subkey,
539*ebfedea0SLionel Sambuc 			   const pgp_sig_t *sig,
540*ebfedea0SLionel Sambuc 			   const pgp_pubkey_t *signer,
541*ebfedea0SLionel Sambuc 			   const uint8_t *raw_packet)
542*ebfedea0SLionel Sambuc {
543*ebfedea0SLionel Sambuc 	pgp_hash_t	hash;
544*ebfedea0SLionel Sambuc 	unsigned	ret;
545*ebfedea0SLionel Sambuc 
546*ebfedea0SLionel Sambuc 	init_key_sig(&hash, sig, key);
547*ebfedea0SLionel Sambuc 	hash_add_key(&hash, subkey);
548*ebfedea0SLionel Sambuc 	ret = finalise_sig(&hash, sig, signer, raw_packet);
549*ebfedea0SLionel Sambuc 	return ret;
550*ebfedea0SLionel Sambuc }
551*ebfedea0SLionel Sambuc 
552*ebfedea0SLionel Sambuc /**
553*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
554*ebfedea0SLionel Sambuc  *
555*ebfedea0SLionel Sambuc  * Verify a direct signature.
556*ebfedea0SLionel Sambuc  *
557*ebfedea0SLionel Sambuc  * \param key The public key which was signed.
558*ebfedea0SLionel Sambuc  * \param sig The signature.
559*ebfedea0SLionel Sambuc  * \param signer The public key of the signer.
560*ebfedea0SLionel Sambuc  * \param raw_packet The raw signature packet.
561*ebfedea0SLionel Sambuc  * \return 1 if OK; else 0
562*ebfedea0SLionel Sambuc  */
563*ebfedea0SLionel Sambuc unsigned
pgp_check_direct_sig(const pgp_pubkey_t * key,const pgp_sig_t * sig,const pgp_pubkey_t * signer,const uint8_t * raw_packet)564*ebfedea0SLionel Sambuc pgp_check_direct_sig(const pgp_pubkey_t *key,
565*ebfedea0SLionel Sambuc 			   const pgp_sig_t *sig,
566*ebfedea0SLionel Sambuc 			   const pgp_pubkey_t *signer,
567*ebfedea0SLionel Sambuc 			   const uint8_t *raw_packet)
568*ebfedea0SLionel Sambuc {
569*ebfedea0SLionel Sambuc 	pgp_hash_t	hash;
570*ebfedea0SLionel Sambuc 	unsigned	ret;
571*ebfedea0SLionel Sambuc 
572*ebfedea0SLionel Sambuc 	init_key_sig(&hash, sig, key);
573*ebfedea0SLionel Sambuc 	ret = finalise_sig(&hash, sig, signer, raw_packet);
574*ebfedea0SLionel Sambuc 	return ret;
575*ebfedea0SLionel Sambuc }
576*ebfedea0SLionel Sambuc 
577*ebfedea0SLionel Sambuc /**
578*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
579*ebfedea0SLionel Sambuc  *
580*ebfedea0SLionel Sambuc  * Verify a signature on a hash (the hash will have already been fed
581*ebfedea0SLionel Sambuc  * the material that was being signed, for example signed cleartext).
582*ebfedea0SLionel Sambuc  *
583*ebfedea0SLionel Sambuc  * \param hash A hash structure of appropriate type that has been fed
584*ebfedea0SLionel Sambuc  * the material to be signed. This MUST NOT have been finalised.
585*ebfedea0SLionel Sambuc  * \param sig The signature to be verified.
586*ebfedea0SLionel Sambuc  * \param signer The public key of the signer.
587*ebfedea0SLionel Sambuc  * \return 1 if OK; else 0
588*ebfedea0SLionel Sambuc  */
589*ebfedea0SLionel Sambuc unsigned
pgp_check_hash_sig(pgp_hash_t * hash,const pgp_sig_t * sig,const pgp_pubkey_t * signer)590*ebfedea0SLionel Sambuc pgp_check_hash_sig(pgp_hash_t *hash,
591*ebfedea0SLionel Sambuc 			 const pgp_sig_t *sig,
592*ebfedea0SLionel Sambuc 			 const pgp_pubkey_t *signer)
593*ebfedea0SLionel Sambuc {
594*ebfedea0SLionel Sambuc 	return (sig->info.hash_alg == hash->alg) ?
595*ebfedea0SLionel Sambuc 		finalise_sig(hash, sig, signer, NULL) :
596*ebfedea0SLionel Sambuc 		0;
597*ebfedea0SLionel Sambuc }
598*ebfedea0SLionel Sambuc 
599*ebfedea0SLionel Sambuc static void
start_sig_in_mem(pgp_create_sig_t * sig)600*ebfedea0SLionel Sambuc start_sig_in_mem(pgp_create_sig_t *sig)
601*ebfedea0SLionel Sambuc {
602*ebfedea0SLionel Sambuc 	/* since this has subpackets and stuff, we have to buffer the whole */
603*ebfedea0SLionel Sambuc 	/* thing to get counts before writing. */
604*ebfedea0SLionel Sambuc 	sig->mem = pgp_memory_new();
605*ebfedea0SLionel Sambuc 	pgp_memory_init(sig->mem, 100);
606*ebfedea0SLionel Sambuc 	pgp_writer_set_memory(sig->output, sig->mem);
607*ebfedea0SLionel Sambuc 
608*ebfedea0SLionel Sambuc 	/* write nearly up to the first subpacket */
609*ebfedea0SLionel Sambuc 	pgp_write_scalar(sig->output, (unsigned)sig->sig.info.version, 1);
610*ebfedea0SLionel Sambuc 	pgp_write_scalar(sig->output, (unsigned)sig->sig.info.type, 1);
611*ebfedea0SLionel Sambuc 	pgp_write_scalar(sig->output, (unsigned)sig->sig.info.key_alg, 1);
612*ebfedea0SLionel Sambuc 	pgp_write_scalar(sig->output, (unsigned)sig->sig.info.hash_alg, 1);
613*ebfedea0SLionel Sambuc 
614*ebfedea0SLionel Sambuc 	/* dummy hashed subpacket count */
615*ebfedea0SLionel Sambuc 	sig->hashoff = (unsigned)pgp_mem_len(sig->mem);
616*ebfedea0SLionel Sambuc 	pgp_write_scalar(sig->output, 0, 2);
617*ebfedea0SLionel Sambuc }
618*ebfedea0SLionel Sambuc 
619*ebfedea0SLionel Sambuc /**
620*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
621*ebfedea0SLionel Sambuc  *
622*ebfedea0SLionel Sambuc  * pgp_sig_start() creates a V4 public key signature with a SHA1 hash.
623*ebfedea0SLionel Sambuc  *
624*ebfedea0SLionel Sambuc  * \param sig The signature structure to initialise
625*ebfedea0SLionel Sambuc  * \param key The public key to be signed
626*ebfedea0SLionel Sambuc  * \param id The user ID being bound to the key
627*ebfedea0SLionel Sambuc  * \param type Signature type
628*ebfedea0SLionel Sambuc  */
629*ebfedea0SLionel Sambuc void
pgp_sig_start_key_sig(pgp_create_sig_t * sig,const pgp_pubkey_t * key,const uint8_t * id,pgp_sig_type_t type)630*ebfedea0SLionel Sambuc pgp_sig_start_key_sig(pgp_create_sig_t *sig,
631*ebfedea0SLionel Sambuc 				  const pgp_pubkey_t *key,
632*ebfedea0SLionel Sambuc 				  const uint8_t *id,
633*ebfedea0SLionel Sambuc 				  pgp_sig_type_t type)
634*ebfedea0SLionel Sambuc {
635*ebfedea0SLionel Sambuc 	sig->output = pgp_output_new();
636*ebfedea0SLionel Sambuc 
637*ebfedea0SLionel Sambuc 	/* XXX:  refactor with check (in several ways - check should
638*ebfedea0SLionel Sambuc 	 * probably use the buffered writer to construct packets
639*ebfedea0SLionel Sambuc 	 * (done), and also should share code for hash calculation) */
640*ebfedea0SLionel Sambuc 	sig->sig.info.version = PGP_V4;
641*ebfedea0SLionel Sambuc 	sig->sig.info.hash_alg = PGP_HASH_SHA1;
642*ebfedea0SLionel Sambuc 	sig->sig.info.key_alg = key->alg;
643*ebfedea0SLionel Sambuc 	sig->sig.info.type = type;
644*ebfedea0SLionel Sambuc 	sig->hashlen = (unsigned)-1;
645*ebfedea0SLionel Sambuc 	init_key_sig(&sig->hash, &sig->sig, key);
646*ebfedea0SLionel Sambuc 	pgp_hash_add_int(&sig->hash, 0xb4, 1);
647*ebfedea0SLionel Sambuc 	pgp_hash_add_int(&sig->hash, (unsigned)strlen((const char *) id), 4);
648*ebfedea0SLionel Sambuc 	sig->hash.add(&sig->hash, id, (unsigned)strlen((const char *) id));
649*ebfedea0SLionel Sambuc 	start_sig_in_mem(sig);
650*ebfedea0SLionel Sambuc }
651*ebfedea0SLionel Sambuc 
652*ebfedea0SLionel Sambuc /**
653*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
654*ebfedea0SLionel Sambuc  *
655*ebfedea0SLionel Sambuc  * Create a V4 public key signature over some cleartext.
656*ebfedea0SLionel Sambuc  *
657*ebfedea0SLionel Sambuc  * \param sig The signature structure to initialise
658*ebfedea0SLionel Sambuc  * \param id
659*ebfedea0SLionel Sambuc  * \param type
660*ebfedea0SLionel Sambuc  * \todo Expand description. Allow other hashes.
661*ebfedea0SLionel Sambuc  */
662*ebfedea0SLionel Sambuc 
663*ebfedea0SLionel Sambuc void
pgp_start_sig(pgp_create_sig_t * sig,const pgp_seckey_t * key,const pgp_hash_alg_t hash,const pgp_sig_type_t type)664*ebfedea0SLionel Sambuc pgp_start_sig(pgp_create_sig_t *sig,
665*ebfedea0SLionel Sambuc 	      const pgp_seckey_t *key,
666*ebfedea0SLionel Sambuc 	      const pgp_hash_alg_t hash,
667*ebfedea0SLionel Sambuc 	      const pgp_sig_type_t type)
668*ebfedea0SLionel Sambuc {
669*ebfedea0SLionel Sambuc 	sig->output = pgp_output_new();
670*ebfedea0SLionel Sambuc 
671*ebfedea0SLionel Sambuc 	/* XXX:  refactor with check (in several ways - check should
672*ebfedea0SLionel Sambuc 	 * probably use the buffered writer to construct packets
673*ebfedea0SLionel Sambuc 	 * (done), and also should share code for hash calculation) */
674*ebfedea0SLionel Sambuc 	sig->sig.info.version = PGP_V4;
675*ebfedea0SLionel Sambuc 	sig->sig.info.key_alg = key->pubkey.alg;
676*ebfedea0SLionel Sambuc 	sig->sig.info.hash_alg = hash;
677*ebfedea0SLionel Sambuc 	sig->sig.info.type = type;
678*ebfedea0SLionel Sambuc 
679*ebfedea0SLionel Sambuc 	sig->hashlen = (unsigned)-1;
680*ebfedea0SLionel Sambuc 
681*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
682*ebfedea0SLionel Sambuc 		fprintf(stderr, "initialising hash for sig in mem\n");
683*ebfedea0SLionel Sambuc 	}
684*ebfedea0SLionel Sambuc 	initialise_hash(&sig->hash, &sig->sig);
685*ebfedea0SLionel Sambuc 	start_sig_in_mem(sig);
686*ebfedea0SLionel Sambuc }
687*ebfedea0SLionel Sambuc 
688*ebfedea0SLionel Sambuc /**
689*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
690*ebfedea0SLionel Sambuc  *
691*ebfedea0SLionel Sambuc  * Add plaintext data to a signature-to-be.
692*ebfedea0SLionel Sambuc  *
693*ebfedea0SLionel Sambuc  * \param sig The signature-to-be.
694*ebfedea0SLionel Sambuc  * \param buf The plaintext data.
695*ebfedea0SLionel Sambuc  * \param length The amount of plaintext data.
696*ebfedea0SLionel Sambuc  */
697*ebfedea0SLionel Sambuc void
pgp_sig_add_data(pgp_create_sig_t * sig,const void * buf,size_t length)698*ebfedea0SLionel Sambuc pgp_sig_add_data(pgp_create_sig_t *sig, const void *buf, size_t length)
699*ebfedea0SLionel Sambuc {
700*ebfedea0SLionel Sambuc 	sig->hash.add(&sig->hash, buf, (unsigned)length);
701*ebfedea0SLionel Sambuc }
702*ebfedea0SLionel Sambuc 
703*ebfedea0SLionel Sambuc /**
704*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
705*ebfedea0SLionel Sambuc  *
706*ebfedea0SLionel Sambuc  * Mark the end of the hashed subpackets in the signature
707*ebfedea0SLionel Sambuc  *
708*ebfedea0SLionel Sambuc  * \param sig
709*ebfedea0SLionel Sambuc  */
710*ebfedea0SLionel Sambuc 
711*ebfedea0SLionel Sambuc unsigned
pgp_end_hashed_subpkts(pgp_create_sig_t * sig)712*ebfedea0SLionel Sambuc pgp_end_hashed_subpkts(pgp_create_sig_t *sig)
713*ebfedea0SLionel Sambuc {
714*ebfedea0SLionel Sambuc 	sig->hashlen = (unsigned)(pgp_mem_len(sig->mem) - sig->hashoff - 2);
715*ebfedea0SLionel Sambuc 	pgp_memory_place_int(sig->mem, sig->hashoff, sig->hashlen, 2);
716*ebfedea0SLionel Sambuc 	/* dummy unhashed subpacket count */
717*ebfedea0SLionel Sambuc 	sig->unhashoff = (unsigned)pgp_mem_len(sig->mem);
718*ebfedea0SLionel Sambuc 	return pgp_write_scalar(sig->output, 0, 2);
719*ebfedea0SLionel Sambuc }
720*ebfedea0SLionel Sambuc 
721*ebfedea0SLionel Sambuc /**
722*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
723*ebfedea0SLionel Sambuc  *
724*ebfedea0SLionel Sambuc  * Write out a signature
725*ebfedea0SLionel Sambuc  *
726*ebfedea0SLionel Sambuc  * \param sig
727*ebfedea0SLionel Sambuc  * \param key
728*ebfedea0SLionel Sambuc  * \param seckey
729*ebfedea0SLionel Sambuc  * \param info
730*ebfedea0SLionel Sambuc  *
731*ebfedea0SLionel Sambuc  */
732*ebfedea0SLionel Sambuc 
733*ebfedea0SLionel Sambuc unsigned
pgp_write_sig(pgp_output_t * output,pgp_create_sig_t * sig,const pgp_pubkey_t * key,const pgp_seckey_t * seckey)734*ebfedea0SLionel Sambuc pgp_write_sig(pgp_output_t *output,
735*ebfedea0SLionel Sambuc 			pgp_create_sig_t *sig,
736*ebfedea0SLionel Sambuc 			const pgp_pubkey_t *key,
737*ebfedea0SLionel Sambuc 			const pgp_seckey_t *seckey)
738*ebfedea0SLionel Sambuc {
739*ebfedea0SLionel Sambuc 	unsigned	ret = 0;
740*ebfedea0SLionel Sambuc 	size_t		len = pgp_mem_len(sig->mem);
741*ebfedea0SLionel Sambuc 
742*ebfedea0SLionel Sambuc 	/* check key not decrypted */
743*ebfedea0SLionel Sambuc 	switch (seckey->pubkey.alg) {
744*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
745*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA_ENCRYPT_ONLY:
746*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA_SIGN_ONLY:
747*ebfedea0SLionel Sambuc 		if (seckey->key.rsa.d == NULL) {
748*ebfedea0SLionel Sambuc 			(void) fprintf(stderr, "pgp_write_sig: null rsa.d\n");
749*ebfedea0SLionel Sambuc 			return 0;
750*ebfedea0SLionel Sambuc 		}
751*ebfedea0SLionel Sambuc 		break;
752*ebfedea0SLionel Sambuc 
753*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
754*ebfedea0SLionel Sambuc 		if (seckey->key.dsa.x == NULL) {
755*ebfedea0SLionel Sambuc 			(void) fprintf(stderr, "pgp_write_sig: null dsa.x\n");
756*ebfedea0SLionel Sambuc 			return 0;
757*ebfedea0SLionel Sambuc 		}
758*ebfedea0SLionel Sambuc 		break;
759*ebfedea0SLionel Sambuc 
760*ebfedea0SLionel Sambuc 	default:
761*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "Unsupported algorithm %d\n",
762*ebfedea0SLionel Sambuc 				seckey->pubkey.alg);
763*ebfedea0SLionel Sambuc 		return 0;
764*ebfedea0SLionel Sambuc 	}
765*ebfedea0SLionel Sambuc 
766*ebfedea0SLionel Sambuc 	if (sig->hashlen == (unsigned) -1) {
767*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
768*ebfedea0SLionel Sambuc 				"ops_write_sig: bad hashed data len\n");
769*ebfedea0SLionel Sambuc 		return 0;
770*ebfedea0SLionel Sambuc 	}
771*ebfedea0SLionel Sambuc 
772*ebfedea0SLionel Sambuc 	pgp_memory_place_int(sig->mem, sig->unhashoff,
773*ebfedea0SLionel Sambuc 			     (unsigned)(len - sig->unhashoff - 2), 2);
774*ebfedea0SLionel Sambuc 
775*ebfedea0SLionel Sambuc 	/* add the packet from version number to end of hashed subpackets */
776*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
777*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "ops_write_sig: hashed packet info\n");
778*ebfedea0SLionel Sambuc 	}
779*ebfedea0SLionel Sambuc 	sig->hash.add(&sig->hash, pgp_mem_data(sig->mem), sig->unhashoff);
780*ebfedea0SLionel Sambuc 
781*ebfedea0SLionel Sambuc 	/* add final trailer */
782*ebfedea0SLionel Sambuc 	pgp_hash_add_int(&sig->hash, (unsigned)sig->sig.info.version, 1);
783*ebfedea0SLionel Sambuc 	pgp_hash_add_int(&sig->hash, 0xff, 1);
784*ebfedea0SLionel Sambuc 	/* +6 for version, type, pk alg, hash alg, hashed subpacket length */
785*ebfedea0SLionel Sambuc 	pgp_hash_add_int(&sig->hash, sig->hashlen + 6, 4);
786*ebfedea0SLionel Sambuc 
787*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
788*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "ops_write_sig: done writing hashed\n");
789*ebfedea0SLionel Sambuc 	}
790*ebfedea0SLionel Sambuc 	/* XXX: technically, we could figure out how big the signature is */
791*ebfedea0SLionel Sambuc 	/* and write it directly to the output instead of via memory. */
792*ebfedea0SLionel Sambuc 	switch (seckey->pubkey.alg) {
793*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA:
794*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA_ENCRYPT_ONLY:
795*ebfedea0SLionel Sambuc 	case PGP_PKA_RSA_SIGN_ONLY:
796*ebfedea0SLionel Sambuc 		if (!rsa_sign(&sig->hash, &key->key.rsa, &seckey->key.rsa,
797*ebfedea0SLionel Sambuc 				sig->output)) {
798*ebfedea0SLionel Sambuc 			(void) fprintf(stderr,
799*ebfedea0SLionel Sambuc 				"pgp_write_sig: rsa_sign failure\n");
800*ebfedea0SLionel Sambuc 			return 0;
801*ebfedea0SLionel Sambuc 		}
802*ebfedea0SLionel Sambuc 		break;
803*ebfedea0SLionel Sambuc 
804*ebfedea0SLionel Sambuc 	case PGP_PKA_DSA:
805*ebfedea0SLionel Sambuc 		if (!dsa_sign(&sig->hash, &key->key.dsa, &seckey->key.dsa,
806*ebfedea0SLionel Sambuc 				sig->output)) {
807*ebfedea0SLionel Sambuc 			(void) fprintf(stderr,
808*ebfedea0SLionel Sambuc 				"pgp_write_sig: dsa_sign failure\n");
809*ebfedea0SLionel Sambuc 			return 0;
810*ebfedea0SLionel Sambuc 		}
811*ebfedea0SLionel Sambuc 		break;
812*ebfedea0SLionel Sambuc 
813*ebfedea0SLionel Sambuc 	default:
814*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "Unsupported algorithm %d\n",
815*ebfedea0SLionel Sambuc 					seckey->pubkey.alg);
816*ebfedea0SLionel Sambuc 		return 0;
817*ebfedea0SLionel Sambuc 	}
818*ebfedea0SLionel Sambuc 
819*ebfedea0SLionel Sambuc 	ret = pgp_write_ptag(output, PGP_PTAG_CT_SIGNATURE);
820*ebfedea0SLionel Sambuc 	if (ret) {
821*ebfedea0SLionel Sambuc 		len = pgp_mem_len(sig->mem);
822*ebfedea0SLionel Sambuc 		ret = pgp_write_length(output, (unsigned)len) &&
823*ebfedea0SLionel Sambuc 			pgp_write(output, pgp_mem_data(sig->mem), (unsigned)len);
824*ebfedea0SLionel Sambuc 	}
825*ebfedea0SLionel Sambuc 	pgp_memory_free(sig->mem);
826*ebfedea0SLionel Sambuc 
827*ebfedea0SLionel Sambuc 	if (ret == 0) {
828*ebfedea0SLionel Sambuc 		PGP_ERROR_1(&output->errors, PGP_E_W, "%s",
829*ebfedea0SLionel Sambuc 		    "Cannot write signature");
830*ebfedea0SLionel Sambuc 	}
831*ebfedea0SLionel Sambuc 	return ret;
832*ebfedea0SLionel Sambuc }
833*ebfedea0SLionel Sambuc 
834*ebfedea0SLionel Sambuc /* add a time stamp to the output */
835*ebfedea0SLionel Sambuc unsigned
pgp_add_time(pgp_create_sig_t * sig,int64_t when,const char * type)836*ebfedea0SLionel Sambuc pgp_add_time(pgp_create_sig_t *sig, int64_t when, const char *type)
837*ebfedea0SLionel Sambuc {
838*ebfedea0SLionel Sambuc 	pgp_content_enum	tag;
839*ebfedea0SLionel Sambuc 
840*ebfedea0SLionel Sambuc 	tag = (strcmp(type, "birth") == 0) ?
841*ebfedea0SLionel Sambuc 		PGP_PTAG_SS_CREATION_TIME : PGP_PTAG_SS_EXPIRATION_TIME;
842*ebfedea0SLionel Sambuc 	/* just do 32-bit timestamps for just now - it's in the protocol */
843*ebfedea0SLionel Sambuc 	return pgp_write_ss_header(sig->output, 5, tag) &&
844*ebfedea0SLionel Sambuc 		pgp_write_scalar(sig->output, (uint32_t)when, (unsigned)sizeof(uint32_t));
845*ebfedea0SLionel Sambuc }
846*ebfedea0SLionel Sambuc 
847*ebfedea0SLionel Sambuc /**
848*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
849*ebfedea0SLionel Sambuc  *
850*ebfedea0SLionel Sambuc  * Adds issuer's key ID to the signature
851*ebfedea0SLionel Sambuc  *
852*ebfedea0SLionel Sambuc  * \param sig
853*ebfedea0SLionel Sambuc  * \param keyid
854*ebfedea0SLionel Sambuc  */
855*ebfedea0SLionel Sambuc 
856*ebfedea0SLionel Sambuc unsigned
pgp_add_issuer_keyid(pgp_create_sig_t * sig,const uint8_t keyid[PGP_KEY_ID_SIZE])857*ebfedea0SLionel Sambuc pgp_add_issuer_keyid(pgp_create_sig_t *sig,
858*ebfedea0SLionel Sambuc 				const uint8_t keyid[PGP_KEY_ID_SIZE])
859*ebfedea0SLionel Sambuc {
860*ebfedea0SLionel Sambuc 	return pgp_write_ss_header(sig->output, PGP_KEY_ID_SIZE + 1,
861*ebfedea0SLionel Sambuc 				PGP_PTAG_SS_ISSUER_KEY_ID) &&
862*ebfedea0SLionel Sambuc 		pgp_write(sig->output, keyid, PGP_KEY_ID_SIZE);
863*ebfedea0SLionel Sambuc }
864*ebfedea0SLionel Sambuc 
865*ebfedea0SLionel Sambuc /**
866*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
867*ebfedea0SLionel Sambuc  *
868*ebfedea0SLionel Sambuc  * Adds primary user ID to the signature
869*ebfedea0SLionel Sambuc  *
870*ebfedea0SLionel Sambuc  * \param sig
871*ebfedea0SLionel Sambuc  * \param primary
872*ebfedea0SLionel Sambuc  */
873*ebfedea0SLionel Sambuc void
pgp_add_primary_userid(pgp_create_sig_t * sig,unsigned primary)874*ebfedea0SLionel Sambuc pgp_add_primary_userid(pgp_create_sig_t *sig, unsigned primary)
875*ebfedea0SLionel Sambuc {
876*ebfedea0SLionel Sambuc 	pgp_write_ss_header(sig->output, 2, PGP_PTAG_SS_PRIMARY_USER_ID);
877*ebfedea0SLionel Sambuc 	pgp_write_scalar(sig->output, primary, 1);
878*ebfedea0SLionel Sambuc }
879*ebfedea0SLionel Sambuc 
880*ebfedea0SLionel Sambuc /**
881*ebfedea0SLionel Sambuc  * \ingroup Core_Signature
882*ebfedea0SLionel Sambuc  *
883*ebfedea0SLionel Sambuc  * Get the hash structure in use for the signature.
884*ebfedea0SLionel Sambuc  *
885*ebfedea0SLionel Sambuc  * \param sig The signature structure.
886*ebfedea0SLionel Sambuc  * \return The hash structure.
887*ebfedea0SLionel Sambuc  */
888*ebfedea0SLionel Sambuc pgp_hash_t     *
pgp_sig_get_hash(pgp_create_sig_t * sig)889*ebfedea0SLionel Sambuc pgp_sig_get_hash(pgp_create_sig_t *sig)
890*ebfedea0SLionel Sambuc {
891*ebfedea0SLionel Sambuc 	return &sig->hash;
892*ebfedea0SLionel Sambuc }
893*ebfedea0SLionel Sambuc 
894*ebfedea0SLionel Sambuc /* open up an output file */
895*ebfedea0SLionel Sambuc static int
open_output_file(pgp_output_t ** output,const char * inname,const char * outname,const char * suffix,const unsigned overwrite)896*ebfedea0SLionel Sambuc open_output_file(pgp_output_t **output,
897*ebfedea0SLionel Sambuc 			const char *inname,
898*ebfedea0SLionel Sambuc 			const char *outname,
899*ebfedea0SLionel Sambuc 			const char *suffix,
900*ebfedea0SLionel Sambuc 			const unsigned overwrite)
901*ebfedea0SLionel Sambuc {
902*ebfedea0SLionel Sambuc 	int             fd;
903*ebfedea0SLionel Sambuc 
904*ebfedea0SLionel Sambuc 	/* setup output file */
905*ebfedea0SLionel Sambuc 	if (outname) {
906*ebfedea0SLionel Sambuc 		fd = pgp_setup_file_write(output, outname, overwrite);
907*ebfedea0SLionel Sambuc 	} else {
908*ebfedea0SLionel Sambuc 		unsigned        flen = (unsigned)(strlen(inname) + 4 + 1);
909*ebfedea0SLionel Sambuc 		char           *f = NULL;
910*ebfedea0SLionel Sambuc 
911*ebfedea0SLionel Sambuc 		if ((f = calloc(1, flen)) == NULL) {
912*ebfedea0SLionel Sambuc 			(void) fprintf(stderr, "open_output_file: bad alloc\n");
913*ebfedea0SLionel Sambuc 			fd = -1;
914*ebfedea0SLionel Sambuc 		} else {
915*ebfedea0SLionel Sambuc 			(void) snprintf(f, flen, "%s.%s", inname, suffix);
916*ebfedea0SLionel Sambuc 			fd = pgp_setup_file_write(output, f, overwrite);
917*ebfedea0SLionel Sambuc 			free(f);
918*ebfedea0SLionel Sambuc 		}
919*ebfedea0SLionel Sambuc 	}
920*ebfedea0SLionel Sambuc 	return fd;
921*ebfedea0SLionel Sambuc }
922*ebfedea0SLionel Sambuc 
923*ebfedea0SLionel Sambuc /**
924*ebfedea0SLionel Sambuc \ingroup HighLevel_Sign
925*ebfedea0SLionel Sambuc \brief Sign a file
926*ebfedea0SLionel Sambuc \param inname Input filename
927*ebfedea0SLionel Sambuc \param outname Output filename. If NULL, a name is constructed from the input filename.
928*ebfedea0SLionel Sambuc \param seckey Secret Key to use for signing
929*ebfedea0SLionel Sambuc \param armored Write armoured text, if set.
930*ebfedea0SLionel Sambuc \param overwrite May overwrite existing file, if set.
931*ebfedea0SLionel Sambuc \return 1 if OK; else 0;
932*ebfedea0SLionel Sambuc 
933*ebfedea0SLionel Sambuc */
934*ebfedea0SLionel Sambuc unsigned
pgp_sign_file(pgp_io_t * io,const char * inname,const char * outname,const pgp_seckey_t * seckey,const char * hashname,const int64_t from,const uint64_t duration,const unsigned armored,const unsigned cleartext,const unsigned overwrite)935*ebfedea0SLionel Sambuc pgp_sign_file(pgp_io_t *io,
936*ebfedea0SLionel Sambuc 		const char *inname,
937*ebfedea0SLionel Sambuc 		const char *outname,
938*ebfedea0SLionel Sambuc 		const pgp_seckey_t *seckey,
939*ebfedea0SLionel Sambuc 		const char *hashname,
940*ebfedea0SLionel Sambuc 		const int64_t from,
941*ebfedea0SLionel Sambuc 		const uint64_t duration,
942*ebfedea0SLionel Sambuc 		const unsigned armored,
943*ebfedea0SLionel Sambuc 		const unsigned cleartext,
944*ebfedea0SLionel Sambuc 		const unsigned overwrite)
945*ebfedea0SLionel Sambuc {
946*ebfedea0SLionel Sambuc 	pgp_create_sig_t	*sig;
947*ebfedea0SLionel Sambuc 	pgp_sig_type_t	 sig_type;
948*ebfedea0SLionel Sambuc 	pgp_hash_alg_t	 hash_alg;
949*ebfedea0SLionel Sambuc 	pgp_memory_t		*infile;
950*ebfedea0SLionel Sambuc 	pgp_output_t		*output;
951*ebfedea0SLionel Sambuc 	pgp_hash_t		*hash;
952*ebfedea0SLionel Sambuc 	unsigned		 ret;
953*ebfedea0SLionel Sambuc 	uint8_t			 keyid[PGP_KEY_ID_SIZE];
954*ebfedea0SLionel Sambuc 	int			 fd_out;
955*ebfedea0SLionel Sambuc 
956*ebfedea0SLionel Sambuc 	sig = NULL;
957*ebfedea0SLionel Sambuc 	sig_type = PGP_SIG_BINARY;
958*ebfedea0SLionel Sambuc 	infile = NULL;
959*ebfedea0SLionel Sambuc 	output = NULL;
960*ebfedea0SLionel Sambuc 	hash = NULL;
961*ebfedea0SLionel Sambuc 	fd_out = 0;
962*ebfedea0SLionel Sambuc 
963*ebfedea0SLionel Sambuc 	/* find the hash algorithm */
964*ebfedea0SLionel Sambuc 	hash_alg = pgp_str_to_hash_alg(hashname);
965*ebfedea0SLionel Sambuc 	if (hash_alg == PGP_HASH_UNKNOWN) {
966*ebfedea0SLionel Sambuc 		(void) fprintf(io->errs,
967*ebfedea0SLionel Sambuc 			"pgp_sign_file: unknown hash algorithm: \"%s\"\n",
968*ebfedea0SLionel Sambuc 			hashname);
969*ebfedea0SLionel Sambuc 		return 0;
970*ebfedea0SLionel Sambuc 	}
971*ebfedea0SLionel Sambuc 
972*ebfedea0SLionel Sambuc 	/* read input file into buf */
973*ebfedea0SLionel Sambuc 	infile = pgp_memory_new();
974*ebfedea0SLionel Sambuc 	if (!pgp_mem_readfile(infile, inname)) {
975*ebfedea0SLionel Sambuc 		return 0;
976*ebfedea0SLionel Sambuc 	}
977*ebfedea0SLionel Sambuc 
978*ebfedea0SLionel Sambuc 	/* setup output file */
979*ebfedea0SLionel Sambuc 	fd_out = open_output_file(&output, inname, outname,
980*ebfedea0SLionel Sambuc 				(armored) ? "asc" : "gpg", overwrite);
981*ebfedea0SLionel Sambuc 	if (fd_out < 0) {
982*ebfedea0SLionel Sambuc 		pgp_memory_free(infile);
983*ebfedea0SLionel Sambuc 		return 0;
984*ebfedea0SLionel Sambuc 	}
985*ebfedea0SLionel Sambuc 
986*ebfedea0SLionel Sambuc 	/* set up signature */
987*ebfedea0SLionel Sambuc 	sig = pgp_create_sig_new();
988*ebfedea0SLionel Sambuc 	if (!sig) {
989*ebfedea0SLionel Sambuc 		pgp_memory_free(infile);
990*ebfedea0SLionel Sambuc 		pgp_teardown_file_write(output, fd_out);
991*ebfedea0SLionel Sambuc 		return 0;
992*ebfedea0SLionel Sambuc 	}
993*ebfedea0SLionel Sambuc 
994*ebfedea0SLionel Sambuc 	pgp_start_sig(sig, seckey, hash_alg, sig_type);
995*ebfedea0SLionel Sambuc 
996*ebfedea0SLionel Sambuc 	if (cleartext) {
997*ebfedea0SLionel Sambuc 		if (pgp_writer_push_clearsigned(output, sig) != 1) {
998*ebfedea0SLionel Sambuc 			return 0;
999*ebfedea0SLionel Sambuc 		}
1000*ebfedea0SLionel Sambuc 
1001*ebfedea0SLionel Sambuc 		/* Do the signing */
1002*ebfedea0SLionel Sambuc 		pgp_write(output, pgp_mem_data(infile), (unsigned)pgp_mem_len(infile));
1003*ebfedea0SLionel Sambuc 		pgp_memory_free(infile);
1004*ebfedea0SLionel Sambuc 
1005*ebfedea0SLionel Sambuc 		/* add signature with subpackets: */
1006*ebfedea0SLionel Sambuc 		/* - creation time */
1007*ebfedea0SLionel Sambuc 		/* - key id */
1008*ebfedea0SLionel Sambuc 		ret = pgp_writer_use_armored_sig(output) &&
1009*ebfedea0SLionel Sambuc 				pgp_add_time(sig, (int64_t)from, "birth") &&
1010*ebfedea0SLionel Sambuc 				pgp_add_time(sig, (int64_t)duration, "expiration");
1011*ebfedea0SLionel Sambuc 		if (ret == 0) {
1012*ebfedea0SLionel Sambuc 			pgp_teardown_file_write(output, fd_out);
1013*ebfedea0SLionel Sambuc 			return 0;
1014*ebfedea0SLionel Sambuc 		}
1015*ebfedea0SLionel Sambuc 
1016*ebfedea0SLionel Sambuc 		pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
1017*ebfedea0SLionel Sambuc 		ret = pgp_add_issuer_keyid(sig, keyid) &&
1018*ebfedea0SLionel Sambuc 			pgp_end_hashed_subpkts(sig) &&
1019*ebfedea0SLionel Sambuc 			pgp_write_sig(output, sig, &seckey->pubkey, seckey);
1020*ebfedea0SLionel Sambuc 
1021*ebfedea0SLionel Sambuc 		pgp_teardown_file_write(output, fd_out);
1022*ebfedea0SLionel Sambuc 
1023*ebfedea0SLionel Sambuc 		if (ret == 0) {
1024*ebfedea0SLionel Sambuc 			PGP_ERROR_1(&output->errors, PGP_E_W, "%s",
1025*ebfedea0SLionel Sambuc 			    "Cannot sign file as cleartext");
1026*ebfedea0SLionel Sambuc 		}
1027*ebfedea0SLionel Sambuc 	} else {
1028*ebfedea0SLionel Sambuc 		/* set armoured/not armoured here */
1029*ebfedea0SLionel Sambuc 		if (armored) {
1030*ebfedea0SLionel Sambuc 			pgp_writer_push_armor_msg(output);
1031*ebfedea0SLionel Sambuc 		}
1032*ebfedea0SLionel Sambuc 
1033*ebfedea0SLionel Sambuc 		/* write one_pass_sig */
1034*ebfedea0SLionel Sambuc 		pgp_write_one_pass_sig(output, seckey, hash_alg, sig_type);
1035*ebfedea0SLionel Sambuc 
1036*ebfedea0SLionel Sambuc 		/* hash file contents */
1037*ebfedea0SLionel Sambuc 		hash = pgp_sig_get_hash(sig);
1038*ebfedea0SLionel Sambuc 		hash->add(hash, pgp_mem_data(infile), (unsigned)pgp_mem_len(infile));
1039*ebfedea0SLionel Sambuc 
1040*ebfedea0SLionel Sambuc #if 1
1041*ebfedea0SLionel Sambuc 		/* output file contents as Literal Data packet */
1042*ebfedea0SLionel Sambuc 		pgp_write_litdata(output, pgp_mem_data(infile),
1043*ebfedea0SLionel Sambuc 			(const int)pgp_mem_len(infile),
1044*ebfedea0SLionel Sambuc 			PGP_LDT_BINARY);
1045*ebfedea0SLionel Sambuc #else
1046*ebfedea0SLionel Sambuc 		/* XXX - agc - sync with writer.c 1094 for ops_writez */
1047*ebfedea0SLionel Sambuc 		pgp_setup_memory_write(&litoutput, &litmem, bufsz);
1048*ebfedea0SLionel Sambuc 		pgp_setup_memory_write(&zoutput, &zmem, bufsz);
1049*ebfedea0SLionel Sambuc 		pgp_write_litdata(litoutput,
1050*ebfedea0SLionel Sambuc 			pgp_mem_data(pgp_mem_data(infile),
1051*ebfedea0SLionel Sambuc 			(const int)pgp_mem_len(infile), PGP_LDT_BINARY);
1052*ebfedea0SLionel Sambuc 		pgp_writez(zoutput, pgp_mem_data(litmem), pgp_mem_len(litmem));
1053*ebfedea0SLionel Sambuc #endif
1054*ebfedea0SLionel Sambuc 
1055*ebfedea0SLionel Sambuc 		/* add creation time to signature */
1056*ebfedea0SLionel Sambuc 		pgp_add_time(sig, (int64_t)from, "birth");
1057*ebfedea0SLionel Sambuc 		pgp_add_time(sig, (int64_t)duration, "expiration");
1058*ebfedea0SLionel Sambuc 		/* add key id to signature */
1059*ebfedea0SLionel Sambuc 		pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
1060*ebfedea0SLionel Sambuc 		pgp_add_issuer_keyid(sig, keyid);
1061*ebfedea0SLionel Sambuc 		pgp_end_hashed_subpkts(sig);
1062*ebfedea0SLionel Sambuc 		pgp_write_sig(output, sig, &seckey->pubkey, seckey);
1063*ebfedea0SLionel Sambuc 
1064*ebfedea0SLionel Sambuc 		/* tidy up */
1065*ebfedea0SLionel Sambuc 		pgp_teardown_file_write(output, fd_out);
1066*ebfedea0SLionel Sambuc 
1067*ebfedea0SLionel Sambuc 		pgp_create_sig_delete(sig);
1068*ebfedea0SLionel Sambuc 		pgp_memory_free(infile);
1069*ebfedea0SLionel Sambuc 
1070*ebfedea0SLionel Sambuc 		ret = 1;
1071*ebfedea0SLionel Sambuc 	}
1072*ebfedea0SLionel Sambuc 
1073*ebfedea0SLionel Sambuc 	return ret;
1074*ebfedea0SLionel Sambuc }
1075*ebfedea0SLionel Sambuc 
1076*ebfedea0SLionel Sambuc /**
1077*ebfedea0SLionel Sambuc \ingroup HighLevel_Sign
1078*ebfedea0SLionel Sambuc \brief Signs a buffer
1079*ebfedea0SLionel Sambuc \param input Input text to be signed
1080*ebfedea0SLionel Sambuc \param input_len Length of input text
1081*ebfedea0SLionel Sambuc \param sig_type Signature type
1082*ebfedea0SLionel Sambuc \param seckey Secret Key
1083*ebfedea0SLionel Sambuc \param armored Write armoured text, if set
1084*ebfedea0SLionel Sambuc \return New pgp_memory_t struct containing signed text
1085*ebfedea0SLionel Sambuc \note It is the caller's responsibility to call pgp_memory_free(me)
1086*ebfedea0SLionel Sambuc 
1087*ebfedea0SLionel Sambuc */
1088*ebfedea0SLionel Sambuc pgp_memory_t *
1089*ebfedea0SLionel Sambuc pgp_sign_buf(pgp_io_t *io,
1090*ebfedea0SLionel Sambuc 		const void *input,
1091*ebfedea0SLionel Sambuc 		const size_t insize,
1092*ebfedea0SLionel Sambuc 		const pgp_seckey_t *seckey,
1093*ebfedea0SLionel Sambuc 		const int64_t from,
1094*ebfedea0SLionel Sambuc 		const uint64_t duration,
1095*ebfedea0SLionel Sambuc 		const char *hashname,
1096*ebfedea0SLionel Sambuc 		const unsigned armored,
1097*ebfedea0SLionel Sambuc 		const unsigned cleartext)
1098*ebfedea0SLionel Sambuc {
1099*ebfedea0SLionel Sambuc 	pgp_litdata_enum	 ld_type;
1100*ebfedea0SLionel Sambuc 	pgp_create_sig_t	*sig;
1101*ebfedea0SLionel Sambuc 	pgp_sig_type_t	 sig_type;
1102*ebfedea0SLionel Sambuc 	pgp_hash_alg_t	 hash_alg;
1103*ebfedea0SLionel Sambuc 	pgp_output_t		*output;
1104*ebfedea0SLionel Sambuc 	pgp_memory_t		*mem;
1105*ebfedea0SLionel Sambuc 	uint8_t			 keyid[PGP_KEY_ID_SIZE];
1106*ebfedea0SLionel Sambuc 	pgp_hash_t		*hash;
1107*ebfedea0SLionel Sambuc 	unsigned		 ret;
1108*ebfedea0SLionel Sambuc 
1109*ebfedea0SLionel Sambuc 	sig = NULL;
1110*ebfedea0SLionel Sambuc 	sig_type = PGP_SIG_BINARY;
1111*ebfedea0SLionel Sambuc 	output = NULL;
1112*ebfedea0SLionel Sambuc 	mem = pgp_memory_new();
1113*ebfedea0SLionel Sambuc 	hash = NULL;
1114*ebfedea0SLionel Sambuc 	ret = 0;
1115*ebfedea0SLionel Sambuc 
1116*ebfedea0SLionel Sambuc 	hash_alg = pgp_str_to_hash_alg(hashname);
1117*ebfedea0SLionel Sambuc 	if (hash_alg == PGP_HASH_UNKNOWN) {
1118*ebfedea0SLionel Sambuc 		(void) fprintf(io->errs,
1119*ebfedea0SLionel Sambuc 			"pgp_sign_buf: unknown hash algorithm: \"%s\"\n",
1120*ebfedea0SLionel Sambuc 			hashname);
1121*ebfedea0SLionel Sambuc 		return NULL;
1122*ebfedea0SLionel Sambuc 	}
1123*ebfedea0SLionel Sambuc 
1124*ebfedea0SLionel Sambuc 	/* setup literal data packet type */
1125*ebfedea0SLionel Sambuc 	ld_type = (cleartext) ? PGP_LDT_TEXT : PGP_LDT_BINARY;
1126*ebfedea0SLionel Sambuc 
1127*ebfedea0SLionel Sambuc 	if (input == NULL) {
1128*ebfedea0SLionel Sambuc 		(void) fprintf(io->errs,
1129*ebfedea0SLionel Sambuc 			"pgp_sign_buf: null input\n");
1130*ebfedea0SLionel Sambuc 		return NULL;
1131*ebfedea0SLionel Sambuc 	}
1132*ebfedea0SLionel Sambuc 
1133*ebfedea0SLionel Sambuc 	/* set up signature */
1134*ebfedea0SLionel Sambuc 	if ((sig = pgp_create_sig_new()) == NULL) {
1135*ebfedea0SLionel Sambuc 		return NULL;
1136*ebfedea0SLionel Sambuc 	}
1137*ebfedea0SLionel Sambuc 	pgp_start_sig(sig, seckey, hash_alg, sig_type);
1138*ebfedea0SLionel Sambuc 
1139*ebfedea0SLionel Sambuc 	/* setup writer */
1140*ebfedea0SLionel Sambuc 	pgp_setup_memory_write(&output, &mem, insize);
1141*ebfedea0SLionel Sambuc 
1142*ebfedea0SLionel Sambuc 	if (cleartext) {
1143*ebfedea0SLionel Sambuc 		/* Do the signing */
1144*ebfedea0SLionel Sambuc 		/* add signature with subpackets: */
1145*ebfedea0SLionel Sambuc 		/* - creation time */
1146*ebfedea0SLionel Sambuc 		/* - key id */
1147*ebfedea0SLionel Sambuc 		ret = pgp_writer_push_clearsigned(output, sig) &&
1148*ebfedea0SLionel Sambuc 			pgp_write(output, input, (unsigned)insize) &&
1149*ebfedea0SLionel Sambuc 			pgp_writer_use_armored_sig(output) &&
1150*ebfedea0SLionel Sambuc 			pgp_add_time(sig, from, "birth") &&
1151*ebfedea0SLionel Sambuc 			pgp_add_time(sig, (int64_t)duration, "expiration");
1152*ebfedea0SLionel Sambuc 		if (ret == 0) {
1153*ebfedea0SLionel Sambuc 			return NULL;
1154*ebfedea0SLionel Sambuc 		}
1155*ebfedea0SLionel Sambuc 		pgp_output_delete(output);
1156*ebfedea0SLionel Sambuc 	} else {
1157*ebfedea0SLionel Sambuc 		/* set armoured/not armoured here */
1158*ebfedea0SLionel Sambuc 		if (armored) {
1159*ebfedea0SLionel Sambuc 			pgp_writer_push_armor_msg(output);
1160*ebfedea0SLionel Sambuc 		}
1161*ebfedea0SLionel Sambuc 		if (pgp_get_debug_level(__FILE__)) {
1162*ebfedea0SLionel Sambuc 			fprintf(io->errs, "** Writing out one pass sig\n");
1163*ebfedea0SLionel Sambuc 		}
1164*ebfedea0SLionel Sambuc 		/* write one_pass_sig */
1165*ebfedea0SLionel Sambuc 		pgp_write_one_pass_sig(output, seckey, hash_alg, sig_type);
1166*ebfedea0SLionel Sambuc 
1167*ebfedea0SLionel Sambuc 		/* hash memory */
1168*ebfedea0SLionel Sambuc 		hash = pgp_sig_get_hash(sig);
1169*ebfedea0SLionel Sambuc 		hash->add(hash, input, (unsigned)insize);
1170*ebfedea0SLionel Sambuc 
1171*ebfedea0SLionel Sambuc 		/* output file contents as Literal Data packet */
1172*ebfedea0SLionel Sambuc 		if (pgp_get_debug_level(__FILE__)) {
1173*ebfedea0SLionel Sambuc 			(void) fprintf(stderr, "** Writing out data now\n");
1174*ebfedea0SLionel Sambuc 		}
1175*ebfedea0SLionel Sambuc 		pgp_write_litdata(output, input, (const int)insize, ld_type);
1176*ebfedea0SLionel Sambuc 		if (pgp_get_debug_level(__FILE__)) {
1177*ebfedea0SLionel Sambuc 			fprintf(stderr, "** After Writing out data now\n");
1178*ebfedea0SLionel Sambuc 		}
1179*ebfedea0SLionel Sambuc 
1180*ebfedea0SLionel Sambuc 		/* add creation time to signature */
1181*ebfedea0SLionel Sambuc 		pgp_add_time(sig, from, "birth");
1182*ebfedea0SLionel Sambuc 		pgp_add_time(sig, (int64_t)duration, "expiration");
1183*ebfedea0SLionel Sambuc 		/* add key id to signature */
1184*ebfedea0SLionel Sambuc 		pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
1185*ebfedea0SLionel Sambuc 		pgp_add_issuer_keyid(sig, keyid);
1186*ebfedea0SLionel Sambuc 		pgp_end_hashed_subpkts(sig);
1187*ebfedea0SLionel Sambuc 
1188*ebfedea0SLionel Sambuc 		/* write out sig */
1189*ebfedea0SLionel Sambuc 		pgp_write_sig(output, sig, &seckey->pubkey, seckey);
1190*ebfedea0SLionel Sambuc 
1191*ebfedea0SLionel Sambuc 		/* tidy up */
1192*ebfedea0SLionel Sambuc 		pgp_writer_close(output);
1193*ebfedea0SLionel Sambuc 		pgp_create_sig_delete(sig);
1194*ebfedea0SLionel Sambuc 	}
1195*ebfedea0SLionel Sambuc 	return mem;
1196*ebfedea0SLionel Sambuc }
1197*ebfedea0SLionel Sambuc 
1198*ebfedea0SLionel Sambuc /* sign a file, and put the signature in a separate file */
1199*ebfedea0SLionel Sambuc int
1200*ebfedea0SLionel Sambuc pgp_sign_detached(pgp_io_t *io,
1201*ebfedea0SLionel Sambuc 			const char *f,
1202*ebfedea0SLionel Sambuc 			char *sigfile,
1203*ebfedea0SLionel Sambuc 			pgp_seckey_t *seckey,
1204*ebfedea0SLionel Sambuc 			const char *hash,
1205*ebfedea0SLionel Sambuc 			const int64_t from,
1206*ebfedea0SLionel Sambuc 			const uint64_t duration,
1207*ebfedea0SLionel Sambuc 			const unsigned armored, const unsigned overwrite)
1208*ebfedea0SLionel Sambuc {
1209*ebfedea0SLionel Sambuc 	pgp_create_sig_t	*sig;
1210*ebfedea0SLionel Sambuc 	pgp_hash_alg_t	 hash_alg;
1211*ebfedea0SLionel Sambuc 	pgp_output_t		*output;
1212*ebfedea0SLionel Sambuc 	pgp_memory_t		*mem;
1213*ebfedea0SLionel Sambuc 	uint8_t	 	 	 keyid[PGP_KEY_ID_SIZE];
1214*ebfedea0SLionel Sambuc 	int			 fd;
1215*ebfedea0SLionel Sambuc 
1216*ebfedea0SLionel Sambuc 	/* find out which hash algorithm to use */
1217*ebfedea0SLionel Sambuc 	hash_alg = pgp_str_to_hash_alg(hash);
1218*ebfedea0SLionel Sambuc 	if (hash_alg == PGP_HASH_UNKNOWN) {
1219*ebfedea0SLionel Sambuc 		(void) fprintf(io->errs,"Unknown hash algorithm: %s\n", hash);
1220*ebfedea0SLionel Sambuc 		return 0;
1221*ebfedea0SLionel Sambuc 	}
1222*ebfedea0SLionel Sambuc 
1223*ebfedea0SLionel Sambuc 	/* setup output file */
1224*ebfedea0SLionel Sambuc 	fd = open_output_file(&output, f, sigfile,
1225*ebfedea0SLionel Sambuc 				(armored) ? "asc" : "sig", overwrite);
1226*ebfedea0SLionel Sambuc 	if (fd < 0) {
1227*ebfedea0SLionel Sambuc 		(void) fprintf(io->errs,"Can't open output file: %s\n", f);
1228*ebfedea0SLionel Sambuc 		return 0;
1229*ebfedea0SLionel Sambuc 	}
1230*ebfedea0SLionel Sambuc 
1231*ebfedea0SLionel Sambuc 	/* create a new signature */
1232*ebfedea0SLionel Sambuc 	sig = pgp_create_sig_new();
1233*ebfedea0SLionel Sambuc 	pgp_start_sig(sig, seckey, hash_alg, PGP_SIG_BINARY);
1234*ebfedea0SLionel Sambuc 
1235*ebfedea0SLionel Sambuc 	/* read the contents of 'f', and add that to the signature */
1236*ebfedea0SLionel Sambuc 	mem = pgp_memory_new();
1237*ebfedea0SLionel Sambuc 	if (!pgp_mem_readfile(mem, f)) {
1238*ebfedea0SLionel Sambuc 		pgp_teardown_file_write(output, fd);
1239*ebfedea0SLionel Sambuc 		return 0;
1240*ebfedea0SLionel Sambuc 	}
1241*ebfedea0SLionel Sambuc 	/* set armoured/not armoured here */
1242*ebfedea0SLionel Sambuc 	if (armored) {
1243*ebfedea0SLionel Sambuc 		pgp_writer_push_armor_msg(output);
1244*ebfedea0SLionel Sambuc 	}
1245*ebfedea0SLionel Sambuc 	pgp_sig_add_data(sig, pgp_mem_data(mem), pgp_mem_len(mem));
1246*ebfedea0SLionel Sambuc 	pgp_memory_free(mem);
1247*ebfedea0SLionel Sambuc 
1248*ebfedea0SLionel Sambuc 	/* calculate the signature */
1249*ebfedea0SLionel Sambuc 	pgp_add_time(sig, from, "birth");
1250*ebfedea0SLionel Sambuc 	pgp_add_time(sig, (int64_t)duration, "expiration");
1251*ebfedea0SLionel Sambuc 	pgp_keyid(keyid, sizeof(keyid), &seckey->pubkey, hash_alg);
1252*ebfedea0SLionel Sambuc 	pgp_add_issuer_keyid(sig, keyid);
1253*ebfedea0SLionel Sambuc 	pgp_end_hashed_subpkts(sig);
1254*ebfedea0SLionel Sambuc 	pgp_write_sig(output, sig, &seckey->pubkey, seckey);
1255*ebfedea0SLionel Sambuc 	pgp_teardown_file_write(output, fd);
1256*ebfedea0SLionel Sambuc 	pgp_seckey_free(seckey);
1257*ebfedea0SLionel Sambuc 
1258*ebfedea0SLionel Sambuc 	return 1;
1259*ebfedea0SLionel Sambuc }
1260