2008-05-15 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / g10 / pkglue.c
blobe4d749a2371186d71c2e3cbee331ad0d31173029
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 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 <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <assert.h>
27 #include "gpg.h"
28 #include "util.h"
29 #include "pkglue.h"
32 static gcry_mpi_t
33 mpi_from_sexp (gcry_sexp_t sexp, const char * item)
35 gcry_sexp_t list;
36 gcry_mpi_t data;
38 list = gcry_sexp_find_token (sexp, item, 0);
39 assert (list);
40 data = gcry_sexp_nth_mpi (list, 1, 0);
41 assert (data);
42 gcry_sexp_release (list);
43 return data;
47 /****************
48 * Emulate our old PK interface here - sometime in the future we might
49 * change the internal design to directly fit to libgcrypt.
51 int
52 pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey)
54 gcry_sexp_t s_sig, s_hash, s_skey;
55 int rc;
57 /* make a sexp from skey */
58 if (algo == GCRY_PK_DSA)
60 rc = gcry_sexp_build (&s_skey, NULL,
61 "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
62 skey[0], skey[1], skey[2], skey[3], skey[4]);
64 else if (algo == GCRY_PK_RSA)
66 rc = gcry_sexp_build (&s_skey, NULL,
67 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
68 skey[0], skey[1], skey[2], skey[3], skey[4],
69 skey[5]);
71 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
73 rc = gcry_sexp_build (&s_skey, NULL,
74 "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
75 skey[0], skey[1], skey[2], skey[3]);
77 else
78 return GPG_ERR_PUBKEY_ALGO;
80 if (rc)
81 BUG ();
83 /* put hash into a S-Exp s_hash */
84 if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
85 BUG ();
87 rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
88 gcry_sexp_release (s_hash);
89 gcry_sexp_release (s_skey);
91 if (rc)
93 else if (algo == GCRY_PK_RSA)
94 data[0] = mpi_from_sexp (s_sig, "s");
95 else
97 data[0] = mpi_from_sexp (s_sig, "r");
98 data[1] = mpi_from_sexp (s_sig, "s");
101 gcry_sexp_release (s_sig);
102 return rc;
105 /****************
106 * Emulate our old PK interface here - sometime in the future we might
107 * change the internal design to directly fit to libgcrypt.
110 pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
112 gcry_sexp_t s_sig, s_hash, s_pkey;
113 int rc;
115 /* make a sexp from pkey */
116 if (algo == GCRY_PK_DSA)
118 rc = gcry_sexp_build (&s_pkey, NULL,
119 "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
120 pkey[0], pkey[1], pkey[2], pkey[3]);
122 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
124 rc = gcry_sexp_build (&s_pkey, NULL,
125 "(public-key(elg(p%m)(g%m)(y%m)))",
126 pkey[0], pkey[1], pkey[2]);
128 else if (algo == GCRY_PK_RSA)
130 rc = gcry_sexp_build (&s_pkey, NULL,
131 "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
133 else
134 return GPG_ERR_PUBKEY_ALGO;
136 if (rc)
137 BUG ();
139 /* put hash into a S-Exp s_hash */
140 if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
141 BUG ();
143 /* put data into a S-Exp s_sig */
144 if (algo == GCRY_PK_DSA)
146 if (!data[0] || !data[1])
147 rc = gpg_error (GPG_ERR_BAD_MPI);
148 else
149 rc = gcry_sexp_build (&s_sig, NULL,
150 "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]);
152 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
154 if (!data[0] || !data[1])
155 rc = gpg_error (GPG_ERR_BAD_MPI);
156 else
157 rc = gcry_sexp_build (&s_sig, NULL,
158 "(sig-val(elg(r%m)(s%m)))", data[0], data[1]);
160 else if (algo == GCRY_PK_RSA)
162 if (!data[0])
163 rc = gpg_error (GPG_ERR_BAD_MPI);
164 else
165 rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", data[0]);
167 else
168 BUG ();
170 if (rc)
171 BUG ();
174 rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
175 gcry_sexp_release (s_sig);
176 gcry_sexp_release (s_hash);
177 gcry_sexp_release (s_pkey);
178 return rc;
184 /****************
185 * Emulate our old PK interface here - sometime in the future we might
186 * change the internal design to directly fit to libgcrypt.
189 pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey)
191 gcry_sexp_t s_ciph, s_data, s_pkey;
192 int rc;
194 /* make a sexp from pkey */
195 if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
197 rc = gcry_sexp_build (&s_pkey, NULL,
198 "(public-key(elg(p%m)(g%m)(y%m)))",
199 pkey[0], pkey[1], pkey[2]);
201 else if (algo == GCRY_PK_RSA)
203 rc = gcry_sexp_build (&s_pkey, NULL,
204 "(public-key(rsa(n%m)(e%m)))",
205 pkey[0], pkey[1]);
207 else
208 return GPG_ERR_PUBKEY_ALGO;
210 if (rc)
211 BUG ();
213 /* put the data into a simple list */
214 if (gcry_sexp_build (&s_data, NULL, "%m", data))
215 BUG ();
217 /* pass it to libgcrypt */
218 rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
219 gcry_sexp_release (s_data);
220 gcry_sexp_release (s_pkey);
222 if (rc)
224 else
225 { /* add better error handling or make gnupg use S-Exp directly */
226 resarr[0] = mpi_from_sexp (s_ciph, "a");
227 if (algo != GCRY_PK_RSA)
228 resarr[1] = mpi_from_sexp (s_ciph, "b");
231 gcry_sexp_release (s_ciph);
232 return rc;
237 /****************
238 * Emulate our old PK interface here - sometime in the future we might
239 * change the internal design to directly fit to libgcrypt.
242 pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data,
243 gcry_mpi_t * skey)
245 gcry_sexp_t s_skey, s_data, s_plain;
246 int rc;
248 *result = NULL;
249 /* make a sexp from skey */
250 if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
252 rc = gcry_sexp_build (&s_skey, NULL,
253 "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
254 skey[0], skey[1], skey[2], skey[3]);
256 else if (algo == GCRY_PK_RSA)
258 rc = gcry_sexp_build (&s_skey, NULL,
259 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
260 skey[0], skey[1], skey[2], skey[3], skey[4],
261 skey[5]);
263 else
264 return GPG_ERR_PUBKEY_ALGO;
266 if (rc)
267 BUG ();
269 /* put data into a S-Exp s_data */
270 if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
272 if (!data[0] || !data[1])
273 rc = gpg_error (GPG_ERR_BAD_MPI);
274 else
275 rc = gcry_sexp_build (&s_data, NULL,
276 "(enc-val(elg(a%m)(b%m)))", data[0], data[1]);
278 else if (algo == GCRY_PK_RSA)
280 if (!data[0])
281 rc = gpg_error (GPG_ERR_BAD_MPI);
282 else
283 rc = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data[0]);
285 else
286 BUG ();
288 if (rc)
289 BUG ();
291 rc = gcry_pk_decrypt (&s_plain, s_data, s_skey);
292 gcry_sexp_release (s_skey);
293 gcry_sexp_release (s_data);
294 if (rc)
295 return rc;
297 *result = gcry_sexp_nth_mpi (s_plain, 0, 0);
298 gcry_sexp_release (s_plain);
299 if (!*result)
300 return -1; /* oops */
302 return 0;
306 /* Check whether SKEY is a suitable secret key. */
308 pk_check_secret_key (int algo, gcry_mpi_t *skey)
310 gcry_sexp_t s_skey;
311 int rc;
313 if (algo == GCRY_PK_DSA)
315 rc = gcry_sexp_build (&s_skey, NULL,
316 "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
317 skey[0], skey[1], skey[2], skey[3], skey[4]);
319 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
321 rc = gcry_sexp_build (&s_skey, NULL,
322 "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
323 skey[0], skey[1], skey[2], skey[3]);
325 else if (algo == GCRY_PK_RSA)
327 rc = gcry_sexp_build (&s_skey, NULL,
328 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
329 skey[0], skey[1], skey[2], skey[3], skey[4],
330 skey[5]);
332 else
333 return GPG_ERR_PUBKEY_ALGO;
335 if (!rc)
337 rc = gcry_pk_testkey (s_skey);
338 gcry_sexp_release (s_skey);
340 return rc;