xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/signature.c (revision 6deb2c22d20de1d75d538e8a5c57b573926fd157)
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.21 2009/10/07 16:19:51 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 	if (!hash->init(hash)) {
382 		(void) fprintf(stderr,
383 			"initialise_hash: bad hash init\n");
384 		/* just continue and die */
385 		/* XXX - agc - no way to return failure */
386 	}
387 }
388 
389 static void
390 init_key_sig(__ops_hash_t *hash, const __ops_sig_t *sig,
391 		   const __ops_pubkey_t *key)
392 {
393 	initialise_hash(hash, sig);
394 	hash_add_key(hash, key);
395 }
396 
397 static void
398 hash_add_trailer(__ops_hash_t *hash, const __ops_sig_t *sig,
399 		 const unsigned char *raw_packet)
400 {
401 	if (sig->info.version == OPS_V4) {
402 		if (raw_packet) {
403 			hash->add(hash, raw_packet + sig->v4_hashstart,
404 				  sig->info.v4_hashlen);
405 		}
406 		__ops_hash_add_int(hash, (unsigned)sig->info.version, 1);
407 		__ops_hash_add_int(hash, 0xff, 1);
408 		__ops_hash_add_int(hash, sig->info.v4_hashlen, 4);
409 	} else {
410 		__ops_hash_add_int(hash, (unsigned)sig->info.type, 1);
411 		__ops_hash_add_int(hash, (unsigned)sig->info.birthtime, 4);
412 	}
413 }
414 
415 /**
416    \ingroup Core_Signature
417    \brief Checks a signature
418    \param hash Signature Hash to be checked
419    \param length Signature Length
420    \param sig The Signature to be checked
421    \param signer The signer's public key
422    \return 1 if good; else 0
423 */
424 unsigned
425 __ops_check_sig(const unsigned char *hash, unsigned length,
426 		    const __ops_sig_t * sig,
427 		    const __ops_pubkey_t * signer)
428 {
429 	unsigned   ret;
430 
431 	if (__ops_get_debug_level(__FILE__)) {
432 		printf("__ops_check_sig: (length %d) hash=", length);
433 		hexdump(stdout, hash, length, "");
434 	}
435 	ret = 0;
436 	switch (sig->info.key_alg) {
437 	case OPS_PKA_DSA:
438 		ret = __ops_dsa_verify(hash, length, &sig->info.sig.dsa,
439 				&signer->key.dsa);
440 		break;
441 
442 	case OPS_PKA_RSA:
443 		ret = rsa_verify(sig->info.hash_alg, hash, length,
444 				&sig->info.sig.rsa,
445 				&signer->key.rsa);
446 		break;
447 
448 	default:
449 		(void) fprintf(stderr, "__ops_check_sig: unusual alg\n");
450 		ret = 0;
451 	}
452 
453 	return ret;
454 }
455 
456 static unsigned
457 hash_and_check_sig(__ops_hash_t *hash,
458 			 const __ops_sig_t *sig,
459 			 const __ops_pubkey_t *signer)
460 {
461 	unsigned char   hashout[OPS_MAX_HASH_SIZE];
462 	unsigned	n;
463 
464 	n = hash->finish(hash, hashout);
465 	return __ops_check_sig(hashout, n, sig, signer);
466 }
467 
468 static unsigned
469 finalise_sig(__ops_hash_t *hash,
470 		   const __ops_sig_t *sig,
471 		   const __ops_pubkey_t *signer,
472 		   const unsigned char *raw_packet)
473 {
474 	hash_add_trailer(hash, sig, raw_packet);
475 	return hash_and_check_sig(hash, sig, signer);
476 }
477 
478 /**
479  * \ingroup Core_Signature
480  *
481  * \brief Verify a certification signature.
482  *
483  * \param key The public key that was signed.
484  * \param id The user ID that was signed
485  * \param sig The signature.
486  * \param signer The public key of the signer.
487  * \param raw_packet The raw signature packet.
488  * \return 1 if OK; else 0
489  */
490 unsigned
491 __ops_check_useridcert_sig(const __ops_pubkey_t *key,
492 			  const __ops_userid_t *id,
493 			  const __ops_sig_t *sig,
494 			  const __ops_pubkey_t *signer,
495 			  const unsigned char *raw_packet)
496 {
497 	__ops_hash_t	hash;
498 	size_t          userid_len = strlen((char *) id->userid);
499 
500 	init_key_sig(&hash, sig, key);
501 
502 	if (sig->info.version == OPS_V4) {
503 		__ops_hash_add_int(&hash, 0xb4, 1);
504 		__ops_hash_add_int(&hash, userid_len, 4);
505 	}
506 	hash.add(&hash, id->userid, userid_len);
507 
508 	return finalise_sig(&hash, sig, signer, raw_packet);
509 }
510 
511 /**
512  * \ingroup Core_Signature
513  *
514  * Verify a certification signature.
515  *
516  * \param key The public key that was signed.
517  * \param attribute The user attribute that was signed
518  * \param sig The signature.
519  * \param signer The public key of the signer.
520  * \param raw_packet The raw signature packet.
521  * \return 1 if OK; else 0
522  */
523 unsigned
524 __ops_check_userattrcert_sig(const __ops_pubkey_t *key,
525 				const __ops_userattr_t *attribute,
526 				const __ops_sig_t *sig,
527 				const __ops_pubkey_t *signer,
528 				const unsigned char *raw_packet)
529 {
530 	__ops_hash_t      hash;
531 
532 	init_key_sig(&hash, sig, key);
533 
534 	if (sig->info.version == OPS_V4) {
535 		__ops_hash_add_int(&hash, 0xd1, 1);
536 		__ops_hash_add_int(&hash, attribute->data.len, 4);
537 	}
538 	hash.add(&hash, attribute->data.contents, attribute->data.len);
539 
540 	return finalise_sig(&hash, sig, signer, raw_packet);
541 }
542 
543 /**
544  * \ingroup Core_Signature
545  *
546  * Verify a subkey signature.
547  *
548  * \param key The public key whose subkey was signed.
549  * \param subkey The subkey of the public key that was signed.
550  * \param sig The signature.
551  * \param signer The public key of the signer.
552  * \param raw_packet The raw signature packet.
553  * \return 1 if OK; else 0
554  */
555 unsigned
556 __ops_check_subkey_sig(const __ops_pubkey_t *key,
557 			   const __ops_pubkey_t *subkey,
558 			   const __ops_sig_t *sig,
559 			   const __ops_pubkey_t *signer,
560 			   const unsigned char *raw_packet)
561 {
562 	__ops_hash_t      hash;
563 
564 	init_key_sig(&hash, sig, key);
565 	hash_add_key(&hash, subkey);
566 
567 	return finalise_sig(&hash, sig, signer, raw_packet);
568 }
569 
570 /**
571  * \ingroup Core_Signature
572  *
573  * Verify a direct signature.
574  *
575  * \param key The public key which was signed.
576  * \param sig The signature.
577  * \param signer The public key of the signer.
578  * \param raw_packet The raw signature packet.
579  * \return 1 if OK; else 0
580  */
581 unsigned
582 __ops_check_direct_sig(const __ops_pubkey_t *key,
583 			   const __ops_sig_t *sig,
584 			   const __ops_pubkey_t *signer,
585 			   const unsigned char *raw_packet)
586 {
587 	__ops_hash_t      hash;
588 
589 	init_key_sig(&hash, sig, key);
590 	return finalise_sig(&hash, sig, signer, raw_packet);
591 }
592 
593 /**
594  * \ingroup Core_Signature
595  *
596  * Verify a signature on a hash (the hash will have already been fed
597  * the material that was being signed, for example signed cleartext).
598  *
599  * \param hash A hash structure of appropriate type that has been fed
600  * the material to be signed. This MUST NOT have been finalised.
601  * \param sig The signature to be verified.
602  * \param signer The public key of the signer.
603  * \return 1 if OK; else 0
604  */
605 unsigned
606 __ops_check_hash_sig(__ops_hash_t *hash,
607 			 const __ops_sig_t *sig,
608 			 const __ops_pubkey_t *signer)
609 {
610 	return (sig->info.hash_alg == hash->alg) ?
611 		finalise_sig(hash, sig, signer, NULL) :
612 		0;
613 }
614 
615 static void
616 start_sig_in_mem(__ops_create_sig_t *sig)
617 {
618 	/* since this has subpackets and stuff, we have to buffer the whole */
619 	/* thing to get counts before writing. */
620 	sig->mem = __ops_memory_new();
621 	__ops_memory_init(sig->mem, 100);
622 	__ops_writer_set_memory(sig->output, sig->mem);
623 
624 	/* write nearly up to the first subpacket */
625 	__ops_write_scalar(sig->output, (unsigned)sig->sig.info.version, 1);
626 	__ops_write_scalar(sig->output, (unsigned)sig->sig.info.type, 1);
627 	__ops_write_scalar(sig->output, (unsigned)sig->sig.info.key_alg, 1);
628 	__ops_write_scalar(sig->output, (unsigned)sig->sig.info.hash_alg, 1);
629 
630 	/* dummy hashed subpacket count */
631 	sig->hashoff = __ops_mem_len(sig->mem);
632 	__ops_write_scalar(sig->output, 0, 2);
633 }
634 
635 /**
636  * \ingroup Core_Signature
637  *
638  * __ops_sig_start() creates a V4 public key signature with a SHA1 hash.
639  *
640  * \param sig The signature structure to initialise
641  * \param key The public key to be signed
642  * \param id The user ID being bound to the key
643  * \param type Signature type
644  */
645 void
646 __ops_sig_start_key_sig(__ops_create_sig_t *sig,
647 				  const __ops_pubkey_t *key,
648 				  const __ops_userid_t *id,
649 				  __ops_sig_type_t type)
650 {
651 	sig->output = __ops_output_new();
652 
653 	/* XXX:  refactor with check (in several ways - check should
654 	 * probably use the buffered writer to construct packets
655 	 * (done), and also should share code for hash calculation) */
656 	sig->sig.info.version = OPS_V4;
657 	sig->sig.info.hash_alg = OPS_HASH_SHA1;
658 	sig->sig.info.key_alg = key->alg;
659 	sig->sig.info.type = type;
660 
661 	sig->hashlen = (unsigned)-1;
662 
663 	init_key_sig(&sig->hash, &sig->sig, key);
664 
665 	__ops_hash_add_int(&sig->hash, 0xb4, 1);
666 	__ops_hash_add_int(&sig->hash, strlen((char *) id->userid), 4);
667 	sig->hash.add(&sig->hash, id->userid, strlen((char *) id->userid));
668 
669 	start_sig_in_mem(sig);
670 }
671 
672 /**
673  * \ingroup Core_Signature
674  *
675  * Create a V4 public key signature over some cleartext.
676  *
677  * \param sig The signature structure to initialise
678  * \param id
679  * \param type
680  * \todo Expand description. Allow other hashes.
681  */
682 
683 void
684 __ops_start_sig(__ops_create_sig_t *sig,
685 	      const __ops_seckey_t *key,
686 	      const __ops_hash_alg_t hash,
687 	      const __ops_sig_type_t type)
688 {
689 	sig->output = __ops_output_new();
690 
691 	/* XXX:  refactor with check (in several ways - check should
692 	 * probably use the buffered writer to construct packets
693 	 * (done), and also should share code for hash calculation) */
694 	sig->sig.info.version = OPS_V4;
695 	sig->sig.info.key_alg = key->pubkey.alg;
696 	sig->sig.info.hash_alg = hash;
697 	sig->sig.info.type = type;
698 
699 	sig->hashlen = (unsigned)-1;
700 
701 	if (__ops_get_debug_level(__FILE__)) {
702 		fprintf(stderr, "initialising hash for sig in mem\n");
703 	}
704 	initialise_hash(&sig->hash, &sig->sig);
705 	start_sig_in_mem(sig);
706 }
707 
708 /**
709  * \ingroup Core_Signature
710  *
711  * Add plaintext data to a signature-to-be.
712  *
713  * \param sig The signature-to-be.
714  * \param buf The plaintext data.
715  * \param length The amount of plaintext data.
716  */
717 void
718 __ops_sig_add_data(__ops_create_sig_t *sig, const void *buf, size_t length)
719 {
720 	sig->hash.add(&sig->hash, buf, length);
721 }
722 
723 /**
724  * \ingroup Core_Signature
725  *
726  * Mark the end of the hashed subpackets in the signature
727  *
728  * \param sig
729  */
730 
731 unsigned
732 __ops_end_hashed_subpkts(__ops_create_sig_t *sig)
733 {
734 	sig->hashlen = __ops_mem_len(sig->mem) - sig->hashoff - 2;
735 	__ops_memory_place_int(sig->mem, sig->hashoff, sig->hashlen, 2);
736 	/* dummy unhashed subpacket count */
737 	sig->unhashoff = __ops_mem_len(sig->mem);
738 	return __ops_write_scalar(sig->output, 0, 2);
739 }
740 
741 /**
742  * \ingroup Core_Signature
743  *
744  * Write out a signature
745  *
746  * \param sig
747  * \param key
748  * \param seckey
749  * \param info
750  *
751  */
752 
753 unsigned
754 __ops_write_sig(__ops_output_t *output,
755 			__ops_create_sig_t *sig,
756 			const __ops_pubkey_t *key,
757 			const __ops_seckey_t *seckey)
758 {
759 	unsigned	ret = 0;
760 	size_t		len = __ops_mem_len(sig->mem);
761 
762 	/* check key not decrypted */
763 	switch (seckey->pubkey.alg) {
764 	case OPS_PKA_RSA:
765 	case OPS_PKA_RSA_ENCRYPT_ONLY:
766 	case OPS_PKA_RSA_SIGN_ONLY:
767 		if (seckey->key.rsa.d == NULL) {
768 			(void) fprintf(stderr, "__ops_write_sig: null rsa.d\n");
769 			return 0;
770 		}
771 		break;
772 
773 	case OPS_PKA_DSA:
774 		if (seckey->key.dsa.x == NULL) {
775 			(void) fprintf(stderr, "__ops_write_sig: null dsa.x\n");
776 			return 0;
777 		}
778 		break;
779 
780 	default:
781 		(void) fprintf(stderr, "Unsupported algorithm %d\n",
782 				seckey->pubkey.alg);
783 		return 0;
784 	}
785 
786 	if (sig->hashlen == (unsigned) -1) {
787 		(void) fprintf(stderr,
788 				"ops_write_sig: bad hashed data len\n");
789 		return 0;
790 	}
791 
792 	__ops_memory_place_int(sig->mem, sig->unhashoff,
793 			     len - sig->unhashoff - 2, 2);
794 
795 	/* add the packet from version number to end of hashed subpackets */
796 	if (__ops_get_debug_level(__FILE__)) {
797 		(void) fprintf(stderr, "ops_write_sig: hashed packet info\n");
798 	}
799 	sig->hash.add(&sig->hash, __ops_mem_data(sig->mem), sig->unhashoff);
800 
801 	/* add final trailer */
802 	__ops_hash_add_int(&sig->hash, (unsigned)sig->sig.info.version, 1);
803 	__ops_hash_add_int(&sig->hash, 0xff, 1);
804 	/* +6 for version, type, pk alg, hash alg, hashed subpacket length */
805 	__ops_hash_add_int(&sig->hash, sig->hashlen + 6, 4);
806 
807 	if (__ops_get_debug_level(__FILE__)) {
808 		(void) fprintf(stderr, "ops_write_sig: done writing hashed\n");
809 	}
810 	/* XXX: technically, we could figure out how big the signature is */
811 	/* and write it directly to the output instead of via memory. */
812 	switch (seckey->pubkey.alg) {
813 	case OPS_PKA_RSA:
814 	case OPS_PKA_RSA_ENCRYPT_ONLY:
815 	case OPS_PKA_RSA_SIGN_ONLY:
816 		if (!rsa_sign(&sig->hash, &key->key.rsa, &seckey->key.rsa,
817 				sig->output)) {
818 			(void) fprintf(stderr,
819 				"__ops_write_sig: rsa_sign failure\n");
820 			return 0;
821 		}
822 		break;
823 
824 	case OPS_PKA_DSA:
825 		if (!dsa_sign(&sig->hash, &key->key.dsa, &seckey->key.dsa,
826 				sig->output)) {
827 			(void) fprintf(stderr,
828 				"__ops_write_sig: dsa_sign failure\n");
829 			return 0;
830 		}
831 		break;
832 
833 	default:
834 		(void) fprintf(stderr, "Unsupported algorithm %d\n",
835 					seckey->pubkey.alg);
836 		return 0;
837 	}
838 
839 	ret = __ops_write_ptag(output, OPS_PTAG_CT_SIGNATURE);
840 	if (ret) {
841 		len = __ops_mem_len(sig->mem);
842 		ret = __ops_write_length(output, len) &&
843 			__ops_write(output, __ops_mem_data(sig->mem), len);
844 	}
845 	__ops_memory_free(sig->mem);
846 
847 	if (ret == 0) {
848 		OPS_ERROR(&output->errors, OPS_E_W, "Cannot write signature");
849 	}
850 	return ret;
851 }
852 
853 /**
854  * \ingroup Core_Signature
855  *
856  * __ops_add_birthtime() adds a creation time to the signature.
857  *
858  * \param sig
859  * \param when
860  */
861 unsigned
862 __ops_add_birthtime(__ops_create_sig_t *sig, time_t when)
863 {
864 	return __ops_write_ss_header(sig->output, 5,
865 					OPS_PTAG_SS_CREATION_TIME) &&
866 		__ops_write_scalar(sig->output, (unsigned)when, 4);
867 }
868 
869 /**
870  * \ingroup Core_Signature
871  *
872  * Adds issuer's key ID to the signature
873  *
874  * \param sig
875  * \param keyid
876  */
877 
878 unsigned
879 __ops_add_issuer_keyid(__ops_create_sig_t *sig,
880 				const unsigned char keyid[OPS_KEY_ID_SIZE])
881 {
882 	return __ops_write_ss_header(sig->output, OPS_KEY_ID_SIZE + 1,
883 				OPS_PTAG_SS_ISSUER_KEY_ID) &&
884 		__ops_write(sig->output, keyid, OPS_KEY_ID_SIZE);
885 }
886 
887 /**
888  * \ingroup Core_Signature
889  *
890  * Adds primary user ID to the signature
891  *
892  * \param sig
893  * \param primary
894  */
895 void
896 __ops_add_primary_userid(__ops_create_sig_t *sig, unsigned primary)
897 {
898 	__ops_write_ss_header(sig->output, 2, OPS_PTAG_SS_PRIMARY_USER_ID);
899 	__ops_write_scalar(sig->output, primary, 1);
900 }
901 
902 /**
903  * \ingroup Core_Signature
904  *
905  * Get the hash structure in use for the signature.
906  *
907  * \param sig The signature structure.
908  * \return The hash structure.
909  */
910 __ops_hash_t     *
911 __ops_sig_get_hash(__ops_create_sig_t *sig)
912 {
913 	return &sig->hash;
914 }
915 
916 static int
917 open_output_file(__ops_output_t **output,
918 			const char *inname,
919 			const char *outname,
920 			const unsigned armored,
921 			const unsigned overwrite)
922 {
923 	int             fd;
924 
925 	/* setup output file */
926 	if (outname) {
927 		fd = __ops_setup_file_write(output, outname, overwrite);
928 	} else {
929 		unsigned        flen = strlen(inname) + 4 + 1;
930 		char           *f = NULL;
931 
932 		if ((f = calloc(1, flen)) == NULL) {
933 			(void) fprintf(stderr, "open_output_file: bad alloc\n");
934 			fd = -1;
935 		} else {
936 			(void) snprintf(f, flen, "%s.%s", inname,
937 					(armored) ? "asc" : "gpg");
938 			fd = __ops_setup_file_write(output, f, overwrite);
939 			free(f);
940 		}
941 	}
942 	return fd;
943 }
944 
945 /**
946    \ingroup HighLevel_Sign
947    \brief Sign a file with a Cleartext Signature
948    \param inname Name of file to be signed
949    \param outname Filename to be created. If NULL, filename will be constructed from the inname.
950    \param seckey Secret Key to sign with
951    \param overwrite Allow output file to be overwritten, if set
952    \return 1 if OK, else 0
953 
954 */
955 unsigned
956 __ops_sign_file_as_cleartext(__ops_io_t *io,
957 			const char *inname,
958 			const char *outname,
959 			const __ops_seckey_t *seckey,
960 			const char *hashname,
961 			const unsigned overwrite)
962 {
963 	__ops_create_sig_t	*sig = NULL;
964 	__ops_sig_type_t	 sig_type = OPS_SIG_BINARY;
965 	__ops_hash_alg_t	 hash_alg;
966 	__ops_output_t		*output = NULL;
967 	unsigned char		 keyid[OPS_KEY_ID_SIZE];
968 	unsigned		 ret = 0;
969 	unsigned		 armored = 1;
970 	int			 fd_out = 0;
971 	__ops_memory_t		*mem;
972 
973 	/* check the hash algorithm */
974 	hash_alg = __ops_str_to_hash_alg(hashname);
975 	if (hash_alg == OPS_HASH_UNKNOWN) {
976 		(void) fprintf(io->errs,
977 			"__ops_sign_file_as_cleartext: unknown hash algorithm"
978 			": \"%s\"\n", hashname);
979 		return 0;
980 	}
981 
982 	/* read the file to be signed */
983 	mem = __ops_memory_new();
984 	if (!__ops_mem_readfile(mem, inname)) {
985 		return 0;
986 	}
987 
988 	/* set up output file */
989 	fd_out = open_output_file(&output, inname, outname, armored, overwrite);
990 	if (fd_out < 0) {
991 		__ops_memory_free(mem);
992 		return 0;
993 	}
994 
995 	/* set up signature */
996 	sig = __ops_create_sig_new();
997 	if (!sig) {
998 		__ops_memory_free(mem);
999 		__ops_teardown_file_write(output, fd_out);
1000 		return 0;
1001 	}
1002 
1003 	/* \todo could add more error detection here */
1004 	__ops_start_sig(sig, seckey, hash_alg, sig_type);
1005 	if (__ops_writer_push_clearsigned(output, sig) != 1) {
1006 		return 0;
1007 	}
1008 
1009 	/* Do the signing */
1010 	__ops_write(output, __ops_mem_data(mem), __ops_mem_len(mem));
1011 	__ops_memory_free(mem);
1012 
1013 	/* add signature with subpackets: */
1014 	/* - creation time */
1015 	/* - key id */
1016 	ret = __ops_writer_use_armored_sig(output) &&
1017 			__ops_add_birthtime(sig, time(NULL));
1018 	if (ret == 0) {
1019 		__ops_teardown_file_write(output, fd_out);
1020 		return 0;
1021 	}
1022 
1023 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1024 	ret = __ops_add_issuer_keyid(sig, keyid) &&
1025 		__ops_end_hashed_subpkts(sig) &&
1026 		__ops_write_sig(output, sig, &seckey->pubkey, seckey);
1027 
1028 	__ops_teardown_file_write(output, fd_out);
1029 
1030 	if (ret == 0) {
1031 		OPS_ERROR(&output->errors, OPS_E_W,
1032 				"Cannot sign file as cleartext");
1033 	}
1034 	return ret;
1035 }
1036 
1037 /**
1038  * \ingroup HighLevel_Sign
1039  * \brief Sign a buffer with a Cleartext signature
1040  * \param cleartext Text to be signed
1041  * \param len Length of text
1042  * \param signed __ops_memory_t struct in which to write the signed cleartext
1043  * \param seckey Secret key with which to sign the cleartext
1044  * \return 1 if OK; else 0
1045 
1046  * \note It is the calling function's responsibility to free signed
1047  * \note signed should be a NULL pointer when passed in
1048 
1049  */
1050 unsigned
1051 __ops_sign_buf_as_cleartext(const char *cleartext,
1052 			const size_t len,
1053 			__ops_memory_t **signedtext,
1054 			const __ops_seckey_t *seckey,
1055 			const char *hashname)
1056 {
1057 	__ops_create_sig_t	*sig = NULL;
1058 	__ops_sig_type_t	 sig_type = OPS_SIG_BINARY;
1059 	__ops_hash_alg_t	 hash_alg;
1060 	__ops_output_t		*output = NULL;
1061 	unsigned char		 keyid[OPS_KEY_ID_SIZE];
1062 	unsigned		 ret = 0;
1063 
1064 	/* check the hash algorithm */
1065 	hash_alg = __ops_str_to_hash_alg(hashname);
1066 	if (hash_alg == OPS_HASH_UNKNOWN) {
1067 		(void) fprintf(stderr,
1068 			"__ops_sign_buf_as_cleartext: unknown hash algorithm"
1069 			": \"%s\"\n", hashname);
1070 		return 0;
1071 	}
1072 
1073 
1074 	if (*signedtext != 0x0) {
1075 		(void) fprintf(stderr,
1076 			"__ops_sign_buf_as_cleartext: non-null cleartext\n");
1077 		return 0;
1078 	}
1079 
1080 	/* set up signature */
1081 	sig = __ops_create_sig_new();
1082 	if (!sig) {
1083 		return 0;
1084 	}
1085 	/* \todo could add more error detection here */
1086 	__ops_start_sig(sig, seckey, hash_alg, sig_type);
1087 
1088 	/* set up output file */
1089 	__ops_setup_memory_write(&output, signedtext, len);
1090 
1091 	/* Do the signing */
1092 	/* add signature with subpackets: */
1093 	/* - creation time */
1094 	/* - key id */
1095 	ret = __ops_writer_push_clearsigned(output, sig) &&
1096 		__ops_write(output, cleartext, len) &&
1097 		__ops_writer_use_armored_sig(output) &&
1098 		__ops_add_birthtime(sig, time(NULL));
1099 
1100 	if (ret == 0) {
1101 		return 0;
1102 	}
1103 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1104 
1105 	ret = __ops_add_issuer_keyid(sig, keyid) &&
1106 		__ops_end_hashed_subpkts(sig) &&
1107 		__ops_write_sig(output, sig, &seckey->pubkey, seckey) &&
1108 		__ops_writer_close(output);
1109 
1110 	/* Note: the calling function must free signed */
1111 	__ops_output_delete(output);
1112 
1113 	return ret;
1114 }
1115 
1116 /**
1117 \ingroup HighLevel_Sign
1118 \brief Sign a file
1119 \param inname Input filename
1120 \param outname Output filename. If NULL, a name is constructed from the input filename.
1121 \param seckey Secret Key to use for signing
1122 \param armored Write armoured text, if set.
1123 \param overwrite May overwrite existing file, if set.
1124 \return 1 if OK; else 0;
1125 
1126 */
1127 unsigned
1128 __ops_sign_file(__ops_io_t *io,
1129 		const char *inname,
1130 		const char *outname,
1131 		const __ops_seckey_t *seckey,
1132 		const char *hashname,
1133 		const unsigned armored,
1134 		const unsigned overwrite)
1135 {
1136 	/* \todo allow choice of hash algorithams */
1137 	/* enforce use of SHA1 for now */
1138 
1139 	__ops_create_sig_t	*sig = NULL;
1140 	__ops_hash_alg_t	 hash_alg;
1141 	__ops_sig_type_t	 sig_type = OPS_SIG_BINARY;
1142 	__ops_memory_t		*infile = NULL;
1143 	__ops_output_t		*output = NULL;
1144 	unsigned char		 keyid[OPS_KEY_ID_SIZE];
1145 	__ops_hash_t		*hash = NULL;
1146 	int			 fd = 0;
1147 
1148 	hash_alg = __ops_str_to_hash_alg(hashname);
1149 	if (hash_alg == OPS_HASH_UNKNOWN) {
1150 		(void) fprintf(io->errs,
1151 			"__ops_sign_file: unknown hash algorithm: \"%s\"\n",
1152 			hashname);
1153 		return 0;
1154 	}
1155 
1156 	/* read input file into buf */
1157 	infile = __ops_memory_new();
1158 	if (!__ops_mem_readfile(infile, inname)) {
1159 		return 0;
1160 	}
1161 
1162 	/* setup output file */
1163 	fd = open_output_file(&output, inname, outname, armored, overwrite);
1164 	if (fd < 0) {
1165 		__ops_memory_free(infile);
1166 		return 0;
1167 	}
1168 
1169 	/* set up signature */
1170 	sig = __ops_create_sig_new();
1171 	__ops_start_sig(sig, seckey, hash_alg, sig_type);
1172 
1173 	/* set armoured/not armoured here */
1174 	if (armored) {
1175 		__ops_writer_push_armor_msg(output);
1176 	}
1177 
1178 	/* write one_pass_sig */
1179 	__ops_write_one_pass_sig(output, seckey, hash_alg, sig_type);
1180 
1181 	/* hash file contents */
1182 	hash = __ops_sig_get_hash(sig);
1183 	hash->add(hash, __ops_mem_data(infile), __ops_mem_len(infile));
1184 
1185 	/* output file contents as Literal Data packet */
1186 	if (__ops_get_debug_level(__FILE__)) {
1187 		fprintf(io->errs, "** Writing out data now\n");
1188 	}
1189 	__ops_write_litdata(output, __ops_mem_data(infile),
1190 		(const int)__ops_mem_len(infile),
1191 		OPS_LDT_BINARY);
1192 
1193 	if (__ops_get_debug_level(__FILE__)) {
1194 		fprintf(io->errs, "** After Writing out data now\n");
1195 	}
1196 
1197 	/* add creation time to signature */
1198 	__ops_add_birthtime(sig, time(NULL));
1199 	/* add key id to signature */
1200 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1201 	__ops_add_issuer_keyid(sig, keyid);
1202 	__ops_end_hashed_subpkts(sig);
1203 
1204 	/* write out sig */
1205 	__ops_write_sig(output, sig, &seckey->pubkey, seckey);
1206 
1207 	/* tidy up */
1208 	__ops_teardown_file_write(output, fd);
1209 	__ops_create_sig_delete(sig);
1210 	__ops_memory_free(infile);
1211 
1212 	return 1;
1213 }
1214 
1215 /**
1216 \ingroup HighLevel_Sign
1217 \brief Signs a buffer
1218 \param input Input text to be signed
1219 \param input_len Length of input text
1220 \param sig_type Signature type
1221 \param seckey Secret Key
1222 \param armored Write armoured text, if set
1223 \return New __ops_memory_t struct containing signed text
1224 \note It is the caller's responsibility to call __ops_memory_free(me)
1225 
1226 */
1227 __ops_memory_t   *
1228 __ops_sign_buf(const void *input,
1229 		const size_t input_len,
1230 		const __ops_sig_type_t sig_type,
1231 		const __ops_seckey_t *seckey,
1232 		const unsigned armored)
1233 {
1234 	__ops_litdata_type_t	 ld_type;
1235 	__ops_create_sig_t	*sig = NULL;
1236 	__ops_hash_alg_t	 hash_alg = OPS_HASH_SHA1;
1237 	__ops_output_t		*output = NULL;
1238 	__ops_memory_t		*mem = __ops_memory_new();
1239 	unsigned char		 keyid[OPS_KEY_ID_SIZE];
1240 	__ops_hash_t		*hash = NULL;
1241 
1242 	/* setup literal data packet type */
1243 	ld_type = (sig_type == OPS_SIG_BINARY) ? OPS_LDT_BINARY : OPS_LDT_TEXT;
1244 
1245 	/* set up signature */
1246 	sig = __ops_create_sig_new();
1247 	__ops_start_sig(sig, seckey, hash_alg, sig_type);
1248 
1249 	/* setup writer */
1250 	__ops_setup_memory_write(&output, &mem, input_len);
1251 
1252 	/* set armoured/not armoured here */
1253 	if (armored) {
1254 		__ops_writer_push_armor_msg(output);
1255 	}
1256 
1257 	if (__ops_get_debug_level(__FILE__)) {
1258 		fprintf(stderr, "** Writing out one pass sig\n");
1259 	}
1260 	/* write one_pass_sig */
1261 	__ops_write_one_pass_sig(output, seckey, hash_alg, sig_type);
1262 
1263 	/* hash file contents */
1264 	hash = __ops_sig_get_hash(sig);
1265 	hash->add(hash, input, input_len);
1266 
1267 	/* output file contents as Literal Data packet */
1268 
1269 	if (__ops_get_debug_level(__FILE__)) {
1270 		(void) fprintf(stderr, "** Writing out data now\n");
1271 	}
1272 	__ops_write_litdata(output, input, (const int)input_len, ld_type);
1273 
1274 	if (__ops_get_debug_level(__FILE__)) {
1275 		fprintf(stderr, "** After Writing out data now\n");
1276 	}
1277 
1278 	/* add creation time to signature */
1279 	__ops_add_birthtime(sig, time(NULL));
1280 	/* add key id to signature */
1281 	__ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1282 	__ops_add_issuer_keyid(sig, keyid);
1283 	__ops_end_hashed_subpkts(sig);
1284 
1285 	/* write out sig */
1286 	__ops_write_sig(output, sig, &seckey->pubkey, seckey);
1287 
1288 	/* tidy up */
1289 	__ops_writer_close(output);
1290 	__ops_create_sig_delete(sig);
1291 
1292 	return mem;
1293 }
1294 
1295 /* sign a file, and put the signature in a separate file */
1296 int
1297 __ops_sign_detached(__ops_io_t *io,
1298 			const char *f,
1299 			char *sigfile,
1300 			__ops_seckey_t *seckey,
1301 			const char *hash)
1302 {
1303 	__ops_create_sig_t	*sig;
1304 	__ops_hash_alg_t	 alg;
1305 	__ops_output_t		*output;
1306 	__ops_memory_t		*mem;
1307 	unsigned char	 	 keyid[OPS_KEY_ID_SIZE];
1308 	time_t			 t;
1309 	char			 fname[MAXPATHLEN];
1310 	int			 fd;
1311 
1312 	/* find out which hash algorithm to use */
1313 	alg = __ops_str_to_hash_alg(hash);
1314 	if (alg == OPS_HASH_UNKNOWN) {
1315 		(void) fprintf(io->errs,"Unknown hash algorithm: %s\n", hash);
1316 		return 0;
1317 	}
1318 
1319 	/* create a new signature */
1320 	sig = __ops_create_sig_new();
1321 	__ops_start_sig(sig, seckey, alg, OPS_SIG_BINARY);
1322 
1323 	/* read the contents of 'f', and add that to the signature */
1324 	mem = __ops_memory_new();
1325 	if (!__ops_mem_readfile(mem, f)) {
1326 		return 0;
1327 	}
1328 	__ops_sig_add_data(sig, __ops_mem_data(mem), __ops_mem_len(mem));
1329 	__ops_memory_free(mem);
1330 
1331 	/* calculate the signature */
1332 	t = time(NULL);
1333 	__ops_add_birthtime(sig, t);
1334 	__ops_keyid(keyid, sizeof(keyid), &seckey->pubkey);
1335 	__ops_add_issuer_keyid(sig, keyid);
1336 	__ops_end_hashed_subpkts(sig);
1337 
1338 	/* write the signature to the detached file */
1339 	if (sigfile == NULL) {
1340 		(void) snprintf(fname, sizeof(fname), "%s.sig", f);
1341 		sigfile = fname;
1342 	}
1343 	fd = open(sigfile, O_CREAT|O_TRUNC|O_WRONLY, 0666);
1344 	if (fd < 0) {
1345 		(void) fprintf(io->errs, "can't write signature to \"%s\"\n",
1346 				sigfile);
1347 		return 0;
1348 	}
1349 
1350 	output = __ops_output_new();
1351 	__ops_writer_set_fd(output, fd);
1352 	__ops_write_sig(output, sig, &seckey->pubkey, seckey);
1353 	__ops_seckey_free(seckey);
1354 	(void) close(fd);
1355 
1356 	return 1;
1357 }
1358