2005-04-11 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / g10 / pkglue.c
blobf062d8366bfc01f718e2e734c60f50092467153a
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
28 #include "gpg.h"
29 #include "util.h"
30 #include "pkglue.h"
33 static gcry_mpi_t
34 mpi_from_sexp (gcry_sexp_t sexp, const char * item)
36 gcry_sexp_t list;
37 gcry_mpi_t data;
39 list = gcry_sexp_find_token (sexp, item, 0);
40 assert (list);
41 data = gcry_sexp_nth_mpi (list, 1, 0);
42 assert (data);
43 gcry_sexp_release (list);
44 return data;
48 /****************
49 * Emulate our old PK interface here - sometime in the future we might
50 * change the internal design to directly fit to libgcrypt.
52 int
53 pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey)
55 gcry_sexp_t s_sig, s_hash, s_skey;
56 int rc;
58 /* make a sexp from skey */
59 if (algo == GCRY_PK_DSA)
61 rc = gcry_sexp_build (&s_skey, NULL,
62 "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
63 skey[0], skey[1], skey[2], skey[3], skey[4]);
65 else if (algo == GCRY_PK_RSA)
67 rc = gcry_sexp_build (&s_skey, NULL,
68 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
69 skey[0], skey[1], skey[2], skey[3], skey[4],
70 skey[5]);
72 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
74 rc = gcry_sexp_build (&s_skey, NULL,
75 "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
76 skey[0], skey[1], skey[2], skey[3]);
78 else
79 return GPG_ERR_PUBKEY_ALGO;
81 if (rc)
82 BUG ();
84 /* put hash into a S-Exp s_hash */
85 if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
86 BUG ();
88 rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
89 gcry_sexp_release (s_hash);
90 gcry_sexp_release (s_skey);
92 if (rc)
94 else if (algo == GCRY_PK_RSA)
95 data[0] = mpi_from_sexp (s_sig, "s");
96 else
98 data[0] = mpi_from_sexp (s_sig, "r");
99 data[1] = mpi_from_sexp (s_sig, "s");
102 gcry_sexp_release (s_sig);
103 return rc;
106 /****************
107 * Emulate our old PK interface here - sometime in the future we might
108 * change the internal design to directly fit to libgcrypt.
111 pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
113 gcry_sexp_t s_sig, s_hash, s_pkey;
114 int rc;
116 /* make a sexp from pkey */
117 if (algo == GCRY_PK_DSA)
119 rc = gcry_sexp_build (&s_pkey, NULL,
120 "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
121 pkey[0], pkey[1], pkey[2], pkey[3]);
123 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
125 rc = gcry_sexp_build (&s_pkey, NULL,
126 "(public-key(elg(p%m)(g%m)(y%m)))",
127 pkey[0], pkey[1], pkey[2]);
129 else if (algo == GCRY_PK_RSA)
131 rc = gcry_sexp_build (&s_pkey, NULL,
132 "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
134 else
135 return GPG_ERR_PUBKEY_ALGO;
137 if (rc)
138 BUG ();
140 /* put hash into a S-Exp s_hash */
141 if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
142 BUG ();
144 /* put data into a S-Exp s_sig */
145 if (algo == GCRY_PK_DSA)
147 if (!data[0] || !data[1])
148 rc = gpg_error (GPG_ERR_BAD_MPI);
149 else
150 rc = gcry_sexp_build (&s_sig, NULL,
151 "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]);
153 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
155 if (!data[0] || !data[1])
156 rc = gpg_error (GPG_ERR_BAD_MPI);
157 else
158 rc = gcry_sexp_build (&s_sig, NULL,
159 "(sig-val(elg(r%m)(s%m)))", data[0], data[1]);
161 else if (algo == GCRY_PK_RSA)
163 if (!data[0])
164 rc = gpg_error (GPG_ERR_BAD_MPI);
165 else
166 rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", data[0]);
168 else
169 BUG ();
171 if (rc)
172 BUG ();
175 rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
176 gcry_sexp_release (s_sig);
177 gcry_sexp_release (s_hash);
178 gcry_sexp_release (s_pkey);
179 return rc;
185 /****************
186 * Emulate our old PK interface here - sometime in the future we might
187 * change the internal design to directly fit to libgcrypt.
190 pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey)
192 gcry_sexp_t s_ciph, s_data, s_pkey;
193 int rc;
195 /* make a sexp from pkey */
196 if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
198 rc = gcry_sexp_build (&s_pkey, NULL,
199 "(public-key(elg(p%m)(g%m)(y%m)))",
200 pkey[0], pkey[1], pkey[2]);
202 else if (algo == GCRY_PK_RSA)
204 rc = gcry_sexp_build (&s_pkey, NULL,
205 "(public-key(rsa(n%m)(e%m)))",
206 pkey[0], pkey[1]);
208 else
209 return GPG_ERR_PUBKEY_ALGO;
211 if (rc)
212 BUG ();
214 /* put the data into a simple list */
215 if (gcry_sexp_build (&s_data, NULL, "%m", data))
216 BUG ();
218 /* pass it to libgcrypt */
219 rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
220 gcry_sexp_release (s_data);
221 gcry_sexp_release (s_pkey);
223 if (rc)
225 else
226 { /* add better error handling or make gnupg use S-Exp directly */
227 resarr[0] = mpi_from_sexp (s_ciph, "a");
228 if (algo != GCRY_PK_RSA)
229 resarr[1] = mpi_from_sexp (s_ciph, "b");
232 gcry_sexp_release (s_ciph);
233 return rc;
238 /****************
239 * Emulate our old PK interface here - sometime in the future we might
240 * change the internal design to directly fit to libgcrypt.
243 pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data,
244 gcry_mpi_t * skey)
246 gcry_sexp_t s_skey, s_data, s_plain;
247 int rc;
249 *result = NULL;
250 /* make a sexp from skey */
251 if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
253 rc = gcry_sexp_build (&s_skey, NULL,
254 "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
255 skey[0], skey[1], skey[2], skey[3]);
257 else if (algo == GCRY_PK_RSA)
259 rc = gcry_sexp_build (&s_skey, NULL,
260 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
261 skey[0], skey[1], skey[2], skey[3], skey[4],
262 skey[5]);
264 else
265 return GPG_ERR_PUBKEY_ALGO;
267 if (rc)
268 BUG ();
270 /* put data into a S-Exp s_data */
271 if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
273 if (!data[0] || !data[1])
274 rc = gpg_error (GPG_ERR_BAD_MPI);
275 else
276 rc = gcry_sexp_build (&s_data, NULL,
277 "(enc-val(elg(a%m)(b%m)))", data[0], data[1]);
279 else if (algo == GCRY_PK_RSA)
281 if (!data[0])
282 rc = gpg_error (GPG_ERR_BAD_MPI);
283 else
284 rc = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data[0]);
286 else
287 BUG ();
289 if (rc)
290 BUG ();
292 rc = gcry_pk_decrypt (&s_plain, s_data, s_skey);
293 gcry_sexp_release (s_skey);
294 gcry_sexp_release (s_data);
295 if (rc)
296 return rc;
298 *result = gcry_sexp_nth_mpi (s_plain, 0, 0);
299 gcry_sexp_release (s_plain);
300 if (!*result)
301 return -1; /* oops */
303 return 0;
307 /* Check whether SKEY is a suitable secret key. */
309 pk_check_secret_key (int algo, gcry_mpi_t *skey)
311 gcry_sexp_t s_skey;
312 int rc;
314 if (algo == GCRY_PK_DSA)
316 rc = gcry_sexp_build (&s_skey, NULL,
317 "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
318 skey[0], skey[1], skey[2], skey[3], skey[4]);
320 else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
322 rc = gcry_sexp_build (&s_skey, NULL,
323 "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
324 skey[0], skey[1], skey[2], skey[3]);
326 else if (algo == GCRY_PK_RSA)
328 rc = gcry_sexp_build (&s_skey, NULL,
329 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
330 skey[0], skey[1], skey[2], skey[3], skey[4],
331 skey[5]);
333 else
334 return GPG_ERR_PUBKEY_ALGO;
336 if (!rc)
338 rc = gcry_pk_testkey (s_skey);
339 gcry_sexp_release (s_skey);
341 return rc;