Add new logo.
[gnupg.git] / g10 / pkglue.c
1 /* pkglue.c - public key operations glue code
2  *      Copyright (C) 2000, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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.
10  *
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.
15  *
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.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28
29 #include "gpg.h"
30 #include "util.h"
31 #include "pkglue.h"
32
33
34 static gcry_mpi_t
35 mpi_from_sexp (gcry_sexp_t sexp, const char * item)
36 {
37   gcry_sexp_t list;
38   gcry_mpi_t data;
39   
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;
46 }
47
48
49 /****************
50  * Emulate our old PK interface here - sometime in the future we might
51  * change the internal design to directly fit to libgcrypt.
52  */
53 int
54 pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey)
55 {
56   gcry_sexp_t s_sig, s_hash, s_skey;
57   int rc;
58
59   /* make a sexp from skey */
60   if (algo == GCRY_PK_DSA)
61     {
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]);
65     }
66   else if (algo == GCRY_PK_RSA)
67     {
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]);
72     }
73   else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
74     {
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]);
78     }
79   else
80     return GPG_ERR_PUBKEY_ALGO;
81
82   if (rc)
83     BUG ();
84
85   /* put hash into a S-Exp s_hash */
86   if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
87     BUG ();
88
89   rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
90   gcry_sexp_release (s_hash);
91   gcry_sexp_release (s_skey);
92
93   if (rc)
94     ;
95   else if (algo == GCRY_PK_RSA)
96     data[0] = mpi_from_sexp (s_sig, "s");
97   else
98     {
99       data[0] = mpi_from_sexp (s_sig, "r");
100       data[1] = mpi_from_sexp (s_sig, "s");
101     }
102
103   gcry_sexp_release (s_sig);
104   return rc;
105 }
106
107 /****************
108  * Emulate our old PK interface here - sometime in the future we might
109  * change the internal design to directly fit to libgcrypt.
110  */
111 int
112 pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
113 {
114   gcry_sexp_t s_sig, s_hash, s_pkey;
115   int rc;
116
117   /* make a sexp from pkey */
118   if (algo == GCRY_PK_DSA)
119     {
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]);
123     }
124   else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
125     {
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]);
129     }
130   else if (algo == GCRY_PK_RSA)
131     {
132       rc = gcry_sexp_build (&s_pkey, NULL,
133                             "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
134     }
135   else
136     return GPG_ERR_PUBKEY_ALGO;
137
138   if (rc)
139     BUG ();
140
141   /* put hash into a S-Exp s_hash */
142   if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
143     BUG ();
144
145   /* put data into a S-Exp s_sig */
146   if (algo == GCRY_PK_DSA)
147     {
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]);
153     }
154   else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
155     {
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]);
161     }
162   else if (algo == GCRY_PK_RSA)
163     {
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]);
168     }
169   else
170     BUG ();
171
172   if (rc)
173     BUG ();
174
175
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;
181 }
182
183
184
185
186 /****************
187  * Emulate our old PK interface here - sometime in the future we might
188  * change the internal design to directly fit to libgcrypt.
189  */
190 int
191 pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey)
192 {
193   gcry_sexp_t s_ciph, s_data, s_pkey;
194   int rc;
195
196   /* make a sexp from pkey */
197   if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
198     {
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]);
202     }
203   else if (algo == GCRY_PK_RSA)
204     {
205       rc = gcry_sexp_build (&s_pkey, NULL,
206                             "(public-key(rsa(n%m)(e%m)))",
207                             pkey[0], pkey[1]);
208     }
209   else
210     return GPG_ERR_PUBKEY_ALGO;
211
212   if (rc)
213     BUG ();
214
215   /* put the data into a simple list */
216   if (gcry_sexp_build (&s_data, NULL, "%m", data))
217     BUG ();
218
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);
223
224   if (rc)
225     ;
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");
231     }
232
233   gcry_sexp_release (s_ciph);
234   return rc;
235 }
236
237
238
239 /****************
240  * Emulate our old PK interface here - sometime in the future we might
241  * change the internal design to directly fit to libgcrypt.
242  */
243 int
244 pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data,
245             gcry_mpi_t * skey)
246 {
247   gcry_sexp_t s_skey, s_data, s_plain;
248   int rc;
249
250   *result = NULL;
251   /* make a sexp from skey */
252   if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
253     {
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]);
257     }
258   else if (algo == GCRY_PK_RSA)
259     {
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]);
264     }
265   else
266     return GPG_ERR_PUBKEY_ALGO;
267
268   if (rc)
269     BUG ();
270
271   /* put data into a S-Exp s_data */
272   if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
273     {
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]);
279     }
280   else if (algo == GCRY_PK_RSA)
281     {
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]);
286     }
287   else
288     BUG ();
289
290   if (rc)
291     BUG ();
292
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;
298
299   *result = gcry_sexp_nth_mpi (s_plain, 0, 0);
300   gcry_sexp_release (s_plain);
301   if (!*result)
302     return -1;                  /* oops */
303
304   return 0;
305 }
306
307
308 /* Check whether SKEY is a suitable secret key. */
309 int
310 pk_check_secret_key (int algo, gcry_mpi_t *skey)
311 {
312   gcry_sexp_t s_skey;
313   int rc;
314
315   if (algo == GCRY_PK_DSA)
316     {
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]);
320     }
321   else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
322     {
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]);
326     }
327   else if (algo == GCRY_PK_RSA)
328     {
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]);
333     }
334   else
335     return GPG_ERR_PUBKEY_ALGO;
336
337   if (!rc)
338     {
339       rc = gcry_pk_testkey (s_skey);
340       gcry_sexp_release (s_skey);
341     }
342   return rc;
343 }