Editorial changes and allow building with old libgcrypts.
[gnupg.git] / g10 / pkglue.c
1 /* pkglue.c - public key operations glue code
2  *      Copyright (C) 2000, 2003, 2010 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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <assert.h>
26
27 #include "gpg.h"
28 #include "util.h"
29 #include "pkglue.h"
30 #include "main.h"
31
32 /* FIXME: Better chnage the fucntion name because mpi_ is used by
33    gcrypt macros.  */
34 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 /****************
51  * Emulate our old PK interface here - sometime in the future we might
52  * change the internal design to directly fit to libgcrypt.
53  */
54 int
55 pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey)
56 {
57   gcry_sexp_t s_sig, s_hash, s_pkey;
58   int rc;
59   const int pkalgo = map_pk_openpgp_to_gcry (algo);
60
61   /* Make a sexp from pkey.  */
62   if (pkalgo == GCRY_PK_DSA)
63     {
64       rc = gcry_sexp_build (&s_pkey, NULL,
65                             "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
66                             pkey[0], pkey[1], pkey[2], pkey[3]);
67     }
68   else if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E)
69     {
70       rc = gcry_sexp_build (&s_pkey, NULL,
71                             "(public-key(elg(p%m)(g%m)(y%m)))",
72                             pkey[0], pkey[1], pkey[2]);
73     }
74   else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_S)
75     {
76       rc = gcry_sexp_build (&s_pkey, NULL,
77                             "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
78     }
79   else if (pkalgo == GCRY_PK_ECDSA) /* Same as GCRY_PK_ECDH */
80     {
81       rc = gcry_sexp_build (&s_pkey, NULL,
82                             "(public-key(ecdsa(c%m)(q%m)))", pkey[0], pkey[1]);
83     }
84   else
85     return GPG_ERR_PUBKEY_ALGO;
86
87   if (rc)
88     BUG ();  /* gcry_sexp_build should never fail.  */
89
90   /* Put hash into a S-Exp s_hash. */
91   if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
92     BUG (); /* gcry_sexp_build should never fail.  */
93
94   /* Put data into a S-Exp s_sig. */
95   s_sig = NULL;
96   if (pkalgo == GCRY_PK_DSA)
97     {
98       if (!data[0] || !data[1])
99         rc = gpg_error (GPG_ERR_BAD_MPI);
100       else
101         rc = gcry_sexp_build (&s_sig, NULL,
102                               "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]);
103     }
104   else if (pkalgo == GCRY_PK_ECDSA)
105     {
106       if (!data[0] || !data[1])
107         rc = gpg_error (GPG_ERR_BAD_MPI);
108       else
109         rc = gcry_sexp_build (&s_sig, NULL,
110                               "(sig-val(ecdsa(r%m)(s%m)))", data[0], data[1]);
111     }
112   else if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E)
113     {
114       if (!data[0] || !data[1])
115         rc = gpg_error (GPG_ERR_BAD_MPI);
116       else
117         rc = gcry_sexp_build (&s_sig, NULL,
118                               "(sig-val(elg(r%m)(s%m)))", data[0], data[1]);
119     }
120   else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_S)
121     {
122       if (!data[0])
123         rc = gpg_error (GPG_ERR_BAD_MPI);
124       else
125         rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", data[0]);
126     }
127   else
128     BUG ();
129
130   if (!rc)
131     rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
132
133   gcry_sexp_release (s_sig);
134   gcry_sexp_release (s_hash);
135   gcry_sexp_release (s_pkey);
136   return rc;
137 }
138
139
140
141
142 /****************
143  * Emulate our old PK interface here - sometime in the future we might
144  * change the internal design to directly fit to libgcrypt.
145  */
146 int
147 pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
148             const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *pkey)
149 {
150   gcry_sexp_t s_ciph, s_data, s_pkey;
151   int rc;
152
153   /* Make a sexp from pkey.  */
154   if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
155     {
156       rc = gcry_sexp_build (&s_pkey, NULL,
157                             "(public-key(elg(p%m)(g%m)(y%m)))",
158                             pkey[0], pkey[1], pkey[2]);
159     }
160   else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_E)
161     {
162       rc = gcry_sexp_build (&s_pkey, NULL,
163                             "(public-key(rsa(n%m)(e%m)))",
164                             pkey[0], pkey[1]);
165     }
166   else if (algo == PUBKEY_ALGO_ECDH)    
167     {
168       return pk_ecdh_encrypt (resarr, pk_fp, data, pkey);
169     }
170   else
171     return GPG_ERR_PUBKEY_ALGO;
172
173   if (rc)
174     BUG ();
175
176   /* Put the data into a simple list.  */
177   if (gcry_sexp_build (&s_data, NULL, "%m", data))
178     BUG ();
179
180   /* Pass it to libgcrypt. */
181   rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
182   gcry_sexp_release (s_data);
183   gcry_sexp_release (s_pkey);
184
185   if (rc)
186     ;
187   else
188     { /* Add better error handling or make gnupg use S-Exp directly.  */
189       resarr[0] = mpi_from_sexp (s_ciph, "a");
190       if (algo != GCRY_PK_RSA 
191           && algo != GCRY_PK_RSA_E
192           && algo != PUBKEY_ALGO_ECDH)
193         resarr[1] = mpi_from_sexp (s_ciph, "b");
194     }
195
196   gcry_sexp_release (s_ciph);
197   return rc;
198 }
199
200
201 /* Check whether SKEY is a suitable secret key. */
202 int
203 pk_check_secret_key (int algo, gcry_mpi_t *skey)
204 {
205   gcry_sexp_t s_skey;
206   int rc;
207   const int gcry_pkalgo = map_pk_openpgp_to_gcry( algo );
208
209   if (gcry_pkalgo == GCRY_PK_DSA)
210     {
211       rc = gcry_sexp_build (&s_skey, NULL,
212                             "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
213                             skey[0], skey[1], skey[2], skey[3], skey[4]);
214     }
215   else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E)
216     {
217       rc = gcry_sexp_build (&s_skey, NULL,
218                             "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
219                             skey[0], skey[1], skey[2], skey[3]);
220     }
221   else if (gcry_pkalgo == GCRY_PK_RSA
222            || gcry_pkalgo == GCRY_PK_RSA_S || gcry_pkalgo == GCRY_PK_RSA_E)
223     {
224       rc = gcry_sexp_build (&s_skey, NULL,
225                             "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
226                             skey[0], skey[1], skey[2], skey[3], skey[4],
227                             skey[5]);
228     }
229   else if (gcry_pkalgo == GCRY_PK_ECDSA || gcry_pkalgo == GCRY_PK_ECDH)
230     {
231       rc = gcry_sexp_build (&s_skey, NULL,
232                             "(private-key(ecdsa(c%m)(q%m)(d%m)))",
233                             skey[0], skey[1], skey[2] );
234     }
235   else
236     return GPG_ERR_PUBKEY_ALGO;
237
238   if (!rc)
239     {
240       rc = gcry_pk_testkey (s_skey);
241       gcry_sexp_release (s_skey);
242     }
243   return rc;
244 }