xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/signature.c (revision da9817918ec7e88db2912a2882967c7570a83f47)
1 /*-
2  * Copyright (c) 2009 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Alistair Crooks (agc@NetBSD.org)
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 /*
30  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31  * All rights reserved.
32  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33  * their moral rights under the UK Copyright Design and Patents Act 1988 to
34  * be recorded as the authors of this copyright work.
35  *
36  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37  * use this file except in compliance with the License.
38  *
39  * You may obtain a copy of the License at
40  *     http://www.apache.org/licenses/LICENSE-2.0
41  *
42  * Unless required by applicable law or agreed to in writing, software
43  * distributed under the License is distributed on an "AS IS" BASIS,
44  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45  *
46  * See the License for the specific language governing permissions and
47  * limitations under the License.
48  */
49 
50 /** \file
51  */
52 #include "config.h"
53 
54 #ifdef HAVE_SYS_CDEFS_H
55 #include <sys/cdefs.h>
56 #endif
57 
58 #if defined(__NetBSD__)
59 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60 __RCSID("$NetBSD: signature.c,v 1.19 2009/06/11 01:12:42 agc Exp $");
61 #endif
62 
63 #include <sys/types.h>
64 #include <sys/param.h>
65 
66 #ifdef HAVE_FCNTL_H
67 #include <fcntl.h>
68 #endif
69 
70 #include <string.h>
71 
72 #ifdef HAVE_UNISTD_H
73 #include <unistd.h>
74 #endif
75 
76 #ifdef HAVE_OPENSSL_DSA_H
77 #include <openssl/dsa.h>
78 #endif
79 
80 #include "signature.h"
81 #include "crypto.h"
82 #include "create.h"
83 #include "netpgpsdk.h"
84 #include "readerwriter.h"
85 #include "validate.h"
86 #include "netpgpdefs.h"
87 #include "netpgpdigest.h"
88 
89 
90 /** \ingroup Core_Create
91  * needed for signature creation
92  */
93 struct __ops_create_sig_t {
94 	__ops_hash_t		 hash;
95 	__ops_sig_t		 sig;
96 	__ops_memory_t		*mem;
97 	__ops_output_t		*output;	/* how to do the writing */
98 	unsigned		 hashoff;	/* hashed count offset */
99 	unsigned		 hashlen;
100 	unsigned 		 unhashoff;
101 };
102 
103 /**
104    \ingroup Core_Signature
105    Creates new __ops_create_sig_t
106    \return new __ops_create_sig_t
107    \note It is the caller's responsibility to call __ops_create_sig_delete()
108    \sa __ops_create_sig_delete()
109 */
110 __ops_create_sig_t *
111 __ops_create_sig_new(void)
112 {
113 	return calloc(1, sizeof(__ops_create_sig_t));
114 }
115 
116 /**
117    \ingroup Core_Signature
118    Free signature and memory associated with it
119    \param sig struct to free
120    \sa __ops_create_sig_new()
121 */
122 void
123 __ops_create_sig_delete(__ops_create_sig_t *sig)
124 {
125 	__ops_output_delete(sig->output);
126 	sig->output = NULL;
127 	free(sig);
128 }
129 
130 static unsigned char prefix_md5[] = {
131 	0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
132 	0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
133 };
134 
135 static unsigned char prefix_sha1[] = {
136 	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02,
137 	0x1A, 0x05, 0x00, 0x04, 0x14
138 };
139 
140 static unsigned char prefix_sha256[] = {
141 	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
142 	0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
143 };
144 
145 
146 /* XXX: both this and verify would be clearer if the signature were */
147 /* treated as an MPI. */
148 static int
149 rsa_sign(__ops_hash_t *hash,
150 	const __ops_rsa_pubkey_t *pubrsa,
151 	const __ops_rsa_seckey_t *secrsa,
152 	__ops_output_t *out)
153 {
154 	unsigned char   hashbuf[NETPGP_BUFSIZ];
155 	unsigned char   sigbuf[NETPGP_BUFSIZ];
156 	unsigned char  *prefix;
157 	unsigned        prefixsize;
158 	unsigned        expected;
159 	unsigned        hashsize;
160 	unsigned        keysize;
161 	unsigned        n;
162 	unsigned        t;
163 	BIGNUM         *bn;
164 
165 	if (strcmp(hash->name, "SHA1") == 0) {
166 		hashsize = OPS_SHA1_HASH_SIZE + sizeof(prefix_sha1);
167 		prefix = prefix_sha1;
168 		prefixsize = sizeof(prefix_sha1);
169 		expected = OPS_SHA1_HASH_SIZE;
170 	} else {
171 		hashsize = OPS_SHA256_HASH_SIZE + sizeof(prefix_sha256);
172 		prefix = prefix_sha256;
173 		prefixsize = sizeof(prefix_sha256);
174 		expected = OPS_SHA256_HASH_SIZE;
175 	}
176 	keysize = (BN_num_bits(pubrsa->n) + 7) / 8;
177 	if (keysize > sizeof(hashbuf)) {
178 		(void) fprintf(stderr, "rsa_sign: keysize too big\n");
179 		return 0;
180 	}
181 	if (10 + hashsize > keysize) {
182 		(void) fprintf(stderr, "rsa_sign: hashsize too big\n");
183 		return 0;
184 	}
185 
186 	hashbuf[0] = 0;
187 	hashbuf[1] = 1;
188 	if (__ops_get_debug_level(__FILE__)) {
189 		printf("rsa_sign: PS is %d\n", keysize - hashsize - 1 - 2);
190 	}
191 	for (n = 2; n < keysize - hashsize - 1; ++n) {
192 		hashbuf[n] = 0xff;
193 	}
194 	hashbuf[n++] = 0;
195 
196 	(void) memcpy(&hashbuf[n], prefix, prefixsize);
197 	n += prefixsize;
198 	if ((t = hash->finish(hash, &hashbuf[n])) != expected) {
199 		(void) fprintf(stderr, "rsa_sign: short %s hash\n", hash->name);
200 		return 0;
201 	}
202 
203 	__ops_write(out, &hashbuf[n], 2);
204 
205 	n += t;
206 	if (n != keysize) {
207 		(void) fprintf(stderr, "rsa_sign: n != keysize\n");
208 		return 0;
209 	}
210 
211 	t = __ops_rsa_private_encrypt(sigbuf, hashbuf, keysize, secrsa, pubrsa);
212 	bn = BN_bin2bn(sigbuf, (int)t, NULL);
213 	__ops_write_mpi(out, bn);
214 	BN_free(bn);
215 	return 1;
216 }
217 
218 static int
219 dsa_sign(__ops_hash_t *hash,
220 	 const __ops_dsa_pubkey_t *dsa,
221 	 const __ops_dsa_seckey_t *sdsa,
222 	 __ops_output_t *output)
223 {
224 	unsigned char   hashbuf[NETPGP_BUFSIZ];
225 	unsigned        hashsize;
226 	unsigned        t;
227 	DSA_SIG        *dsasig;
228 
229 	/* hashsize must be "equal in size to the number of bits of q,  */
230 	/* the group generated by the DSA key's generator value */
231 	/* 160/8 = 20 */
232 
233 	hashsize = 20;
234 
235 	/* finalise hash */
236 	t = hash->finish(hash, &hashbuf[0]);
237 	if (t != 20) {
238 		(void) fprintf(stderr, "dsa_sign: hashfinish not 20\n");
239 		return 0;
240 	}
241 
242 	__ops_write(output, &hashbuf[0], 2);
243 
244 	/* write signature to buf */
245 	dsasig = __ops_dsa_sign(hashbuf, hashsize, sdsa, dsa);
246 
247 	/* convert and write the sig out to memory */
248 	__ops_write_mpi(output, dsasig->r);
249 	__ops_write_mpi(output, dsasig->s);
250 	DSA_SIG_free(dsasig);
251 	return 1;
252 }
253 
254 static unsigned
255 rsa_verify(__ops_hash_alg_t type,
256 	   const unsigned char *hash,
257 	   size_t hash_length,
258 	   const __ops_rsa_sig_t *sig,
259 	   const __ops_rsa_pubkey_t *pubrsa)
260 {
261 	const unsigned char	*prefix;
262 	unsigned char   	 sigbuf[NETPGP_BUFSIZ];
263 	unsigned char   	 hashbuf_from_sig[NETPGP_BUFSIZ];
264 	unsigned        	 n;
265 	unsigned        	 keysize;
266 	unsigned		 plen;
267 	unsigned		 debug_len_decrypted;
268 
269 	plen = 0;
270 	prefix = (const unsigned char *) "";
271 	keysize = BN_num_bytes(pubrsa->n);
272 	/* RSA key can't be bigger than 65535 bits, so... */
273 	if (keysize > sizeof(hashbuf_from_sig)) {
274 		(void) fprintf(stderr, "rsa_verify: keysize too big\n");
275 		return 0;
276 	}
277 	if ((unsigned) BN_num_bits(sig->sig) > 8 * sizeof(sigbuf)) {
278 		(void) fprintf(stderr, "rsa_verify: BN_numbits too big\n");
279 		return 0;
280 	}
281 	BN_bn2bin(sig->sig, sigbuf);
282 
283 	n = __ops_rsa_public_decrypt(hashbuf_from_sig, sigbuf,
284 		(unsigned)(BN_num_bits(sig->sig) + 7) / 8, pubrsa);
285 	debug_len_decrypted = n;
286 
287 	if (n != keysize) {
288 		/* obviously, this includes error returns */
289 		return 0;
290 	}
291 
292 	/* XXX: why is there a leading 0? The first byte should be 1... */
293 	/* XXX: because the decrypt should use keysize and not sigsize? */
294 	if (hashbuf_from_sig[0] != 0 || hashbuf_from_sig[1] != 1) {
295 		return 0;
296 	}
297 
298 	switch (type) {
299 	case OPS_HASH_MD5:
300 		prefix = prefix_md5;
301 		plen = sizeof(prefix_md5);
302 		break;
303 	case OPS_HASH_SHA1:
304 		prefix = prefix_sha1;
305 		plen = sizeof(prefix_sha1);
306 		break;
307 	case OPS_HASH_SHA256:
308 		prefix = prefix_sha256;
309 		plen = sizeof(prefix_sha256);
310 		break;
311 	default:
312 		(void) fprintf(stderr, "Unknown hash algorithm: %d\n", type);
313 		return 0;
314 	}
315 
316 	if (keysize - plen - hash_length < 10) {
317 		return 0;
318 	}
319 
320 	for (n = 2; n < keysize - plen - hash_length - 1; ++n) {
321 		if (hashbuf_from_sig[n] != 0xff) {
322 			return 0;
323 		}
324 	}
325 
326 	if (hashbuf_from_sig[n++] != 0) {
327 		return 0;
328 	}
329 
330 	if (__ops_get_debug_level(__FILE__)) {
331 		unsigned	zz;
332 		unsigned	uu;
333 
334 		printf("\n");
335 		printf("hashbuf_from_sig\n");
336 		for (zz = 0; zz < debug_len_decrypted; zz++) {
337 			printf("%02x ", hashbuf_from_sig[n + zz]);
338 		}
339 		printf("\n");
340 		printf("prefix\n");
341 		for (zz = 0; zz < plen; zz++) {
342 			printf("%02x ", prefix[zz]);
343 		}
344 		printf("\n");
345 
346 		printf("\n");
347 		printf("hash from sig\n");
348 		for (uu = 0; uu < hash_length; uu++) {
349 			printf("%02x ", hashbuf_from_sig[n + plen + uu]);
350 		}
351 		printf("\n");
352 		printf("hash passed in (should match hash from sig)\n");
353 		for (uu = 0; uu < hash_length; uu++) {
354 			printf("%02x ", hash[uu]);
355 		}
356 		printf("\n");
357 	}
358 	return (memcmp(&hashbuf_from_sig[n], prefix, plen) == 0 &&
359 	        memcmp(&hashbuf_from_sig[n + plen], hash, hash_length) == 0);
360 }
361 
362 static void
363 hash_add_key(__ops_hash_t *hash, const __ops_pubkey_t *key)
364 {
365 	__ops_memory_t	*mem = __ops_memory_new();
366 	const unsigned 	 dontmakepacket = 0;
367 	size_t		 len;
368 
369 	__ops_build_pubkey(mem, key, dontmakepacket);
370 	len = __ops_mem_len(mem);
371 	__ops_hash_add_int(hash, 0x99, 1);
372 	__ops_hash_add_int(hash, len, 2);
373 	hash->add(hash, __ops_mem_data(mem), len);
374 	__ops_memory_free(mem);
375 }
376 
377 static void
378 initialise_hash(__ops_hash_t *hash, const __ops_sig_t *sig)
379 {
380 	__ops_hash_any(hash, sig->info.hash_alg);
381 	hash->init(hash);
382 }
383 
384 static void
385 init_key_sig(__ops_hash_t *hash, const __ops_sig_t *sig,
386 		   const __ops_pubkey_t *key)
387 {
388 	initialise_hash(hash, sig);
389 	hash_add_key(hash, key);
390 }
391 
392 static void
393 hash_add_trailer(__ops_hash_t *hash, const __ops_sig_t *sig,
394 		 const unsigned char *raw_packet)
395 {
396 	if (sig->info.version == OPS_V4) {
397 		if (raw_packet) {
398 			hash->add(hash, raw_packet + sig->v4_hashstart,
399 				  sig->info.v4_hashlen);
400 		}
401 		__ops_hash_add_int(hash, (unsigned)sig->info.version, 1);
402 		__ops_hash_add_int(hash, 0xff, 1);
403 		__ops_hash_add_int(hash, sig->info.v4_hashlen, 4);
404 	} else {
405 		__ops_hash_add_int(hash, (unsigned)sig->info.type, 1);
406 		__ops_hash_add_int(hash, (unsigned)sig->info.birthtime, 4);
407 	}
408 }
409 
410 /**
411    \ingroup Core_Signature
412    \brief Checks a signature
413    \param hash Signature Hash to be checked
414    \param length Signature Length
415    \param sig The Signature to be checked
416    \param signer The signer's public key
417    \return 1 if good; else 0
418 */
419 unsigned
420 __ops_check_sig(const unsigned char *hash, unsigned length,
421 		    const __ops_sig_t * sig,
422 		    const __ops_pubkey_t * signer)
423 {
424 	unsigned   ret;
425 
426 	if (__ops_get_debug_level(__FILE__)) {
427 		printf("__ops_check_sig: (length %d) hash=", length);
428 		hexdump(stdout, hash, length, "");
429 	}
430 	ret = 0;
431 	switch (sig->info.key_alg) {
432 	case OPS_PKA_DSA:
433 		ret = __ops_dsa_verify(hash, length, &sig->info.sig.dsa,
434 				&signer->key.dsa);
435 		break;
436 
437 	case OPS_PKA_RSA:
438 		ret = rsa_verify(sig->info.hash_alg, hash, length,
439 				&sig->info.sig.rsa,
440 				&signer->key.rsa);
441 		break;
442 
443 	default:
444 		(void) fprintf(stderr, "__ops_check_sig: unusual alg\n");
445 		ret = 0;
446 	}
447 
448 	return ret;
449 }
450 
451 static unsigned
452 hash_and_check_sig(__ops_hash_t *hash,
453 			 const __ops_sig_t *sig,
454 			 const __ops_pubkey_t *signer)
455 {
456 	unsigned char   hashout[OPS_MAX_HASH_SIZE];
457 	unsigned	n;
458 
459 	n = hash->finish(hash, hashout);
460 	return __ops_check_sig(hashout, n, sig, signer);
461 }
462 
463 static unsigned
464 finalise_sig(__ops_hash_t *hash,
465 		   const __ops_sig_t *sig,
466 		   const __ops_pubkey_t *signer,
467 		   const unsigned char *raw_packet)
468 {
469 	hash_add_trailer(hash, sig, raw_packet);
470 	return hash_and_check_sig(hash, sig, signer);
471 }
472 
473 /**
474  * \ingroup Core_Signature
475  *
476  * \brief Verify a certification signature.
477  *
478  * \param key The public key that was signed.
479  * \param id The user ID that was signed
480  * \param sig The signature.
481  * \param signer The public key of the signer.
482  * \param raw_packet The raw signature packet.
483  * \return 1 if OK; else 0
484  */
485 unsigned
486 __ops_check_useridcert_sig(const __ops_pubkey_t *key,
487 			  const __ops_userid_t *id,
488 			  const __ops_sig_t *sig,
489 			  const __ops_pubkey_t *signer,
490 			  const unsigned char *raw_packet)
491 {
492 	__ops_hash_t	hash;
493 	size_t          userid_len = strlen((char *) id->userid);
494 
495 	init_key_sig(&hash, sig, key);
496 
497 	if (sig->info.version == OPS_V4) {
498 		__ops_hash_add_int(&hash, 0xb4, 1);
499 		__ops_hash_add_int(&hash, userid_len, 4);
500 	}
501 	hash.add(&hash, id->userid, userid_len);
502 
503 	return finalise_sig(&hash, sig, signer, raw_packet);
504 }
505 
506 /**
507  * \ingroup Core_Signature
508  *
509  * Verify a certification signature.
510  *
511  * \param key The public key that was signed.
512  * \param attribute The user attribute that was signed
513  * \param sig The signature.
514  * \param signer The public key of the signer.
515  * \param raw_packet The raw signature packet.
516  * \return 1 if OK; else 0
517  */
518 unsigned
519 __ops_check_userattrcert_sig(const __ops_pubkey_t *key,
520 				const __ops_userattr_t *attribute,
521 				const __ops_sig_t *sig,
522 				const __ops_pubkey_t *signer,
523 				const unsigned char *raw_packet)
524 {
525 	__ops_hash_t      hash;
526 
527 	init_key_sig(&hash, sig, key);
528 
529 	if (sig->info.version == OPS_V4) {
530 		__ops_hash_add_int(&hash, 0xd1, 1);
531 		__ops_hash_add_int(&hash, attribute->data.len, 4);
532 	}
533 	hash.add(&hash, attribute->data.contents, attribute->data.len);
534 
535 	return finalise_sig(&hash, sig, signer, raw_packet);
536 }
537 
538 /**
539  * \ingroup Core_Signature
540  *
541  * Verify a subkey signature.
542  *
543  * \param key The public key whose subkey was signed.
544  * \param subkey The subkey of the public key that was signed.
545  * \param sig The signature.
546  * \param signer The public key of the signer.
547  * \param raw_packet The raw signature packet.
548  * \return 1 if OK; else 0
549  */
550 unsigned
551 __ops_check_subkey_sig(const __ops_pubkey_t *key,
552 			   const __ops_pubkey_t *subkey,
553 			   const __ops_sig_t *sig,
554 			   const __ops_pubkey_t *signer,
555 			   const unsigned char *raw_packet)
556 {
557 	__ops_hash_t      hash;
558 
559 	init_key_sig(&hash, sig, key);
560 	hash_add_key(&hash, subkey);
561 
562 	return finalise_sig(&hash, sig, signer, raw_packet);
563 }
564 
565 /**
566  * \ingroup Core_Signature
567  *
568  * Verify a direct signature.
569  *
570  * \param key The public key which was signed.
571  * \param sig The signature.
572  * \param signer The public key of the signer.
573  * \param raw_packet The raw signature packet.
574  * \return 1 if OK; else 0
575  */
576 unsigned
577 __ops_check_direct_sig(const __ops_pubkey_t *key,
578 			   const __ops_sig_t *sig,
579 			   const __ops_pubkey_t *signer,
580 			   const unsigned char *raw_packet)
581 {
582 	__ops_hash_t      hash;
583 
584 	init_key_sig(&hash, sig, key);
585 	return finalise_sig(&hash, sig, signer, raw_packet);
586 }
587 
588 /**
589  * \ingroup Core_Signature
590  *
591  * Verify a signature on a hash (the hash will have already been fed
592  * the material that was being signed, for example signed cleartext).
593  *
594  * \param hash A hash structure of appropriate type that has been fed
595  * the material to be signed. This MUST NOT have been finalised.
596  * \param sig The signature to be verified.
597  * \param signer The public key of the signer.
598  * \return 1 if OK; else 0
599  */
600 unsigned
601 __ops_check_hash_sig(__ops_hash_t *hash,
602 			 const __ops_sig_t *sig,
603 			 const __ops_pubkey_t *signer)
604 {
605 	return (sig->info.hash_alg == hash->alg) ?
606 		finalise_sig(hash, sig, signer, NULL) :
607 		0;
608 }
609 
610 static void
611 start_sig_in_mem(__ops_create_sig_t *sig)
612 {
613 	/* since this has subpackets and stuff, we have to buffer the whole */
614 	/* thing to get counts before writing. */
615 	sig->mem = __ops_memory_new();
616 	__ops_memory_init(sig->mem, 100);
617 	__ops_writer_set_memory(sig->output, sig->mem);
618 
619 	/* write nearly up to the first subpacket */
620 	__ops_write_scalar(sig->output, (unsigned)sig->sig.info.version, 1);
621 	__ops_write_scalar(sig->output, (unsigned)sig->sig.info.type, 1);
622 	__ops_write_scalar(sig->output, (unsigned)sig->sig.info.key_alg, 1);
623 	__ops_write_scalar(sig->output, (unsigned)sig->sig.info.hash_alg, 1);
624 
625 	/* dummy hashed subpacket count */
626 	sig->hashoff = __ops_mem_len(sig->mem);
627 	__ops_write_scalar(sig->output, 0, 2);
628 }
629 
630 /**
631  * \ingroup Core_Signature
632  *
633  * __ops_sig_start() creates a V4 public key signature with a SHA1 hash.
634  *
635  * \param sig The signature structure to initialise
636  * \param key The public key to be signed
637  * \param id The user ID being bound to the key
638  * \param type Signature type
639  */
640 void
641 __ops_sig_start_key_sig(__ops_create_sig_t *sig,
642 				  const __ops_pubkey_t *key,
643 				  const __ops_userid_t *id,
644 				  __ops_sig_type_t type)
645 {
646 	sig->output = __ops_output_new();
647 
648 	/* XXX:  refactor with check (in several ways - check should
649 	 * probably use the buffered writer to construct packets
650 	 * (done), and also should share code for hash calculation) */
651 	sig->sig.info.version = OPS_V4;
652 	sig->sig.info.hash_alg = OPS_HASH_SHA1;
653 	sig->sig.info.key_alg = key->alg;
654 	sig->sig.info.type = type;
655 
656 	sig->hashlen = (unsigned)-1;
657 
658 	init_key_sig(&sig->hash, &sig->sig, key);
659 
660 	__ops_hash_add_int(&sig->hash, 0xb4, 1);
661 	__ops_hash_add_int(&sig->hash, strlen((char *) id->userid), 4);
662 	sig->hash.add(&sig->hash, id->userid, strlen((char *) id->userid));
663 
664 	start_sig_in_mem(sig);
665 }
666 
667 /**
668  * \ingroup Core_Signature
669  *
670  * Create a V4 public key signature over some cleartext.
671  *
672  * \param sig The signature structure to initialise
673  * \param id
674  * \param type
675  * \todo Expand description. Allow other hashes.
676  */
677 
678 void
679 __ops_start_sig(__ops_create_sig_t *sig,
680 	      const __ops_seckey_t *key,
681 	      const __ops_hash_alg_t hash,
682 	      const __ops_sig_type_t type)
683 {
684 	sig->output = __ops_output_new();
685 
686 	/* XXX:  refactor with check (in several ways - check should
687 	 * probably use the buffered writer to construct packets
688 	 * (done), and also should share code for hash calculation) */
689 	sig->sig.info.version = OPS_V4;
690 	sig->sig.info.key_alg = key->pubkey.alg;
691 	sig->sig.info.hash_alg = hash;
692 	sig->sig.info.type = type;
693 
694 	sig->hashlen = (unsigned)-1;
695 
696 	if (__ops_get_debug_level(__FILE__)) {
697 		fprintf(stderr, "initialising hash for sig in mem\n");
698 	}
699 	initialise_hash(&sig->hash, &sig->sig);
700 	start_sig_in_mem(sig);
701 }
702 
703 /**
704  * \ingroup Core_Signature
705  *
706  * Add plaintext data to a signature-to-be.
707  *
708  * \param sig The signature-to-be.
709  * \param buf The plaintext data.
710  * \param length The amount of plaintext data.
711  */
712 void
713 __ops_sig_add_data(__ops_create_sig_t *sig, const void *buf, size_t length)
714 {
715 	sig->hash.add(&sig->hash, buf, length);
716 }
717 
718 /**
719  * \ingroup Core_Signature
720  *
721  * Mark the end of the hashed subpackets in the signature
722  *
723  * \param sig
724  */
725 
726 unsigned
727 __ops_end_hashed_subpkts(__ops_create_sig_t *sig)
728 {
729 	sig->hashlen = __ops_mem_len(sig->mem) - sig->hashoff - 2;
730 	__ops_memory_place_int(sig->mem, sig->hashoff, sig->hashlen, 2);
731 	/* dummy unhashed subpacket count */
732 	sig->unhashoff = __ops_mem_len(sig->mem);
733 	return __ops_write_scalar(sig->output, 0, 2);
734 }
735 
736 /**
737  * \ingroup Core_Signature
738  *
739  * Write out a signature
740  *
741  * \param sig
742  * \param key
743  * \param seckey
744  * \param info
745  *
746  */
747 
748 unsigned
749 __ops_write_sig(__ops_output_t *output,
750 			__ops_create_sig_t *sig,
751 			const __ops_pubkey_t *key,
752 			const __ops_seckey_t *seckey)
753 {
754 	unsigned	ret = 0;
755 	size_t		len = __ops_mem_len(sig->mem);
756 
757 	/* check key not decrypted */
758 	switch (seckey->pubkey.alg) {
759 	case OPS_PKA_RSA:
760 	case OPS_PKA_RSA_ENCRYPT_ONLY:
761 	case OPS_PKA_RSA_SIGN_ONLY:
762 		if (seckey->key.rsa.d == NULL) {
763 			(void) fprintf(stderr, "__ops_write_sig: null rsa.d\n");
764 			return 0;
765 		}
766 		break;
767 
768 	case OPS_PKA_DSA:
769 		if (seckey->key.dsa.x == NULL) {
770 			(void) fprintf(stderr, "__ops_write_sig: null dsa.x\n");
771 			return 0;
772 		}
773 		break;
774 
775 	default:
776 		(void) fprintf(stderr, "Unsupported algorithm %d\n",
777 				seckey->pubkey.alg);
778 		return 0;
779 	}
780 
781 	if (sig->hashlen == (unsigned) -1) {
782 		(void) fprintf(stderr,
783 				"ops_write_sig: bad hashed data len\n");
784 		return 0;
785 	}
786 
787 	__ops_memory_place_int(sig->mem, sig->unhashoff,
788 			     len - sig->unhashoff - 2, 2);
789 
790 	/* add the packet from version number to end of hashed subpackets */
791 	if (__ops_get_debug_level(__FILE__)) {
792 		(void) fprintf(stderr, "ops_write_sig: hashed packet info\n");
793 	}
794 	sig->hash.add(&sig->hash, __ops_mem_data(sig->mem), sig->unhashoff);
795 
796 	/* add final trailer */
797 	__ops_hash_add_int(&sig->hash, (unsigned)sig->sig.info.version, 1);
798 	__ops_hash_add_int(&sig->hash, 0xff, 1);
799 	/* +6 for version, type, pk alg, hash alg, hashed subpacket length */
800 	__ops_hash_add_int(&sig->hash, sig->hashlen + 6, 4);
801 
802 	if (__ops_get_debug_level(__FILE__)) {
803 		(void) fprintf(stderr, "ops_write_sig: done writing hashed\n");
804 	}
805 	/* XXX: technically, we could figure out how big the signature is */
806 	/* and write it directly to the output instead of via memory. */
807 	switch (seckey->pubkey.alg) {
808 	case OPS_PKA_RSA:
809 	case OPS_PKA_RSA_ENCRYPT_ONLY:
810 	case OPS_PKA_RSA_SIGN_ONLY:
811 		if (!rsa_sign(&sig->hash, &key->key.rsa, &seckey->key.rsa,
812 				sig->output)) {
813 			(void) fprintf(stderr,
814 				"__ops_write_sig: rsa_sign failure\n");
815 			return 0;
816 		}
817 		break;
818 
819 	case OPS_PKA_DSA:
820 		if (!dsa_sign(&sig->hash, &key->key.dsa, &seckey->key.dsa,
821 				sig->output)) {
822 			(void) fprintf(stderr,
823 				"__ops_write_sig: dsa_sign failure\n");
824 			return 0;
825 		}
826 		break;
827 
828 	default:
829 		(void) fprintf(stderr, "Unsupported algorithm %d\n",
830 					seckey->pubkey.alg);
831 		return 0;
832 	}
833 
834 	ret = __ops_write_ptag(output, OPS_PTAG_CT_SIGNATURE);
835 	if (ret) {
836 		len = __ops_mem_len(sig->mem);
837 		ret = __ops_write_length(output, len) &&
838 			__ops_write(output, __ops_mem_data(sig->mem), len);
839 	}
840 	__ops_memory_free(sig->mem);
841 
842 	if (ret == 0) {
843 		OPS_ERROR(&output->errors, OPS_E_W, "Cannot write signature");
844 	}
845 	return ret;
846 }
847 
848 /**
849  * \ingroup Core_Signature
850  *
851  * __ops_add_birthtime() adds a creation time to the signature.
852  *
853  * \param sig
854  * \param when
855  */
856 unsigned
857 __ops_add_birthtime(__ops_create_sig_t *sig, time_t when)
858 {
859 	return __ops_write_ss_header(sig->output, 5,
860 					OPS_PTAG_SS_CREATION_TIME) &&
861 		__ops_write_scalar(sig->output, (unsigned)when, 4);
862 }
863 
864 /**
865  * \ingroup Core_Signature
866  *
867  * Adds issuer's key ID to the signature
868  *
869  * \param sig
870  * \param keyid
871  */
872 
873 unsigned
874 __ops_add_issuer_keyid(__ops_create_sig_t *sig,
875 				const unsigned char keyid[OPS_KEY_ID_SIZE])
876 {
877 	return __ops_write_ss_header(sig->output, OPS_KEY_ID_SIZE + 1,
878 				OPS_PTAG_SS_ISSUER_KEY_ID) &&
879 		__ops_write(sig->output, keyid, OPS_KEY_ID_SIZE);
880 }
881 
882 /**
883  * \ingroup Core_Signature
884  *
885  * Adds primary user ID to the signature
886  *
887  * \param sig
888  * \param primary
889  */
890 void
891 __ops_add_primary_userid(__ops_create_sig_t *sig, unsigned primary)
892 {
893 	__ops_write_ss_header(sig->output, 2, OPS_PTAG_SS_PRIMARY_USER_ID);
894 	__ops_write_scalar(sig->output, primary, 1);
895 }
896 
897 /**
898  * \ingroup Core_Signature
899  *
900  * Get the hash structure in use for the signature.
901  *
902  * \param sig The signature structure.
903  * \return The hash structure.
904  */
905 __ops_hash_t     *
906 __ops_sig_get_hash(__ops_create_sig_t *sig)
907 {
908 	return &sig->hash;
909 }
910 
911 static int
912 open_output_file(__ops_output_t **output,
913 			const char *inname,
914 			const char *outname,
915 			const unsigned armored,
916 			const unsigned overwrite)
917 {
918 	int             fd;
919 
920 	/* setup output file */
921 	if (outname) {
922 		fd = __ops_setup_file_write(output, outname, overwrite);
923 	} else {
924 		unsigned        flen = strlen(inname) + 4 + 1;
925 		char           *f = NULL;
926 
927 		f = calloc(1, flen);
928 		(void) snprintf(f, flen, "%s.%s", inname,
929 					(armored) ? "asc" : "gpg");
930 		fd = __ops_setup_file_write(output, f, overwrite);
931 		(void) free(f);
932 	}
933 	return fd;
934 }
935 
936 /**
937    \ingroup HighLevel_Sign
938    \brief Sign a file with a Cleartext Signature
939    \param inname Name of file to be signed
940    \param outname Filename to be created. If NULL, filename will be constructed from the inname.
941    \param seckey Secret Key to sign with
942    \param overwrite Allow output file to be overwritten, if set
943    \return 1 if OK, else 0
944 
945 */
946 unsigned
947 __ops_sign_file_as_cleartext(__ops_io_t *io,
948 			const char *inname,
949 			const char *outname,
950 			const __ops_seckey_t *seckey,
951 			const char *hashname,
952 			const unsigned overwrite)
953 {
954 	__ops_create_sig_t	*sig = NULL;
955 	__ops_sig_type_t	 sig_type = OPS_SIG_BINARY;
956 	__ops_hash_alg_t	 hash_alg;
957 	__ops_output_t		*output = NULL;
958 	unsigned char		 keyid[OPS_KEY_ID_SIZE];
959 	unsigned		 ret = 0;
960 	unsigned		 armored = 1;
961 	int			 fd_out = 0;
962 	__ops_memory_t		*mem;
963 
964 	/* check the hash algorithm */
965 	hash_alg = __ops_str_to_hash_alg(hashname);
966 	if (hash_alg == OPS_HASH_UNKNOWN) {
967 		(void) fprintf(io->errs,
968 			"__ops_sign_file_as_cleartext: unknown hash algorithm"
969 			": \"%s\"\n", hashname);
970 		return 0;
971 	}
972 
973 	/* read the file to be signed */
974 	mem = __ops_memory_new();
975 	if (!__ops_mem_readfile(mem, inname)) {
976 		return 0;
977 	}
978 
979 	/* set up output file */
980 	fd_out = open_output_file(&output, inname, outname, armored, overwrite);
981 	if (fd_out < 0) {
982 		__ops_memory_free(mem);
983 		return 0;
984 	}
985 
986 	/* set up signature */
987 	sig = __ops_create_sig_new();
988 	if (!sig) {
989 		__ops_memory_free(mem);
990 		__ops_teardown_file_write(output, fd_out);
991 		return 0;
992 	}
993 
994 	/* \todo could add more error detection here */
995 	__ops_start_sig(sig, seckey, hash_alg, sig_type);
996 	if (__ops_writer_push_clearsigned(output, sig) != 1) {
997 		return 0;
998 	}
999 
1000 	/* Do the signing */
1001 	__ops_write(output, __ops_mem_data(mem), __ops_mem_len(mem));
1002 	__ops_memory_free(mem);
1003 
1004 	/* add signature with subpackets: */
1005 	/* - creation time */
1006 	/* - key id */
1007 	ret = __ops_writer_use_armored_sig(output) &&
1008 			__ops_add_birthtime(sig, time(NULL));
1009 	if (ret == 0) {
1010 		__ops_teardown_file_write(output, fd_out);
1011 		return 0;
1012 	}
1013 
1014 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1015 	ret = __ops_add_issuer_keyid(sig, keyid) &&
1016 		__ops_end_hashed_subpkts(sig) &&
1017 		__ops_write_sig(output, sig, &seckey->pubkey, seckey);
1018 
1019 	__ops_teardown_file_write(output, fd_out);
1020 
1021 	if (ret == 0) {
1022 		OPS_ERROR(&output->errors, OPS_E_W,
1023 				"Cannot sign file as cleartext");
1024 	}
1025 	return ret;
1026 }
1027 
1028 /**
1029  * \ingroup HighLevel_Sign
1030  * \brief Sign a buffer with a Cleartext signature
1031  * \param cleartext Text to be signed
1032  * \param len Length of text
1033  * \param signed __ops_memory_t struct in which to write the signed cleartext
1034  * \param seckey Secret key with which to sign the cleartext
1035  * \return 1 if OK; else 0
1036 
1037  * \note It is the calling function's responsibility to free signed
1038  * \note signed should be a NULL pointer when passed in
1039 
1040  */
1041 unsigned
1042 __ops_sign_buf_as_cleartext(const char *cleartext,
1043 			const size_t len,
1044 			__ops_memory_t **signedtext,
1045 			const __ops_seckey_t *seckey,
1046 			const char *hashname)
1047 {
1048 	__ops_create_sig_t	*sig = NULL;
1049 	__ops_sig_type_t	 sig_type = OPS_SIG_BINARY;
1050 	__ops_hash_alg_t	 hash_alg;
1051 	__ops_output_t		*output = NULL;
1052 	unsigned char		 keyid[OPS_KEY_ID_SIZE];
1053 	unsigned		 ret = 0;
1054 
1055 	/* check the hash algorithm */
1056 	hash_alg = __ops_str_to_hash_alg(hashname);
1057 	if (hash_alg == OPS_HASH_UNKNOWN) {
1058 		(void) fprintf(stderr,
1059 			"__ops_sign_buf_as_cleartext: unknown hash algorithm"
1060 			": \"%s\"\n", hashname);
1061 		return 0;
1062 	}
1063 
1064 
1065 	if (*signedtext != 0x0) {
1066 		(void) fprintf(stderr,
1067 			"__ops_sign_buf_as_cleartext: non-null cleartext\n");
1068 		return 0;
1069 	}
1070 
1071 	/* set up signature */
1072 	sig = __ops_create_sig_new();
1073 	if (!sig) {
1074 		return 0;
1075 	}
1076 	/* \todo could add more error detection here */
1077 	__ops_start_sig(sig, seckey, hash_alg, sig_type);
1078 
1079 	/* set up output file */
1080 	__ops_setup_memory_write(&output, signedtext, len);
1081 
1082 	/* Do the signing */
1083 	/* add signature with subpackets: */
1084 	/* - creation time */
1085 	/* - key id */
1086 	ret = __ops_writer_push_clearsigned(output, sig) &&
1087 		__ops_write(output, cleartext, len) &&
1088 		__ops_writer_use_armored_sig(output) &&
1089 		__ops_add_birthtime(sig, time(NULL));
1090 
1091 	if (ret == 0) {
1092 		return 0;
1093 	}
1094 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1095 
1096 	ret = __ops_add_issuer_keyid(sig, keyid) &&
1097 		__ops_end_hashed_subpkts(sig) &&
1098 		__ops_write_sig(output, sig, &seckey->pubkey, seckey) &&
1099 		__ops_writer_close(output);
1100 
1101 	/* Note: the calling function must free signed */
1102 	__ops_output_delete(output);
1103 
1104 	return ret;
1105 }
1106 
1107 /**
1108 \ingroup HighLevel_Sign
1109 \brief Sign a file
1110 \param inname Input filename
1111 \param outname Output filename. If NULL, a name is constructed from the input filename.
1112 \param seckey Secret Key to use for signing
1113 \param armored Write armoured text, if set.
1114 \param overwrite May overwrite existing file, if set.
1115 \return 1 if OK; else 0;
1116 
1117 */
1118 unsigned
1119 __ops_sign_file(__ops_io_t *io,
1120 		const char *inname,
1121 		const char *outname,
1122 		const __ops_seckey_t *seckey,
1123 		const char *hashname,
1124 		const unsigned armored,
1125 		const unsigned overwrite)
1126 {
1127 	/* \todo allow choice of hash algorithams */
1128 	/* enforce use of SHA1 for now */
1129 
1130 	__ops_create_sig_t	*sig = NULL;
1131 	__ops_hash_alg_t	 hash_alg;
1132 	__ops_sig_type_t	 sig_type = OPS_SIG_BINARY;
1133 	__ops_memory_t		*infile = NULL;
1134 	__ops_output_t		*output = NULL;
1135 	unsigned char		 keyid[OPS_KEY_ID_SIZE];
1136 	__ops_hash_t		*hash = NULL;
1137 	int			 fd = 0;
1138 
1139 	hash_alg = __ops_str_to_hash_alg(hashname);
1140 	if (hash_alg == OPS_HASH_UNKNOWN) {
1141 		(void) fprintf(io->errs,
1142 			"__ops_sign_file: unknown hash algorithm: \"%s\"\n",
1143 			hashname);
1144 		return 0;
1145 	}
1146 
1147 	/* read input file into buf */
1148 	infile = __ops_memory_new();
1149 	if (!__ops_mem_readfile(infile, inname)) {
1150 		return 0;
1151 	}
1152 
1153 	/* setup output file */
1154 	fd = open_output_file(&output, inname, outname, armored, overwrite);
1155 	if (fd < 0) {
1156 		__ops_memory_free(infile);
1157 		return 0;
1158 	}
1159 
1160 	/* set up signature */
1161 	sig = __ops_create_sig_new();
1162 	__ops_start_sig(sig, seckey, hash_alg, sig_type);
1163 
1164 	/* set armoured/not armoured here */
1165 	if (armored) {
1166 		__ops_writer_push_armor_msg(output);
1167 	}
1168 
1169 	/* write one_pass_sig */
1170 	__ops_write_one_pass_sig(output, seckey, hash_alg, sig_type);
1171 
1172 	/* hash file contents */
1173 	hash = __ops_sig_get_hash(sig);
1174 	hash->add(hash, __ops_mem_data(infile), __ops_mem_len(infile));
1175 
1176 	/* output file contents as Literal Data packet */
1177 	if (__ops_get_debug_level(__FILE__)) {
1178 		fprintf(io->errs, "** Writing out data now\n");
1179 	}
1180 	__ops_write_litdata(output, __ops_mem_data(infile),
1181 		(const int)__ops_mem_len(infile),
1182 		OPS_LDT_BINARY);
1183 
1184 	if (__ops_get_debug_level(__FILE__)) {
1185 		fprintf(io->errs, "** After Writing out data now\n");
1186 	}
1187 
1188 	/* add creation time to signature */
1189 	__ops_add_birthtime(sig, time(NULL));
1190 	/* add key id to signature */
1191 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1192 	__ops_add_issuer_keyid(sig, keyid);
1193 	__ops_end_hashed_subpkts(sig);
1194 
1195 	/* write out sig */
1196 	__ops_write_sig(output, sig, &seckey->pubkey, seckey);
1197 
1198 	/* tidy up */
1199 	__ops_teardown_file_write(output, fd);
1200 	__ops_create_sig_delete(sig);
1201 	__ops_memory_free(infile);
1202 
1203 	return 1;
1204 }
1205 
1206 /**
1207 \ingroup HighLevel_Sign
1208 \brief Signs a buffer
1209 \param input Input text to be signed
1210 \param input_len Length of input text
1211 \param sig_type Signature type
1212 \param seckey Secret Key
1213 \param armored Write armoured text, if set
1214 \return New __ops_memory_t struct containing signed text
1215 \note It is the caller's responsibility to call __ops_memory_free(me)
1216 
1217 */
1218 __ops_memory_t   *
1219 __ops_sign_buf(const void *input,
1220 		const size_t input_len,
1221 		const __ops_sig_type_t sig_type,
1222 		const __ops_seckey_t *seckey,
1223 		const unsigned armored)
1224 {
1225 	__ops_litdata_type_t	 ld_type;
1226 	__ops_create_sig_t	*sig = NULL;
1227 	__ops_hash_alg_t	 hash_alg = OPS_HASH_SHA1;
1228 	__ops_output_t		*output = NULL;
1229 	__ops_memory_t		*mem = __ops_memory_new();
1230 	unsigned char		 keyid[OPS_KEY_ID_SIZE];
1231 	__ops_hash_t		*hash = NULL;
1232 
1233 	/* setup literal data packet type */
1234 	ld_type = (sig_type == OPS_SIG_BINARY) ? OPS_LDT_BINARY : OPS_LDT_TEXT;
1235 
1236 	/* set up signature */
1237 	sig = __ops_create_sig_new();
1238 	__ops_start_sig(sig, seckey, hash_alg, sig_type);
1239 
1240 	/* setup writer */
1241 	__ops_setup_memory_write(&output, &mem, input_len);
1242 
1243 	/* set armoured/not armoured here */
1244 	if (armored) {
1245 		__ops_writer_push_armor_msg(output);
1246 	}
1247 
1248 	if (__ops_get_debug_level(__FILE__)) {
1249 		fprintf(stderr, "** Writing out one pass sig\n");
1250 	}
1251 	/* write one_pass_sig */
1252 	__ops_write_one_pass_sig(output, seckey, hash_alg, sig_type);
1253 
1254 	/* hash file contents */
1255 	hash = __ops_sig_get_hash(sig);
1256 	hash->add(hash, input, input_len);
1257 
1258 	/* output file contents as Literal Data packet */
1259 
1260 	if (__ops_get_debug_level(__FILE__)) {
1261 		(void) fprintf(stderr, "** Writing out data now\n");
1262 	}
1263 	__ops_write_litdata(output, input, (const int)input_len, ld_type);
1264 
1265 	if (__ops_get_debug_level(__FILE__)) {
1266 		fprintf(stderr, "** After Writing out data now\n");
1267 	}
1268 
1269 	/* add creation time to signature */
1270 	__ops_add_birthtime(sig, time(NULL));
1271 	/* add key id to signature */
1272 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1273 	__ops_add_issuer_keyid(sig, keyid);
1274 	__ops_end_hashed_subpkts(sig);
1275 
1276 	/* write out sig */
1277 	__ops_write_sig(output, sig, &seckey->pubkey, seckey);
1278 
1279 	/* tidy up */
1280 	__ops_writer_close(output);
1281 	__ops_create_sig_delete(sig);
1282 
1283 	return mem;
1284 }
1285 
1286 /* sign a file, and put the signature in a separate file */
1287 int
1288 __ops_sign_detached(__ops_io_t *io,
1289 			const char *f,
1290 			char *sigfile,
1291 			__ops_seckey_t *seckey,
1292 			const char *hash)
1293 {
1294 	__ops_create_sig_t	*sig;
1295 	__ops_hash_alg_t	 alg;
1296 	__ops_output_t		*output;
1297 	__ops_memory_t		*mem;
1298 	unsigned char	 	 keyid[OPS_KEY_ID_SIZE];
1299 	time_t			 t;
1300 	char			 fname[MAXPATHLEN];
1301 	int			 fd;
1302 
1303 	/* find out which hash algorithm to use */
1304 	alg = __ops_str_to_hash_alg(hash);
1305 	if (alg == OPS_HASH_UNKNOWN) {
1306 		(void) fprintf(io->errs,"Unknown hash algorithm: %s\n", hash);
1307 		return 0;
1308 	}
1309 
1310 	/* create a new signature */
1311 	sig = __ops_create_sig_new();
1312 	__ops_start_sig(sig, seckey, alg, OPS_SIG_BINARY);
1313 
1314 	/* read the contents of 'f', and add that to the signature */
1315 	mem = __ops_memory_new();
1316 	if (!__ops_mem_readfile(mem, f)) {
1317 		return 0;
1318 	}
1319 	__ops_sig_add_data(sig, __ops_mem_data(mem), __ops_mem_len(mem));
1320 	__ops_memory_free(mem);
1321 
1322 	/* calculate the signature */
1323 	t = time(NULL);
1324 	__ops_add_birthtime(sig, t);
1325 	__ops_keyid(keyid, sizeof(keyid), &seckey->pubkey);
1326 	__ops_add_issuer_keyid(sig, keyid);
1327 	__ops_end_hashed_subpkts(sig);
1328 
1329 	/* write the signature to the detached file */
1330 	if (sigfile == NULL) {
1331 		(void) snprintf(fname, sizeof(fname), "%s.sig", f);
1332 		sigfile = fname;
1333 	}
1334 	fd = open(sigfile, O_CREAT|O_TRUNC|O_WRONLY, 0666);
1335 	if (fd < 0) {
1336 		(void) fprintf(io->errs, "can't write signature to \"%s\"\n",
1337 				sigfile);
1338 		return 0;
1339 	}
1340 
1341 	output = __ops_output_new();
1342 	__ops_writer_set_fd(output, fd);
1343 	__ops_write_sig(output, sig, &seckey->pubkey, seckey);
1344 	__ops_seckey_free(seckey);
1345 	(void) close(fd);
1346 
1347 	return 1;
1348 }
1349