Avoid catch-22 with README.main not being distributed but having the
[gnupg.git] / agent / pksign.c
blob25cadb29ea798c81da78148c7c5b0a15ffc7843d
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 3 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, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <assert.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
30 #include "agent.h"
33 static int
34 do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash,
35 int raw_value)
37 gcry_sexp_t hash;
38 int rc;
40 if (!raw_value)
42 const char *s;
43 char tmp[16+1];
44 int i;
46 s = gcry_md_algo_name (algo);
47 if (s && strlen (s) < 16)
49 for (i=0; i < strlen (s); i++)
50 tmp[i] = tolower (s[i]);
51 tmp[i] = '\0';
54 rc = gcry_sexp_build (&hash, NULL,
55 "(data (flags pkcs1) (hash %s %b))",
56 tmp, (int)mdlen, md);
58 else
60 gcry_mpi_t mpi;
62 rc = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, md, mdlen, NULL);
63 if (! rc)
65 rc = gcry_sexp_build (&hash, NULL,
66 "(data (flags raw) (value %m))",
67 mpi);
68 gcry_mpi_release (mpi);
73 *r_hash = hash;
74 return rc;
78 /* Special version of do_encode_md to take care of pkcs#1 padding.
79 For TLS-MD5SHA1 we need to do the padding ourself as Libgrypt does
80 not know about this special scheme. Fixme: We should have a
81 pkcs1-only-padding flag for Libgcrypt. */
82 static int
83 do_encode_raw_pkcs1 (const byte *md, size_t mdlen, unsigned int nbits,
84 gcry_sexp_t *r_hash)
86 int rc;
87 gcry_sexp_t hash;
88 unsigned char *frame;
89 size_t i, n, nframe;
91 nframe = (nbits+7) / 8;
92 if ( !mdlen || mdlen + 8 + 4 > nframe )
94 /* Can't encode this hash into a frame of size NFRAME. */
95 return gpg_error (GPG_ERR_TOO_SHORT);
98 frame = xtrymalloc (nframe);
99 if (!frame)
100 return gpg_error_from_syserror ();
102 /* Assemble the pkcs#1 block type 1. */
103 n = 0;
104 frame[n++] = 0;
105 frame[n++] = 1; /* Block type. */
106 i = nframe - mdlen - 3 ;
107 assert (i >= 8); /* At least 8 bytes of padding. */
108 memset (frame+n, 0xff, i );
109 n += i;
110 frame[n++] = 0;
111 memcpy (frame+n, md, mdlen );
112 n += mdlen;
113 assert (n == nframe);
115 /* Create the S-expression. */
116 rc = gcry_sexp_build (&hash, NULL,
117 "(data (flags raw) (value %b))",
118 (int)nframe, frame);
119 xfree (frame);
121 *r_hash = hash;
122 return rc;
127 /* SIGN whatever information we have accumulated in CTRL and return
128 the signature S-expression. LOOKUP is an optional function to
129 provide a way for lower layers to ask for the caching TTL. */
131 agent_pksign_do (ctrl_t ctrl, const char *desc_text,
132 gcry_sexp_t *signature_sexp,
133 cache_mode_t cache_mode, lookup_ttl_t lookup_ttl)
135 gcry_sexp_t s_skey = NULL, s_sig = NULL;
136 unsigned char *shadow_info = NULL;
137 unsigned int rc = 0; /* FIXME: gpg-error? */
139 if (! ctrl->have_keygrip)
140 return gpg_error (GPG_ERR_NO_SECKEY);
142 rc = agent_key_from_file (ctrl, desc_text, ctrl->keygrip,
143 &shadow_info, cache_mode, lookup_ttl,
144 &s_skey);
145 if (rc)
147 log_error ("failed to read the secret key\n");
148 goto leave;
151 if (!s_skey)
153 /* Divert operation to the smartcard */
155 unsigned char *buf = NULL;
156 size_t len = 0;
158 rc = divert_pksign (ctrl,
159 ctrl->digest.value,
160 ctrl->digest.valuelen,
161 ctrl->digest.algo,
162 shadow_info, &buf);
163 if (rc)
165 log_error ("smartcard signing failed: %s\n", gpg_strerror (rc));
166 goto leave;
168 len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
169 assert (len);
171 rc = gcry_sexp_sscan (&s_sig, NULL, (char*)buf, len);
172 xfree (buf);
173 if (rc)
175 log_error ("failed to convert sigbuf returned by divert_pksign "
176 "into S-Exp: %s", gpg_strerror (rc));
177 goto leave;
180 else
182 /* No smartcard, but a private key */
184 gcry_sexp_t s_hash = NULL;
186 /* Put the hash into a sexp */
187 if (ctrl->digest.algo == MD_USER_TLS_MD5SHA1)
188 rc = do_encode_raw_pkcs1 (ctrl->digest.value,
189 ctrl->digest.valuelen,
190 gcry_pk_get_nbits (s_skey),
191 &s_hash);
192 else
193 rc = do_encode_md (ctrl->digest.value,
194 ctrl->digest.valuelen,
195 ctrl->digest.algo,
196 &s_hash,
197 ctrl->digest.raw_value);
198 if (rc)
199 goto leave;
201 if (DBG_CRYPTO)
203 log_debug ("skey: ");
204 gcry_sexp_dump (s_skey);
207 /* sign */
208 rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
209 gcry_sexp_release (s_hash);
210 if (rc)
212 log_error ("signing failed: %s\n", gpg_strerror (rc));
213 goto leave;
216 if (DBG_CRYPTO)
218 log_debug ("result: ");
219 gcry_sexp_dump (s_sig);
223 leave:
225 *signature_sexp = s_sig;
227 gcry_sexp_release (s_skey);
228 xfree (shadow_info);
230 return rc;
233 /* SIGN whatever information we have accumulated in CTRL and write it
234 back to OUTFP. */
236 agent_pksign (ctrl_t ctrl, const char *desc_text,
237 membuf_t *outbuf, cache_mode_t cache_mode)
239 gcry_sexp_t s_sig = NULL;
240 char *buf = NULL;
241 size_t len = 0;
242 int rc = 0;
244 rc = agent_pksign_do (ctrl, desc_text, &s_sig, cache_mode, NULL);
245 if (rc)
246 goto leave;
248 len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0);
249 assert (len);
250 buf = xmalloc (len);
251 len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len);
252 assert (len);
254 put_membuf (outbuf, buf, len);
256 leave:
257 gcry_sexp_release (s_sig);
258 xfree (buf);
260 return rc;