Fix buglet.
[gnupg.git] / agent / pksign.c
blobacde66029f5d8f7bcbb1f7a957941142a5a53a06
1 /* pksign.c - public key signing (well, actually using a secret key)
2 * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
31 #include "agent.h"
34 static int
35 do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash)
37 gcry_sexp_t hash;
38 const char *s;
39 char tmp[16+1];
40 int i, rc;
42 s = gcry_md_algo_name (algo);
43 if (s && strlen (s) < 16)
45 for (i=0; i < strlen (s); i++)
46 tmp[i] = tolower (s[i]);
47 tmp[i] = '\0';
49 rc = gcry_sexp_build (&hash, NULL,
50 "(data (flags pkcs1) (hash %s %b))",
51 tmp,
52 mdlen, md);
53 *r_hash = hash;
54 return rc;
58 /* SIGN whatever information we have accumulated in CTRL and write it
59 back to OUTFP. */
60 int
61 agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache)
63 gcry_sexp_t s_skey = NULL, s_hash = NULL, s_sig = NULL;
64 unsigned char *shadow_info = NULL;
65 int rc;
66 char *buf = NULL;
67 size_t len;
69 if (!ctrl->have_keygrip)
70 return gpg_error (GPG_ERR_NO_SECKEY);
72 rc = agent_key_from_file (ctrl, desc_text, ctrl->keygrip,
73 &shadow_info, ignore_cache, &s_skey);
74 if (rc)
76 log_error ("failed to read the secret key\n");
77 goto leave;
80 if (!s_skey)
81 { /* divert operation to the smartcard */
82 unsigned char *sigbuf;
84 rc = divert_pksign (ctrl,
85 ctrl->digest.value,
86 ctrl->digest.valuelen,
87 ctrl->digest.algo,
88 shadow_info, &sigbuf);
89 if (rc)
91 log_error ("smartcard signing failed: %s\n", gpg_strerror (rc));
92 goto leave;
94 len = gcry_sexp_canon_len (sigbuf, 0, NULL, NULL);
95 assert (len);
96 buf = sigbuf;
98 else
99 { /* no smartcard, but a private key */
101 /* put the hash into a sexp */
102 rc = do_encode_md (ctrl->digest.value,
103 ctrl->digest.valuelen,
104 ctrl->digest.algo,
105 &s_hash);
106 if (rc)
107 goto leave;
109 if (DBG_CRYPTO)
111 log_debug ("skey: ");
112 gcry_sexp_dump (s_skey);
115 /* sign */
116 rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
117 if (rc)
119 log_error ("signing failed: %s\n", gpg_strerror (rc));
120 goto leave;
123 if (DBG_CRYPTO)
125 log_debug ("result: ");
126 gcry_sexp_dump (s_sig);
129 len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0);
130 assert (len);
131 buf = xmalloc (len);
132 len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len);
133 assert (len);
136 /* FIXME: we must make sure that no buffering takes place or we are
137 in full control of the buffer memory (easy to do) - should go
138 into assuan. */
139 fwrite (buf, 1, len, outfp);
141 leave:
142 gcry_sexp_release (s_skey);
143 gcry_sexp_release (s_hash);
144 gcry_sexp_release (s_sig);
145 xfree (buf);
146 xfree (shadow_info);
147 return rc;