Sync usage with man page.
[netbsd-mini2440.git] / crypto / external / bsd / netpgp / dist / src / lib / signature.c
blobf05c47d63ba14d5aec957f91bfcd7df539ef8c40
1 /*-
2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
3 * All rights reserved.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org)
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.
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.
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.
36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37 * use this file except in compliance with the License.
39 * You may obtain a copy of the License at
40 * http://www.apache.org/licenses/LICENSE-2.0
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.
46 * See the License for the specific language governing permissions and
47 * limitations under the License.
50 /** \file
52 #include "config.h"
54 #ifdef HAVE_SYS_CDEFS_H
55 #include <sys/cdefs.h>
56 #endif
58 #if defined(__NetBSD__)
59 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60 __RCSID("$NetBSD: signature.c,v 1.23 2009/11/20 07:17:07 agc Exp $");
61 #endif
63 #include <sys/types.h>
64 #include <sys/param.h>
66 #ifdef HAVE_FCNTL_H
67 #include <fcntl.h>
68 #endif
70 #include <string.h>
72 #ifdef HAVE_UNISTD_H
73 #include <unistd.h>
74 #endif
76 #ifdef HAVE_OPENSSL_DSA_H
77 #include <openssl/dsa.h>
78 #endif
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"
90 /** \ingroup Core_Create
91 * needed for signature creation
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;
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()
110 __ops_create_sig_t *
111 __ops_create_sig_new(void)
113 return calloc(1, sizeof(__ops_create_sig_t));
117 \ingroup Core_Signature
118 Free signature and memory associated with it
119 \param sig struct to free
120 \sa __ops_create_sig_new()
122 void
123 __ops_create_sig_delete(__ops_create_sig_t *sig)
125 __ops_output_delete(sig->output);
126 sig->output = NULL;
127 free(sig);
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
135 static unsigned char prefix_sha1[] = {
136 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02,
137 0x1A, 0x05, 0x00, 0x04, 0x14
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
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)
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;
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;
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;
181 if (10 + hashsize > keysize) {
182 (void) fprintf(stderr, "rsa_sign: hashsize too big\n");
183 return 0;
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);
191 for (n = 2; n < keysize - hashsize - 1; ++n) {
192 hashbuf[n] = 0xff;
194 hashbuf[n++] = 0;
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;
203 __ops_write(out, &hashbuf[n], 2);
205 n += t;
206 if (n != keysize) {
207 (void) fprintf(stderr, "rsa_sign: n != keysize\n");
208 return 0;
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;
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)
224 unsigned char hashbuf[NETPGP_BUFSIZ];
225 unsigned hashsize;
226 unsigned t;
227 DSA_SIG *dsasig;
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 */
233 hashsize = 20;
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;
242 __ops_write(output, &hashbuf[0], 2);
244 /* write signature to buf */
245 dsasig = __ops_dsa_sign(hashbuf, hashsize, sdsa, dsa);
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;
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)
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;
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;
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;
281 BN_bn2bin(sig->sig, sigbuf);
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;
287 if (n != keysize) {
288 /* obviously, this includes error returns */
289 return 0;
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;
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;
316 if (keysize - plen - hash_length < 10) {
317 return 0;
320 for (n = 2; n < keysize - plen - hash_length - 1; ++n) {
321 if (hashbuf_from_sig[n] != 0xff) {
322 return 0;
326 if (hashbuf_from_sig[n++] != 0) {
327 return 0;
330 if (__ops_get_debug_level(__FILE__)) {
331 unsigned zz;
332 unsigned uu;
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]);
339 printf("\n");
340 printf("prefix\n");
341 for (zz = 0; zz < plen; zz++) {
342 printf("%02x ", prefix[zz]);
344 printf("\n");
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]);
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]);
356 printf("\n");
358 return (memcmp(&hashbuf_from_sig[n], prefix, plen) == 0 &&
359 memcmp(&hashbuf_from_sig[n + plen], hash, hash_length) == 0);
362 static void
363 hash_add_key(__ops_hash_t *hash, const __ops_pubkey_t *key)
365 __ops_memory_t *mem = __ops_memory_new();
366 const unsigned dontmakepacket = 0;
367 size_t len;
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);
377 static void
378 initialise_hash(__ops_hash_t *hash, const __ops_sig_t *sig)
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 */
389 static void
390 init_key_sig(__ops_hash_t *hash, const __ops_sig_t *sig,
391 const __ops_pubkey_t *key)
393 initialise_hash(hash, sig);
394 hash_add_key(hash, key);
397 static void
398 hash_add_trailer(__ops_hash_t *hash, const __ops_sig_t *sig,
399 const unsigned char *raw_packet)
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);
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);
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
424 unsigned
425 __ops_check_sig(const unsigned char *hash, unsigned length,
426 const __ops_sig_t * sig,
427 const __ops_pubkey_t * signer)
429 unsigned ret;
431 if (__ops_get_debug_level(__FILE__)) {
432 printf("__ops_check_sig: (length %d) hash=", length);
433 hexdump(stdout, hash, length, "");
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;
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;
448 default:
449 (void) fprintf(stderr, "__ops_check_sig: unusual alg\n");
450 ret = 0;
453 return ret;
456 static unsigned
457 hash_and_check_sig(__ops_hash_t *hash,
458 const __ops_sig_t *sig,
459 const __ops_pubkey_t *signer)
461 unsigned char hashout[OPS_MAX_HASH_SIZE];
462 unsigned n;
464 n = hash->finish(hash, hashout);
465 return __ops_check_sig(hashout, n, sig, signer);
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)
474 hash_add_trailer(hash, sig, raw_packet);
475 return hash_and_check_sig(hash, sig, signer);
479 * \ingroup Core_Signature
481 * \brief Verify a certification signature.
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
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)
497 __ops_hash_t hash;
498 size_t userid_len = strlen((char *) id->userid);
500 init_key_sig(&hash, sig, key);
502 if (sig->info.version == OPS_V4) {
503 __ops_hash_add_int(&hash, 0xb4, 1);
504 __ops_hash_add_int(&hash, userid_len, 4);
506 hash.add(&hash, id->userid, userid_len);
508 return finalise_sig(&hash, sig, signer, raw_packet);
512 * \ingroup Core_Signature
514 * Verify a certification signature.
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
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)
530 __ops_hash_t hash;
532 init_key_sig(&hash, sig, key);
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);
538 hash.add(&hash, attribute->data.contents, attribute->data.len);
540 return finalise_sig(&hash, sig, signer, raw_packet);
544 * \ingroup Core_Signature
546 * Verify a subkey signature.
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
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)
562 __ops_hash_t hash;
564 init_key_sig(&hash, sig, key);
565 hash_add_key(&hash, subkey);
567 return finalise_sig(&hash, sig, signer, raw_packet);
571 * \ingroup Core_Signature
573 * Verify a direct signature.
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
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)
587 __ops_hash_t hash;
589 init_key_sig(&hash, sig, key);
590 return finalise_sig(&hash, sig, signer, raw_packet);
594 * \ingroup Core_Signature
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).
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
605 unsigned
606 __ops_check_hash_sig(__ops_hash_t *hash,
607 const __ops_sig_t *sig,
608 const __ops_pubkey_t *signer)
610 return (sig->info.hash_alg == hash->alg) ?
611 finalise_sig(hash, sig, signer, NULL) :
615 static void
616 start_sig_in_mem(__ops_create_sig_t *sig)
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);
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);
630 /* dummy hashed subpacket count */
631 sig->hashoff = __ops_mem_len(sig->mem);
632 __ops_write_scalar(sig->output, 0, 2);
636 * \ingroup Core_Signature
638 * __ops_sig_start() creates a V4 public key signature with a SHA1 hash.
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
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)
651 sig->output = __ops_output_new();
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;
661 sig->hashlen = (unsigned)-1;
663 init_key_sig(&sig->hash, &sig->sig, key);
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));
669 start_sig_in_mem(sig);
673 * \ingroup Core_Signature
675 * Create a V4 public key signature over some cleartext.
677 * \param sig The signature structure to initialise
678 * \param id
679 * \param type
680 * \todo Expand description. Allow other hashes.
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)
689 sig->output = __ops_output_new();
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;
699 sig->hashlen = (unsigned)-1;
701 if (__ops_get_debug_level(__FILE__)) {
702 fprintf(stderr, "initialising hash for sig in mem\n");
704 initialise_hash(&sig->hash, &sig->sig);
705 start_sig_in_mem(sig);
709 * \ingroup Core_Signature
711 * Add plaintext data to a signature-to-be.
713 * \param sig The signature-to-be.
714 * \param buf The plaintext data.
715 * \param length The amount of plaintext data.
717 void
718 __ops_sig_add_data(__ops_create_sig_t *sig, const void *buf, size_t length)
720 sig->hash.add(&sig->hash, buf, length);
724 * \ingroup Core_Signature
726 * Mark the end of the hashed subpackets in the signature
728 * \param sig
731 unsigned
732 __ops_end_hashed_subpkts(__ops_create_sig_t *sig)
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);
742 * \ingroup Core_Signature
744 * Write out a signature
746 * \param sig
747 * \param key
748 * \param seckey
749 * \param info
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)
759 unsigned ret = 0;
760 size_t len = __ops_mem_len(sig->mem);
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;
771 break;
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;
778 break;
780 default:
781 (void) fprintf(stderr, "Unsupported algorithm %d\n",
782 seckey->pubkey.alg);
783 return 0;
786 if (sig->hashlen == (unsigned) -1) {
787 (void) fprintf(stderr,
788 "ops_write_sig: bad hashed data len\n");
789 return 0;
792 __ops_memory_place_int(sig->mem, sig->unhashoff,
793 len - sig->unhashoff - 2, 2);
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");
799 sig->hash.add(&sig->hash, __ops_mem_data(sig->mem), sig->unhashoff);
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);
807 if (__ops_get_debug_level(__FILE__)) {
808 (void) fprintf(stderr, "ops_write_sig: done writing hashed\n");
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;
822 break;
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;
831 break;
833 default:
834 (void) fprintf(stderr, "Unsupported algorithm %d\n",
835 seckey->pubkey.alg);
836 return 0;
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);
845 __ops_memory_free(sig->mem);
847 if (ret == 0) {
848 OPS_ERROR(&output->errors, OPS_E_W, "Cannot write signature");
850 return ret;
854 * \ingroup Core_Signature
856 * __ops_add_birthtime() adds a creation time to the signature.
858 * \param sig
859 * \param when
861 unsigned
862 __ops_add_birthtime(__ops_create_sig_t *sig, time_t when)
864 return __ops_write_ss_header(sig->output, 5,
865 OPS_PTAG_SS_CREATION_TIME) &&
866 __ops_write_scalar(sig->output, (unsigned)when, 4);
870 * \ingroup Core_Signature
872 * Adds issuer's key ID to the signature
874 * \param sig
875 * \param keyid
878 unsigned
879 __ops_add_issuer_keyid(__ops_create_sig_t *sig,
880 const unsigned char keyid[OPS_KEY_ID_SIZE])
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);
888 * \ingroup Core_Signature
890 * Adds primary user ID to the signature
892 * \param sig
893 * \param primary
895 void
896 __ops_add_primary_userid(__ops_create_sig_t *sig, unsigned primary)
898 __ops_write_ss_header(sig->output, 2, OPS_PTAG_SS_PRIMARY_USER_ID);
899 __ops_write_scalar(sig->output, primary, 1);
903 * \ingroup Core_Signature
905 * Get the hash structure in use for the signature.
907 * \param sig The signature structure.
908 * \return The hash structure.
910 __ops_hash_t *
911 __ops_sig_get_hash(__ops_create_sig_t *sig)
913 return &sig->hash;
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)
923 int fd;
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;
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);
942 return fd;
946 \ingroup HighLevel_Sign
947 \brief Sign a file
948 \param inname Input filename
949 \param outname Output filename. If NULL, a name is constructed from the input filename.
950 \param seckey Secret Key to use for signing
951 \param armored Write armoured text, if set.
952 \param overwrite May overwrite existing file, if set.
953 \return 1 if OK; else 0;
956 unsigned
957 __ops_sign_file(__ops_io_t *io,
958 const char *inname,
959 const char *outname,
960 const __ops_seckey_t *seckey,
961 const char *hashname,
962 const unsigned armored,
963 const unsigned cleartext,
964 const unsigned overwrite)
966 __ops_create_sig_t *sig;
967 __ops_sig_type_t sig_type;
968 __ops_hash_alg_t hash_alg;
969 __ops_memory_t *infile;
970 __ops_output_t *output;
971 unsigned char keyid[OPS_KEY_ID_SIZE];
972 __ops_hash_t *hash;
973 unsigned ret;
974 int fd_out;
976 sig = NULL;
977 sig_type = OPS_SIG_BINARY;
978 infile = NULL;
979 output = NULL;
980 hash = NULL;
981 fd_out = 0;
983 /* find the hash algorithm */
984 hash_alg = __ops_str_to_hash_alg(hashname);
985 if (hash_alg == OPS_HASH_UNKNOWN) {
986 (void) fprintf(io->errs,
987 "__ops_sign_file: unknown hash algorithm: \"%s\"\n",
988 hashname);
989 return 0;
992 /* read input file into buf */
993 infile = __ops_memory_new();
994 if (!__ops_mem_readfile(infile, inname)) {
995 return 0;
998 /* setup output file */
999 fd_out = open_output_file(&output, inname, outname, armored, overwrite);
1000 if (fd_out < 0) {
1001 __ops_memory_free(infile);
1002 return 0;
1005 /* set up signature */
1006 sig = __ops_create_sig_new();
1007 if (!sig) {
1008 __ops_memory_free(infile);
1009 __ops_teardown_file_write(output, fd_out);
1010 return 0;
1013 __ops_start_sig(sig, seckey, hash_alg, sig_type);
1015 if (cleartext) {
1016 if (__ops_writer_push_clearsigned(output, sig) != 1) {
1017 return 0;
1020 /* Do the signing */
1021 __ops_write(output, __ops_mem_data(infile), __ops_mem_len(infile));
1022 __ops_memory_free(infile);
1024 /* add signature with subpackets: */
1025 /* - creation time */
1026 /* - key id */
1027 ret = __ops_writer_use_armored_sig(output) &&
1028 __ops_add_birthtime(sig, time(NULL));
1029 if (ret == 0) {
1030 __ops_teardown_file_write(output, fd_out);
1031 return 0;
1034 __ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1035 ret = __ops_add_issuer_keyid(sig, keyid) &&
1036 __ops_end_hashed_subpkts(sig) &&
1037 __ops_write_sig(output, sig, &seckey->pubkey, seckey);
1039 __ops_teardown_file_write(output, fd_out);
1041 if (ret == 0) {
1042 OPS_ERROR(&output->errors, OPS_E_W,
1043 "Cannot sign file as cleartext");
1045 } else {
1046 /* set armoured/not armoured here */
1047 if (armored) {
1048 __ops_writer_push_armor_msg(output);
1051 /* write one_pass_sig */
1052 __ops_write_one_pass_sig(output, seckey, hash_alg, sig_type);
1054 /* hash file contents */
1055 hash = __ops_sig_get_hash(sig);
1056 hash->add(hash, __ops_mem_data(infile), __ops_mem_len(infile));
1058 /* output file contents as Literal Data packet */
1059 if (__ops_get_debug_level(__FILE__)) {
1060 fprintf(io->errs, "** Writing out data now\n");
1062 __ops_write_litdata(output, __ops_mem_data(infile),
1063 (const int)__ops_mem_len(infile),
1064 OPS_LDT_BINARY);
1066 if (__ops_get_debug_level(__FILE__)) {
1067 fprintf(io->errs, "** After Writing out data now\n");
1070 /* add creation time to signature */
1071 __ops_add_birthtime(sig, time(NULL));
1072 /* add key id to signature */
1073 __ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1074 __ops_add_issuer_keyid(sig, keyid);
1075 __ops_end_hashed_subpkts(sig);
1076 __ops_write_sig(output, sig, &seckey->pubkey, seckey);
1078 /* tidy up */
1079 __ops_teardown_file_write(output, fd_out);
1081 __ops_create_sig_delete(sig);
1082 __ops_memory_free(infile);
1084 ret = 1;
1087 return ret;
1091 \ingroup HighLevel_Sign
1092 \brief Signs a buffer
1093 \param input Input text to be signed
1094 \param input_len Length of input text
1095 \param sig_type Signature type
1096 \param seckey Secret Key
1097 \param armored Write armoured text, if set
1098 \return New __ops_memory_t struct containing signed text
1099 \note It is the caller's responsibility to call __ops_memory_free(me)
1102 __ops_memory_t *
1103 __ops_sign_buf(__ops_io_t *io,
1104 const void *input,
1105 const size_t insize,
1106 const __ops_seckey_t *seckey,
1107 const char *hashname,
1108 const unsigned armored,
1109 const unsigned cleartext)
1111 __ops_litdata_type_t ld_type;
1112 __ops_create_sig_t *sig;
1113 __ops_sig_type_t sig_type;
1114 __ops_hash_alg_t hash_alg;
1115 __ops_output_t *output;
1116 __ops_memory_t *mem;
1117 unsigned char keyid[OPS_KEY_ID_SIZE];
1118 __ops_hash_t *hash;
1119 unsigned ret;
1121 sig = NULL;
1122 sig_type = OPS_SIG_BINARY;
1123 output = NULL;
1124 mem = __ops_memory_new();
1125 hash = NULL;
1126 ret = 0;
1128 hash_alg = __ops_str_to_hash_alg(hashname);
1129 if (hash_alg == OPS_HASH_UNKNOWN) {
1130 (void) fprintf(io->errs,
1131 "__ops_sign_buf: unknown hash algorithm: \"%s\"\n",
1132 hashname);
1133 return NULL;
1136 /* setup literal data packet type */
1137 ld_type = (cleartext) ? OPS_LDT_TEXT : OPS_LDT_BINARY;
1139 if (input == NULL) {
1140 (void) fprintf(io->errs,
1141 "__ops_sign_buf: null input\n");
1142 return NULL;
1145 /* set up signature */
1146 if ((sig = __ops_create_sig_new()) == NULL) {
1147 return NULL;
1149 __ops_start_sig(sig, seckey, hash_alg, sig_type);
1151 /* setup writer */
1152 __ops_setup_memory_write(&output, &mem, insize);
1154 if (cleartext) {
1155 /* Do the signing */
1156 /* add signature with subpackets: */
1157 /* - creation time */
1158 /* - key id */
1159 ret = __ops_writer_push_clearsigned(output, sig) &&
1160 __ops_write(output, input, insize) &&
1161 __ops_writer_use_armored_sig(output) &&
1162 __ops_add_birthtime(sig, time(NULL));
1163 if (ret == 0) {
1164 return NULL;
1166 __ops_output_delete(output);
1167 } else {
1168 /* set armoured/not armoured here */
1169 if (armored) {
1170 __ops_writer_push_armor_msg(output);
1172 if (__ops_get_debug_level(__FILE__)) {
1173 fprintf(io->errs, "** Writing out one pass sig\n");
1175 /* write one_pass_sig */
1176 __ops_write_one_pass_sig(output, seckey, hash_alg, sig_type);
1178 /* hash memory */
1179 hash = __ops_sig_get_hash(sig);
1180 hash->add(hash, input, insize);
1182 /* output file contents as Literal Data packet */
1183 if (__ops_get_debug_level(__FILE__)) {
1184 (void) fprintf(stderr, "** Writing out data now\n");
1186 __ops_write_litdata(output, input, (const int)insize, ld_type);
1187 if (__ops_get_debug_level(__FILE__)) {
1188 fprintf(stderr, "** After Writing out data now\n");
1191 /* add creation time to signature */
1192 __ops_add_birthtime(sig, time(NULL));
1193 /* add key id to signature */
1194 __ops_keyid(keyid, OPS_KEY_ID_SIZE, &seckey->pubkey);
1195 __ops_add_issuer_keyid(sig, keyid);
1196 __ops_end_hashed_subpkts(sig);
1198 /* write out sig */
1199 __ops_write_sig(output, sig, &seckey->pubkey, seckey);
1201 /* tidy up */
1202 __ops_writer_close(output);
1203 __ops_create_sig_delete(sig);
1205 return mem;
1208 /* sign a file, and put the signature in a separate file */
1210 __ops_sign_detached(__ops_io_t *io,
1211 const char *f,
1212 char *sigfile,
1213 __ops_seckey_t *seckey,
1214 const char *hash)
1216 __ops_create_sig_t *sig;
1217 __ops_hash_alg_t alg;
1218 __ops_output_t *output;
1219 __ops_memory_t *mem;
1220 unsigned char keyid[OPS_KEY_ID_SIZE];
1221 time_t t;
1222 char fname[MAXPATHLEN];
1223 int fd;
1225 /* find out which hash algorithm to use */
1226 alg = __ops_str_to_hash_alg(hash);
1227 if (alg == OPS_HASH_UNKNOWN) {
1228 (void) fprintf(io->errs,"Unknown hash algorithm: %s\n", hash);
1229 return 0;
1232 /* create a new signature */
1233 sig = __ops_create_sig_new();
1234 __ops_start_sig(sig, seckey, alg, OPS_SIG_BINARY);
1236 /* read the contents of 'f', and add that to the signature */
1237 mem = __ops_memory_new();
1238 if (!__ops_mem_readfile(mem, f)) {
1239 return 0;
1241 __ops_sig_add_data(sig, __ops_mem_data(mem), __ops_mem_len(mem));
1242 __ops_memory_free(mem);
1244 /* calculate the signature */
1245 t = time(NULL);
1246 __ops_add_birthtime(sig, t);
1247 __ops_keyid(keyid, sizeof(keyid), &seckey->pubkey);
1248 __ops_add_issuer_keyid(sig, keyid);
1249 __ops_end_hashed_subpkts(sig);
1251 /* write the signature to the detached file */
1252 if (sigfile == NULL) {
1253 (void) snprintf(fname, sizeof(fname), "%s.sig", f);
1254 sigfile = fname;
1256 fd = open(sigfile, O_CREAT|O_TRUNC|O_WRONLY, 0666);
1257 if (fd < 0) {
1258 (void) fprintf(io->errs, "can't write signature to \"%s\"\n",
1259 sigfile);
1260 return 0;
1263 output = __ops_output_new();
1264 __ops_writer_set_fd(output, fd);
1265 __ops_write_sig(output, sig, &seckey->pubkey, seckey);
1266 __ops_seckey_free(seckey);
1267 (void) close(fd);
1269 return 1;