Finished the bulk of changes for gnupg 1.9. This included switching
[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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27
28 #include "gpg.h"
29 #include "util.h"
30 #include "pkglue.h"
31
32
33
34 /****************
35  * Emulate our old PK interface here - sometime in the future we might
36  * change the internal design to directly fit to libgcrypt.
37  */
38 int
39 pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey)
40 {
41   gcry_sexp_t s_sig, s_hash, s_skey, list;
42   int rc;
43
44   /* make a sexp from skey */
45   if (algo == GCRY_PK_DSA)
46     {
47       rc = gcry_sexp_build (&s_skey, NULL,
48                             "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
49                             skey[0], skey[1], skey[2], skey[3], skey[4]);
50     }
51   else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
52     {
53       rc = gcry_sexp_build (&s_skey, NULL,
54                             "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
55                             skey[0], skey[1], skey[2], skey[3]);
56     }
57   else
58     return GPG_ERR_PUBKEY_ALGO;
59
60   if (rc)
61     BUG ();
62
63   /* put hash into a S-Exp s_hash */
64   if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
65     BUG ();
66
67   rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
68   gcry_sexp_release (s_hash);
69   gcry_sexp_release (s_skey);
70
71   if (rc)
72     ;
73   else
74     {
75       list = gcry_sexp_find_token (s_sig, "r", 0);
76       assert (list);
77       data[0] = gcry_sexp_nth_mpi (list, 1, 0);
78       assert (data[0]);
79       gcry_sexp_release (list);
80
81       list = gcry_sexp_find_token (s_sig, "s", 0);
82       assert (list);
83       data[1] = gcry_sexp_nth_mpi (list, 1, 0);
84       assert (data[1]);
85       gcry_sexp_release (list);
86     }
87
88
89   gcry_sexp_release (s_sig);
90   return rc;
91 }
92
93 /****************
94  * Emulate our old PK interface here - sometime in the future we might
95  * change the internal design to directly fit to libgcrypt.
96  */
97 int
98 pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
99 {
100   gcry_sexp_t s_sig, s_hash, s_pkey;
101   int rc;
102
103   /* make a sexp from pkey */
104   if (algo == GCRY_PK_DSA)
105     {
106       rc = gcry_sexp_build (&s_pkey, NULL,
107                             "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
108                             pkey[0], pkey[1], pkey[2], pkey[3]);
109     }
110   else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
111     {
112       rc = gcry_sexp_build (&s_pkey, NULL,
113                             "(public-key(elg(p%m)(g%m)(y%m)))",
114                             pkey[0], pkey[1], pkey[2]);
115     }
116   else if (algo == GCRY_PK_RSA)
117     {
118       rc = gcry_sexp_build (&s_pkey, NULL,
119                             "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
120     }
121   else
122     return GPG_ERR_PUBKEY_ALGO;
123
124   if (rc)
125     BUG ();
126
127   /* put hash into a S-Exp s_hash */
128   if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
129     BUG ();
130
131   /* put data into a S-Exp s_sig */
132   if (algo == GCRY_PK_DSA)
133     {
134       rc = gcry_sexp_build (&s_sig, NULL,
135                             "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]);
136     }
137   else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
138     {
139       rc = gcry_sexp_build (&s_sig, NULL,
140                             "(sig-val(elg(r%m)(s%m)))", data[0], data[1]);
141     }
142   else if (algo == GCRY_PK_RSA)
143     {
144       rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", data[0]);
145     }
146   else
147     BUG ();
148
149   if (rc)
150     BUG ();
151
152
153   rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
154   gcry_sexp_release (s_sig);
155   gcry_sexp_release (s_hash);
156   gcry_sexp_release (s_pkey);
157   return rc;
158 }
159
160
161
162
163 /****************
164  * Emulate our old PK interface here - sometime in the future we might
165  * change the internal design to directly fit to libgcrypt.
166  */
167 int
168 pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey)
169 {
170   gcry_sexp_t s_ciph, s_data, s_pkey;
171   int rc;
172
173   /* make a sexp from pkey */
174   if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
175     {
176       rc = gcry_sexp_build (&s_pkey, NULL,
177                             "(public-key(elg(p%m)(g%m)(y%m)))",
178                             pkey[0], pkey[1], pkey[2]);
179     }
180   else
181     return GPG_ERR_PUBKEY_ALGO;
182
183   if (rc)
184     BUG ();
185
186   /* put the data into a simple list */
187   if (gcry_sexp_build (&s_data, NULL, "%m", data))
188     BUG ();
189
190   /* pass it to libgcrypt */
191   rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
192   gcry_sexp_release (s_data);
193   gcry_sexp_release (s_pkey);
194
195   if (rc)
196     ;
197   else
198     { /* add better error handling or make gnupg use S-Exp directly */
199       gcry_sexp_t list = gcry_sexp_find_token (s_ciph, "a", 0);
200       assert (list);
201       resarr[0] = gcry_sexp_nth_mpi (list, 1, 0);
202       assert (resarr[0]);
203       gcry_sexp_release (list);
204
205       list = gcry_sexp_find_token (s_ciph, "b", 0);
206       assert (list);
207       resarr[1] = gcry_sexp_nth_mpi (list, 1, 0);
208       assert (resarr[1]);
209       gcry_sexp_release (list);
210     }
211
212   gcry_sexp_release (s_ciph);
213   return rc;
214 }
215
216
217
218 /****************
219  * Emulate our old PK interface here - sometime in the future we might
220  * change the internal design to directly fit to libgcrypt.
221  */
222 int
223 pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data,
224             gcry_mpi_t * skey)
225 {
226   gcry_sexp_t s_skey, s_data, s_plain;
227   int rc;
228
229   *result = NULL;
230   /* make a sexp from skey */
231   if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
232     {
233       rc = gcry_sexp_build (&s_skey, NULL,
234                             "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
235                             skey[0], skey[1], skey[2], skey[3]);
236     }
237   else if (algo == GCRY_PK_RSA)
238     {
239       rc = gcry_sexp_build (&s_skey, NULL,
240                             "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
241                             skey[0], skey[1], skey[2], skey[3], skey[4],
242                             skey[5]);
243     }
244   else
245     return GPG_ERR_PUBKEY_ALGO;
246
247   if (rc)
248     BUG ();
249
250   /* put data into a S-Exp s_data */
251   if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
252     {
253       rc = gcry_sexp_build (&s_data, NULL,
254                             "(enc-val(elg(a%m)(b%m)))", data[0], data[1]);
255     }
256   else if (algo == GCRY_PK_RSA)
257     {
258       rc = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data[0]);
259     }
260   else
261     BUG ();
262
263   if (rc)
264     BUG ();
265
266   rc = gcry_pk_decrypt (&s_plain, s_data, s_skey);
267   gcry_sexp_release (s_skey);
268   gcry_sexp_release (s_data);
269   if (rc)
270     return rc;
271
272   *result = gcry_sexp_nth_mpi (s_plain, 0, 0);
273   gcry_sexp_release (s_plain);
274   if (!*result)
275     return -1;                  /* oops */
276
277   return 0;
278 }