2006-09-06 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / g10 / pkglue.c
blob3f9669d27e89fb563600e93cf6b7fd8126c2b4a7
1 /* pkglue.c - public key operations glue code
2 * Copyright (C) 2000, 2003 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 * USA.
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
29 #include "gpg.h"
30 #include "util.h"
31 #include "pkglue.h"
34 static gcry_mpi_t
35 mpi_from_sexp (gcry_sexp_t sexp, const char * item)
37 gcry_sexp_t list;
38 gcry_mpi_t data;
40 list = gcry_sexp_find_token (sexp, item, 0);
41 assert (list);
42 data = gcry_sexp_nth_mpi (list, 1, 0);
43 assert (data);
44 gcry_sexp_release (list);
45 return data;
49 /****************
50 * Emulate our old PK interface here - sometime in the future we might
51 * change the internal design to directly fit to libgcrypt.
53 int
54 pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey)
56 gcry_sexp_t s_sig, s_hash, s_skey;
57 int rc;
59 /* make a sexp from skey */
60 if (algo == GCRY_PK_DSA)
62 rc = gcry_sexp_build (&s_skey, NULL,
63 "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
64 skey[0], skey[1], skey[2], skey[3], skey[4]);
66 else if (algo == GCRY_PK_RSA)
68 rc = gcry_sexp_build (&s_skey, NULL,
69 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
70 skey[0], skey[1], skey[2], skey[3], skey[4],
71 skey[5]);
73 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
75 rc = gcry_sexp_build (&s_skey, NULL,
76 "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
77 skey[0], skey[1], skey[2], skey[3]);
79 else
80 return GPG_ERR_PUBKEY_ALGO;
82 if (rc)
83 BUG ();
85 /* put hash into a S-Exp s_hash */
86 if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
87 BUG ();
89 rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
90 gcry_sexp_release (s_hash);
91 gcry_sexp_release (s_skey);
93 if (rc)
95 else if (algo == GCRY_PK_RSA)
96 data[0] = mpi_from_sexp (s_sig, "s");
97 else
99 data[0] = mpi_from_sexp (s_sig, "r");
100 data[1] = mpi_from_sexp (s_sig, "s");
103 gcry_sexp_release (s_sig);
104 return rc;
107 /****************
108 * Emulate our old PK interface here - sometime in the future we might
109 * change the internal design to directly fit to libgcrypt.
112 pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
114 gcry_sexp_t s_sig, s_hash, s_pkey;
115 int rc;
117 /* make a sexp from pkey */
118 if (algo == GCRY_PK_DSA)
120 rc = gcry_sexp_build (&s_pkey, NULL,
121 "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
122 pkey[0], pkey[1], pkey[2], pkey[3]);
124 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
126 rc = gcry_sexp_build (&s_pkey, NULL,
127 "(public-key(elg(p%m)(g%m)(y%m)))",
128 pkey[0], pkey[1], pkey[2]);
130 else if (algo == GCRY_PK_RSA)
132 rc = gcry_sexp_build (&s_pkey, NULL,
133 "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
135 else
136 return GPG_ERR_PUBKEY_ALGO;
138 if (rc)
139 BUG ();
141 /* put hash into a S-Exp s_hash */
142 if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
143 BUG ();
145 /* put data into a S-Exp s_sig */
146 if (algo == GCRY_PK_DSA)
148 if (!data[0] || !data[1])
149 rc = gpg_error (GPG_ERR_BAD_MPI);
150 else
151 rc = gcry_sexp_build (&s_sig, NULL,
152 "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]);
154 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
156 if (!data[0] || !data[1])
157 rc = gpg_error (GPG_ERR_BAD_MPI);
158 else
159 rc = gcry_sexp_build (&s_sig, NULL,
160 "(sig-val(elg(r%m)(s%m)))", data[0], data[1]);
162 else if (algo == GCRY_PK_RSA)
164 if (!data[0])
165 rc = gpg_error (GPG_ERR_BAD_MPI);
166 else
167 rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", data[0]);
169 else
170 BUG ();
172 if (rc)
173 BUG ();
176 rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
177 gcry_sexp_release (s_sig);
178 gcry_sexp_release (s_hash);
179 gcry_sexp_release (s_pkey);
180 return rc;
186 /****************
187 * Emulate our old PK interface here - sometime in the future we might
188 * change the internal design to directly fit to libgcrypt.
191 pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey)
193 gcry_sexp_t s_ciph, s_data, s_pkey;
194 int rc;
196 /* make a sexp from pkey */
197 if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
199 rc = gcry_sexp_build (&s_pkey, NULL,
200 "(public-key(elg(p%m)(g%m)(y%m)))",
201 pkey[0], pkey[1], pkey[2]);
203 else if (algo == GCRY_PK_RSA)
205 rc = gcry_sexp_build (&s_pkey, NULL,
206 "(public-key(rsa(n%m)(e%m)))",
207 pkey[0], pkey[1]);
209 else
210 return GPG_ERR_PUBKEY_ALGO;
212 if (rc)
213 BUG ();
215 /* put the data into a simple list */
216 if (gcry_sexp_build (&s_data, NULL, "%m", data))
217 BUG ();
219 /* pass it to libgcrypt */
220 rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
221 gcry_sexp_release (s_data);
222 gcry_sexp_release (s_pkey);
224 if (rc)
226 else
227 { /* add better error handling or make gnupg use S-Exp directly */
228 resarr[0] = mpi_from_sexp (s_ciph, "a");
229 if (algo != GCRY_PK_RSA)
230 resarr[1] = mpi_from_sexp (s_ciph, "b");
233 gcry_sexp_release (s_ciph);
234 return rc;
239 /****************
240 * Emulate our old PK interface here - sometime in the future we might
241 * change the internal design to directly fit to libgcrypt.
244 pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data,
245 gcry_mpi_t * skey)
247 gcry_sexp_t s_skey, s_data, s_plain;
248 int rc;
250 *result = NULL;
251 /* make a sexp from skey */
252 if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
254 rc = gcry_sexp_build (&s_skey, NULL,
255 "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
256 skey[0], skey[1], skey[2], skey[3]);
258 else if (algo == GCRY_PK_RSA)
260 rc = gcry_sexp_build (&s_skey, NULL,
261 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
262 skey[0], skey[1], skey[2], skey[3], skey[4],
263 skey[5]);
265 else
266 return GPG_ERR_PUBKEY_ALGO;
268 if (rc)
269 BUG ();
271 /* put data into a S-Exp s_data */
272 if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
274 if (!data[0] || !data[1])
275 rc = gpg_error (GPG_ERR_BAD_MPI);
276 else
277 rc = gcry_sexp_build (&s_data, NULL,
278 "(enc-val(elg(a%m)(b%m)))", data[0], data[1]);
280 else if (algo == GCRY_PK_RSA)
282 if (!data[0])
283 rc = gpg_error (GPG_ERR_BAD_MPI);
284 else
285 rc = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data[0]);
287 else
288 BUG ();
290 if (rc)
291 BUG ();
293 rc = gcry_pk_decrypt (&s_plain, s_data, s_skey);
294 gcry_sexp_release (s_skey);
295 gcry_sexp_release (s_data);
296 if (rc)
297 return rc;
299 *result = gcry_sexp_nth_mpi (s_plain, 0, 0);
300 gcry_sexp_release (s_plain);
301 if (!*result)
302 return -1; /* oops */
304 return 0;
308 /* Check whether SKEY is a suitable secret key. */
310 pk_check_secret_key (int algo, gcry_mpi_t *skey)
312 gcry_sexp_t s_skey;
313 int rc;
315 if (algo == GCRY_PK_DSA)
317 rc = gcry_sexp_build (&s_skey, NULL,
318 "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
319 skey[0], skey[1], skey[2], skey[3], skey[4]);
321 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
323 rc = gcry_sexp_build (&s_skey, NULL,
324 "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
325 skey[0], skey[1], skey[2], skey[3]);
327 else if (algo == GCRY_PK_RSA)
329 rc = gcry_sexp_build (&s_skey, NULL,
330 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
331 skey[0], skey[1], skey[2], skey[3], skey[4],
332 skey[5]);
334 else
335 return GPG_ERR_PUBKEY_ALGO;
337 if (!rc)
339 rc = gcry_pk_testkey (s_skey);
340 gcry_sexp_release (s_skey);
342 return rc;