xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/signature.c (revision 0294a66b694d2a57b43f64b66c7a4aee89316c4e)
12232f800Sagc /*-
22232f800Sagc  * Copyright (c) 2009 The NetBSD Foundation, Inc.
32232f800Sagc  * All rights reserved.
42232f800Sagc  *
52232f800Sagc  * This code is derived from software contributed to The NetBSD Foundation
62232f800Sagc  * by Alistair Crooks (agc@NetBSD.org)
72232f800Sagc  *
82232f800Sagc  * Redistribution and use in source and binary forms, with or without
92232f800Sagc  * modification, are permitted provided that the following conditions
102232f800Sagc  * are met:
112232f800Sagc  * 1. Redistributions of source code must retain the above copyright
122232f800Sagc  *    notice, this list of conditions and the following disclaimer.
132232f800Sagc  * 2. Redistributions in binary form must reproduce the above copyright
142232f800Sagc  *    notice, this list of conditions and the following disclaimer in the
152232f800Sagc  *    documentation and/or other materials provided with the distribution.
162232f800Sagc  *
172232f800Sagc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
182232f800Sagc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
192232f800Sagc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
202232f800Sagc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
212232f800Sagc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
222232f800Sagc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
232232f800Sagc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
242232f800Sagc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
252232f800Sagc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
262232f800Sagc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
272232f800Sagc  * POSSIBILITY OF SUCH DAMAGE.
282232f800Sagc  */
2993bf6008Sagc /*
3093bf6008Sagc  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
3193bf6008Sagc  * All rights reserved.
3293bf6008Sagc  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
3393bf6008Sagc  * their moral rights under the UK Copyright Design and Patents Act 1988 to
3493bf6008Sagc  * be recorded as the authors of this copyright work.
3593bf6008Sagc  *
3693bf6008Sagc  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
3793bf6008Sagc  * use this file except in compliance with the License.
3893bf6008Sagc  *
3993bf6008Sagc  * You may obtain a copy of the License at
4093bf6008Sagc  *     http://www.apache.org/licenses/LICENSE-2.0
4193bf6008Sagc  *
4293bf6008Sagc  * Unless required by applicable law or agreed to in writing, software
4393bf6008Sagc  * distributed under the License is distributed on an "AS IS" BASIS,
4493bf6008Sagc  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4593bf6008Sagc  *
4693bf6008Sagc  * See the License for the specific language governing permissions and
4793bf6008Sagc  * limitations under the License.
4893bf6008Sagc  */
4993bf6008Sagc 
5093bf6008Sagc /** \file
5193bf6008Sagc  */
5293bf6008Sagc #include "config.h"
5393bf6008Sagc 
5457324b9fSagc #ifdef HAVE_SYS_CDEFS_H
5557324b9fSagc #include <sys/cdefs.h>
5657324b9fSagc #endif
5757324b9fSagc 
5857324b9fSagc #if defined(__NetBSD__)
5957324b9fSagc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60*0294a66bSjhigh __RCSID("$NetBSD: signature.c,v 1.39 2022/08/26 19:18:38 jhigh Exp $");
6157324b9fSagc #endif
6257324b9fSagc 
630df5e957Sagc #include <sys/types.h>
640df5e957Sagc #include <sys/param.h>
650df5e957Sagc 
66ed0df671Sagc #ifdef HAVE_FCNTL_H
67ed0df671Sagc #include <fcntl.h>
6893bf6008Sagc #endif
6993bf6008Sagc 
7093bf6008Sagc #include <string.h>
7193bf6008Sagc 
7293bf6008Sagc #ifdef HAVE_UNISTD_H
7393bf6008Sagc #include <unistd.h>
7493bf6008Sagc #endif
7593bf6008Sagc 
7693bf6008Sagc #ifdef HAVE_OPENSSL_DSA_H
7793bf6008Sagc #include <openssl/dsa.h>
7893bf6008Sagc #endif
7993bf6008Sagc 
80ed0df671Sagc #include "signature.h"
81ed0df671Sagc #include "crypto.h"
82ed0df671Sagc #include "create.h"
83ed0df671Sagc #include "netpgpsdk.h"
84ed0df671Sagc #include "readerwriter.h"
85ed0df671Sagc #include "validate.h"
86ed0df671Sagc #include "netpgpdefs.h"
876715e11aSagc #include "netpgpdigest.h"
886715e11aSagc 
89ed0df671Sagc 
9093bf6008Sagc /** \ingroup Core_Create
9193bf6008Sagc  * needed for signature creation
9293bf6008Sagc  */
93fc1f8641Sagc struct pgp_create_sig_t {
94fc1f8641Sagc 	pgp_hash_t		 hash;
95fc1f8641Sagc 	pgp_sig_t		 sig;
96fc1f8641Sagc 	pgp_memory_t		*mem;
97fc1f8641Sagc 	pgp_output_t		*output;	/* how to do the writing */
9857324b9fSagc 	unsigned		 hashoff;	/* hashed count offset */
9957324b9fSagc 	unsigned		 hashlen;
10057324b9fSagc 	unsigned 		 unhashoff;
10193bf6008Sagc };
10293bf6008Sagc 
10393bf6008Sagc /**
10493bf6008Sagc    \ingroup Core_Signature
105fc1f8641Sagc    Creates new pgp_create_sig_t
106fc1f8641Sagc    \return new pgp_create_sig_t
107fc1f8641Sagc    \note It is the caller's responsibility to call pgp_create_sig_delete()
108fc1f8641Sagc    \sa pgp_create_sig_delete()
10993bf6008Sagc */
110fc1f8641Sagc pgp_create_sig_t *
pgp_create_sig_new(void)111fc1f8641Sagc pgp_create_sig_new(void)
11293bf6008Sagc {
113fc1f8641Sagc 	return calloc(1, sizeof(pgp_create_sig_t));
11493bf6008Sagc }
11593bf6008Sagc 
11693bf6008Sagc /**
11793bf6008Sagc    \ingroup Core_Signature
11893bf6008Sagc    Free signature and memory associated with it
11993bf6008Sagc    \param sig struct to free
120fc1f8641Sagc    \sa pgp_create_sig_new()
12193bf6008Sagc */
12293bf6008Sagc void
pgp_create_sig_delete(pgp_create_sig_t * sig)123fc1f8641Sagc pgp_create_sig_delete(pgp_create_sig_t *sig)
12493bf6008Sagc {
125fc1f8641Sagc 	pgp_output_delete(sig->output);
12657324b9fSagc 	sig->output = NULL;
12793bf6008Sagc 	free(sig);
12893bf6008Sagc }
12993bf6008Sagc 
130600b302bSagc #if 0
131600b302bSagc void
pgp_dump_sig(pgp_sig_t * sig)132fc1f8641Sagc pgp_dump_sig(pgp_sig_t *sig)
133600b302bSagc {
134600b302bSagc }
135600b302bSagc #endif
136600b302bSagc 
137b15ec256Sagc static uint8_t prefix_md5[] = {
138b1b58706Sagc 	0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
139b1b58706Sagc 	0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
140b1b58706Sagc };
14193bf6008Sagc 
142b15ec256Sagc static uint8_t prefix_sha1[] = {
143b1b58706Sagc 	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02,
144b1b58706Sagc 	0x1A, 0x05, 0x00, 0x04, 0x14
145b1b58706Sagc };
14693bf6008Sagc 
147b15ec256Sagc static uint8_t prefix_sha256[] = {
148b1b58706Sagc 	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
149b1b58706Sagc 	0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
150b1b58706Sagc };
15193bf6008Sagc 
15293bf6008Sagc 
15393bf6008Sagc /* XXX: both this and verify would be clearer if the signature were */
15493bf6008Sagc /* treated as an MPI. */
155b1b58706Sagc static int
rsa_sign(pgp_hash_t * hash,const pgp_rsa_pubkey_t * pubrsa,const pgp_rsa_seckey_t * secrsa,pgp_output_t * out)156fc1f8641Sagc rsa_sign(pgp_hash_t *hash,
157fc1f8641Sagc 	const pgp_rsa_pubkey_t *pubrsa,
158fc1f8641Sagc 	const pgp_rsa_seckey_t *secrsa,
159fc1f8641Sagc 	pgp_output_t *out)
16093bf6008Sagc {
16157324b9fSagc 	unsigned        prefixsize;
16257324b9fSagc 	unsigned        expected;
16393bf6008Sagc 	unsigned        hashsize;
1642232f800Sagc 	unsigned        keysize;
16593bf6008Sagc 	unsigned        n;
16693bf6008Sagc 	unsigned        t;
167b15ec256Sagc 	uint8_t		hashbuf[NETPGP_BUFSIZ];
168b15ec256Sagc 	uint8_t		sigbuf[NETPGP_BUFSIZ];
169b15ec256Sagc 	uint8_t		*prefix;
17093bf6008Sagc 	BIGNUM         *bn;
17193bf6008Sagc 
1722232f800Sagc 	if (strcmp(hash->name, "SHA1") == 0) {
173fc1f8641Sagc 		hashsize = PGP_SHA1_HASH_SIZE + sizeof(prefix_sha1);
17457324b9fSagc 		prefix = prefix_sha1;
17557324b9fSagc 		prefixsize = sizeof(prefix_sha1);
176fc1f8641Sagc 		expected = PGP_SHA1_HASH_SIZE;
1772232f800Sagc 	} else {
178fc1f8641Sagc 		hashsize = PGP_SHA256_HASH_SIZE + sizeof(prefix_sha256);
17957324b9fSagc 		prefix = prefix_sha256;
18057324b9fSagc 		prefixsize = sizeof(prefix_sha256);
181fc1f8641Sagc 		expected = PGP_SHA256_HASH_SIZE;
1822232f800Sagc 	}
183b1b58706Sagc 	keysize = (BN_num_bits(pubrsa->n) + 7) / 8;
184ed0df671Sagc 	if (keysize > sizeof(hashbuf)) {
185ed0df671Sagc 		(void) fprintf(stderr, "rsa_sign: keysize too big\n");
186b1b58706Sagc 		return 0;
187ed0df671Sagc 	}
188ed0df671Sagc 	if (10 + hashsize > keysize) {
189ed0df671Sagc 		(void) fprintf(stderr, "rsa_sign: hashsize too big\n");
190b1b58706Sagc 		return 0;
191ed0df671Sagc 	}
19293bf6008Sagc 
19393bf6008Sagc 	hashbuf[0] = 0;
19493bf6008Sagc 	hashbuf[1] = 1;
195fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
19693bf6008Sagc 		printf("rsa_sign: PS is %d\n", keysize - hashsize - 1 - 2);
19793bf6008Sagc 	}
198bcfd8565Sagc 	for (n = 2; n < keysize - hashsize - 1; ++n) {
19993bf6008Sagc 		hashbuf[n] = 0xff;
200bcfd8565Sagc 	}
20193bf6008Sagc 	hashbuf[n++] = 0;
20293bf6008Sagc 
20357324b9fSagc 	(void) memcpy(&hashbuf[n], prefix, prefixsize);
20457324b9fSagc 	n += prefixsize;
20557324b9fSagc 	if ((t = hash->finish(hash, &hashbuf[n])) != expected) {
20657324b9fSagc 		(void) fprintf(stderr, "rsa_sign: short %s hash\n", hash->name);
207b1b58706Sagc 		return 0;
208ed0df671Sagc 	}
20993bf6008Sagc 
210fc1f8641Sagc 	pgp_write(out, &hashbuf[n], 2);
21193bf6008Sagc 
21293bf6008Sagc 	n += t;
213ed0df671Sagc 	if (n != keysize) {
214ed0df671Sagc 		(void) fprintf(stderr, "rsa_sign: n != keysize\n");
215b1b58706Sagc 		return 0;
216ed0df671Sagc 	}
21793bf6008Sagc 
218fc1f8641Sagc 	t = pgp_rsa_private_encrypt(sigbuf, hashbuf, keysize, secrsa, pubrsa);
219efdd9dbaSagc 	bn = BN_bin2bn(sigbuf, (int)t, NULL);
220fc1f8641Sagc 	pgp_write_mpi(out, bn);
22193bf6008Sagc 	BN_free(bn);
222b1b58706Sagc 	return 1;
22393bf6008Sagc }
22493bf6008Sagc 
225b1b58706Sagc static int
dsa_sign(pgp_hash_t * hash,const pgp_dsa_pubkey_t * dsa,const pgp_dsa_seckey_t * sdsa,pgp_output_t * output)226fc1f8641Sagc dsa_sign(pgp_hash_t *hash,
227fc1f8641Sagc 	 const pgp_dsa_pubkey_t *dsa,
228fc1f8641Sagc 	 const pgp_dsa_seckey_t *sdsa,
229fc1f8641Sagc 	 pgp_output_t *output)
23093bf6008Sagc {
23193bf6008Sagc 	unsigned        hashsize;
23293bf6008Sagc 	unsigned        t;
233b15ec256Sagc 	uint8_t		hashbuf[NETPGP_BUFSIZ];
23493bf6008Sagc 	DSA_SIG        *dsasig;
235c9d078dcSchristos 	const BIGNUM   *r, *s;
23693bf6008Sagc 
23793bf6008Sagc 	/* hashsize must be "equal in size to the number of bits of q,  */
23893bf6008Sagc 	/* the group generated by the DSA key's generator value */
23993bf6008Sagc 	/* 160/8 = 20 */
24093bf6008Sagc 
24193bf6008Sagc 	hashsize = 20;
24293bf6008Sagc 
24393bf6008Sagc 	/* finalise hash */
24493bf6008Sagc 	t = hash->finish(hash, &hashbuf[0]);
245ed0df671Sagc 	if (t != 20) {
246ed0df671Sagc 		(void) fprintf(stderr, "dsa_sign: hashfinish not 20\n");
247b1b58706Sagc 		return 0;
248ed0df671Sagc 	}
24993bf6008Sagc 
250fc1f8641Sagc 	pgp_write(output, &hashbuf[0], 2);
25193bf6008Sagc 
25293bf6008Sagc 	/* write signature to buf */
253fc1f8641Sagc 	dsasig = pgp_dsa_sign(hashbuf, hashsize, sdsa, dsa);
25493bf6008Sagc 
25593bf6008Sagc 	/* convert and write the sig out to memory */
256c9d078dcSchristos #if OPENSSL_VERSION_NUMBER >= 0x10100000
257c9d078dcSchristos 	DSA_SIG_get0(dsasig, &r, &s);
258c9d078dcSchristos #else
259c9d078dcSchristos 	r = dsasig->r;
260c9d078dcSchristos 	s = dsasig->s;
261c9d078dcSchristos #endif
262c9d078dcSchristos 	pgp_write_mpi(output, r);
263c9d078dcSchristos 	pgp_write_mpi(output, s);
26493bf6008Sagc 	DSA_SIG_free(dsasig);
265b1b58706Sagc 	return 1;
26693bf6008Sagc }
26793bf6008Sagc 
268*0294a66bSjhigh static int
ecdsa_sign(pgp_hash_t * hash,const pgp_ecdsa_pubkey_t * ecdsa,const pgp_ecdsa_seckey_t * secdsa,pgp_output_t * output)269*0294a66bSjhigh ecdsa_sign(pgp_hash_t *hash,
270*0294a66bSjhigh 	   const pgp_ecdsa_pubkey_t *ecdsa,
271*0294a66bSjhigh 	   const pgp_ecdsa_seckey_t *secdsa,
272*0294a66bSjhigh 	   pgp_output_t *output)
273*0294a66bSjhigh {
274*0294a66bSjhigh 	unsigned        hashsize;
275*0294a66bSjhigh 	unsigned        t;
276*0294a66bSjhigh 	uint8_t         hashbuf[NETPGP_BUFSIZ];
277*0294a66bSjhigh 	ECDSA_SIG        *ecdsasig;
278*0294a66bSjhigh 	const BIGNUM   *r, *s;
279*0294a66bSjhigh 
280*0294a66bSjhigh 	hashsize = ecdsa_hashsize(ecdsa);
281*0294a66bSjhigh 
282*0294a66bSjhigh 	if (hashsize == -1) {
283*0294a66bSjhigh 		return 0;
284*0294a66bSjhigh 	}
285*0294a66bSjhigh 
286*0294a66bSjhigh 	t = hash->finish(hash, &hashbuf[0]);
287*0294a66bSjhigh 
288*0294a66bSjhigh 	if (t != hashsize) {
289*0294a66bSjhigh 		(void) fprintf(stderr, "ecdsa_sign: hashfinish %d not %d\n", t, hashsize);
290*0294a66bSjhigh 		return 0;
291*0294a66bSjhigh 	}
292*0294a66bSjhigh 
293*0294a66bSjhigh 	pgp_write(output, &hashbuf[0], 2);
294*0294a66bSjhigh 
295*0294a66bSjhigh 	/* write signature to buf */
296*0294a66bSjhigh 	ecdsasig = pgp_ecdsa_sign(hashbuf, hashsize, secdsa, ecdsa);
297*0294a66bSjhigh 
298*0294a66bSjhigh 	if (ecdsasig == NULL) {
299*0294a66bSjhigh 		(void) fprintf(stderr, "ecdsa_sign: invalid ecdsa sig\n");
300*0294a66bSjhigh 		return 0;
301*0294a66bSjhigh 	}
302*0294a66bSjhigh 
303*0294a66bSjhigh 	/* convert and write the sig out to memory */
304*0294a66bSjhigh #if OPENSSL_VERSION_NUMBER >= 0x10100000
305*0294a66bSjhigh 	ECDSA_SIG_get0(ecdsasig, &r, &s);
306*0294a66bSjhigh #else
307*0294a66bSjhigh 	r = ecdsasig->r;
308*0294a66bSjhigh 	s = ecdsasig->s;
309*0294a66bSjhigh #endif
310*0294a66bSjhigh 	pgp_write_mpi(output, r);
311*0294a66bSjhigh 	pgp_write_mpi(output, s);
312*0294a66bSjhigh 
313*0294a66bSjhigh 	ECDSA_SIG_free(ecdsasig);
314*0294a66bSjhigh 
315*0294a66bSjhigh 	return 1;
316*0294a66bSjhigh }
317*0294a66bSjhigh 
3184b3a3e18Sagc 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)319fc1f8641Sagc rsa_verify(pgp_hash_alg_t type,
320b15ec256Sagc 	   const uint8_t *hash,
32193bf6008Sagc 	   size_t hash_length,
322fc1f8641Sagc 	   const pgp_rsa_sig_t *sig,
323fc1f8641Sagc 	   const pgp_rsa_pubkey_t *pubrsa)
32493bf6008Sagc {
325b15ec256Sagc 	const uint8_t	*prefix;
32693bf6008Sagc 	unsigned       	 n;
32793bf6008Sagc 	unsigned       	 keysize;
328efdd9dbaSagc 	unsigned	 plen;
32985073018Sagc 	unsigned	 debug_len_decrypted;
330b15ec256Sagc 	uint8_t   	 sigbuf[NETPGP_BUFSIZ];
331b15ec256Sagc 	uint8_t   	 hashbuf_from_sig[NETPGP_BUFSIZ];
33293bf6008Sagc 
33393bf6008Sagc 	plen = 0;
334b15ec256Sagc 	prefix = (const uint8_t *) "";
335b1b58706Sagc 	keysize = BN_num_bytes(pubrsa->n);
33693bf6008Sagc 	/* RSA key can't be bigger than 65535 bits, so... */
337ed0df671Sagc 	if (keysize > sizeof(hashbuf_from_sig)) {
338ed0df671Sagc 		(void) fprintf(stderr, "rsa_verify: keysize too big\n");
3394b3a3e18Sagc 		return 0;
340ed0df671Sagc 	}
341ed0df671Sagc 	if ((unsigned) BN_num_bits(sig->sig) > 8 * sizeof(sigbuf)) {
342ed0df671Sagc 		(void) fprintf(stderr, "rsa_verify: BN_numbits too big\n");
3434b3a3e18Sagc 		return 0;
344ed0df671Sagc 	}
34593bf6008Sagc 	BN_bn2bin(sig->sig, sigbuf);
34693bf6008Sagc 
347fc1f8641Sagc 	n = pgp_rsa_public_decrypt(hashbuf_from_sig, sigbuf,
348b1b58706Sagc 		(unsigned)(BN_num_bits(sig->sig) + 7) / 8, pubrsa);
34993bf6008Sagc 	debug_len_decrypted = n;
35093bf6008Sagc 
3512232f800Sagc 	if (n != keysize) {
3522232f800Sagc 		/* obviously, this includes error returns */
3534b3a3e18Sagc 		return 0;
3542232f800Sagc 	}
35593bf6008Sagc 
35693bf6008Sagc 	/* XXX: why is there a leading 0? The first byte should be 1... */
35793bf6008Sagc 	/* XXX: because the decrypt should use keysize and not sigsize? */
358bcfd8565Sagc 	if (hashbuf_from_sig[0] != 0 || hashbuf_from_sig[1] != 1) {
3594b3a3e18Sagc 		return 0;
360bcfd8565Sagc 	}
36193bf6008Sagc 
36293bf6008Sagc 	switch (type) {
363fc1f8641Sagc 	case PGP_HASH_MD5:
36493bf6008Sagc 		prefix = prefix_md5;
36593bf6008Sagc 		plen = sizeof(prefix_md5);
36693bf6008Sagc 		break;
367fc1f8641Sagc 	case PGP_HASH_SHA1:
36893bf6008Sagc 		prefix = prefix_sha1;
36993bf6008Sagc 		plen = sizeof(prefix_sha1);
37093bf6008Sagc 		break;
371fc1f8641Sagc 	case PGP_HASH_SHA256:
37293bf6008Sagc 		prefix = prefix_sha256;
37393bf6008Sagc 		plen = sizeof(prefix_sha256);
37493bf6008Sagc 		break;
37593bf6008Sagc 	default:
37693bf6008Sagc 		(void) fprintf(stderr, "Unknown hash algorithm: %d\n", type);
3774b3a3e18Sagc 		return 0;
37893bf6008Sagc 	}
37993bf6008Sagc 
380bcfd8565Sagc 	if (keysize - plen - hash_length < 10) {
3814b3a3e18Sagc 		return 0;
382bcfd8565Sagc 	}
38393bf6008Sagc 
384bcfd8565Sagc 	for (n = 2; n < keysize - plen - hash_length - 1; ++n) {
385bcfd8565Sagc 		if (hashbuf_from_sig[n] != 0xff) {
3864b3a3e18Sagc 			return 0;
387bcfd8565Sagc 		}
388bcfd8565Sagc 	}
38993bf6008Sagc 
390bcfd8565Sagc 	if (hashbuf_from_sig[n++] != 0) {
3914b3a3e18Sagc 		return 0;
392bcfd8565Sagc 	}
39393bf6008Sagc 
394fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
39547561e26Sagc 		hexdump(stderr, "sig hashbuf", hashbuf_from_sig, debug_len_decrypted);
39647561e26Sagc 		hexdump(stderr, "prefix", prefix, plen);
39747561e26Sagc 		hexdump(stderr, "sig hash", &hashbuf_from_sig[n + plen], hash_length);
39847561e26Sagc 		hexdump(stderr, "input hash", hash, hash_length);
39993bf6008Sagc 	}
400648b5a99Sagc 	return (memcmp(&hashbuf_from_sig[n], prefix, plen) == 0 &&
401648b5a99Sagc 	        memcmp(&hashbuf_from_sig[n + plen], hash, hash_length) == 0);
40293bf6008Sagc }
40393bf6008Sagc 
40493bf6008Sagc static void
hash_add_key(pgp_hash_t * hash,const pgp_pubkey_t * key)405fc1f8641Sagc hash_add_key(pgp_hash_t *hash, const pgp_pubkey_t *key)
40693bf6008Sagc {
407fc1f8641Sagc 	pgp_memory_t	*mem = pgp_memory_new();
408393ecd92Sagc 	const unsigned 	 dontmakepacket = 0;
4092232f800Sagc 	size_t		 len;
41093bf6008Sagc 
411fc1f8641Sagc 	pgp_build_pubkey(mem, key, dontmakepacket);
412fc1f8641Sagc 	len = pgp_mem_len(mem);
413fc1f8641Sagc 	pgp_hash_add_int(hash, 0x99, 1);
414fc1f8641Sagc 	pgp_hash_add_int(hash, (unsigned)len, 2);
415fc1f8641Sagc 	hash->add(hash, pgp_mem_data(mem), (unsigned)len);
416fc1f8641Sagc 	pgp_memory_free(mem);
41793bf6008Sagc }
41893bf6008Sagc 
41993bf6008Sagc static void
initialise_hash(pgp_hash_t * hash,const pgp_sig_t * sig)420fc1f8641Sagc initialise_hash(pgp_hash_t *hash, const pgp_sig_t *sig)
42193bf6008Sagc {
422fc1f8641Sagc 	pgp_hash_any(hash, sig->info.hash_alg);
4237affbacaSagc 	if (!hash->init(hash)) {
4247affbacaSagc 		(void) fprintf(stderr,
4257affbacaSagc 			"initialise_hash: bad hash init\n");
4267affbacaSagc 		/* just continue and die */
4277affbacaSagc 		/* XXX - agc - no way to return failure */
4287affbacaSagc 	}
42993bf6008Sagc }
43093bf6008Sagc 
43193bf6008Sagc static void
init_key_sig(pgp_hash_t * hash,const pgp_sig_t * sig,const pgp_pubkey_t * key)432fc1f8641Sagc init_key_sig(pgp_hash_t *hash, const pgp_sig_t *sig,
433fc1f8641Sagc 		   const pgp_pubkey_t *key)
43493bf6008Sagc {
43593bf6008Sagc 	initialise_hash(hash, sig);
43693bf6008Sagc 	hash_add_key(hash, key);
43793bf6008Sagc }
43893bf6008Sagc 
43993bf6008Sagc static void
hash_add_trailer(pgp_hash_t * hash,const pgp_sig_t * sig,const uint8_t * raw_packet)440fc1f8641Sagc hash_add_trailer(pgp_hash_t *hash, const pgp_sig_t *sig,
441b15ec256Sagc 		 const uint8_t *raw_packet)
44293bf6008Sagc {
443fc1f8641Sagc 	if (sig->info.version == PGP_V4) {
444bcfd8565Sagc 		if (raw_packet) {
4456715e11aSagc 			hash->add(hash, raw_packet + sig->v4_hashstart,
44669d4f30fSagc 				  (unsigned)sig->info.v4_hashlen);
447bcfd8565Sagc 		}
448fc1f8641Sagc 		pgp_hash_add_int(hash, (unsigned)sig->info.version, 1);
449fc1f8641Sagc 		pgp_hash_add_int(hash, 0xff, 1);
450fc1f8641Sagc 		pgp_hash_add_int(hash, (unsigned)sig->info.v4_hashlen, 4);
45193bf6008Sagc 	} else {
452fc1f8641Sagc 		pgp_hash_add_int(hash, (unsigned)sig->info.type, 1);
453fc1f8641Sagc 		pgp_hash_add_int(hash, (unsigned)sig->info.birthtime, 4);
45493bf6008Sagc 	}
45593bf6008Sagc }
45693bf6008Sagc 
45793bf6008Sagc /**
45893bf6008Sagc    \ingroup Core_Signature
45993bf6008Sagc    \brief Checks a signature
46093bf6008Sagc    \param hash Signature Hash to be checked
46193bf6008Sagc    \param length Signature Length
46293bf6008Sagc    \param sig The Signature to be checked
46393bf6008Sagc    \param signer The signer's public key
4644b3a3e18Sagc    \return 1 if good; else 0
46593bf6008Sagc */
4664b3a3e18Sagc unsigned
pgp_check_sig(const uint8_t * hash,unsigned length,const pgp_sig_t * sig,const pgp_pubkey_t * signer)467fc1f8641Sagc pgp_check_sig(const uint8_t *hash, unsigned length,
468fc1f8641Sagc 		    const pgp_sig_t * sig,
469fc1f8641Sagc 		    const pgp_pubkey_t * signer)
47093bf6008Sagc {
4714b3a3e18Sagc 	unsigned   ret;
47293bf6008Sagc 
473fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
47447561e26Sagc 		hexdump(stdout, "hash", hash, length);
47593bf6008Sagc 	}
47693bf6008Sagc 	ret = 0;
4772232f800Sagc 	switch (sig->info.key_alg) {
478fc1f8641Sagc 	case PGP_PKA_DSA:
479fc1f8641Sagc 		ret = pgp_dsa_verify(hash, length, &sig->info.sig.dsa,
480bcfd8565Sagc 				&signer->key.dsa);
48193bf6008Sagc 		break;
48293bf6008Sagc 
483*0294a66bSjhigh 	case PGP_PKA_ECDSA:
484*0294a66bSjhigh 		ret = pgp_ecdsa_verify(hash, length,
485*0294a66bSjhigh 				&sig->info.sig.ecdsa,
486*0294a66bSjhigh 				&signer->key.ecdsa);
487*0294a66bSjhigh 		break;
488*0294a66bSjhigh 
489fc1f8641Sagc 	case PGP_PKA_RSA:
4902232f800Sagc 		ret = rsa_verify(sig->info.hash_alg, hash, length,
4913326c4c5Sagc 				&sig->info.sig.rsa,
49293bf6008Sagc 				&signer->key.rsa);
49393bf6008Sagc 		break;
49493bf6008Sagc 
49593bf6008Sagc 	default:
496fc1f8641Sagc 		(void) fprintf(stderr, "pgp_check_sig: unusual alg\n");
4974b3a3e18Sagc 		ret = 0;
49893bf6008Sagc 	}
49993bf6008Sagc 
50093bf6008Sagc 	return ret;
50193bf6008Sagc }
50293bf6008Sagc 
5034b3a3e18Sagc static unsigned
hash_and_check_sig(pgp_hash_t * hash,const pgp_sig_t * sig,const pgp_pubkey_t * signer)504fc1f8641Sagc hash_and_check_sig(pgp_hash_t *hash,
505fc1f8641Sagc 			 const pgp_sig_t *sig,
506fc1f8641Sagc 			 const pgp_pubkey_t *signer)
50793bf6008Sagc {
508fc1f8641Sagc 	uint8_t   hashout[PGP_MAX_HASH_SIZE];
509efdd9dbaSagc 	unsigned	n;
51093bf6008Sagc 
51193bf6008Sagc 	n = hash->finish(hash, hashout);
512fc1f8641Sagc 	return pgp_check_sig(hashout, n, sig, signer);
51393bf6008Sagc }
51493bf6008Sagc 
5154b3a3e18Sagc static unsigned
finalise_sig(pgp_hash_t * hash,const pgp_sig_t * sig,const pgp_pubkey_t * signer,const uint8_t * raw_packet)516fc1f8641Sagc finalise_sig(pgp_hash_t *hash,
517fc1f8641Sagc 		   const pgp_sig_t *sig,
518fc1f8641Sagc 		   const pgp_pubkey_t *signer,
519b15ec256Sagc 		   const uint8_t *raw_packet)
52093bf6008Sagc {
52193bf6008Sagc 	hash_add_trailer(hash, sig, raw_packet);
5223326c4c5Sagc 	return hash_and_check_sig(hash, sig, signer);
52393bf6008Sagc }
52493bf6008Sagc 
52593bf6008Sagc /**
52693bf6008Sagc  * \ingroup Core_Signature
52793bf6008Sagc  *
52893bf6008Sagc  * \brief Verify a certification signature.
52993bf6008Sagc  *
53093bf6008Sagc  * \param key The public key that was signed.
53193bf6008Sagc  * \param id The user ID that was signed
53293bf6008Sagc  * \param sig The signature.
53393bf6008Sagc  * \param signer The public key of the signer.
53493bf6008Sagc  * \param raw_packet The raw signature packet.
5354b3a3e18Sagc  * \return 1 if OK; else 0
53693bf6008Sagc  */
5374b3a3e18Sagc 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)538fc1f8641Sagc pgp_check_useridcert_sig(const pgp_pubkey_t *key,
539d427c17dSagc 			  const uint8_t *id,
540fc1f8641Sagc 			  const pgp_sig_t *sig,
541fc1f8641Sagc 			  const pgp_pubkey_t *signer,
542b15ec256Sagc 			  const uint8_t *raw_packet)
54393bf6008Sagc {
544fc1f8641Sagc 	pgp_hash_t	hash;
545d427c17dSagc 	size_t          userid_len;
54693bf6008Sagc 
547d427c17dSagc 	userid_len = strlen((const char *) id);
5483326c4c5Sagc 	init_key_sig(&hash, sig, key);
549fc1f8641Sagc 	if (sig->info.version == PGP_V4) {
550fc1f8641Sagc 		pgp_hash_add_int(&hash, 0xb4, 1);
551fc1f8641Sagc 		pgp_hash_add_int(&hash, (unsigned)userid_len, 4);
55293bf6008Sagc 	}
55369d4f30fSagc 	hash.add(&hash, id, (unsigned)userid_len);
5543326c4c5Sagc 	return finalise_sig(&hash, sig, signer, raw_packet);
55593bf6008Sagc }
55693bf6008Sagc 
55793bf6008Sagc /**
55893bf6008Sagc  * \ingroup Core_Signature
55993bf6008Sagc  *
56093bf6008Sagc  * Verify a certification signature.
56193bf6008Sagc  *
56293bf6008Sagc  * \param key The public key that was signed.
56393bf6008Sagc  * \param attribute The user attribute that was signed
56493bf6008Sagc  * \param sig The signature.
56593bf6008Sagc  * \param signer The public key of the signer.
56693bf6008Sagc  * \param raw_packet The raw signature packet.
5674b3a3e18Sagc  * \return 1 if OK; else 0
56893bf6008Sagc  */
5694b3a3e18Sagc 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)570fc1f8641Sagc pgp_check_userattrcert_sig(const pgp_pubkey_t *key,
571fc1f8641Sagc 				const pgp_data_t *attribute,
572fc1f8641Sagc 				const pgp_sig_t *sig,
573fc1f8641Sagc 				const pgp_pubkey_t *signer,
574b15ec256Sagc 				const uint8_t *raw_packet)
57593bf6008Sagc {
576fc1f8641Sagc 	pgp_hash_t      hash;
57793bf6008Sagc 
5783326c4c5Sagc 	init_key_sig(&hash, sig, key);
579fc1f8641Sagc 	if (sig->info.version == PGP_V4) {
580fc1f8641Sagc 		pgp_hash_add_int(&hash, 0xd1, 1);
581fc1f8641Sagc 		pgp_hash_add_int(&hash, (unsigned)attribute->len, 4);
58293bf6008Sagc 	}
58369d4f30fSagc 	hash.add(&hash, attribute->contents, (unsigned)attribute->len);
5843326c4c5Sagc 	return finalise_sig(&hash, sig, signer, raw_packet);
58593bf6008Sagc }
58693bf6008Sagc 
58793bf6008Sagc /**
58893bf6008Sagc  * \ingroup Core_Signature
58993bf6008Sagc  *
59093bf6008Sagc  * Verify a subkey signature.
59193bf6008Sagc  *
59293bf6008Sagc  * \param key The public key whose subkey was signed.
59393bf6008Sagc  * \param subkey The subkey of the public key that was signed.
59493bf6008Sagc  * \param sig The signature.
59593bf6008Sagc  * \param signer The public key of the signer.
59693bf6008Sagc  * \param raw_packet The raw signature packet.
5974b3a3e18Sagc  * \return 1 if OK; else 0
59893bf6008Sagc  */
5994b3a3e18Sagc 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)600fc1f8641Sagc pgp_check_subkey_sig(const pgp_pubkey_t *key,
601fc1f8641Sagc 			   const pgp_pubkey_t *subkey,
602fc1f8641Sagc 			   const pgp_sig_t *sig,
603fc1f8641Sagc 			   const pgp_pubkey_t *signer,
604b15ec256Sagc 			   const uint8_t *raw_packet)
60593bf6008Sagc {
606fc1f8641Sagc 	pgp_hash_t	hash;
607600b302bSagc 	unsigned	ret;
60893bf6008Sagc 
6093326c4c5Sagc 	init_key_sig(&hash, sig, key);
61093bf6008Sagc 	hash_add_key(&hash, subkey);
611600b302bSagc 	ret = finalise_sig(&hash, sig, signer, raw_packet);
612600b302bSagc 	return ret;
61393bf6008Sagc }
61493bf6008Sagc 
61593bf6008Sagc /**
61693bf6008Sagc  * \ingroup Core_Signature
61793bf6008Sagc  *
61893bf6008Sagc  * Verify a direct signature.
61993bf6008Sagc  *
62093bf6008Sagc  * \param key The public key which was signed.
62193bf6008Sagc  * \param sig The signature.
62293bf6008Sagc  * \param signer The public key of the signer.
62393bf6008Sagc  * \param raw_packet The raw signature packet.
6244b3a3e18Sagc  * \return 1 if OK; else 0
62593bf6008Sagc  */
6264b3a3e18Sagc 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)627fc1f8641Sagc pgp_check_direct_sig(const pgp_pubkey_t *key,
628fc1f8641Sagc 			   const pgp_sig_t *sig,
629fc1f8641Sagc 			   const pgp_pubkey_t *signer,
630b15ec256Sagc 			   const uint8_t *raw_packet)
63193bf6008Sagc {
632fc1f8641Sagc 	pgp_hash_t	hash;
633600b302bSagc 	unsigned	ret;
63493bf6008Sagc 
6353326c4c5Sagc 	init_key_sig(&hash, sig, key);
636600b302bSagc 	ret = finalise_sig(&hash, sig, signer, raw_packet);
637600b302bSagc 	return ret;
63893bf6008Sagc }
63993bf6008Sagc 
64093bf6008Sagc /**
64193bf6008Sagc  * \ingroup Core_Signature
64293bf6008Sagc  *
64393bf6008Sagc  * Verify a signature on a hash (the hash will have already been fed
64493bf6008Sagc  * the material that was being signed, for example signed cleartext).
64593bf6008Sagc  *
64693bf6008Sagc  * \param hash A hash structure of appropriate type that has been fed
64793bf6008Sagc  * the material to be signed. This MUST NOT have been finalised.
64893bf6008Sagc  * \param sig The signature to be verified.
64993bf6008Sagc  * \param signer The public key of the signer.
6504b3a3e18Sagc  * \return 1 if OK; else 0
65193bf6008Sagc  */
6524b3a3e18Sagc unsigned
pgp_check_hash_sig(pgp_hash_t * hash,const pgp_sig_t * sig,const pgp_pubkey_t * signer)653fc1f8641Sagc pgp_check_hash_sig(pgp_hash_t *hash,
654fc1f8641Sagc 			 const pgp_sig_t *sig,
655fc1f8641Sagc 			 const pgp_pubkey_t *signer)
65693bf6008Sagc {
6572232f800Sagc 	return (sig->info.hash_alg == hash->alg) ?
6583326c4c5Sagc 		finalise_sig(hash, sig, signer, NULL) :
6594b3a3e18Sagc 		0;
66093bf6008Sagc }
66193bf6008Sagc 
66293bf6008Sagc static void
start_sig_in_mem(pgp_create_sig_t * sig)663fc1f8641Sagc start_sig_in_mem(pgp_create_sig_t *sig)
66493bf6008Sagc {
66593bf6008Sagc 	/* since this has subpackets and stuff, we have to buffer the whole */
66693bf6008Sagc 	/* thing to get counts before writing. */
667fc1f8641Sagc 	sig->mem = pgp_memory_new();
668fc1f8641Sagc 	pgp_memory_init(sig->mem, 100);
669fc1f8641Sagc 	pgp_writer_set_memory(sig->output, sig->mem);
67093bf6008Sagc 
67193bf6008Sagc 	/* write nearly up to the first subpacket */
672fc1f8641Sagc 	pgp_write_scalar(sig->output, (unsigned)sig->sig.info.version, 1);
673fc1f8641Sagc 	pgp_write_scalar(sig->output, (unsigned)sig->sig.info.type, 1);
674fc1f8641Sagc 	pgp_write_scalar(sig->output, (unsigned)sig->sig.info.key_alg, 1);
675fc1f8641Sagc 	pgp_write_scalar(sig->output, (unsigned)sig->sig.info.hash_alg, 1);
67693bf6008Sagc 
67793bf6008Sagc 	/* dummy hashed subpacket count */
678fc1f8641Sagc 	sig->hashoff = (unsigned)pgp_mem_len(sig->mem);
679fc1f8641Sagc 	pgp_write_scalar(sig->output, 0, 2);
68093bf6008Sagc }
68193bf6008Sagc 
68293bf6008Sagc /**
68393bf6008Sagc  * \ingroup Core_Signature
68493bf6008Sagc  *
685fc1f8641Sagc  * pgp_sig_start() creates a V4 public key signature with a SHA1 hash.
68693bf6008Sagc  *
68793bf6008Sagc  * \param sig The signature structure to initialise
68893bf6008Sagc  * \param key The public key to be signed
68993bf6008Sagc  * \param id The user ID being bound to the key
69093bf6008Sagc  * \param type Signature type
69193bf6008Sagc  */
69293bf6008Sagc 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)693fc1f8641Sagc pgp_sig_start_key_sig(pgp_create_sig_t *sig,
694fc1f8641Sagc 				  const pgp_pubkey_t *key,
695d427c17dSagc 				  const uint8_t *id,
696fc1f8641Sagc 				  pgp_sig_type_t type)
69793bf6008Sagc {
698fc1f8641Sagc 	sig->output = pgp_output_new();
69993bf6008Sagc 
700efdd9dbaSagc 	/* XXX:  refactor with check (in several ways - check should
701efdd9dbaSagc 	 * probably use the buffered writer to construct packets
702efdd9dbaSagc 	 * (done), and also should share code for hash calculation) */
703fc1f8641Sagc 	sig->sig.info.version = PGP_V4;
704fc1f8641Sagc 	sig->sig.info.hash_alg = PGP_HASH_SHA1;
7052232f800Sagc 	sig->sig.info.key_alg = key->alg;
70693bf6008Sagc 	sig->sig.info.type = type;
70757324b9fSagc 	sig->hashlen = (unsigned)-1;
7083326c4c5Sagc 	init_key_sig(&sig->hash, &sig->sig, key);
709fc1f8641Sagc 	pgp_hash_add_int(&sig->hash, 0xb4, 1);
710fc1f8641Sagc 	pgp_hash_add_int(&sig->hash, (unsigned)strlen((const char *) id), 4);
71169d4f30fSagc 	sig->hash.add(&sig->hash, id, (unsigned)strlen((const char *) id));
7123326c4c5Sagc 	start_sig_in_mem(sig);
71393bf6008Sagc }
71493bf6008Sagc 
71593bf6008Sagc /**
71693bf6008Sagc  * \ingroup Core_Signature
71793bf6008Sagc  *
71893bf6008Sagc  * Create a V4 public key signature over some cleartext.
71993bf6008Sagc  *
72093bf6008Sagc  * \param sig The signature structure to initialise
72193bf6008Sagc  * \param id
72293bf6008Sagc  * \param type
72393bf6008Sagc  * \todo Expand description. Allow other hashes.
72493bf6008Sagc  */
72593bf6008Sagc 
726b1b58706Sagc 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)727fc1f8641Sagc pgp_start_sig(pgp_create_sig_t *sig,
728fc1f8641Sagc 	      const pgp_seckey_t *key,
729fc1f8641Sagc 	      const pgp_hash_alg_t hash,
730fc1f8641Sagc 	      const pgp_sig_type_t type)
73193bf6008Sagc {
732fc1f8641Sagc 	sig->output = pgp_output_new();
73393bf6008Sagc 
734b1b58706Sagc 	/* XXX:  refactor with check (in several ways - check should
735b1b58706Sagc 	 * probably use the buffered writer to construct packets
736b1b58706Sagc 	 * (done), and also should share code for hash calculation) */
737fc1f8641Sagc 	sig->sig.info.version = PGP_V4;
7382232f800Sagc 	sig->sig.info.key_alg = key->pubkey.alg;
7392232f800Sagc 	sig->sig.info.hash_alg = hash;
74093bf6008Sagc 	sig->sig.info.type = type;
74193bf6008Sagc 
74257324b9fSagc 	sig->hashlen = (unsigned)-1;
74393bf6008Sagc 
744fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
74593bf6008Sagc 		fprintf(stderr, "initialising hash for sig in mem\n");
74693bf6008Sagc 	}
74793bf6008Sagc 	initialise_hash(&sig->hash, &sig->sig);
7483326c4c5Sagc 	start_sig_in_mem(sig);
74993bf6008Sagc }
75093bf6008Sagc 
75193bf6008Sagc /**
75293bf6008Sagc  * \ingroup Core_Signature
75393bf6008Sagc  *
75493bf6008Sagc  * Add plaintext data to a signature-to-be.
75593bf6008Sagc  *
75693bf6008Sagc  * \param sig The signature-to-be.
75793bf6008Sagc  * \param buf The plaintext data.
75893bf6008Sagc  * \param length The amount of plaintext data.
75993bf6008Sagc  */
76093bf6008Sagc void
pgp_sig_add_data(pgp_create_sig_t * sig,const void * buf,size_t length)761fc1f8641Sagc pgp_sig_add_data(pgp_create_sig_t *sig, const void *buf, size_t length)
76293bf6008Sagc {
76369d4f30fSagc 	sig->hash.add(&sig->hash, buf, (unsigned)length);
76493bf6008Sagc }
76593bf6008Sagc 
76693bf6008Sagc /**
76793bf6008Sagc  * \ingroup Core_Signature
76893bf6008Sagc  *
76993bf6008Sagc  * Mark the end of the hashed subpackets in the signature
77093bf6008Sagc  *
77193bf6008Sagc  * \param sig
77293bf6008Sagc  */
77393bf6008Sagc 
7744b3a3e18Sagc unsigned
pgp_end_hashed_subpkts(pgp_create_sig_t * sig)775fc1f8641Sagc pgp_end_hashed_subpkts(pgp_create_sig_t *sig)
77693bf6008Sagc {
777fc1f8641Sagc 	sig->hashlen = (unsigned)(pgp_mem_len(sig->mem) - sig->hashoff - 2);
778fc1f8641Sagc 	pgp_memory_place_int(sig->mem, sig->hashoff, sig->hashlen, 2);
77993bf6008Sagc 	/* dummy unhashed subpacket count */
780fc1f8641Sagc 	sig->unhashoff = (unsigned)pgp_mem_len(sig->mem);
781fc1f8641Sagc 	return pgp_write_scalar(sig->output, 0, 2);
78293bf6008Sagc }
78393bf6008Sagc 
78493bf6008Sagc /**
78593bf6008Sagc  * \ingroup Core_Signature
78693bf6008Sagc  *
78793bf6008Sagc  * Write out a signature
78893bf6008Sagc  *
78993bf6008Sagc  * \param sig
79093bf6008Sagc  * \param key
7910c310959Sagc  * \param seckey
79293bf6008Sagc  * \param info
79393bf6008Sagc  *
79493bf6008Sagc  */
79593bf6008Sagc 
7964b3a3e18Sagc unsigned
pgp_write_sig(pgp_output_t * output,pgp_create_sig_t * sig,const pgp_pubkey_t * key,const pgp_seckey_t * seckey)797fc1f8641Sagc pgp_write_sig(pgp_output_t *output,
798fc1f8641Sagc 			pgp_create_sig_t *sig,
799fc1f8641Sagc 			const pgp_pubkey_t *key,
800fc1f8641Sagc 			const pgp_seckey_t *seckey)
80193bf6008Sagc {
80257324b9fSagc 	unsigned	ret = 0;
803fc1f8641Sagc 	size_t		len = pgp_mem_len(sig->mem);
80493bf6008Sagc 
80593bf6008Sagc 	/* check key not decrypted */
8062232f800Sagc 	switch (seckey->pubkey.alg) {
807fc1f8641Sagc 	case PGP_PKA_RSA:
808fc1f8641Sagc 	case PGP_PKA_RSA_ENCRYPT_ONLY:
809fc1f8641Sagc 	case PGP_PKA_RSA_SIGN_ONLY:
8100c310959Sagc 		if (seckey->key.rsa.d == NULL) {
811fc1f8641Sagc 			(void) fprintf(stderr, "pgp_write_sig: null rsa.d\n");
8124b3a3e18Sagc 			return 0;
813ed0df671Sagc 		}
81493bf6008Sagc 		break;
81593bf6008Sagc 
816fc1f8641Sagc 	case PGP_PKA_DSA:
8170c310959Sagc 		if (seckey->key.dsa.x == NULL) {
818fc1f8641Sagc 			(void) fprintf(stderr, "pgp_write_sig: null dsa.x\n");
8194b3a3e18Sagc 			return 0;
820ed0df671Sagc 		}
82193bf6008Sagc 		break;
82293bf6008Sagc 
823*0294a66bSjhigh 	case PGP_PKA_ECDSA:
824*0294a66bSjhigh 		if (seckey->key.ecdsa.x == NULL) {
825*0294a66bSjhigh 			(void) fprintf(stderr, "pgp_write_sig: null ecdsa.x\n");
826*0294a66bSjhigh 			return 0;
827*0294a66bSjhigh 		}
828*0294a66bSjhigh 
829*0294a66bSjhigh 		break;
830*0294a66bSjhigh 
83193bf6008Sagc 	default:
832bcfd8565Sagc 		(void) fprintf(stderr, "Unsupported algorithm %d\n",
8332232f800Sagc 				seckey->pubkey.alg);
8344b3a3e18Sagc 		return 0;
83593bf6008Sagc 	}
83693bf6008Sagc 
83757324b9fSagc 	if (sig->hashlen == (unsigned) -1) {
838ed0df671Sagc 		(void) fprintf(stderr,
8393326c4c5Sagc 				"ops_write_sig: bad hashed data len\n");
8404b3a3e18Sagc 		return 0;
841ed0df671Sagc 	}
84293bf6008Sagc 
843fc1f8641Sagc 	pgp_memory_place_int(sig->mem, sig->unhashoff,
84469d4f30fSagc 			     (unsigned)(len - sig->unhashoff - 2), 2);
84593bf6008Sagc 
84693bf6008Sagc 	/* add the packet from version number to end of hashed subpackets */
847fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
84857324b9fSagc 		(void) fprintf(stderr, "ops_write_sig: hashed packet info\n");
84993bf6008Sagc 	}
850fc1f8641Sagc 	sig->hash.add(&sig->hash, pgp_mem_data(sig->mem), sig->unhashoff);
85193bf6008Sagc 
85293bf6008Sagc 	/* add final trailer */
853fc1f8641Sagc 	pgp_hash_add_int(&sig->hash, (unsigned)sig->sig.info.version, 1);
854fc1f8641Sagc 	pgp_hash_add_int(&sig->hash, 0xff, 1);
85593bf6008Sagc 	/* +6 for version, type, pk alg, hash alg, hashed subpacket length */
856fc1f8641Sagc 	pgp_hash_add_int(&sig->hash, sig->hashlen + 6, 4);
85793bf6008Sagc 
858fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
85957324b9fSagc 		(void) fprintf(stderr, "ops_write_sig: done writing hashed\n");
86093bf6008Sagc 	}
86193bf6008Sagc 	/* XXX: technically, we could figure out how big the signature is */
86293bf6008Sagc 	/* and write it directly to the output instead of via memory. */
8632232f800Sagc 	switch (seckey->pubkey.alg) {
864fc1f8641Sagc 	case PGP_PKA_RSA:
865fc1f8641Sagc 	case PGP_PKA_RSA_ENCRYPT_ONLY:
866fc1f8641Sagc 	case PGP_PKA_RSA_SIGN_ONLY:
867b1b58706Sagc 		if (!rsa_sign(&sig->hash, &key->key.rsa, &seckey->key.rsa,
86857324b9fSagc 				sig->output)) {
869b1b58706Sagc 			(void) fprintf(stderr,
870fc1f8641Sagc 				"pgp_write_sig: rsa_sign failure\n");
8714b3a3e18Sagc 			return 0;
872b1b58706Sagc 		}
87393bf6008Sagc 		break;
87493bf6008Sagc 
875fc1f8641Sagc 	case PGP_PKA_DSA:
876b1b58706Sagc 		if (!dsa_sign(&sig->hash, &key->key.dsa, &seckey->key.dsa,
87757324b9fSagc 				sig->output)) {
878b1b58706Sagc 			(void) fprintf(stderr,
879fc1f8641Sagc 				"pgp_write_sig: dsa_sign failure\n");
8804b3a3e18Sagc 			return 0;
881b1b58706Sagc 		}
88293bf6008Sagc 		break;
88393bf6008Sagc 
884*0294a66bSjhigh 	case PGP_PKA_ECDSA:
885*0294a66bSjhigh 		if (!ecdsa_sign(&sig->hash, &key->key.ecdsa, &seckey->key.ecdsa,
886*0294a66bSjhigh 				sig->output)) {
887*0294a66bSjhigh 			(void) fprintf(stderr,
888*0294a66bSjhigh 				"pgp_write_sig: ecdsa_sign failure\n");
889*0294a66bSjhigh 			return 0;
890*0294a66bSjhigh 		}
891*0294a66bSjhigh 		break;
892*0294a66bSjhigh 
89393bf6008Sagc 	default:
894bcfd8565Sagc 		(void) fprintf(stderr, "Unsupported algorithm %d\n",
8952232f800Sagc 					seckey->pubkey.alg);
8964b3a3e18Sagc 		return 0;
89793bf6008Sagc 	}
89893bf6008Sagc 
899fc1f8641Sagc 	ret = pgp_write_ptag(output, PGP_PTAG_CT_SIGNATURE);
90057324b9fSagc 	if (ret) {
901fc1f8641Sagc 		len = pgp_mem_len(sig->mem);
902fc1f8641Sagc 		ret = pgp_write_length(output, (unsigned)len) &&
903fc1f8641Sagc 			pgp_write(output, pgp_mem_data(sig->mem), (unsigned)len);
90493bf6008Sagc 	}
905fc1f8641Sagc 	pgp_memory_free(sig->mem);
90693bf6008Sagc 
90757324b9fSagc 	if (ret == 0) {
90894fcde8eSchristos 		PGP_ERROR_1(&output->errors, PGP_E_W, "%s",
90994fcde8eSchristos 		    "Cannot write signature");
91093bf6008Sagc 	}
91157324b9fSagc 	return ret;
91293bf6008Sagc }
91393bf6008Sagc 
91469d4f30fSagc /* add a time stamp to the output */
9154b3a3e18Sagc unsigned
pgp_add_time(pgp_create_sig_t * sig,int64_t when,const char * type)916fc1f8641Sagc pgp_add_time(pgp_create_sig_t *sig, int64_t when, const char *type)
91793bf6008Sagc {
918fc1f8641Sagc 	pgp_content_enum	tag;
91993bf6008Sagc 
92069d4f30fSagc 	tag = (strcmp(type, "birth") == 0) ?
921fc1f8641Sagc 		PGP_PTAG_SS_CREATION_TIME : PGP_PTAG_SS_EXPIRATION_TIME;
92269d4f30fSagc 	/* just do 32-bit timestamps for just now - it's in the protocol */
923fc1f8641Sagc 	return pgp_write_ss_header(sig->output, 5, tag) &&
924fc1f8641Sagc 		pgp_write_scalar(sig->output, (uint32_t)when, (unsigned)sizeof(uint32_t));
925600b302bSagc }
926600b302bSagc 
927600b302bSagc /**
92893bf6008Sagc  * \ingroup Core_Signature
92993bf6008Sagc  *
93093bf6008Sagc  * Adds issuer's key ID to the signature
93193bf6008Sagc  *
93293bf6008Sagc  * \param sig
93393bf6008Sagc  * \param keyid
93493bf6008Sagc  */
93593bf6008Sagc 
9364b3a3e18Sagc unsigned
pgp_add_issuer_keyid(pgp_create_sig_t * sig,const uint8_t keyid[PGP_KEY_ID_SIZE])937fc1f8641Sagc pgp_add_issuer_keyid(pgp_create_sig_t *sig,
938fc1f8641Sagc 				const uint8_t keyid[PGP_KEY_ID_SIZE])
93993bf6008Sagc {
940fc1f8641Sagc 	return pgp_write_ss_header(sig->output, PGP_KEY_ID_SIZE + 1,
941fc1f8641Sagc 				PGP_PTAG_SS_ISSUER_KEY_ID) &&
942fc1f8641Sagc 		pgp_write(sig->output, keyid, PGP_KEY_ID_SIZE);
94393bf6008Sagc }
94493bf6008Sagc 
94593bf6008Sagc /**
94693bf6008Sagc  * \ingroup Core_Signature
94793bf6008Sagc  *
94893bf6008Sagc  * Adds primary user ID to the signature
94993bf6008Sagc  *
95093bf6008Sagc  * \param sig
95193bf6008Sagc  * \param primary
95293bf6008Sagc  */
95393bf6008Sagc void
pgp_add_primary_userid(pgp_create_sig_t * sig,unsigned primary)954fc1f8641Sagc pgp_add_primary_userid(pgp_create_sig_t *sig, unsigned primary)
95593bf6008Sagc {
956fc1f8641Sagc 	pgp_write_ss_header(sig->output, 2, PGP_PTAG_SS_PRIMARY_USER_ID);
957fc1f8641Sagc 	pgp_write_scalar(sig->output, primary, 1);
95893bf6008Sagc }
95993bf6008Sagc 
96093bf6008Sagc /**
96193bf6008Sagc  * \ingroup Core_Signature
96293bf6008Sagc  *
96393bf6008Sagc  * Get the hash structure in use for the signature.
96493bf6008Sagc  *
96593bf6008Sagc  * \param sig The signature structure.
96693bf6008Sagc  * \return The hash structure.
96793bf6008Sagc  */
968fc1f8641Sagc pgp_hash_t     *
pgp_sig_get_hash(pgp_create_sig_t * sig)969fc1f8641Sagc pgp_sig_get_hash(pgp_create_sig_t *sig)
97093bf6008Sagc {
97193bf6008Sagc 	return &sig->hash;
97293bf6008Sagc }
97393bf6008Sagc 
974afcc02d5Sagc /* open up an output file */
97593bf6008Sagc static int
open_output_file(pgp_output_t ** output,const char * inname,const char * outname,const char * suffix,const unsigned overwrite)976fc1f8641Sagc open_output_file(pgp_output_t **output,
97757324b9fSagc 			const char *inname,
97857324b9fSagc 			const char *outname,
979afcc02d5Sagc 			const char *suffix,
9804b3a3e18Sagc 			const unsigned overwrite)
98193bf6008Sagc {
98257324b9fSagc 	int             fd;
98393bf6008Sagc 
98493bf6008Sagc 	/* setup output file */
98557324b9fSagc 	if (outname) {
986a4f591ebSkhorben 		if (strcmp(outname, "-") == 0) {
987a4f591ebSkhorben 			fd = pgp_setup_file_write(output, NULL, overwrite);
988a4f591ebSkhorben 		} else {
989fc1f8641Sagc 			fd = pgp_setup_file_write(output, outname, overwrite);
990a4f591ebSkhorben 		}
99193bf6008Sagc 	} else {
992020e2e0fSkhorben 		size_t          flen = strlen(inname) + 1 + strlen(suffix) + 1;
99357324b9fSagc 		char           *f = NULL;
994bcfd8565Sagc 
99583cfb9deSagc 		if ((f = calloc(1, flen)) == NULL) {
99683cfb9deSagc 			(void) fprintf(stderr, "open_output_file: bad alloc\n");
99783cfb9deSagc 			fd = -1;
99883cfb9deSagc 		} else {
999afcc02d5Sagc 			(void) snprintf(f, flen, "%s.%s", inname, suffix);
1000fc1f8641Sagc 			fd = pgp_setup_file_write(output, f, overwrite);
100183cfb9deSagc 			free(f);
100283cfb9deSagc 		}
1003bcfd8565Sagc 	}
100457324b9fSagc 	return fd;
100593bf6008Sagc }
100693bf6008Sagc 
100793bf6008Sagc /**
100893bf6008Sagc \ingroup HighLevel_Sign
1009ad7bc21dSagc \brief Sign a file
1010ad7bc21dSagc \param inname Input filename
1011ad7bc21dSagc \param outname Output filename. If NULL, a name is constructed from the input filename.
1012ad7bc21dSagc \param seckey Secret Key to use for signing
1013ad7bc21dSagc \param armored Write armoured text, if set.
1014ad7bc21dSagc \param overwrite May overwrite existing file, if set.
1015ad7bc21dSagc \return 1 if OK; else 0;
101693bf6008Sagc 
101793bf6008Sagc */
10184b3a3e18Sagc 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)1019fc1f8641Sagc pgp_sign_file(pgp_io_t *io,
1020d21b929eSagc 		const char *inname,
102157324b9fSagc 		const char *outname,
1022fc1f8641Sagc 		const pgp_seckey_t *seckey,
10232232f800Sagc 		const char *hashname,
1024600b302bSagc 		const int64_t from,
1025600b302bSagc 		const uint64_t duration,
1026ad7bc21dSagc 		const unsigned armored,
1027ad7bc21dSagc 		const unsigned cleartext,
10284b3a3e18Sagc 		const unsigned overwrite)
102993bf6008Sagc {
1030fc1f8641Sagc 	pgp_create_sig_t	*sig;
1031fc1f8641Sagc 	pgp_sig_type_t	 sig_type;
1032fc1f8641Sagc 	pgp_hash_alg_t	 hash_alg;
1033fc1f8641Sagc 	pgp_memory_t		*infile;
1034fc1f8641Sagc 	pgp_output_t		*output;
1035fc1f8641Sagc 	pgp_hash_t		*hash;
1036ad7bc21dSagc 	unsigned		 ret;
1037fc1f8641Sagc 	uint8_t			 keyid[PGP_KEY_ID_SIZE];
1038ad7bc21dSagc 	int			 fd_out;
10392232f800Sagc 
1040ad7bc21dSagc 	sig = NULL;
1041fc1f8641Sagc 	sig_type = PGP_SIG_BINARY;
1042ad7bc21dSagc 	infile = NULL;
1043ad7bc21dSagc 	output = NULL;
1044ad7bc21dSagc 	hash = NULL;
1045ad7bc21dSagc 	fd_out = 0;
1046ad7bc21dSagc 
1047ad7bc21dSagc 	/* find the hash algorithm */
1048*0294a66bSjhigh 	switch (seckey->pubkey.alg) {
1049*0294a66bSjhigh 		case PGP_PKA_ECDSA:
1050*0294a66bSjhigh 			hash_alg = ecdsa_hashalg(&seckey->pubkey.key.ecdsa);
1051*0294a66bSjhigh 			break;
1052*0294a66bSjhigh 		default:
1053fc1f8641Sagc 			hash_alg = pgp_str_to_hash_alg(hashname);
1054*0294a66bSjhigh 	}
1055*0294a66bSjhigh 
1056fc1f8641Sagc 	if (hash_alg == PGP_HASH_UNKNOWN) {
1057d21b929eSagc 		(void) fprintf(io->errs,
1058fc1f8641Sagc 			"pgp_sign_file: unknown hash algorithm: \"%s\"\n",
1059ad7bc21dSagc 			hashname);
10604b3a3e18Sagc 		return 0;
10612232f800Sagc 	}
106293bf6008Sagc 
1063ad7bc21dSagc 	/* read input file into buf */
1064fc1f8641Sagc 	infile = pgp_memory_new();
1065fc1f8641Sagc 	if (!pgp_mem_readfile(infile, inname)) {
10664b3a3e18Sagc 		return 0;
106793bf6008Sagc 	}
10682232f800Sagc 
106993bf6008Sagc 	/* setup output file */
1070afcc02d5Sagc 	fd_out = open_output_file(&output, inname, outname,
1071afcc02d5Sagc 				(armored) ? "asc" : "gpg", overwrite);
107293bf6008Sagc 	if (fd_out < 0) {
1073fc1f8641Sagc 		pgp_memory_free(infile);
10744b3a3e18Sagc 		return 0;
107593bf6008Sagc 	}
10762232f800Sagc 
107793bf6008Sagc 	/* set up signature */
1078fc1f8641Sagc 	sig = pgp_create_sig_new();
107993bf6008Sagc 	if (!sig) {
1080fc1f8641Sagc 		pgp_memory_free(infile);
1081fc1f8641Sagc 		pgp_teardown_file_write(output, fd_out);
10824b3a3e18Sagc 		return 0;
108393bf6008Sagc 	}
10842232f800Sagc 
1085fc1f8641Sagc 	pgp_start_sig(sig, seckey, hash_alg, sig_type);
1086ad7bc21dSagc 
1087ad7bc21dSagc 	if (cleartext) {
1088fc1f8641Sagc 		if (pgp_writer_push_clearsigned(output, sig) != 1) {
10894b3a3e18Sagc 			return 0;
109093bf6008Sagc 		}
109193bf6008Sagc 
1092de704779Sagc 		/* Do the signing */
1093fc1f8641Sagc 		pgp_write(output, pgp_mem_data(infile), (unsigned)pgp_mem_len(infile));
1094fc1f8641Sagc 		pgp_memory_free(infile);
109593bf6008Sagc 
109693bf6008Sagc 		/* add signature with subpackets: */
109793bf6008Sagc 		/* - creation time */
109893bf6008Sagc 		/* - key id */
1099fc1f8641Sagc 		ret = pgp_writer_use_armored_sig(output) &&
1100fc1f8641Sagc 				pgp_add_time(sig, (int64_t)from, "birth") &&
1101fc1f8641Sagc 				pgp_add_time(sig, (int64_t)duration, "expiration");
110257324b9fSagc 		if (ret == 0) {
1103fc1f8641Sagc 			pgp_teardown_file_write(output, fd_out);
11044b3a3e18Sagc 			return 0;
110593bf6008Sagc 		}
110657324b9fSagc 
1107fc1f8641Sagc 		pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
1108fc1f8641Sagc 		ret = pgp_add_issuer_keyid(sig, keyid) &&
1109fc1f8641Sagc 			pgp_end_hashed_subpkts(sig) &&
1110fc1f8641Sagc 			pgp_write_sig(output, sig, &seckey->pubkey, seckey);
111193bf6008Sagc 
1112fc1f8641Sagc 		pgp_teardown_file_write(output, fd_out);
111393bf6008Sagc 
111457324b9fSagc 		if (ret == 0) {
111594fcde8eSchristos 			PGP_ERROR_1(&output->errors, PGP_E_W, "%s",
1116bcfd8565Sagc 			    "Cannot sign file as cleartext");
111793bf6008Sagc 		}
1118ad7bc21dSagc 	} else {
111993bf6008Sagc 		/* set armoured/not armoured here */
112057324b9fSagc 		if (armored) {
1121fc1f8641Sagc 			pgp_writer_push_armor_msg(output);
1122bcfd8565Sagc 		}
112393bf6008Sagc 
112493bf6008Sagc 		/* write one_pass_sig */
1125fc1f8641Sagc 		pgp_write_one_pass_sig(output, seckey, hash_alg, sig_type);
112693bf6008Sagc 
112793bf6008Sagc 		/* hash file contents */
1128fc1f8641Sagc 		hash = pgp_sig_get_hash(sig);
1129fc1f8641Sagc 		hash->add(hash, pgp_mem_data(infile), (unsigned)pgp_mem_len(infile));
113093bf6008Sagc 
1131b15ec256Sagc #if 1
113293bf6008Sagc 		/* output file contents as Literal Data packet */
1133fc1f8641Sagc 		pgp_write_litdata(output, pgp_mem_data(infile),
1134fc1f8641Sagc 			(const int)pgp_mem_len(infile),
1135fc1f8641Sagc 			PGP_LDT_BINARY);
1136b15ec256Sagc #else
1137b15ec256Sagc 		/* XXX - agc - sync with writer.c 1094 for ops_writez */
1138fc1f8641Sagc 		pgp_setup_memory_write(&litoutput, &litmem, bufsz);
1139fc1f8641Sagc 		pgp_setup_memory_write(&zoutput, &zmem, bufsz);
1140fc1f8641Sagc 		pgp_write_litdata(litoutput,
1141fc1f8641Sagc 			pgp_mem_data(pgp_mem_data(infile),
1142fc1f8641Sagc 			(const int)pgp_mem_len(infile), PGP_LDT_BINARY);
1143fc1f8641Sagc 		pgp_writez(zoutput, pgp_mem_data(litmem), pgp_mem_len(litmem));
1144b15ec256Sagc #endif
114593bf6008Sagc 
114657324b9fSagc 		/* add creation time to signature */
1147fc1f8641Sagc 		pgp_add_time(sig, (int64_t)from, "birth");
1148fc1f8641Sagc 		pgp_add_time(sig, (int64_t)duration, "expiration");
114957324b9fSagc 		/* add key id to signature */
1150fc1f8641Sagc 		pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
1151fc1f8641Sagc 		pgp_add_issuer_keyid(sig, keyid);
1152fc1f8641Sagc 		pgp_end_hashed_subpkts(sig);
1153fc1f8641Sagc 		pgp_write_sig(output, sig, &seckey->pubkey, seckey);
115493bf6008Sagc 
115593bf6008Sagc 		/* tidy up */
1156fc1f8641Sagc 		pgp_teardown_file_write(output, fd_out);
1157ad7bc21dSagc 
1158fc1f8641Sagc 		pgp_create_sig_delete(sig);
1159fc1f8641Sagc 		pgp_memory_free(infile);
1160632dc3acSagc 
1161632dc3acSagc 		ret = 1;
1162ad7bc21dSagc 	}
116393bf6008Sagc 
1164ad7bc21dSagc 	return ret;
116593bf6008Sagc }
116693bf6008Sagc 
116793bf6008Sagc /**
116893bf6008Sagc \ingroup HighLevel_Sign
116993bf6008Sagc \brief Signs a buffer
117093bf6008Sagc \param input Input text to be signed
117193bf6008Sagc \param input_len Length of input text
117293bf6008Sagc \param sig_type Signature type
11730c310959Sagc \param seckey Secret Key
117457324b9fSagc \param armored Write armoured text, if set
1175fc1f8641Sagc \return New pgp_memory_t struct containing signed text
1176fc1f8641Sagc \note It is the caller's responsibility to call pgp_memory_free(me)
117793bf6008Sagc 
117893bf6008Sagc */
1179fc1f8641Sagc pgp_memory_t *
1180fc1f8641Sagc pgp_sign_buf(pgp_io_t *io,
1181ad7bc21dSagc 		const void *input,
1182ad7bc21dSagc 		const size_t insize,
1183fc1f8641Sagc 		const pgp_seckey_t *seckey,
1184600b302bSagc 		const int64_t from,
1185600b302bSagc 		const uint64_t duration,
1186ad7bc21dSagc 		const char *hashname,
1187ad7bc21dSagc 		const unsigned armored,
1188ad7bc21dSagc 		const unsigned cleartext)
118993bf6008Sagc {
1190fc1f8641Sagc 	pgp_litdata_enum	 ld_type;
1191fc1f8641Sagc 	pgp_create_sig_t	*sig;
1192fc1f8641Sagc 	pgp_sig_type_t	 sig_type;
1193fc1f8641Sagc 	pgp_hash_alg_t	 hash_alg;
1194fc1f8641Sagc 	pgp_output_t		*output;
1195fc1f8641Sagc 	pgp_memory_t		*mem;
1196fc1f8641Sagc 	uint8_t			 keyid[PGP_KEY_ID_SIZE];
1197fc1f8641Sagc 	pgp_hash_t		*hash;
1198ad7bc21dSagc 	unsigned		 ret;
1199ad7bc21dSagc 
1200ad7bc21dSagc 	sig = NULL;
1201fc1f8641Sagc 	sig_type = PGP_SIG_BINARY;
1202ad7bc21dSagc 	output = NULL;
1203fc1f8641Sagc 	mem = pgp_memory_new();
1204ad7bc21dSagc 	hash = NULL;
1205ad7bc21dSagc 	ret = 0;
1206ad7bc21dSagc 
1207fc1f8641Sagc 	hash_alg = pgp_str_to_hash_alg(hashname);
1208fc1f8641Sagc 	if (hash_alg == PGP_HASH_UNKNOWN) {
1209ad7bc21dSagc 		(void) fprintf(io->errs,
1210fc1f8641Sagc 			"pgp_sign_buf: unknown hash algorithm: \"%s\"\n",
1211ad7bc21dSagc 			hashname);
1212ad7bc21dSagc 		return NULL;
1213ad7bc21dSagc 	}
121493bf6008Sagc 
121593bf6008Sagc 	/* setup literal data packet type */
1216fc1f8641Sagc 	ld_type = (cleartext) ? PGP_LDT_TEXT : PGP_LDT_BINARY;
1217ad7bc21dSagc 
1218ad7bc21dSagc 	if (input == NULL) {
1219ad7bc21dSagc 		(void) fprintf(io->errs,
1220fc1f8641Sagc 			"pgp_sign_buf: null input\n");
1221d369874eSagc 		return NULL;
1222ad7bc21dSagc 	}
1223bcfd8565Sagc 
122493bf6008Sagc 	/* set up signature */
1225fc1f8641Sagc 	if ((sig = pgp_create_sig_new()) == NULL) {
1226ad7bc21dSagc 		return NULL;
1227ad7bc21dSagc 	}
1228fc1f8641Sagc 	pgp_start_sig(sig, seckey, hash_alg, sig_type);
122993bf6008Sagc 
123093bf6008Sagc 	/* setup writer */
1231fc1f8641Sagc 	pgp_setup_memory_write(&output, &mem, insize);
123293bf6008Sagc 
1233ad7bc21dSagc 	if (cleartext) {
1234ad7bc21dSagc 		/* Do the signing */
1235ad7bc21dSagc 		/* add signature with subpackets: */
1236ad7bc21dSagc 		/* - creation time */
1237ad7bc21dSagc 		/* - key id */
1238fc1f8641Sagc 		ret = pgp_writer_push_clearsigned(output, sig) &&
1239fc1f8641Sagc 			pgp_write(output, input, (unsigned)insize) &&
1240fc1f8641Sagc 			pgp_writer_use_armored_sig(output) &&
1241fc1f8641Sagc 			pgp_add_time(sig, from, "birth") &&
1242fc1f8641Sagc 			pgp_add_time(sig, (int64_t)duration, "expiration");
1243ad7bc21dSagc 		if (ret == 0) {
1244ad7bc21dSagc 			return NULL;
1245ad7bc21dSagc 		}
1246fc1f8641Sagc 		pgp_output_delete(output);
1247ad7bc21dSagc 	} else {
124893bf6008Sagc 		/* set armoured/not armoured here */
124957324b9fSagc 		if (armored) {
1250fc1f8641Sagc 			pgp_writer_push_armor_msg(output);
1251bcfd8565Sagc 		}
1252fc1f8641Sagc 		if (pgp_get_debug_level(__FILE__)) {
1253ad7bc21dSagc 			fprintf(io->errs, "** Writing out one pass sig\n");
125493bf6008Sagc 		}
125593bf6008Sagc 		/* write one_pass_sig */
1256fc1f8641Sagc 		pgp_write_one_pass_sig(output, seckey, hash_alg, sig_type);
125793bf6008Sagc 
1258ad7bc21dSagc 		/* hash memory */
1259fc1f8641Sagc 		hash = pgp_sig_get_hash(sig);
12603f685a78Sagc 		hash->add(hash, input, (unsigned)insize);
126193bf6008Sagc 
126293bf6008Sagc 		/* output file contents as Literal Data packet */
1263fc1f8641Sagc 		if (pgp_get_debug_level(__FILE__)) {
126457324b9fSagc 			(void) fprintf(stderr, "** Writing out data now\n");
126593bf6008Sagc 		}
1266fc1f8641Sagc 		pgp_write_litdata(output, input, (const int)insize, ld_type);
1267fc1f8641Sagc 		if (pgp_get_debug_level(__FILE__)) {
126893bf6008Sagc 			fprintf(stderr, "** After Writing out data now\n");
126993bf6008Sagc 		}
127093bf6008Sagc 
127157324b9fSagc 		/* add creation time to signature */
1272fc1f8641Sagc 		pgp_add_time(sig, from, "birth");
1273fc1f8641Sagc 		pgp_add_time(sig, (int64_t)duration, "expiration");
127457324b9fSagc 		/* add key id to signature */
1275fc1f8641Sagc 		pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
1276fc1f8641Sagc 		pgp_add_issuer_keyid(sig, keyid);
1277fc1f8641Sagc 		pgp_end_hashed_subpkts(sig);
127893bf6008Sagc 
127993bf6008Sagc 		/* write out sig */
1280fc1f8641Sagc 		pgp_write_sig(output, sig, &seckey->pubkey, seckey);
128193bf6008Sagc 
128293bf6008Sagc 		/* tidy up */
1283fc1f8641Sagc 		pgp_writer_close(output);
1284fc1f8641Sagc 		pgp_create_sig_delete(sig);
1285ad7bc21dSagc 	}
128693bf6008Sagc 	return mem;
128793bf6008Sagc }
12880df5e957Sagc 
12890df5e957Sagc /* sign a file, and put the signature in a separate file */
12900df5e957Sagc int
1291fc1f8641Sagc pgp_sign_detached(pgp_io_t *io,
1292d21b929eSagc 			const char *f,
12930df5e957Sagc 			char *sigfile,
1294fc1f8641Sagc 			pgp_seckey_t *seckey,
1295600b302bSagc 			const char *hash,
1296600b302bSagc 			const int64_t from,
1297afcc02d5Sagc 			const uint64_t duration,
1298afcc02d5Sagc 			const unsigned armored, const unsigned overwrite)
12990df5e957Sagc {
1300fc1f8641Sagc 	pgp_create_sig_t	*sig;
1301fc1f8641Sagc 	pgp_hash_alg_t	 hash_alg;
1302fc1f8641Sagc 	pgp_output_t		*output;
1303fc1f8641Sagc 	pgp_memory_t		*mem;
1304fc1f8641Sagc 	uint8_t	 	 	 keyid[PGP_KEY_ID_SIZE];
13050df5e957Sagc 	int			 fd;
13060df5e957Sagc 
13070df5e957Sagc 	/* find out which hash algorithm to use */
1308fc1f8641Sagc 	hash_alg = pgp_str_to_hash_alg(hash);
1309fc1f8641Sagc 	if (hash_alg == PGP_HASH_UNKNOWN) {
1310d21b929eSagc 		(void) fprintf(io->errs,"Unknown hash algorithm: %s\n", hash);
13110df5e957Sagc 		return 0;
13120df5e957Sagc 	}
13130df5e957Sagc 
1314afcc02d5Sagc 	/* setup output file */
1315afcc02d5Sagc 	fd = open_output_file(&output, f, sigfile,
1316afcc02d5Sagc 				(armored) ? "asc" : "sig", overwrite);
1317afcc02d5Sagc 	if (fd < 0) {
1318afcc02d5Sagc 		(void) fprintf(io->errs,"Can't open output file: %s\n", f);
1319afcc02d5Sagc 		return 0;
1320afcc02d5Sagc 	}
1321afcc02d5Sagc 
13220df5e957Sagc 	/* create a new signature */
1323fc1f8641Sagc 	sig = pgp_create_sig_new();
1324fc1f8641Sagc 	pgp_start_sig(sig, seckey, hash_alg, PGP_SIG_BINARY);
13250df5e957Sagc 
13260df5e957Sagc 	/* read the contents of 'f', and add that to the signature */
1327fc1f8641Sagc 	mem = pgp_memory_new();
1328fc1f8641Sagc 	if (!pgp_mem_readfile(mem, f)) {
1329fc1f8641Sagc 		pgp_teardown_file_write(output, fd);
13300df5e957Sagc 		return 0;
13310df5e957Sagc 	}
1332afcc02d5Sagc 	/* set armoured/not armoured here */
1333afcc02d5Sagc 	if (armored) {
1334fc1f8641Sagc 		pgp_writer_push_armor_msg(output);
1335afcc02d5Sagc 	}
1336fc1f8641Sagc 	pgp_sig_add_data(sig, pgp_mem_data(mem), pgp_mem_len(mem));
1337fc1f8641Sagc 	pgp_memory_free(mem);
13380df5e957Sagc 
13390df5e957Sagc 	/* calculate the signature */
1340fc1f8641Sagc 	pgp_add_time(sig, from, "birth");
1341fc1f8641Sagc 	pgp_add_time(sig, (int64_t)duration, "expiration");
1342fc1f8641Sagc 	pgp_keyid(keyid, sizeof(keyid), &seckey->pubkey, hash_alg);
1343fc1f8641Sagc 	pgp_add_issuer_keyid(sig, keyid);
1344fc1f8641Sagc 	pgp_end_hashed_subpkts(sig);
1345fc1f8641Sagc 	pgp_write_sig(output, sig, &seckey->pubkey, seckey);
1346fc1f8641Sagc 	pgp_teardown_file_write(output, fd);
1347fc1f8641Sagc 	pgp_seckey_free(seckey);
13480df5e957Sagc 
13490df5e957Sagc 	return 1;
13500df5e957Sagc }
1351