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. */
130 agent_pksign_do (ctrl_t ctrl
, const char *desc_text
,
131 gcry_sexp_t
*signature_sexp
, cache_mode_t cache_mode
)
133 gcry_sexp_t s_skey
= NULL
, s_sig
= NULL
;
134 unsigned char *shadow_info
= NULL
;
135 unsigned int rc
= 0; /* FIXME: gpg-error? */
137 if (! ctrl
->have_keygrip
)
138 return gpg_error (GPG_ERR_NO_SECKEY
);
140 rc
= agent_key_from_file (ctrl
, desc_text
, ctrl
->keygrip
,
141 &shadow_info
, cache_mode
, &s_skey
);
144 log_error ("failed to read the secret key\n");
150 /* Divert operation to the smartcard */
152 unsigned char *buf
= NULL
;
155 rc
= divert_pksign (ctrl
,
157 ctrl
->digest
.valuelen
,
162 log_error ("smartcard signing failed: %s\n", gpg_strerror (rc
));
165 len
= gcry_sexp_canon_len (buf
, 0, NULL
, NULL
);
168 rc
= gcry_sexp_sscan (&s_sig
, NULL
, (char*)buf
, len
);
172 log_error ("failed to convert sigbuf returned by divert_pksign "
173 "into S-Exp: %s", gpg_strerror (rc
));
179 /* No smartcard, but a private key */
181 gcry_sexp_t s_hash
= NULL
;
183 /* Put the hash into a sexp */
184 if (ctrl
->digest
.algo
== MD_USER_TLS_MD5SHA1
)
185 rc
= do_encode_raw_pkcs1 (ctrl
->digest
.value
,
186 ctrl
->digest
.valuelen
,
187 gcry_pk_get_nbits (s_skey
),
190 rc
= do_encode_md (ctrl
->digest
.value
,
191 ctrl
->digest
.valuelen
,
194 ctrl
->digest
.raw_value
);
200 log_debug ("skey: ");
201 gcry_sexp_dump (s_skey
);
205 rc
= gcry_pk_sign (&s_sig
, s_hash
, s_skey
);
206 gcry_sexp_release (s_hash
);
209 log_error ("signing failed: %s\n", gpg_strerror (rc
));
215 log_debug ("result: ");
216 gcry_sexp_dump (s_sig
);
222 *signature_sexp
= s_sig
;
224 gcry_sexp_release (s_skey
);
230 /* SIGN whatever information we have accumulated in CTRL and write it
233 agent_pksign (ctrl_t ctrl
, const char *desc_text
,
234 membuf_t
*outbuf
, cache_mode_t cache_mode
)
236 gcry_sexp_t s_sig
= NULL
;
241 rc
= agent_pksign_do (ctrl
, desc_text
, &s_sig
, cache_mode
);
245 len
= gcry_sexp_sprint (s_sig
, GCRYSEXP_FMT_CANON
, NULL
, 0);
248 len
= gcry_sexp_sprint (s_sig
, GCRYSEXP_FMT_CANON
, buf
, len
);
251 put_membuf (outbuf
, buf
, len
);
254 gcry_sexp_release (s_sig
);