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/>.
34 do_encode_md (const byte
* md
, size_t mdlen
, int algo
, gcry_sexp_t
* r_hash
,
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
]);
54 rc
= gcry_sexp_build (&hash
, NULL
,
55 "(data (flags pkcs1) (hash %s %b))",
62 rc
= gcry_mpi_scan (&mpi
, GCRYMPI_FMT_USG
, md
, mdlen
, NULL
);
65 rc
= gcry_sexp_build (&hash
, NULL
,
66 "(data (flags raw) (value %m))",
68 gcry_mpi_release (mpi
);
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. */
83 do_encode_raw_pkcs1 (const byte
*md
, size_t mdlen
, unsigned int nbits
,
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
);
100 return gpg_error_from_syserror ();
102 /* Assemble the pkcs#1 block type 1. */
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
);
111 memcpy (frame
+n
, md
, mdlen
);
113 assert (n
== nframe
);
115 /* Create the S-expression. */
116 rc
= gcry_sexp_build (&hash
, NULL
,
117 "(data (flags raw) (value %b))",
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
,
147 log_error ("failed to read the secret key\n");
153 /* Divert operation to the smartcard */
155 unsigned char *buf
= NULL
;
158 rc
= divert_pksign (ctrl
,
160 ctrl
->digest
.valuelen
,
165 log_error ("smartcard signing failed: %s\n", gpg_strerror (rc
));
168 len
= gcry_sexp_canon_len (buf
, 0, NULL
, NULL
);
171 rc
= gcry_sexp_sscan (&s_sig
, NULL
, (char*)buf
, len
);
175 log_error ("failed to convert sigbuf returned by divert_pksign "
176 "into S-Exp: %s", gpg_strerror (rc
));
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
),
193 rc
= do_encode_md (ctrl
->digest
.value
,
194 ctrl
->digest
.valuelen
,
197 ctrl
->digest
.raw_value
);
203 log_debug ("skey: ");
204 gcry_sexp_dump (s_skey
);
208 rc
= gcry_pk_sign (&s_sig
, s_hash
, s_skey
);
209 gcry_sexp_release (s_hash
);
212 log_error ("signing failed: %s\n", gpg_strerror (rc
));
218 log_debug ("result: ");
219 gcry_sexp_dump (s_sig
);
225 *signature_sexp
= s_sig
;
227 gcry_sexp_release (s_skey
);
233 /* SIGN whatever information we have accumulated in CTRL and write it
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
;
244 rc
= agent_pksign_do (ctrl
, desc_text
, &s_sig
, cache_mode
, NULL
);
248 len
= gcry_sexp_sprint (s_sig
, GCRYSEXP_FMT_CANON
, NULL
, 0);
251 len
= gcry_sexp_sprint (s_sig
, GCRYSEXP_FMT_CANON
, buf
, len
);
254 put_membuf (outbuf
, buf
, len
);
257 gcry_sexp_release (s_sig
);