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