diff options
Diffstat (limited to 'linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/pubkey.c')
-rw-r--r--[-rwxr-xr-x] | linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/pubkey.c | 4720 |
1 files changed, 2360 insertions, 2360 deletions
diff --git a/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/pubkey.c b/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/pubkey.c index 4bed8a5..35ac8f2 100755..100644 --- a/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/pubkey.c +++ b/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/pubkey.c | |||
@@ -1,2360 +1,2360 @@ | |||
1 | /* pubkey.c - pubkey dispatcher | 1 | /* pubkey.c - pubkey dispatcher |
2 | * Copyright (C) 1998,1999,2000,2002,2003 Free Software Foundation, Inc. | 2 | * Copyright (C) 1998,1999,2000,2002,2003 Free Software Foundation, Inc. |
3 | * | 3 | * |
4 | * This file is part of Libgcrypt. | 4 | * This file is part of Libgcrypt. |
5 | * | 5 | * |
6 | * Libgcrypt is free software; you can redistribute it and/or modify | 6 | * Libgcrypt is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU Lesser general Public License as | 7 | * it under the terms of the GNU Lesser general Public License as |
8 | * published by the Free Software Foundation; either version 2.1 of | 8 | * published by the Free Software Foundation; either version 2.1 of |
9 | * the License, or (at your option) any later version. | 9 | * the License, or (at your option) any later version. |
10 | * | 10 | * |
11 | * Libgcrypt is distributed in the hope that it will be useful, | 11 | * Libgcrypt is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU Lesser General Public License for more details. | 14 | * GNU Lesser General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU Lesser General Public | 16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with this program; if not, write to the Free Software | 17 | * License along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <config.h> | 21 | #include <config.h> |
22 | #include <stdio.h> | 22 | #include <stdio.h> |
23 | #include <stdlib.h> | 23 | #include <stdlib.h> |
24 | #include <string.h> | 24 | #include <string.h> |
25 | #include <errno.h> | 25 | #include <errno.h> |
26 | #include <assert.h> | 26 | #include <assert.h> |
27 | 27 | ||
28 | #include "g10lib.h" | 28 | #include "g10lib.h" |
29 | #include "mpi.h" | 29 | #include "mpi.h" |
30 | #include "cipher.h" | 30 | #include "cipher.h" |
31 | #include "ath.h" | 31 | #include "ath.h" |
32 | 32 | ||
33 | static gcry_err_code_t pubkey_decrypt (int algo, gcry_mpi_t *result, | 33 | static gcry_err_code_t pubkey_decrypt (int algo, gcry_mpi_t *result, |
34 | gcry_mpi_t *data, gcry_mpi_t *skey, | 34 | gcry_mpi_t *data, gcry_mpi_t *skey, |
35 | int flags); | 35 | int flags); |
36 | static gcry_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr, | 36 | static gcry_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr, |
37 | gcry_mpi_t hash, gcry_mpi_t *skey); | 37 | gcry_mpi_t hash, gcry_mpi_t *skey); |
38 | static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash, | 38 | static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash, |
39 | gcry_mpi_t *data, gcry_mpi_t *pkey, | 39 | gcry_mpi_t *data, gcry_mpi_t *pkey, |
40 | int (*cmp) (void *, gcry_mpi_t), | 40 | int (*cmp) (void *, gcry_mpi_t), |
41 | void *opaque); | 41 | void *opaque); |
42 | 42 | ||
43 | /* This is the list of the default public-key ciphers included in | 43 | /* This is the list of the default public-key ciphers included in |
44 | libgcrypt. */ | 44 | libgcrypt. */ |
45 | static struct pubkey_table_entry | 45 | static struct pubkey_table_entry |
46 | { | 46 | { |
47 | gcry_pk_spec_t *pubkey; | 47 | gcry_pk_spec_t *pubkey; |
48 | unsigned int algorithm; | 48 | unsigned int algorithm; |
49 | } pubkey_table[] = | 49 | } pubkey_table[] = |
50 | { | 50 | { |
51 | #if USE_RSA | 51 | #if USE_RSA |
52 | { &_gcry_pubkey_spec_rsa, GCRY_PK_RSA }, | 52 | { &_gcry_pubkey_spec_rsa, GCRY_PK_RSA }, |
53 | #endif | 53 | #endif |
54 | #if USE_ELGAMAL | 54 | #if USE_ELGAMAL |
55 | { &_gcry_pubkey_spec_elg, GCRY_PK_ELG }, | 55 | { &_gcry_pubkey_spec_elg, GCRY_PK_ELG }, |
56 | { &_gcry_pubkey_spec_elg, GCRY_PK_ELG_E }, | 56 | { &_gcry_pubkey_spec_elg, GCRY_PK_ELG_E }, |
57 | #endif | 57 | #endif |
58 | #if USE_DSA | 58 | #if USE_DSA |
59 | { &_gcry_pubkey_spec_dsa, GCRY_PK_DSA }, | 59 | { &_gcry_pubkey_spec_dsa, GCRY_PK_DSA }, |
60 | #endif | 60 | #endif |
61 | { NULL, 0 }, | 61 | { NULL, 0 }, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | /* List of registered ciphers. */ | 64 | /* List of registered ciphers. */ |
65 | static gcry_module_t pubkeys_registered; | 65 | static gcry_module_t pubkeys_registered; |
66 | 66 | ||
67 | /* This is the lock protecting PUBKEYS_REGISTERED. */ | 67 | /* This is the lock protecting PUBKEYS_REGISTERED. */ |
68 | static ath_mutex_t pubkeys_registered_lock; | 68 | static ath_mutex_t pubkeys_registered_lock; |
69 | 69 | ||
70 | /* Flag to check wether the default pubkeys have already been | 70 | /* Flag to check wether the default pubkeys have already been |
71 | registered. */ | 71 | registered. */ |
72 | static int default_pubkeys_registered; | 72 | static int default_pubkeys_registered; |
73 | 73 | ||
74 | /* Convenient macro for registering the default digests. */ | 74 | /* Convenient macro for registering the default digests. */ |
75 | #define REGISTER_DEFAULT_PUBKEYS \ | 75 | #define REGISTER_DEFAULT_PUBKEYS \ |
76 | do \ | 76 | do \ |
77 | { \ | 77 | { \ |
78 | ath_mutex_lock (&pubkeys_registered_lock); \ | 78 | ath_mutex_lock (&pubkeys_registered_lock); \ |
79 | if (! default_pubkeys_registered) \ | 79 | if (! default_pubkeys_registered) \ |
80 | { \ | 80 | { \ |
81 | gcry_pk_register_default (); \ | 81 | gcry_pk_register_default (); \ |
82 | default_pubkeys_registered = 1; \ | 82 | default_pubkeys_registered = 1; \ |
83 | } \ | 83 | } \ |
84 | ath_mutex_unlock (&pubkeys_registered_lock); \ | 84 | ath_mutex_unlock (&pubkeys_registered_lock); \ |
85 | } \ | 85 | } \ |
86 | while (0) | 86 | while (0) |
87 | 87 | ||
88 | /* These dummy functions are used in case a cipher implementation | 88 | /* These dummy functions are used in case a cipher implementation |
89 | refuses to provide it's own functions. */ | 89 | refuses to provide it's own functions. */ |
90 | 90 | ||
91 | static gcry_err_code_t | 91 | static gcry_err_code_t |
92 | dummy_generate (int algorithm, unsigned int nbits, unsigned long dummy, | 92 | dummy_generate (int algorithm, unsigned int nbits, unsigned long dummy, |
93 | gcry_mpi_t *skey, gcry_mpi_t **retfactors) | 93 | gcry_mpi_t *skey, gcry_mpi_t **retfactors) |
94 | { | 94 | { |
95 | log_bug ("no generate() for %d\n", algorithm); | 95 | log_bug ("no generate() for %d\n", algorithm); |
96 | return GPG_ERR_PUBKEY_ALGO; | 96 | return GPG_ERR_PUBKEY_ALGO; |
97 | } | 97 | } |
98 | 98 | ||
99 | static gcry_err_code_t | 99 | static gcry_err_code_t |
100 | dummy_check_secret_key (int algorithm, gcry_mpi_t *skey) | 100 | dummy_check_secret_key (int algorithm, gcry_mpi_t *skey) |
101 | { | 101 | { |
102 | log_bug ("no check_secret_key() for %d\n", algorithm); | 102 | log_bug ("no check_secret_key() for %d\n", algorithm); |
103 | return GPG_ERR_PUBKEY_ALGO; | 103 | return GPG_ERR_PUBKEY_ALGO; |
104 | } | 104 | } |
105 | 105 | ||
106 | static gcry_err_code_t | 106 | static gcry_err_code_t |
107 | dummy_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, | 107 | dummy_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, |
108 | gcry_mpi_t *pkey, int flags) | 108 | gcry_mpi_t *pkey, int flags) |
109 | { | 109 | { |
110 | log_bug ("no encrypt() for %d\n", algorithm); | 110 | log_bug ("no encrypt() for %d\n", algorithm); |
111 | return GPG_ERR_PUBKEY_ALGO; | 111 | return GPG_ERR_PUBKEY_ALGO; |
112 | } | 112 | } |
113 | 113 | ||
114 | static gcry_err_code_t | 114 | static gcry_err_code_t |
115 | dummy_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, | 115 | dummy_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, |
116 | gcry_mpi_t *skey, int flags) | 116 | gcry_mpi_t *skey, int flags) |
117 | { | 117 | { |
118 | log_bug ("no decrypt() for %d\n", algorithm); | 118 | log_bug ("no decrypt() for %d\n", algorithm); |
119 | return GPG_ERR_PUBKEY_ALGO; | 119 | return GPG_ERR_PUBKEY_ALGO; |
120 | } | 120 | } |
121 | 121 | ||
122 | static gcry_err_code_t | 122 | static gcry_err_code_t |
123 | dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, | 123 | dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, |
124 | gcry_mpi_t *skey) | 124 | gcry_mpi_t *skey) |
125 | { | 125 | { |
126 | log_bug ("no sign() for %d\n", algorithm); | 126 | log_bug ("no sign() for %d\n", algorithm); |
127 | return GPG_ERR_PUBKEY_ALGO; | 127 | return GPG_ERR_PUBKEY_ALGO; |
128 | } | 128 | } |
129 | 129 | ||
130 | static gcry_err_code_t | 130 | static gcry_err_code_t |
131 | dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, | 131 | dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, |
132 | gcry_mpi_t *pkey, | 132 | gcry_mpi_t *pkey, |
133 | int (*cmp) (void *, gcry_mpi_t), void *opaquev) | 133 | int (*cmp) (void *, gcry_mpi_t), void *opaquev) |
134 | { | 134 | { |
135 | log_bug ("no verify() for %d\n", algorithm); | 135 | log_bug ("no verify() for %d\n", algorithm); |
136 | return GPG_ERR_PUBKEY_ALGO; | 136 | return GPG_ERR_PUBKEY_ALGO; |
137 | } | 137 | } |
138 | 138 | ||
139 | static unsigned | 139 | static unsigned |
140 | dummy_get_nbits (int algorithm, gcry_mpi_t *pkey) | 140 | dummy_get_nbits (int algorithm, gcry_mpi_t *pkey) |
141 | { | 141 | { |
142 | log_bug ("no get_nbits() for %d\n", algorithm); | 142 | log_bug ("no get_nbits() for %d\n", algorithm); |
143 | return 0; | 143 | return 0; |
144 | } | 144 | } |
145 | 145 | ||
146 | /* Internal function. Register all the pubkeys included in | 146 | /* Internal function. Register all the pubkeys included in |
147 | PUBKEY_TABLE. Returns zero on success or an error code. */ | 147 | PUBKEY_TABLE. Returns zero on success or an error code. */ |
148 | static void | 148 | static void |
149 | gcry_pk_register_default (void) | 149 | gcry_pk_register_default (void) |
150 | { | 150 | { |
151 | gcry_err_code_t err = 0; | 151 | gcry_err_code_t err = 0; |
152 | int i; | 152 | int i; |
153 | 153 | ||
154 | for (i = 0; (! err) && pubkey_table[i].pubkey; i++) | 154 | for (i = 0; (! err) && pubkey_table[i].pubkey; i++) |
155 | { | 155 | { |
156 | #define pubkey_use_dummy(func) \ | 156 | #define pubkey_use_dummy(func) \ |
157 | if (! pubkey_table[i].pubkey->func) \ | 157 | if (! pubkey_table[i].pubkey->func) \ |
158 | pubkey_table[i].pubkey->func = dummy_##func; | 158 | pubkey_table[i].pubkey->func = dummy_##func; |
159 | 159 | ||
160 | pubkey_use_dummy (generate); | 160 | pubkey_use_dummy (generate); |
161 | pubkey_use_dummy (check_secret_key); | 161 | pubkey_use_dummy (check_secret_key); |
162 | pubkey_use_dummy (encrypt); | 162 | pubkey_use_dummy (encrypt); |
163 | pubkey_use_dummy (decrypt); | 163 | pubkey_use_dummy (decrypt); |
164 | pubkey_use_dummy (sign); | 164 | pubkey_use_dummy (sign); |
165 | pubkey_use_dummy (verify); | 165 | pubkey_use_dummy (verify); |
166 | pubkey_use_dummy (get_nbits); | 166 | pubkey_use_dummy (get_nbits); |
167 | #undef pubkey_use_dummy | 167 | #undef pubkey_use_dummy |
168 | err = _gcry_module_add (&pubkeys_registered, | 168 | err = _gcry_module_add (&pubkeys_registered, |
169 | pubkey_table[i].algorithm, | 169 | pubkey_table[i].algorithm, |
170 | (void *) pubkey_table[i].pubkey, NULL); | 170 | (void *) pubkey_table[i].pubkey, NULL); |
171 | } | 171 | } |
172 | 172 | ||
173 | if (err) | 173 | if (err) |
174 | BUG (); | 174 | BUG (); |
175 | } | 175 | } |
176 | 176 | ||
177 | /* Internal callback function. Used via _gcry_module_lookup. */ | 177 | /* Internal callback function. Used via _gcry_module_lookup. */ |
178 | static int | 178 | static int |
179 | gcry_pk_lookup_func_name (void *spec, void *data) | 179 | gcry_pk_lookup_func_name (void *spec, void *data) |
180 | { | 180 | { |
181 | gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) spec; | 181 | gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) spec; |
182 | char *name = (char *) data; | 182 | char *name = (char *) data; |
183 | char **aliases = pubkey->aliases; | 183 | char **aliases = pubkey->aliases; |
184 | int ret = stricmp (name, pubkey->name); | 184 | int ret = stricmp (name, pubkey->name); |
185 | 185 | ||
186 | while (ret && *aliases) | 186 | while (ret && *aliases) |
187 | ret = stricmp (name, *aliases++); | 187 | ret = stricmp (name, *aliases++); |
188 | 188 | ||
189 | return ! ret; | 189 | return ! ret; |
190 | } | 190 | } |
191 | 191 | ||
192 | /* Internal function. Lookup a pubkey entry by it's name. */ | 192 | /* Internal function. Lookup a pubkey entry by it's name. */ |
193 | static gcry_module_t | 193 | static gcry_module_t |
194 | gcry_pk_lookup_name (const char *name) | 194 | gcry_pk_lookup_name (const char *name) |
195 | { | 195 | { |
196 | gcry_module_t pubkey; | 196 | gcry_module_t pubkey; |
197 | 197 | ||
198 | pubkey = _gcry_module_lookup (pubkeys_registered, (void *) name, | 198 | pubkey = _gcry_module_lookup (pubkeys_registered, (void *) name, |
199 | gcry_pk_lookup_func_name); | 199 | gcry_pk_lookup_func_name); |
200 | 200 | ||
201 | return pubkey; | 201 | return pubkey; |
202 | } | 202 | } |
203 | 203 | ||
204 | /* Register a new pubkey module whose specification can be found in | 204 | /* Register a new pubkey module whose specification can be found in |
205 | PUBKEY. On success, a new algorithm ID is stored in ALGORITHM_ID | 205 | PUBKEY. On success, a new algorithm ID is stored in ALGORITHM_ID |
206 | and a pointer representhing this module is stored in MODULE. */ | 206 | and a pointer representhing this module is stored in MODULE. */ |
207 | gcry_error_t | 207 | gcry_error_t |
208 | gcry_pk_register (gcry_pk_spec_t *pubkey, | 208 | gcry_pk_register (gcry_pk_spec_t *pubkey, |
209 | unsigned int *algorithm_id, | 209 | unsigned int *algorithm_id, |
210 | gcry_module_t *module) | 210 | gcry_module_t *module) |
211 | { | 211 | { |
212 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 212 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
213 | gcry_module_t mod; | 213 | gcry_module_t mod; |
214 | 214 | ||
215 | ath_mutex_lock (&pubkeys_registered_lock); | 215 | ath_mutex_lock (&pubkeys_registered_lock); |
216 | err = _gcry_module_add (&pubkeys_registered, 0, | 216 | err = _gcry_module_add (&pubkeys_registered, 0, |
217 | (void *) pubkey, &mod); | 217 | (void *) pubkey, &mod); |
218 | ath_mutex_unlock (&pubkeys_registered_lock); | 218 | ath_mutex_unlock (&pubkeys_registered_lock); |
219 | 219 | ||
220 | if (! err) | 220 | if (! err) |
221 | { | 221 | { |
222 | *module = mod; | 222 | *module = mod; |
223 | *algorithm_id = mod->mod_id; | 223 | *algorithm_id = mod->mod_id; |
224 | } | 224 | } |
225 | 225 | ||
226 | return err; | 226 | return err; |
227 | } | 227 | } |
228 | 228 | ||
229 | /* Unregister the pubkey identified by ID, which must have been | 229 | /* Unregister the pubkey identified by ID, which must have been |
230 | registered with gcry_pk_register. */ | 230 | registered with gcry_pk_register. */ |
231 | void | 231 | void |
232 | gcry_pk_unregister (gcry_module_t module) | 232 | gcry_pk_unregister (gcry_module_t module) |
233 | { | 233 | { |
234 | ath_mutex_lock (&pubkeys_registered_lock); | 234 | ath_mutex_lock (&pubkeys_registered_lock); |
235 | _gcry_module_release (module); | 235 | _gcry_module_release (module); |
236 | ath_mutex_unlock (&pubkeys_registered_lock); | 236 | ath_mutex_unlock (&pubkeys_registered_lock); |
237 | } | 237 | } |
238 | 238 | ||
239 | static void | 239 | static void |
240 | release_mpi_array (gcry_mpi_t *array) | 240 | release_mpi_array (gcry_mpi_t *array) |
241 | { | 241 | { |
242 | for (; *array; array++) | 242 | for (; *array; array++) |
243 | { | 243 | { |
244 | mpi_free(*array); | 244 | mpi_free(*array); |
245 | *array = NULL; | 245 | *array = NULL; |
246 | } | 246 | } |
247 | } | 247 | } |
248 | 248 | ||
249 | /**************** | 249 | /**************** |
250 | * Map a string to the pubkey algo | 250 | * Map a string to the pubkey algo |
251 | */ | 251 | */ |
252 | int | 252 | int |
253 | gcry_pk_map_name (const char *string) | 253 | gcry_pk_map_name (const char *string) |
254 | { | 254 | { |
255 | gcry_module_t pubkey; | 255 | gcry_module_t pubkey; |
256 | int algorithm = 0; | 256 | int algorithm = 0; |
257 | 257 | ||
258 | if (!string) | 258 | if (!string) |
259 | return 0; | 259 | return 0; |
260 | 260 | ||
261 | REGISTER_DEFAULT_PUBKEYS; | 261 | REGISTER_DEFAULT_PUBKEYS; |
262 | 262 | ||
263 | ath_mutex_lock (&pubkeys_registered_lock); | 263 | ath_mutex_lock (&pubkeys_registered_lock); |
264 | pubkey = gcry_pk_lookup_name (string); | 264 | pubkey = gcry_pk_lookup_name (string); |
265 | if (pubkey) | 265 | if (pubkey) |
266 | { | 266 | { |
267 | algorithm = pubkey->mod_id; | 267 | algorithm = pubkey->mod_id; |
268 | _gcry_module_release (pubkey); | 268 | _gcry_module_release (pubkey); |
269 | } | 269 | } |
270 | ath_mutex_unlock (&pubkeys_registered_lock); | 270 | ath_mutex_unlock (&pubkeys_registered_lock); |
271 | 271 | ||
272 | return algorithm; | 272 | return algorithm; |
273 | } | 273 | } |
274 | 274 | ||
275 | 275 | ||
276 | /**************** | 276 | /**************** |
277 | * Map a pubkey algo to a string | 277 | * Map a pubkey algo to a string |
278 | */ | 278 | */ |
279 | const char * | 279 | const char * |
280 | gcry_pk_algo_name (int algorithm) | 280 | gcry_pk_algo_name (int algorithm) |
281 | { | 281 | { |
282 | const char *name = NULL; | 282 | const char *name = NULL; |
283 | gcry_module_t pubkey; | 283 | gcry_module_t pubkey; |
284 | 284 | ||
285 | REGISTER_DEFAULT_PUBKEYS; | 285 | REGISTER_DEFAULT_PUBKEYS; |
286 | 286 | ||
287 | ath_mutex_lock (&pubkeys_registered_lock); | 287 | ath_mutex_lock (&pubkeys_registered_lock); |
288 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 288 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
289 | if (pubkey) | 289 | if (pubkey) |
290 | { | 290 | { |
291 | name = ((gcry_pk_spec_t *) pubkey->spec)->name; | 291 | name = ((gcry_pk_spec_t *) pubkey->spec)->name; |
292 | _gcry_module_release (pubkey); | 292 | _gcry_module_release (pubkey); |
293 | } | 293 | } |
294 | ath_mutex_unlock (&pubkeys_registered_lock); | 294 | ath_mutex_unlock (&pubkeys_registered_lock); |
295 | 295 | ||
296 | return name; | 296 | return name; |
297 | } | 297 | } |
298 | 298 | ||
299 | 299 | ||
300 | /* A special version of gcry_pk_algo name to return the first aliased | 300 | /* A special version of gcry_pk_algo name to return the first aliased |
301 | name of the algorithm. This is required to adhere to the spki | 301 | name of the algorithm. This is required to adhere to the spki |
302 | specs where the algorithm names are lowercase. */ | 302 | specs where the algorithm names are lowercase. */ |
303 | const char * | 303 | const char * |
304 | _gcry_pk_aliased_algo_name (int algorithm) | 304 | _gcry_pk_aliased_algo_name (int algorithm) |
305 | { | 305 | { |
306 | const char *name = NULL; | 306 | const char *name = NULL; |
307 | gcry_module_t module; | 307 | gcry_module_t module; |
308 | 308 | ||
309 | REGISTER_DEFAULT_PUBKEYS; | 309 | REGISTER_DEFAULT_PUBKEYS; |
310 | 310 | ||
311 | ath_mutex_lock (&pubkeys_registered_lock); | 311 | ath_mutex_lock (&pubkeys_registered_lock); |
312 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 312 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
313 | if (module) | 313 | if (module) |
314 | { | 314 | { |
315 | gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) module->spec; | 315 | gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) module->spec; |
316 | 316 | ||
317 | name = pubkey->aliases? *pubkey->aliases : NULL; | 317 | name = pubkey->aliases? *pubkey->aliases : NULL; |
318 | if (!name || !*name) | 318 | if (!name || !*name) |
319 | name = pubkey->name; | 319 | name = pubkey->name; |
320 | _gcry_module_release (module); | 320 | _gcry_module_release (module); |
321 | } | 321 | } |
322 | ath_mutex_unlock (&pubkeys_registered_lock); | 322 | ath_mutex_unlock (&pubkeys_registered_lock); |
323 | 323 | ||
324 | return name; | 324 | return name; |
325 | } | 325 | } |
326 | 326 | ||
327 | 327 | ||
328 | static void | 328 | static void |
329 | disable_pubkey_algo (int algorithm) | 329 | disable_pubkey_algo (int algorithm) |
330 | { | 330 | { |
331 | gcry_module_t pubkey; | 331 | gcry_module_t pubkey; |
332 | 332 | ||
333 | ath_mutex_lock (&pubkeys_registered_lock); | 333 | ath_mutex_lock (&pubkeys_registered_lock); |
334 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 334 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
335 | if (pubkey) | 335 | if (pubkey) |
336 | { | 336 | { |
337 | if (! (pubkey-> flags & FLAG_MODULE_DISABLED)) | 337 | if (! (pubkey-> flags & FLAG_MODULE_DISABLED)) |
338 | pubkey->flags |= FLAG_MODULE_DISABLED; | 338 | pubkey->flags |= FLAG_MODULE_DISABLED; |
339 | _gcry_module_release (pubkey); | 339 | _gcry_module_release (pubkey); |
340 | } | 340 | } |
341 | ath_mutex_unlock (&pubkeys_registered_lock); | 341 | ath_mutex_unlock (&pubkeys_registered_lock); |
342 | } | 342 | } |
343 | 343 | ||
344 | 344 | ||
345 | /**************** | 345 | /**************** |
346 | * A USE of 0 means: don't care. | 346 | * A USE of 0 means: don't care. |
347 | */ | 347 | */ |
348 | static gcry_err_code_t | 348 | static gcry_err_code_t |
349 | check_pubkey_algo (int algorithm, unsigned use) | 349 | check_pubkey_algo (int algorithm, unsigned use) |
350 | { | 350 | { |
351 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 351 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
352 | gcry_pk_spec_t *pubkey; | 352 | gcry_pk_spec_t *pubkey; |
353 | gcry_module_t module; | 353 | gcry_module_t module; |
354 | 354 | ||
355 | REGISTER_DEFAULT_PUBKEYS; | 355 | REGISTER_DEFAULT_PUBKEYS; |
356 | 356 | ||
357 | ath_mutex_lock (&pubkeys_registered_lock); | 357 | ath_mutex_lock (&pubkeys_registered_lock); |
358 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 358 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
359 | if (module) | 359 | if (module) |
360 | { | 360 | { |
361 | pubkey = (gcry_pk_spec_t *) module->spec; | 361 | pubkey = (gcry_pk_spec_t *) module->spec; |
362 | 362 | ||
363 | if (((use & GCRY_PK_USAGE_SIGN) | 363 | if (((use & GCRY_PK_USAGE_SIGN) |
364 | && (! (pubkey->use & GCRY_PK_USAGE_SIGN))) | 364 | && (! (pubkey->use & GCRY_PK_USAGE_SIGN))) |
365 | || ((use & GCRY_PK_USAGE_ENCR) | 365 | || ((use & GCRY_PK_USAGE_ENCR) |
366 | && (! (pubkey->use & GCRY_PK_USAGE_ENCR)))) | 366 | && (! (pubkey->use & GCRY_PK_USAGE_ENCR)))) |
367 | err = GPG_ERR_WRONG_PUBKEY_ALGO; | 367 | err = GPG_ERR_WRONG_PUBKEY_ALGO; |
368 | else if (module->flags & FLAG_MODULE_DISABLED) | 368 | else if (module->flags & FLAG_MODULE_DISABLED) |
369 | err = GPG_ERR_PUBKEY_ALGO; | 369 | err = GPG_ERR_PUBKEY_ALGO; |
370 | _gcry_module_release (module); | 370 | _gcry_module_release (module); |
371 | } | 371 | } |
372 | else | 372 | else |
373 | err = GPG_ERR_PUBKEY_ALGO; | 373 | err = GPG_ERR_PUBKEY_ALGO; |
374 | ath_mutex_unlock (&pubkeys_registered_lock); | 374 | ath_mutex_unlock (&pubkeys_registered_lock); |
375 | 375 | ||
376 | return err; | 376 | return err; |
377 | } | 377 | } |
378 | 378 | ||
379 | 379 | ||
380 | /**************** | 380 | /**************** |
381 | * Return the number of public key material numbers | 381 | * Return the number of public key material numbers |
382 | */ | 382 | */ |
383 | static int | 383 | static int |
384 | pubkey_get_npkey (int algorithm) | 384 | pubkey_get_npkey (int algorithm) |
385 | { | 385 | { |
386 | gcry_module_t pubkey; | 386 | gcry_module_t pubkey; |
387 | int npkey = 0; | 387 | int npkey = 0; |
388 | 388 | ||
389 | REGISTER_DEFAULT_PUBKEYS; | 389 | REGISTER_DEFAULT_PUBKEYS; |
390 | 390 | ||
391 | ath_mutex_lock (&pubkeys_registered_lock); | 391 | ath_mutex_lock (&pubkeys_registered_lock); |
392 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 392 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
393 | if (pubkey) | 393 | if (pubkey) |
394 | { | 394 | { |
395 | npkey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_pkey); | 395 | npkey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_pkey); |
396 | _gcry_module_release (pubkey); | 396 | _gcry_module_release (pubkey); |
397 | } | 397 | } |
398 | ath_mutex_unlock (&pubkeys_registered_lock); | 398 | ath_mutex_unlock (&pubkeys_registered_lock); |
399 | 399 | ||
400 | return npkey; | 400 | return npkey; |
401 | } | 401 | } |
402 | 402 | ||
403 | /**************** | 403 | /**************** |
404 | * Return the number of secret key material numbers | 404 | * Return the number of secret key material numbers |
405 | */ | 405 | */ |
406 | static int | 406 | static int |
407 | pubkey_get_nskey (int algorithm) | 407 | pubkey_get_nskey (int algorithm) |
408 | { | 408 | { |
409 | gcry_module_t pubkey; | 409 | gcry_module_t pubkey; |
410 | int nskey = 0; | 410 | int nskey = 0; |
411 | 411 | ||
412 | REGISTER_DEFAULT_PUBKEYS; | 412 | REGISTER_DEFAULT_PUBKEYS; |
413 | 413 | ||
414 | ath_mutex_lock (&pubkeys_registered_lock); | 414 | ath_mutex_lock (&pubkeys_registered_lock); |
415 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 415 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
416 | if (pubkey) | 416 | if (pubkey) |
417 | { | 417 | { |
418 | nskey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_skey); | 418 | nskey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_skey); |
419 | _gcry_module_release (pubkey); | 419 | _gcry_module_release (pubkey); |
420 | } | 420 | } |
421 | ath_mutex_unlock (&pubkeys_registered_lock); | 421 | ath_mutex_unlock (&pubkeys_registered_lock); |
422 | 422 | ||
423 | return nskey; | 423 | return nskey; |
424 | } | 424 | } |
425 | 425 | ||
426 | /**************** | 426 | /**************** |
427 | * Return the number of signature material numbers | 427 | * Return the number of signature material numbers |
428 | */ | 428 | */ |
429 | static int | 429 | static int |
430 | pubkey_get_nsig (int algorithm) | 430 | pubkey_get_nsig (int algorithm) |
431 | { | 431 | { |
432 | gcry_module_t pubkey; | 432 | gcry_module_t pubkey; |
433 | int nsig = 0; | 433 | int nsig = 0; |
434 | 434 | ||
435 | REGISTER_DEFAULT_PUBKEYS; | 435 | REGISTER_DEFAULT_PUBKEYS; |
436 | 436 | ||
437 | ath_mutex_lock (&pubkeys_registered_lock); | 437 | ath_mutex_lock (&pubkeys_registered_lock); |
438 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 438 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
439 | if (pubkey) | 439 | if (pubkey) |
440 | { | 440 | { |
441 | nsig = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_sig); | 441 | nsig = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_sig); |
442 | _gcry_module_release (pubkey); | 442 | _gcry_module_release (pubkey); |
443 | } | 443 | } |
444 | ath_mutex_unlock (&pubkeys_registered_lock); | 444 | ath_mutex_unlock (&pubkeys_registered_lock); |
445 | 445 | ||
446 | return nsig; | 446 | return nsig; |
447 | } | 447 | } |
448 | 448 | ||
449 | /**************** | 449 | /**************** |
450 | * Return the number of encryption material numbers | 450 | * Return the number of encryption material numbers |
451 | */ | 451 | */ |
452 | static int | 452 | static int |
453 | pubkey_get_nenc (int algorithm) | 453 | pubkey_get_nenc (int algorithm) |
454 | { | 454 | { |
455 | gcry_module_t pubkey; | 455 | gcry_module_t pubkey; |
456 | int nenc = 0; | 456 | int nenc = 0; |
457 | 457 | ||
458 | REGISTER_DEFAULT_PUBKEYS; | 458 | REGISTER_DEFAULT_PUBKEYS; |
459 | 459 | ||
460 | ath_mutex_lock (&pubkeys_registered_lock); | 460 | ath_mutex_lock (&pubkeys_registered_lock); |
461 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 461 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
462 | if (pubkey) | 462 | if (pubkey) |
463 | { | 463 | { |
464 | nenc = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_enc); | 464 | nenc = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_enc); |
465 | _gcry_module_release (pubkey); | 465 | _gcry_module_release (pubkey); |
466 | } | 466 | } |
467 | ath_mutex_unlock (&pubkeys_registered_lock); | 467 | ath_mutex_unlock (&pubkeys_registered_lock); |
468 | 468 | ||
469 | return nenc; | 469 | return nenc; |
470 | } | 470 | } |
471 | 471 | ||
472 | 472 | ||
473 | static gcry_err_code_t | 473 | static gcry_err_code_t |
474 | pubkey_generate (int algorithm, unsigned int nbits, unsigned long use_e, | 474 | pubkey_generate (int algorithm, unsigned int nbits, unsigned long use_e, |
475 | gcry_mpi_t *skey, gcry_mpi_t **retfactors) | 475 | gcry_mpi_t *skey, gcry_mpi_t **retfactors) |
476 | { | 476 | { |
477 | gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO; | 477 | gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO; |
478 | gcry_module_t pubkey; | 478 | gcry_module_t pubkey; |
479 | 479 | ||
480 | REGISTER_DEFAULT_PUBKEYS; | 480 | REGISTER_DEFAULT_PUBKEYS; |
481 | 481 | ||
482 | ath_mutex_lock (&pubkeys_registered_lock); | 482 | ath_mutex_lock (&pubkeys_registered_lock); |
483 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 483 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
484 | if (pubkey) | 484 | if (pubkey) |
485 | { | 485 | { |
486 | err = ((gcry_pk_spec_t *) pubkey->spec)->generate | 486 | err = ((gcry_pk_spec_t *) pubkey->spec)->generate |
487 | (algorithm, nbits, use_e, skey, retfactors); | 487 | (algorithm, nbits, use_e, skey, retfactors); |
488 | _gcry_module_release (pubkey); | 488 | _gcry_module_release (pubkey); |
489 | } | 489 | } |
490 | ath_mutex_unlock (&pubkeys_registered_lock); | 490 | ath_mutex_unlock (&pubkeys_registered_lock); |
491 | 491 | ||
492 | return err; | 492 | return err; |
493 | } | 493 | } |
494 | 494 | ||
495 | static gcry_err_code_t | 495 | static gcry_err_code_t |
496 | pubkey_check_secret_key (int algorithm, gcry_mpi_t *skey) | 496 | pubkey_check_secret_key (int algorithm, gcry_mpi_t *skey) |
497 | { | 497 | { |
498 | gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO; | 498 | gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO; |
499 | gcry_module_t pubkey; | 499 | gcry_module_t pubkey; |
500 | 500 | ||
501 | REGISTER_DEFAULT_PUBKEYS; | 501 | REGISTER_DEFAULT_PUBKEYS; |
502 | 502 | ||
503 | ath_mutex_lock (&pubkeys_registered_lock); | 503 | ath_mutex_lock (&pubkeys_registered_lock); |
504 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 504 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
505 | if (pubkey) | 505 | if (pubkey) |
506 | { | 506 | { |
507 | err = ((gcry_pk_spec_t *) pubkey->spec)->check_secret_key | 507 | err = ((gcry_pk_spec_t *) pubkey->spec)->check_secret_key |
508 | (algorithm, skey); | 508 | (algorithm, skey); |
509 | _gcry_module_release (pubkey); | 509 | _gcry_module_release (pubkey); |
510 | } | 510 | } |
511 | ath_mutex_unlock (&pubkeys_registered_lock); | 511 | ath_mutex_unlock (&pubkeys_registered_lock); |
512 | 512 | ||
513 | return err; | 513 | return err; |
514 | } | 514 | } |
515 | 515 | ||
516 | 516 | ||
517 | /**************** | 517 | /**************** |
518 | * This is the interface to the public key encryption. Encrypt DATA | 518 | * This is the interface to the public key encryption. Encrypt DATA |
519 | * with PKEY and put it into RESARR which should be an array of MPIs | 519 | * with PKEY and put it into RESARR which should be an array of MPIs |
520 | * of size PUBKEY_MAX_NENC (or less if the algorithm allows this - | 520 | * of size PUBKEY_MAX_NENC (or less if the algorithm allows this - |
521 | * check with pubkey_get_nenc() ) | 521 | * check with pubkey_get_nenc() ) |
522 | */ | 522 | */ |
523 | static gcry_err_code_t | 523 | static gcry_err_code_t |
524 | pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, | 524 | pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, |
525 | gcry_mpi_t *pkey, int flags) | 525 | gcry_mpi_t *pkey, int flags) |
526 | { | 526 | { |
527 | gcry_pk_spec_t *pubkey; | 527 | gcry_pk_spec_t *pubkey; |
528 | gcry_module_t module; | 528 | gcry_module_t module; |
529 | gcry_err_code_t rc; | 529 | gcry_err_code_t rc; |
530 | int i; | 530 | int i; |
531 | 531 | ||
532 | if (DBG_CIPHER) | 532 | if (DBG_CIPHER) |
533 | { | 533 | { |
534 | log_debug ("pubkey_encrypt: algo=%d\n", algorithm); | 534 | log_debug ("pubkey_encrypt: algo=%d\n", algorithm); |
535 | for(i = 0; i < pubkey_get_npkey (algorithm); i++) | 535 | for(i = 0; i < pubkey_get_npkey (algorithm); i++) |
536 | log_mpidump (" pkey:", pkey[i]); | 536 | log_mpidump (" pkey:", pkey[i]); |
537 | log_mpidump (" data:", data); | 537 | log_mpidump (" data:", data); |
538 | } | 538 | } |
539 | 539 | ||
540 | ath_mutex_lock (&pubkeys_registered_lock); | 540 | ath_mutex_lock (&pubkeys_registered_lock); |
541 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 541 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
542 | if (module) | 542 | if (module) |
543 | { | 543 | { |
544 | pubkey = (gcry_pk_spec_t *) module->spec; | 544 | pubkey = (gcry_pk_spec_t *) module->spec; |
545 | rc = pubkey->encrypt (algorithm, resarr, data, pkey, flags); | 545 | rc = pubkey->encrypt (algorithm, resarr, data, pkey, flags); |
546 | _gcry_module_release (module); | 546 | _gcry_module_release (module); |
547 | goto ready; | 547 | goto ready; |
548 | } | 548 | } |
549 | rc = GPG_ERR_PUBKEY_ALGO; | 549 | rc = GPG_ERR_PUBKEY_ALGO; |
550 | 550 | ||
551 | ready: | 551 | ready: |
552 | ath_mutex_unlock (&pubkeys_registered_lock); | 552 | ath_mutex_unlock (&pubkeys_registered_lock); |
553 | 553 | ||
554 | if (!rc && DBG_CIPHER) | 554 | if (!rc && DBG_CIPHER) |
555 | { | 555 | { |
556 | for(i = 0; i < pubkey_get_nenc (algorithm); i++) | 556 | for(i = 0; i < pubkey_get_nenc (algorithm); i++) |
557 | log_mpidump(" encr:", resarr[i] ); | 557 | log_mpidump(" encr:", resarr[i] ); |
558 | } | 558 | } |
559 | return rc; | 559 | return rc; |
560 | } | 560 | } |
561 | 561 | ||
562 | 562 | ||
563 | /**************** | 563 | /**************** |
564 | * This is the interface to the public key decryption. | 564 | * This is the interface to the public key decryption. |
565 | * ALGO gives the algorithm to use and this implicitly determines | 565 | * ALGO gives the algorithm to use and this implicitly determines |
566 | * the size of the arrays. | 566 | * the size of the arrays. |
567 | * result is a pointer to a mpi variable which will receive a | 567 | * result is a pointer to a mpi variable which will receive a |
568 | * newly allocated mpi or NULL in case of an error. | 568 | * newly allocated mpi or NULL in case of an error. |
569 | */ | 569 | */ |
570 | static gcry_err_code_t | 570 | static gcry_err_code_t |
571 | pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, | 571 | pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, |
572 | gcry_mpi_t *skey, int flags) | 572 | gcry_mpi_t *skey, int flags) |
573 | { | 573 | { |
574 | gcry_pk_spec_t *pubkey; | 574 | gcry_pk_spec_t *pubkey; |
575 | gcry_module_t module; | 575 | gcry_module_t module; |
576 | gcry_err_code_t rc; | 576 | gcry_err_code_t rc; |
577 | int i; | 577 | int i; |
578 | 578 | ||
579 | *result = NULL; /* so the caller can always do a mpi_free */ | 579 | *result = NULL; /* so the caller can always do a mpi_free */ |
580 | if (DBG_CIPHER) | 580 | if (DBG_CIPHER) |
581 | { | 581 | { |
582 | log_debug ("pubkey_decrypt: algo=%d\n", algorithm); | 582 | log_debug ("pubkey_decrypt: algo=%d\n", algorithm); |
583 | for(i = 0; i < pubkey_get_nskey (algorithm); i++) | 583 | for(i = 0; i < pubkey_get_nskey (algorithm); i++) |
584 | log_mpidump (" skey:", skey[i]); | 584 | log_mpidump (" skey:", skey[i]); |
585 | for(i = 0; i < pubkey_get_nenc (algorithm); i++) | 585 | for(i = 0; i < pubkey_get_nenc (algorithm); i++) |
586 | log_mpidump (" data:", data[i]); | 586 | log_mpidump (" data:", data[i]); |
587 | } | 587 | } |
588 | 588 | ||
589 | ath_mutex_lock (&pubkeys_registered_lock); | 589 | ath_mutex_lock (&pubkeys_registered_lock); |
590 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 590 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
591 | if (module) | 591 | if (module) |
592 | { | 592 | { |
593 | pubkey = (gcry_pk_spec_t *) module->spec; | 593 | pubkey = (gcry_pk_spec_t *) module->spec; |
594 | rc = pubkey->decrypt (algorithm, result, data, skey, flags); | 594 | rc = pubkey->decrypt (algorithm, result, data, skey, flags); |
595 | _gcry_module_release (module); | 595 | _gcry_module_release (module); |
596 | goto ready; | 596 | goto ready; |
597 | } | 597 | } |
598 | 598 | ||
599 | rc = GPG_ERR_PUBKEY_ALGO; | 599 | rc = GPG_ERR_PUBKEY_ALGO; |
600 | 600 | ||
601 | ready: | 601 | ready: |
602 | ath_mutex_unlock (&pubkeys_registered_lock); | 602 | ath_mutex_unlock (&pubkeys_registered_lock); |
603 | 603 | ||
604 | if (! rc && DBG_CIPHER) | 604 | if (! rc && DBG_CIPHER) |
605 | log_mpidump (" plain:", *result); | 605 | log_mpidump (" plain:", *result); |
606 | 606 | ||
607 | return rc; | 607 | return rc; |
608 | } | 608 | } |
609 | 609 | ||
610 | 610 | ||
611 | /**************** | 611 | /**************** |
612 | * This is the interface to the public key signing. | 612 | * This is the interface to the public key signing. |
613 | * Sign data with skey and put the result into resarr which | 613 | * Sign data with skey and put the result into resarr which |
614 | * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the | 614 | * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the |
615 | * algorithm allows this - check with pubkey_get_nsig() ) | 615 | * algorithm allows this - check with pubkey_get_nsig() ) |
616 | */ | 616 | */ |
617 | static gcry_err_code_t | 617 | static gcry_err_code_t |
618 | pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, | 618 | pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, |
619 | gcry_mpi_t *skey) | 619 | gcry_mpi_t *skey) |
620 | { | 620 | { |
621 | gcry_pk_spec_t *pubkey; | 621 | gcry_pk_spec_t *pubkey; |
622 | gcry_module_t module; | 622 | gcry_module_t module; |
623 | gcry_err_code_t rc; | 623 | gcry_err_code_t rc; |
624 | int i; | 624 | int i; |
625 | 625 | ||
626 | if (DBG_CIPHER) | 626 | if (DBG_CIPHER) |
627 | { | 627 | { |
628 | log_debug ("pubkey_sign: algo=%d\n", algorithm); | 628 | log_debug ("pubkey_sign: algo=%d\n", algorithm); |
629 | for(i = 0; i < pubkey_get_nskey (algorithm); i++) | 629 | for(i = 0; i < pubkey_get_nskey (algorithm); i++) |
630 | log_mpidump (" skey:", skey[i]); | 630 | log_mpidump (" skey:", skey[i]); |
631 | log_mpidump(" data:", data ); | 631 | log_mpidump(" data:", data ); |
632 | } | 632 | } |
633 | 633 | ||
634 | ath_mutex_lock (&pubkeys_registered_lock); | 634 | ath_mutex_lock (&pubkeys_registered_lock); |
635 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 635 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
636 | if (module) | 636 | if (module) |
637 | { | 637 | { |
638 | pubkey = (gcry_pk_spec_t *) module->spec; | 638 | pubkey = (gcry_pk_spec_t *) module->spec; |
639 | rc = pubkey->sign (algorithm, resarr, data, skey); | 639 | rc = pubkey->sign (algorithm, resarr, data, skey); |
640 | _gcry_module_release (module); | 640 | _gcry_module_release (module); |
641 | goto ready; | 641 | goto ready; |
642 | } | 642 | } |
643 | 643 | ||
644 | rc = GPG_ERR_PUBKEY_ALGO; | 644 | rc = GPG_ERR_PUBKEY_ALGO; |
645 | 645 | ||
646 | ready: | 646 | ready: |
647 | ath_mutex_unlock (&pubkeys_registered_lock); | 647 | ath_mutex_unlock (&pubkeys_registered_lock); |
648 | 648 | ||
649 | if (! rc && DBG_CIPHER) | 649 | if (! rc && DBG_CIPHER) |
650 | for (i = 0; i < pubkey_get_nsig (algorithm); i++) | 650 | for (i = 0; i < pubkey_get_nsig (algorithm); i++) |
651 | log_mpidump (" sig:", resarr[i]); | 651 | log_mpidump (" sig:", resarr[i]); |
652 | 652 | ||
653 | return rc; | 653 | return rc; |
654 | } | 654 | } |
655 | 655 | ||
656 | /**************** | 656 | /**************** |
657 | * Verify a public key signature. | 657 | * Verify a public key signature. |
658 | * Return 0 if the signature is good | 658 | * Return 0 if the signature is good |
659 | */ | 659 | */ |
660 | static gcry_err_code_t | 660 | static gcry_err_code_t |
661 | pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, | 661 | pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, |
662 | gcry_mpi_t *pkey, | 662 | gcry_mpi_t *pkey, |
663 | int (*cmp)(void *, gcry_mpi_t), void *opaquev) | 663 | int (*cmp)(void *, gcry_mpi_t), void *opaquev) |
664 | { | 664 | { |
665 | gcry_pk_spec_t *pubkey; | 665 | gcry_pk_spec_t *pubkey; |
666 | gcry_module_t module; | 666 | gcry_module_t module; |
667 | gcry_err_code_t rc; | 667 | gcry_err_code_t rc; |
668 | int i; | 668 | int i; |
669 | 669 | ||
670 | if (DBG_CIPHER) | 670 | if (DBG_CIPHER) |
671 | { | 671 | { |
672 | log_debug ("pubkey_verify: algo=%d\n", algorithm); | 672 | log_debug ("pubkey_verify: algo=%d\n", algorithm); |
673 | for (i = 0; i < pubkey_get_npkey (algorithm); i++) | 673 | for (i = 0; i < pubkey_get_npkey (algorithm); i++) |
674 | log_mpidump (" pkey:", pkey[i]); | 674 | log_mpidump (" pkey:", pkey[i]); |
675 | for (i = 0; i < pubkey_get_nsig (algorithm); i++) | 675 | for (i = 0; i < pubkey_get_nsig (algorithm); i++) |
676 | log_mpidump (" sig:", data[i]); | 676 | log_mpidump (" sig:", data[i]); |
677 | log_mpidump (" hash:", hash); | 677 | log_mpidump (" hash:", hash); |
678 | } | 678 | } |
679 | 679 | ||
680 | ath_mutex_lock (&pubkeys_registered_lock); | 680 | ath_mutex_lock (&pubkeys_registered_lock); |
681 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 681 | module = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
682 | if (module) | 682 | if (module) |
683 | { | 683 | { |
684 | pubkey = (gcry_pk_spec_t *) module->spec; | 684 | pubkey = (gcry_pk_spec_t *) module->spec; |
685 | rc = pubkey->verify (algorithm, hash, data, pkey, cmp, opaquev); | 685 | rc = pubkey->verify (algorithm, hash, data, pkey, cmp, opaquev); |
686 | _gcry_module_release (module); | 686 | _gcry_module_release (module); |
687 | goto ready; | 687 | goto ready; |
688 | } | 688 | } |
689 | 689 | ||
690 | rc = GPG_ERR_PUBKEY_ALGO; | 690 | rc = GPG_ERR_PUBKEY_ALGO; |
691 | 691 | ||
692 | ready: | 692 | ready: |
693 | ath_mutex_unlock (&pubkeys_registered_lock); | 693 | ath_mutex_unlock (&pubkeys_registered_lock); |
694 | return rc; | 694 | return rc; |
695 | } | 695 | } |
696 | 696 | ||
697 | 697 | ||
698 | /* Internal function. */ | 698 | /* Internal function. */ |
699 | static gcry_err_code_t | 699 | static gcry_err_code_t |
700 | sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names, | 700 | sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names, |
701 | gcry_mpi_t *elements) | 701 | gcry_mpi_t *elements) |
702 | { | 702 | { |
703 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 703 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
704 | int i, idx; | 704 | int i, idx; |
705 | const char *name; | 705 | const char *name; |
706 | gcry_sexp_t list; | 706 | gcry_sexp_t list; |
707 | 707 | ||
708 | for (name = element_names, idx = 0; *name && !err; name++, idx++) | 708 | for (name = element_names, idx = 0; *name && !err; name++, idx++) |
709 | { | 709 | { |
710 | list = gcry_sexp_find_token (key_sexp, name, 1); | 710 | list = gcry_sexp_find_token (key_sexp, name, 1); |
711 | if (! list) | 711 | if (! list) |
712 | err = GPG_ERR_NO_OBJ; | 712 | err = GPG_ERR_NO_OBJ; |
713 | else | 713 | else |
714 | { | 714 | { |
715 | elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); | 715 | elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); |
716 | gcry_sexp_release (list); | 716 | gcry_sexp_release (list); |
717 | if (! elements[idx]) | 717 | if (! elements[idx]) |
718 | err = GPG_ERR_INV_OBJ; | 718 | err = GPG_ERR_INV_OBJ; |
719 | } | 719 | } |
720 | } | 720 | } |
721 | 721 | ||
722 | if (err) | 722 | if (err) |
723 | { | 723 | { |
724 | for (i = 0; i < idx; i++) | 724 | for (i = 0; i < idx; i++) |
725 | if (elements[i]) | 725 | if (elements[i]) |
726 | gcry_free (elements[i]); | 726 | gcry_free (elements[i]); |
727 | } | 727 | } |
728 | return err; | 728 | return err; |
729 | } | 729 | } |
730 | 730 | ||
731 | /**************** | 731 | /**************** |
732 | * Convert a S-Exp with either a private or a public key to our | 732 | * Convert a S-Exp with either a private or a public key to our |
733 | * internal format. Currently we do only support the following | 733 | * internal format. Currently we do only support the following |
734 | * algorithms: | 734 | * algorithms: |
735 | * dsa | 735 | * dsa |
736 | * rsa | 736 | * rsa |
737 | * openpgp-dsa | 737 | * openpgp-dsa |
738 | * openpgp-rsa | 738 | * openpgp-rsa |
739 | * openpgp-elg | 739 | * openpgp-elg |
740 | * openpgp-elg-sig | 740 | * openpgp-elg-sig |
741 | * Provide a SE with the first element be either "private-key" or | 741 | * Provide a SE with the first element be either "private-key" or |
742 | * or "public-key". It is followed by a list with its first element | 742 | * or "public-key". It is followed by a list with its first element |
743 | * be one of the above algorithm identifiers and the remaning | 743 | * be one of the above algorithm identifiers and the remaning |
744 | * elements are pairs with parameter-id and value. | 744 | * elements are pairs with parameter-id and value. |
745 | * NOTE: we look through the list to find a list beginning with | 745 | * NOTE: we look through the list to find a list beginning with |
746 | * "private-key" or "public-key" - the first one found is used. | 746 | * "private-key" or "public-key" - the first one found is used. |
747 | * | 747 | * |
748 | * FIXME: Allow for encrypted secret keys here. | 748 | * FIXME: Allow for encrypted secret keys here. |
749 | * | 749 | * |
750 | * Returns: A pointer to an allocated array of MPIs if the return value is | 750 | * Returns: A pointer to an allocated array of MPIs if the return value is |
751 | * zero; the caller has to release this array. | 751 | * zero; the caller has to release this array. |
752 | * | 752 | * |
753 | * Example of a DSA public key: | 753 | * Example of a DSA public key: |
754 | * (private-key | 754 | * (private-key |
755 | * (dsa | 755 | * (dsa |
756 | * (p <mpi>) | 756 | * (p <mpi>) |
757 | * (g <mpi>) | 757 | * (g <mpi>) |
758 | * (y <mpi>) | 758 | * (y <mpi>) |
759 | * (x <mpi>) | 759 | * (x <mpi>) |
760 | * ) | 760 | * ) |
761 | * ) | 761 | * ) |
762 | * The <mpi> are expected to be in GCRYMPI_FMT_USG | 762 | * The <mpi> are expected to be in GCRYMPI_FMT_USG |
763 | */ | 763 | */ |
764 | static gcry_err_code_t | 764 | static gcry_err_code_t |
765 | sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, | 765 | sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, |
766 | gcry_module_t *retalgo) | 766 | gcry_module_t *retalgo) |
767 | { | 767 | { |
768 | gcry_sexp_t list, l2; | 768 | gcry_sexp_t list, l2; |
769 | const char *name; | 769 | const char *name; |
770 | size_t n; | 770 | size_t n; |
771 | const char *elems; | 771 | const char *elems; |
772 | gcry_mpi_t *array; | 772 | gcry_mpi_t *array; |
773 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 773 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
774 | gcry_module_t module; | 774 | gcry_module_t module; |
775 | gcry_pk_spec_t *pubkey; | 775 | gcry_pk_spec_t *pubkey; |
776 | 776 | ||
777 | /* check that the first element is valid */ | 777 | /* check that the first element is valid */ |
778 | list = gcry_sexp_find_token( sexp, want_private? "private-key" | 778 | list = gcry_sexp_find_token( sexp, want_private? "private-key" |
779 | :"public-key", 0 ); | 779 | :"public-key", 0 ); |
780 | if( !list ) | 780 | if( !list ) |
781 | return GPG_ERR_INV_OBJ; /* Does not contain a public- | 781 | return GPG_ERR_INV_OBJ; /* Does not contain a public- |
782 | or private-key object */ | 782 | or private-key object */ |
783 | l2 = gcry_sexp_cadr( list ); | 783 | l2 = gcry_sexp_cadr( list ); |
784 | gcry_sexp_release ( list ); | 784 | gcry_sexp_release ( list ); |
785 | list = l2; | 785 | list = l2; |
786 | name = gcry_sexp_nth_data( list, 0, &n ); | 786 | name = gcry_sexp_nth_data( list, 0, &n ); |
787 | if( !name ) { | 787 | if( !name ) { |
788 | gcry_sexp_release ( list ); | 788 | gcry_sexp_release ( list ); |
789 | return GPG_ERR_INV_OBJ; /* invalid structure of object */ | 789 | return GPG_ERR_INV_OBJ; /* invalid structure of object */ |
790 | } | 790 | } |
791 | 791 | ||
792 | { | 792 | { |
793 | char *name_terminated = gcry_xmalloc (n + 1); | 793 | char *name_terminated = gcry_xmalloc (n + 1); |
794 | memcpy (name_terminated, name, n); | 794 | memcpy (name_terminated, name, n); |
795 | name_terminated[n] = 0; | 795 | name_terminated[n] = 0; |
796 | 796 | ||
797 | ath_mutex_lock (&pubkeys_registered_lock); | 797 | ath_mutex_lock (&pubkeys_registered_lock); |
798 | module = gcry_pk_lookup_name (name_terminated); | 798 | module = gcry_pk_lookup_name (name_terminated); |
799 | ath_mutex_unlock (&pubkeys_registered_lock); | 799 | ath_mutex_unlock (&pubkeys_registered_lock); |
800 | 800 | ||
801 | gcry_free (name_terminated); | 801 | gcry_free (name_terminated); |
802 | } | 802 | } |
803 | 803 | ||
804 | if (! module) | 804 | if (! module) |
805 | { | 805 | { |
806 | gcry_sexp_release (list); | 806 | gcry_sexp_release (list); |
807 | return GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */ | 807 | return GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */ |
808 | } | 808 | } |
809 | else | 809 | else |
810 | pubkey = (gcry_pk_spec_t *) module->spec; | 810 | pubkey = (gcry_pk_spec_t *) module->spec; |
811 | 811 | ||
812 | elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey; | 812 | elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey; |
813 | array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); | 813 | array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); |
814 | if (! array) | 814 | if (! array) |
815 | err = gpg_err_code_from_errno (errno); | 815 | err = gpg_err_code_from_errno (errno); |
816 | if (! err) | 816 | if (! err) |
817 | err = sexp_elements_extract (list, elems, array); | 817 | err = sexp_elements_extract (list, elems, array); |
818 | 818 | ||
819 | if (list) | 819 | if (list) |
820 | gcry_sexp_release (list); | 820 | gcry_sexp_release (list); |
821 | 821 | ||
822 | if (err) | 822 | if (err) |
823 | { | 823 | { |
824 | if (array) | 824 | if (array) |
825 | gcry_free (array); | 825 | gcry_free (array); |
826 | 826 | ||
827 | ath_mutex_lock (&pubkeys_registered_lock); | 827 | ath_mutex_lock (&pubkeys_registered_lock); |
828 | _gcry_module_release (module); | 828 | _gcry_module_release (module); |
829 | ath_mutex_unlock (&pubkeys_registered_lock); | 829 | ath_mutex_unlock (&pubkeys_registered_lock); |
830 | } | 830 | } |
831 | else | 831 | else |
832 | { | 832 | { |
833 | *retarray = array; | 833 | *retarray = array; |
834 | *retalgo = module; | 834 | *retalgo = module; |
835 | } | 835 | } |
836 | 836 | ||
837 | return err; | 837 | return err; |
838 | } | 838 | } |
839 | 839 | ||
840 | static gcry_err_code_t | 840 | static gcry_err_code_t |
841 | sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, | 841 | sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, |
842 | gcry_module_t *retalgo) | 842 | gcry_module_t *retalgo) |
843 | { | 843 | { |
844 | gcry_sexp_t list, l2; | 844 | gcry_sexp_t list, l2; |
845 | const char *name; | 845 | const char *name; |
846 | size_t n; | 846 | size_t n; |
847 | const char *elems; | 847 | const char *elems; |
848 | gcry_mpi_t *array; | 848 | gcry_mpi_t *array; |
849 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 849 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
850 | gcry_module_t module; | 850 | gcry_module_t module; |
851 | gcry_pk_spec_t *pubkey; | 851 | gcry_pk_spec_t *pubkey; |
852 | 852 | ||
853 | /* check that the first element is valid */ | 853 | /* check that the first element is valid */ |
854 | list = gcry_sexp_find_token( sexp, "sig-val" , 0 ); | 854 | list = gcry_sexp_find_token( sexp, "sig-val" , 0 ); |
855 | if( !list ) | 855 | if( !list ) |
856 | return GPG_ERR_INV_OBJ; /* Does not contain a signature value object */ | 856 | return GPG_ERR_INV_OBJ; /* Does not contain a signature value object */ |
857 | l2 = gcry_sexp_nth (list, 1); | 857 | l2 = gcry_sexp_nth (list, 1); |
858 | if(! l2) | 858 | if(! l2) |
859 | { | 859 | { |
860 | gcry_sexp_release (list); | 860 | gcry_sexp_release (list); |
861 | return GPG_ERR_NO_OBJ; /* no cadr for the sig object */ | 861 | return GPG_ERR_NO_OBJ; /* no cadr for the sig object */ |
862 | } | 862 | } |
863 | name = gcry_sexp_nth_data( l2, 0, &n ); | 863 | name = gcry_sexp_nth_data( l2, 0, &n ); |
864 | if( !name ) { | 864 | if( !name ) { |
865 | gcry_sexp_release ( list ); | 865 | gcry_sexp_release ( list ); |
866 | gcry_sexp_release ( l2 ); | 866 | gcry_sexp_release ( l2 ); |
867 | return GPG_ERR_INV_OBJ; /* invalid structure of object */ | 867 | return GPG_ERR_INV_OBJ; /* invalid structure of object */ |
868 | } | 868 | } |
869 | else if (n == 5 && (! memcmp (name, "flags", 5))) { | 869 | else if (n == 5 && (! memcmp (name, "flags", 5))) { |
870 | /* Skip flags, since they are not used but just here for the | 870 | /* Skip flags, since they are not used but just here for the |
871 | sake of consistent S-expressions. */ | 871 | sake of consistent S-expressions. */ |
872 | gcry_sexp_release (l2); | 872 | gcry_sexp_release (l2); |
873 | l2 = gcry_sexp_nth (list, 2); | 873 | l2 = gcry_sexp_nth (list, 2); |
874 | if (! l2) | 874 | if (! l2) |
875 | { | 875 | { |
876 | gcry_sexp_release (list); | 876 | gcry_sexp_release (list); |
877 | return GPG_ERR_INV_OBJ; | 877 | return GPG_ERR_INV_OBJ; |
878 | } | 878 | } |
879 | name = gcry_sexp_nth_data (l2, 0, &n); | 879 | name = gcry_sexp_nth_data (l2, 0, &n); |
880 | } | 880 | } |
881 | 881 | ||
882 | { | 882 | { |
883 | char *name_terminated = gcry_xmalloc (n + 1); | 883 | char *name_terminated = gcry_xmalloc (n + 1); |
884 | memcpy (name_terminated, name, n); | 884 | memcpy (name_terminated, name, n); |
885 | name_terminated[n] = 0; | 885 | name_terminated[n] = 0; |
886 | 886 | ||
887 | ath_mutex_lock (&pubkeys_registered_lock); | 887 | ath_mutex_lock (&pubkeys_registered_lock); |
888 | module = gcry_pk_lookup_name (name_terminated); | 888 | module = gcry_pk_lookup_name (name_terminated); |
889 | ath_mutex_unlock (&pubkeys_registered_lock); | 889 | ath_mutex_unlock (&pubkeys_registered_lock); |
890 | 890 | ||
891 | gcry_free (name_terminated); | 891 | gcry_free (name_terminated); |
892 | } | 892 | } |
893 | 893 | ||
894 | if (! module) | 894 | if (! module) |
895 | { | 895 | { |
896 | gcry_sexp_release (l2); | 896 | gcry_sexp_release (l2); |
897 | gcry_sexp_release (list); | 897 | gcry_sexp_release (list); |
898 | return GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */ | 898 | return GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */ |
899 | } | 899 | } |
900 | else | 900 | else |
901 | pubkey = (gcry_pk_spec_t *) module->spec; | 901 | pubkey = (gcry_pk_spec_t *) module->spec; |
902 | 902 | ||
903 | elems = pubkey->elements_sig; | 903 | elems = pubkey->elements_sig; |
904 | array = gcry_calloc (strlen (elems) + 1 , sizeof (*array)); | 904 | array = gcry_calloc (strlen (elems) + 1 , sizeof (*array)); |
905 | if (! array) | 905 | if (! array) |
906 | err = gpg_err_code_from_errno (errno); | 906 | err = gpg_err_code_from_errno (errno); |
907 | 907 | ||
908 | if (! err) | 908 | if (! err) |
909 | err = sexp_elements_extract (list, elems, array); | 909 | err = sexp_elements_extract (list, elems, array); |
910 | 910 | ||
911 | gcry_sexp_release (l2); | 911 | gcry_sexp_release (l2); |
912 | gcry_sexp_release (list); | 912 | gcry_sexp_release (list); |
913 | 913 | ||
914 | if (err) | 914 | if (err) |
915 | { | 915 | { |
916 | ath_mutex_lock (&pubkeys_registered_lock); | 916 | ath_mutex_lock (&pubkeys_registered_lock); |
917 | _gcry_module_release (module); | 917 | _gcry_module_release (module); |
918 | ath_mutex_unlock (&pubkeys_registered_lock); | 918 | ath_mutex_unlock (&pubkeys_registered_lock); |
919 | 919 | ||
920 | if (array) | 920 | if (array) |
921 | gcry_free (array); | 921 | gcry_free (array); |
922 | } | 922 | } |
923 | else | 923 | else |
924 | { | 924 | { |
925 | *retarray = array; | 925 | *retarray = array; |
926 | *retalgo = module; | 926 | *retalgo = module; |
927 | } | 927 | } |
928 | 928 | ||
929 | return err; | 929 | return err; |
930 | } | 930 | } |
931 | 931 | ||
932 | 932 | ||
933 | /**************** | 933 | /**************** |
934 | * Take sexp and return an array of MPI as used for our internal decrypt | 934 | * Take sexp and return an array of MPI as used for our internal decrypt |
935 | * function. | 935 | * function. |
936 | * s_data = (enc-val | 936 | * s_data = (enc-val |
937 | * [(flags [pkcs1]) | 937 | * [(flags [pkcs1]) |
938 | * (<algo> | 938 | * (<algo> |
939 | * (<param_name1> <mpi>) | 939 | * (<param_name1> <mpi>) |
940 | * ... | 940 | * ... |
941 | * (<param_namen> <mpi>) | 941 | * (<param_namen> <mpi>) |
942 | * )) | 942 | * )) |
943 | * RET_MODERN is set to true when at least an empty flags list has been found. | 943 | * RET_MODERN is set to true when at least an empty flags list has been found. |
944 | */ | 944 | */ |
945 | static gcry_err_code_t | 945 | static gcry_err_code_t |
946 | sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo, | 946 | sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo, |
947 | int *ret_modern, int *ret_want_pkcs1, int *flags) | 947 | int *ret_modern, int *ret_want_pkcs1, int *flags) |
948 | { | 948 | { |
949 | gcry_sexp_t list = NULL, l2 = NULL; | 949 | gcry_sexp_t list = NULL, l2 = NULL; |
950 | gcry_pk_spec_t *pubkey = NULL; | 950 | gcry_pk_spec_t *pubkey = NULL; |
951 | gcry_module_t module = NULL; | 951 | gcry_module_t module = NULL; |
952 | const char *name; | 952 | const char *name; |
953 | size_t n; | 953 | size_t n; |
954 | int parsed_flags = 0; | 954 | int parsed_flags = 0; |
955 | const char *elems; | 955 | const char *elems; |
956 | gcry_mpi_t *array = NULL; | 956 | gcry_mpi_t *array = NULL; |
957 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 957 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
958 | 958 | ||
959 | *ret_want_pkcs1 = 0; | 959 | *ret_want_pkcs1 = 0; |
960 | *ret_modern = 0; | 960 | *ret_modern = 0; |
961 | 961 | ||
962 | /* check that the first element is valid */ | 962 | /* check that the first element is valid */ |
963 | list = gcry_sexp_find_token (sexp, "enc-val" , 0); | 963 | list = gcry_sexp_find_token (sexp, "enc-val" , 0); |
964 | if (! list) | 964 | if (! list) |
965 | { | 965 | { |
966 | err = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object */ | 966 | err = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object */ |
967 | goto leave; | 967 | goto leave; |
968 | } | 968 | } |
969 | 969 | ||
970 | l2 = gcry_sexp_nth (list, 1); | 970 | l2 = gcry_sexp_nth (list, 1); |
971 | if (! l2) | 971 | if (! l2) |
972 | { | 972 | { |
973 | err = GPG_ERR_NO_OBJ; /* no cdr for the data object */ | 973 | err = GPG_ERR_NO_OBJ; /* no cdr for the data object */ |
974 | goto leave; | 974 | goto leave; |
975 | } | 975 | } |
976 | 976 | ||
977 | /* Extract identifier of sublist. */ | 977 | /* Extract identifier of sublist. */ |
978 | name = gcry_sexp_nth_data (l2, 0, &n); | 978 | name = gcry_sexp_nth_data (l2, 0, &n); |
979 | if (! name) | 979 | if (! name) |
980 | { | 980 | { |
981 | err = GPG_ERR_INV_OBJ; /* invalid structure of object */ | 981 | err = GPG_ERR_INV_OBJ; /* invalid structure of object */ |
982 | goto leave; | 982 | goto leave; |
983 | } | 983 | } |
984 | 984 | ||
985 | if ((n == 5) && (! memcmp (name, "flags", 5))) | 985 | if ((n == 5) && (! memcmp (name, "flags", 5))) |
986 | { | 986 | { |
987 | /* There is a flags element - process it */ | 987 | /* There is a flags element - process it */ |
988 | const char *s; | 988 | const char *s; |
989 | int i; | 989 | int i; |
990 | 990 | ||
991 | *ret_modern = 1; | 991 | *ret_modern = 1; |
992 | for (i = gcry_sexp_length (l2) - 1; i > 0; i--) | 992 | for (i = gcry_sexp_length (l2) - 1; i > 0; i--) |
993 | { | 993 | { |
994 | s = gcry_sexp_nth_data (l2, i, &n); | 994 | s = gcry_sexp_nth_data (l2, i, &n); |
995 | if (! s) | 995 | if (! s) |
996 | ; /* not a data element - ignore */ | 996 | ; /* not a data element - ignore */ |
997 | else if (n == 3 && ! memcmp (s, "raw", 3)) | 997 | else if (n == 3 && ! memcmp (s, "raw", 3)) |
998 | ; /* just a dummy because it is the default */ | 998 | ; /* just a dummy because it is the default */ |
999 | else if (n == 5 && ! memcmp (s, "pkcs1", 5)) | 999 | else if (n == 5 && ! memcmp (s, "pkcs1", 5)) |
1000 | *ret_want_pkcs1 = 1; | 1000 | *ret_want_pkcs1 = 1; |
1001 | else if (n == 11 && ! memcmp (s, "no-blinding", 11)) | 1001 | else if (n == 11 && ! memcmp (s, "no-blinding", 11)) |
1002 | parsed_flags |= PUBKEY_FLAG_NO_BLINDING; | 1002 | parsed_flags |= PUBKEY_FLAG_NO_BLINDING; |
1003 | else | 1003 | else |
1004 | { | 1004 | { |
1005 | err = GPG_ERR_INV_FLAG; | 1005 | err = GPG_ERR_INV_FLAG; |
1006 | goto leave; | 1006 | goto leave; |
1007 | } | 1007 | } |
1008 | } | 1008 | } |
1009 | 1009 | ||
1010 | /* Get the next which has the actual data */ | 1010 | /* Get the next which has the actual data */ |
1011 | gcry_sexp_release (l2); | 1011 | gcry_sexp_release (l2); |
1012 | l2 = gcry_sexp_nth (list, 2); | 1012 | l2 = gcry_sexp_nth (list, 2); |
1013 | if (! l2) | 1013 | if (! l2) |
1014 | { | 1014 | { |
1015 | err = GPG_ERR_NO_OBJ; /* no cdr for the data object */ | 1015 | err = GPG_ERR_NO_OBJ; /* no cdr for the data object */ |
1016 | goto leave; | 1016 | goto leave; |
1017 | } | 1017 | } |
1018 | 1018 | ||
1019 | /* Extract sublist identifier. */ | 1019 | /* Extract sublist identifier. */ |
1020 | name = gcry_sexp_nth_data (l2, 0, &n); | 1020 | name = gcry_sexp_nth_data (l2, 0, &n); |
1021 | if (! name) | 1021 | if (! name) |
1022 | { | 1022 | { |
1023 | err = GPG_ERR_INV_OBJ; /* invalid structure of object */ | 1023 | err = GPG_ERR_INV_OBJ; /* invalid structure of object */ |
1024 | goto leave; | 1024 | goto leave; |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | gcry_sexp_release (list); | 1027 | gcry_sexp_release (list); |
1028 | list = l2; | 1028 | list = l2; |
1029 | l2 = NULL; | 1029 | l2 = NULL; |
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | { | 1032 | { |
1033 | char *name_terminated = gcry_xmalloc (n + 1); | 1033 | char *name_terminated = gcry_xmalloc (n + 1); |
1034 | memcpy (name_terminated, name, n); | 1034 | memcpy (name_terminated, name, n); |
1035 | name_terminated[n] = 0; | 1035 | name_terminated[n] = 0; |
1036 | 1036 | ||
1037 | ath_mutex_lock (&pubkeys_registered_lock); | 1037 | ath_mutex_lock (&pubkeys_registered_lock); |
1038 | module = gcry_pk_lookup_name (name_terminated); | 1038 | module = gcry_pk_lookup_name (name_terminated); |
1039 | ath_mutex_unlock (&pubkeys_registered_lock); | 1039 | ath_mutex_unlock (&pubkeys_registered_lock); |
1040 | 1040 | ||
1041 | gcry_free (name_terminated); | 1041 | gcry_free (name_terminated); |
1042 | 1042 | ||
1043 | if (! module) | 1043 | if (! module) |
1044 | { | 1044 | { |
1045 | err = GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */ | 1045 | err = GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */ |
1046 | goto leave; | 1046 | goto leave; |
1047 | } | 1047 | } |
1048 | pubkey = (gcry_pk_spec_t *) module->spec; | 1048 | pubkey = (gcry_pk_spec_t *) module->spec; |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | elems = pubkey->elements_enc; | 1051 | elems = pubkey->elements_enc; |
1052 | array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); | 1052 | array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); |
1053 | if (! array) | 1053 | if (! array) |
1054 | { | 1054 | { |
1055 | err = gpg_err_code_from_errno (errno); | 1055 | err = gpg_err_code_from_errno (errno); |
1056 | goto leave; | 1056 | goto leave; |
1057 | } | 1057 | } |
1058 | 1058 | ||
1059 | err = sexp_elements_extract (list, elems, array); | 1059 | err = sexp_elements_extract (list, elems, array); |
1060 | 1060 | ||
1061 | leave: | 1061 | leave: |
1062 | if (list) | 1062 | if (list) |
1063 | gcry_sexp_release (list); | 1063 | gcry_sexp_release (list); |
1064 | if (l2) | 1064 | if (l2) |
1065 | gcry_sexp_release (l2); | 1065 | gcry_sexp_release (l2); |
1066 | 1066 | ||
1067 | if (err) | 1067 | if (err) |
1068 | { | 1068 | { |
1069 | ath_mutex_lock (&pubkeys_registered_lock); | 1069 | ath_mutex_lock (&pubkeys_registered_lock); |
1070 | _gcry_module_release (module); | 1070 | _gcry_module_release (module); |
1071 | ath_mutex_unlock (&pubkeys_registered_lock); | 1071 | ath_mutex_unlock (&pubkeys_registered_lock); |
1072 | if (array) | 1072 | if (array) |
1073 | gcry_free (array); | 1073 | gcry_free (array); |
1074 | } | 1074 | } |
1075 | else | 1075 | else |
1076 | { | 1076 | { |
1077 | *retarray = array; | 1077 | *retarray = array; |
1078 | *retalgo = module; | 1078 | *retalgo = module; |
1079 | *flags = parsed_flags; | 1079 | *flags = parsed_flags; |
1080 | } | 1080 | } |
1081 | 1081 | ||
1082 | return err; | 1082 | return err; |
1083 | } | 1083 | } |
1084 | 1084 | ||
1085 | /* Take the hash value and convert into an MPI, suitable for for | 1085 | /* Take the hash value and convert into an MPI, suitable for for |
1086 | passing to the low level functions. We currently support the | 1086 | passing to the low level functions. We currently support the |
1087 | old style way of passing just a MPI and the modern interface which | 1087 | old style way of passing just a MPI and the modern interface which |
1088 | allows to pass flags so that we can choose between raw and pkcs1 | 1088 | allows to pass flags so that we can choose between raw and pkcs1 |
1089 | padding - may be more padding options later. | 1089 | padding - may be more padding options later. |
1090 | 1090 | ||
1091 | (<mpi>) | 1091 | (<mpi>) |
1092 | or | 1092 | or |
1093 | (data | 1093 | (data |
1094 | [(flags [pkcs1])] | 1094 | [(flags [pkcs1])] |
1095 | [(hash <algo> <value>)] | 1095 | [(hash <algo> <value>)] |
1096 | [(value <text>)] | 1096 | [(value <text>)] |
1097 | ) | 1097 | ) |
1098 | 1098 | ||
1099 | Either the VALUE or the HASH element must be present for use | 1099 | Either the VALUE or the HASH element must be present for use |
1100 | with signatures. VALUE is used for encryption. | 1100 | with signatures. VALUE is used for encryption. |
1101 | 1101 | ||
1102 | NBITS is the length of the key in bits. | 1102 | NBITS is the length of the key in bits. |
1103 | 1103 | ||
1104 | */ | 1104 | */ |
1105 | static gcry_err_code_t | 1105 | static gcry_err_code_t |
1106 | sexp_data_to_mpi (gcry_sexp_t input, unsigned int nbits, gcry_mpi_t *ret_mpi, | 1106 | sexp_data_to_mpi (gcry_sexp_t input, unsigned int nbits, gcry_mpi_t *ret_mpi, |
1107 | int for_encryption, int *flags) | 1107 | int for_encryption, int *flags) |
1108 | { | 1108 | { |
1109 | gcry_err_code_t rc = 0; | 1109 | gcry_err_code_t rc = 0; |
1110 | gcry_sexp_t ldata, lhash, lvalue; | 1110 | gcry_sexp_t ldata, lhash, lvalue; |
1111 | int i; | 1111 | int i; |
1112 | size_t n; | 1112 | size_t n; |
1113 | const char *s; | 1113 | const char *s; |
1114 | int is_raw = 0, is_pkcs1 = 0, unknown_flag=0; | 1114 | int is_raw = 0, is_pkcs1 = 0, unknown_flag=0; |
1115 | int parsed_flags = 0, dummy_flags; | 1115 | int parsed_flags = 0, dummy_flags; |
1116 | 1116 | ||
1117 | if (! flags) | 1117 | if (! flags) |
1118 | flags = &dummy_flags; | 1118 | flags = &dummy_flags; |
1119 | 1119 | ||
1120 | *ret_mpi = NULL; | 1120 | *ret_mpi = NULL; |
1121 | ldata = gcry_sexp_find_token (input, "data", 0); | 1121 | ldata = gcry_sexp_find_token (input, "data", 0); |
1122 | if (!ldata) | 1122 | if (!ldata) |
1123 | { /* assume old style */ | 1123 | { /* assume old style */ |
1124 | *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0); | 1124 | *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0); |
1125 | return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ; | 1125 | return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ; |
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | /* see whether there is a flags object */ | 1128 | /* see whether there is a flags object */ |
1129 | { | 1129 | { |
1130 | gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0); | 1130 | gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0); |
1131 | if (lflags) | 1131 | if (lflags) |
1132 | { /* parse the flags list. */ | 1132 | { /* parse the flags list. */ |
1133 | for (i=gcry_sexp_length (lflags)-1; i > 0; i--) | 1133 | for (i=gcry_sexp_length (lflags)-1; i > 0; i--) |
1134 | { | 1134 | { |
1135 | s = gcry_sexp_nth_data (lflags, i, &n); | 1135 | s = gcry_sexp_nth_data (lflags, i, &n); |
1136 | if (!s) | 1136 | if (!s) |
1137 | ; /* not a data element*/ | 1137 | ; /* not a data element*/ |
1138 | else if ( n == 3 && !memcmp (s, "raw", 3)) | 1138 | else if ( n == 3 && !memcmp (s, "raw", 3)) |
1139 | is_raw = 1; | 1139 | is_raw = 1; |
1140 | else if ( n == 5 && !memcmp (s, "pkcs1", 5)) | 1140 | else if ( n == 5 && !memcmp (s, "pkcs1", 5)) |
1141 | is_pkcs1 = 1; | 1141 | is_pkcs1 = 1; |
1142 | else if (n == 11 && ! memcmp (s, "no-blinding", 11)) | 1142 | else if (n == 11 && ! memcmp (s, "no-blinding", 11)) |
1143 | parsed_flags |= PUBKEY_FLAG_NO_BLINDING; | 1143 | parsed_flags |= PUBKEY_FLAG_NO_BLINDING; |
1144 | else | 1144 | else |
1145 | unknown_flag = 1; | 1145 | unknown_flag = 1; |
1146 | } | 1146 | } |
1147 | gcry_sexp_release (lflags); | 1147 | gcry_sexp_release (lflags); |
1148 | } | 1148 | } |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | if (!is_pkcs1 && !is_raw) | 1151 | if (!is_pkcs1 && !is_raw) |
1152 | is_raw = 1; /* default to raw */ | 1152 | is_raw = 1; /* default to raw */ |
1153 | 1153 | ||
1154 | /* Get HASH or MPI */ | 1154 | /* Get HASH or MPI */ |
1155 | lhash = gcry_sexp_find_token (ldata, "hash", 0); | 1155 | lhash = gcry_sexp_find_token (ldata, "hash", 0); |
1156 | lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0); | 1156 | lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0); |
1157 | 1157 | ||
1158 | if (!(!lhash ^ !lvalue)) | 1158 | if (!(!lhash ^ !lvalue)) |
1159 | rc = GPG_ERR_INV_OBJ; /* none or both given */ | 1159 | rc = GPG_ERR_INV_OBJ; /* none or both given */ |
1160 | else if (unknown_flag) | 1160 | else if (unknown_flag) |
1161 | rc = GPG_ERR_INV_FLAG; | 1161 | rc = GPG_ERR_INV_FLAG; |
1162 | else if (is_raw && is_pkcs1 && !for_encryption) | 1162 | else if (is_raw && is_pkcs1 && !for_encryption) |
1163 | rc = GPG_ERR_CONFLICT; | 1163 | rc = GPG_ERR_CONFLICT; |
1164 | else if (is_raw && lvalue) | 1164 | else if (is_raw && lvalue) |
1165 | { | 1165 | { |
1166 | *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, 0); | 1166 | *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, 0); |
1167 | if (!*ret_mpi) | 1167 | if (!*ret_mpi) |
1168 | rc = GPG_ERR_INV_OBJ; | 1168 | rc = GPG_ERR_INV_OBJ; |
1169 | } | 1169 | } |
1170 | else if (is_pkcs1 && lvalue && for_encryption) | 1170 | else if (is_pkcs1 && lvalue && for_encryption) |
1171 | { /* Create pkcs#1 block type 2 padding. */ | 1171 | { /* Create pkcs#1 block type 2 padding. */ |
1172 | unsigned char *frame = NULL; | 1172 | unsigned char *frame = NULL; |
1173 | size_t nframe = (nbits+7) / 8; | 1173 | size_t nframe = (nbits+7) / 8; |
1174 | const void * value; | 1174 | const void * value; |
1175 | size_t valuelen; | 1175 | size_t valuelen; |
1176 | unsigned char *p; | 1176 | unsigned char *p; |
1177 | 1177 | ||
1178 | if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen ) | 1178 | if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen ) |
1179 | rc = GPG_ERR_INV_OBJ; | 1179 | rc = GPG_ERR_INV_OBJ; |
1180 | else if (valuelen + 7 > nframe || !nframe) | 1180 | else if (valuelen + 7 > nframe || !nframe) |
1181 | { | 1181 | { |
1182 | /* Can't encode a VALUELEN value in a NFRAME bytes frame. */ | 1182 | /* Can't encode a VALUELEN value in a NFRAME bytes frame. */ |
1183 | rc = GPG_ERR_TOO_SHORT; /* the key is too short */ | 1183 | rc = GPG_ERR_TOO_SHORT; /* the key is too short */ |
1184 | } | 1184 | } |
1185 | else if ( !(frame = gcry_malloc_secure (nframe))) | 1185 | else if ( !(frame = gcry_malloc_secure (nframe))) |
1186 | rc = gpg_err_code_from_errno (errno); | 1186 | rc = gpg_err_code_from_errno (errno); |
1187 | else | 1187 | else |
1188 | { | 1188 | { |
1189 | n = 0; | 1189 | n = 0; |
1190 | frame[n++] = 0; | 1190 | frame[n++] = 0; |
1191 | frame[n++] = 2; /* block type */ | 1191 | frame[n++] = 2; /* block type */ |
1192 | i = nframe - 3 - valuelen; | 1192 | i = nframe - 3 - valuelen; |
1193 | assert (i > 0); | 1193 | assert (i > 0); |
1194 | p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); | 1194 | p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); |
1195 | /* Replace zero bytes by new values. */ | 1195 | /* Replace zero bytes by new values. */ |
1196 | for (;;) | 1196 | for (;;) |
1197 | { | 1197 | { |
1198 | int j, k; | 1198 | int j, k; |
1199 | unsigned char *pp; | 1199 | unsigned char *pp; |
1200 | 1200 | ||
1201 | /* Count the zero bytes. */ | 1201 | /* Count the zero bytes. */ |
1202 | for (j=k=0; j < i; j++) | 1202 | for (j=k=0; j < i; j++) |
1203 | { | 1203 | { |
1204 | if (!p[j]) | 1204 | if (!p[j]) |
1205 | k++; | 1205 | k++; |
1206 | } | 1206 | } |
1207 | if (!k) | 1207 | if (!k) |
1208 | break; /* Okay: no (more) zero bytes. */ | 1208 | break; /* Okay: no (more) zero bytes. */ |
1209 | 1209 | ||
1210 | k += k/128 + 3; /* Better get some more. */ | 1210 | k += k/128 + 3; /* Better get some more. */ |
1211 | pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); | 1211 | pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); |
1212 | for (j=0; j < i && k;) | 1212 | for (j=0; j < i && k;) |
1213 | { | 1213 | { |
1214 | if (!p[j]) | 1214 | if (!p[j]) |
1215 | p[j] = pp[--k]; | 1215 | p[j] = pp[--k]; |
1216 | if (p[j]) | 1216 | if (p[j]) |
1217 | j++; | 1217 | j++; |
1218 | } | 1218 | } |
1219 | gcry_free (pp); | 1219 | gcry_free (pp); |
1220 | } | 1220 | } |
1221 | memcpy (frame+n, p, i); | 1221 | memcpy (frame+n, p, i); |
1222 | n += i; | 1222 | n += i; |
1223 | gcry_free (p); | 1223 | gcry_free (p); |
1224 | 1224 | ||
1225 | frame[n++] = 0; | 1225 | frame[n++] = 0; |
1226 | memcpy (frame+n, value, valuelen); | 1226 | memcpy (frame+n, value, valuelen); |
1227 | n += valuelen; | 1227 | n += valuelen; |
1228 | assert (n == nframe); | 1228 | assert (n == nframe); |
1229 | 1229 | ||
1230 | /* FIXME, error checking? */ | 1230 | /* FIXME, error checking? */ |
1231 | gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe); | 1231 | gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe); |
1232 | } | 1232 | } |
1233 | 1233 | ||
1234 | gcry_free(frame); | 1234 | gcry_free(frame); |
1235 | } | 1235 | } |
1236 | else if (is_pkcs1 && lhash && !for_encryption) | 1236 | else if (is_pkcs1 && lhash && !for_encryption) |
1237 | { /* Create pkcs#1 block type 1 padding. */ | 1237 | { /* Create pkcs#1 block type 1 padding. */ |
1238 | if (gcry_sexp_length (lhash) != 3) | 1238 | if (gcry_sexp_length (lhash) != 3) |
1239 | rc = GPG_ERR_INV_OBJ; | 1239 | rc = GPG_ERR_INV_OBJ; |
1240 | else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n ) | 1240 | else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n ) |
1241 | rc = GPG_ERR_INV_OBJ; | 1241 | rc = GPG_ERR_INV_OBJ; |
1242 | else | 1242 | else |
1243 | { | 1243 | { |
1244 | static struct { const char *name; int algo; } hashnames[] = | 1244 | static struct { const char *name; int algo; } hashnames[] = |
1245 | { { "sha1", GCRY_MD_SHA1 }, | 1245 | { { "sha1", GCRY_MD_SHA1 }, |
1246 | { "md5", GCRY_MD_MD5 }, | 1246 | { "md5", GCRY_MD_MD5 }, |
1247 | { "rmd160", GCRY_MD_RMD160 }, | 1247 | { "rmd160", GCRY_MD_RMD160 }, |
1248 | { "sha256", GCRY_MD_SHA256 }, | 1248 | { "sha256", GCRY_MD_SHA256 }, |
1249 | { "sha384", GCRY_MD_SHA384 }, | 1249 | { "sha384", GCRY_MD_SHA384 }, |
1250 | { "sha512", GCRY_MD_SHA512 }, | 1250 | { "sha512", GCRY_MD_SHA512 }, |
1251 | { "md2", GCRY_MD_MD2 }, | 1251 | { "md2", GCRY_MD_MD2 }, |
1252 | { "md4", GCRY_MD_MD4 }, | 1252 | { "md4", GCRY_MD_MD4 }, |
1253 | { "tiger", GCRY_MD_TIGER }, | 1253 | { "tiger", GCRY_MD_TIGER }, |
1254 | { "haval", GCRY_MD_HAVAL }, | 1254 | { "haval", GCRY_MD_HAVAL }, |
1255 | { NULL } | 1255 | { NULL } |
1256 | }; | 1256 | }; |
1257 | int algo; | 1257 | int algo; |
1258 | byte asn[100]; | 1258 | byte asn[100]; |
1259 | byte *frame = NULL; | 1259 | byte *frame = NULL; |
1260 | size_t nframe = (nbits+7) / 8; | 1260 | size_t nframe = (nbits+7) / 8; |
1261 | const void * value; | 1261 | const void * value; |
1262 | size_t valuelen; | 1262 | size_t valuelen; |
1263 | size_t asnlen, dlen; | 1263 | size_t asnlen, dlen; |
1264 | 1264 | ||
1265 | for (i=0; hashnames[i].name; i++) | 1265 | for (i=0; hashnames[i].name; i++) |
1266 | { | 1266 | { |
1267 | if ( strlen (hashnames[i].name) == n | 1267 | if ( strlen (hashnames[i].name) == n |
1268 | && !memcmp (hashnames[i].name, s, n)) | 1268 | && !memcmp (hashnames[i].name, s, n)) |
1269 | break; | 1269 | break; |
1270 | } | 1270 | } |
1271 | 1271 | ||
1272 | algo = hashnames[i].algo; | 1272 | algo = hashnames[i].algo; |
1273 | asnlen = DIM(asn); | 1273 | asnlen = DIM(asn); |
1274 | dlen = gcry_md_get_algo_dlen (algo); | 1274 | dlen = gcry_md_get_algo_dlen (algo); |
1275 | 1275 | ||
1276 | if (!hashnames[i].name) | 1276 | if (!hashnames[i].name) |
1277 | rc = GPG_ERR_DIGEST_ALGO; | 1277 | rc = GPG_ERR_DIGEST_ALGO; |
1278 | else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen)) | 1278 | else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen)) |
1279 | || !valuelen ) | 1279 | || !valuelen ) |
1280 | rc = GPG_ERR_INV_OBJ; | 1280 | rc = GPG_ERR_INV_OBJ; |
1281 | else if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) | 1281 | else if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) |
1282 | { | 1282 | { |
1283 | /* We don't have yet all of the above algorithms. */ | 1283 | /* We don't have yet all of the above algorithms. */ |
1284 | rc = GPG_ERR_NOT_IMPLEMENTED; | 1284 | rc = GPG_ERR_NOT_IMPLEMENTED; |
1285 | } | 1285 | } |
1286 | else if ( valuelen != dlen ) | 1286 | else if ( valuelen != dlen ) |
1287 | { | 1287 | { |
1288 | /* Hash value does not match the length of digest for | 1288 | /* Hash value does not match the length of digest for |
1289 | the given algorithm. */ | 1289 | the given algorithm. */ |
1290 | rc = GPG_ERR_CONFLICT; | 1290 | rc = GPG_ERR_CONFLICT; |
1291 | } | 1291 | } |
1292 | else if( !dlen || dlen + asnlen + 4 > nframe) | 1292 | else if( !dlen || dlen + asnlen + 4 > nframe) |
1293 | { | 1293 | { |
1294 | /* Can't encode an DLEN byte digest MD into a NFRAME | 1294 | /* Can't encode an DLEN byte digest MD into a NFRAME |
1295 | byte frame. */ | 1295 | byte frame. */ |
1296 | rc = GPG_ERR_TOO_SHORT; | 1296 | rc = GPG_ERR_TOO_SHORT; |
1297 | } | 1297 | } |
1298 | else if ( !(frame = gcry_malloc (nframe)) ) | 1298 | else if ( !(frame = gcry_malloc (nframe)) ) |
1299 | rc = gpg_err_code_from_errno (errno); | 1299 | rc = gpg_err_code_from_errno (errno); |
1300 | else | 1300 | else |
1301 | { /* Assemble the pkcs#1 block type 1. */ | 1301 | { /* Assemble the pkcs#1 block type 1. */ |
1302 | n = 0; | 1302 | n = 0; |
1303 | frame[n++] = 0; | 1303 | frame[n++] = 0; |
1304 | frame[n++] = 1; /* block type */ | 1304 | frame[n++] = 1; /* block type */ |
1305 | i = nframe - valuelen - asnlen - 3 ; | 1305 | i = nframe - valuelen - asnlen - 3 ; |
1306 | assert (i > 1); | 1306 | assert (i > 1); |
1307 | memset (frame+n, 0xff, i ); | 1307 | memset (frame+n, 0xff, i ); |
1308 | n += i; | 1308 | n += i; |
1309 | frame[n++] = 0; | 1309 | frame[n++] = 0; |
1310 | memcpy (frame+n, asn, asnlen); | 1310 | memcpy (frame+n, asn, asnlen); |
1311 | n += asnlen; | 1311 | n += asnlen; |
1312 | memcpy (frame+n, value, valuelen ); | 1312 | memcpy (frame+n, value, valuelen ); |
1313 | n += valuelen; | 1313 | n += valuelen; |
1314 | assert (n == nframe); | 1314 | assert (n == nframe); |
1315 | 1315 | ||
1316 | /* convert it into an MPI, FIXME: error checking? */ | 1316 | /* convert it into an MPI, FIXME: error checking? */ |
1317 | gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe); | 1317 | gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe); |
1318 | } | 1318 | } |
1319 | 1319 | ||
1320 | gcry_free (frame); | 1320 | gcry_free (frame); |
1321 | } | 1321 | } |
1322 | } | 1322 | } |
1323 | else | 1323 | else |
1324 | rc = GPG_ERR_CONFLICT; | 1324 | rc = GPG_ERR_CONFLICT; |
1325 | 1325 | ||
1326 | gcry_sexp_release (ldata); | 1326 | gcry_sexp_release (ldata); |
1327 | gcry_sexp_release (lhash); | 1327 | gcry_sexp_release (lhash); |
1328 | gcry_sexp_release (lvalue); | 1328 | gcry_sexp_release (lvalue); |
1329 | 1329 | ||
1330 | if (!rc) | 1330 | if (!rc) |
1331 | *flags = parsed_flags; | 1331 | *flags = parsed_flags; |
1332 | 1332 | ||
1333 | return rc; | 1333 | return rc; |
1334 | } | 1334 | } |
1335 | 1335 | ||
1336 | 1336 | ||
1337 | /* | 1337 | /* |
1338 | Do a PK encrypt operation | 1338 | Do a PK encrypt operation |
1339 | 1339 | ||
1340 | Caller has to provide a public key as the SEXP pkey and data as a | 1340 | Caller has to provide a public key as the SEXP pkey and data as a |
1341 | SEXP with just one MPI in it. Alternativly S_DATA might be a | 1341 | SEXP with just one MPI in it. Alternativly S_DATA might be a |
1342 | complex S-Expression, similar to the one used for signature | 1342 | complex S-Expression, similar to the one used for signature |
1343 | verification. This provides a flag which allows to handle PKCS#1 | 1343 | verification. This provides a flag which allows to handle PKCS#1 |
1344 | block type 2 padding. The function returns a a sexp which may be | 1344 | block type 2 padding. The function returns a a sexp which may be |
1345 | passed to to pk_decrypt. | 1345 | passed to to pk_decrypt. |
1346 | 1346 | ||
1347 | Returns: 0 or an errorcode. | 1347 | Returns: 0 or an errorcode. |
1348 | 1348 | ||
1349 | s_data = See comment for sexp_data_to_mpi | 1349 | s_data = See comment for sexp_data_to_mpi |
1350 | s_pkey = <key-as-defined-in-sexp_to_key> | 1350 | s_pkey = <key-as-defined-in-sexp_to_key> |
1351 | r_ciph = (enc-val | 1351 | r_ciph = (enc-val |
1352 | (<algo> | 1352 | (<algo> |
1353 | (<param_name1> <mpi>) | 1353 | (<param_name1> <mpi>) |
1354 | ... | 1354 | ... |
1355 | (<param_namen> <mpi>) | 1355 | (<param_namen> <mpi>) |
1356 | )) | 1356 | )) |
1357 | 1357 | ||
1358 | */ | 1358 | */ |
1359 | gcry_error_t | 1359 | gcry_error_t |
1360 | gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) | 1360 | gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) |
1361 | { | 1361 | { |
1362 | gcry_mpi_t *pkey = NULL, data = NULL, *ciph = NULL; | 1362 | gcry_mpi_t *pkey = NULL, data = NULL, *ciph = NULL; |
1363 | const char *algo_name, *algo_elems; | 1363 | const char *algo_name, *algo_elems; |
1364 | int flags; | 1364 | int flags; |
1365 | gcry_err_code_t rc; | 1365 | gcry_err_code_t rc; |
1366 | gcry_pk_spec_t *pubkey = NULL; | 1366 | gcry_pk_spec_t *pubkey = NULL; |
1367 | gcry_module_t module = NULL; | 1367 | gcry_module_t module = NULL; |
1368 | 1368 | ||
1369 | REGISTER_DEFAULT_PUBKEYS; | 1369 | REGISTER_DEFAULT_PUBKEYS; |
1370 | 1370 | ||
1371 | *r_ciph = NULL; | 1371 | *r_ciph = NULL; |
1372 | /* get the key */ | 1372 | /* get the key */ |
1373 | rc = sexp_to_key (s_pkey, 0, &pkey, &module); | 1373 | rc = sexp_to_key (s_pkey, 0, &pkey, &module); |
1374 | if (rc) | 1374 | if (rc) |
1375 | goto leave; | 1375 | goto leave; |
1376 | 1376 | ||
1377 | assert (module); | 1377 | assert (module); |
1378 | pubkey = (gcry_pk_spec_t *) module->spec; | 1378 | pubkey = (gcry_pk_spec_t *) module->spec; |
1379 | 1379 | ||
1380 | /* If aliases for the algorithm name exists, take the first one | 1380 | /* If aliases for the algorithm name exists, take the first one |
1381 | instead of the regular name to adhere to SPKI conventions. We | 1381 | instead of the regular name to adhere to SPKI conventions. We |
1382 | assume that the first alias name is the lowercase version of the | 1382 | assume that the first alias name is the lowercase version of the |
1383 | regular one. This change is required for compatibility with | 1383 | regular one. This change is required for compatibility with |
1384 | 1.1.12 generated S-expressions. */ | 1384 | 1.1.12 generated S-expressions. */ |
1385 | algo_name = pubkey->aliases? *pubkey->aliases : NULL; | 1385 | algo_name = pubkey->aliases? *pubkey->aliases : NULL; |
1386 | if (!algo_name || !*algo_name) | 1386 | if (!algo_name || !*algo_name) |
1387 | algo_name = pubkey->name; | 1387 | algo_name = pubkey->name; |
1388 | 1388 | ||
1389 | algo_elems = pubkey->elements_enc; | 1389 | algo_elems = pubkey->elements_enc; |
1390 | 1390 | ||
1391 | /* Get the stuff we want to encrypt. */ | 1391 | /* Get the stuff we want to encrypt. */ |
1392 | rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1, | 1392 | rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1, |
1393 | &flags); | 1393 | &flags); |
1394 | if (rc) | 1394 | if (rc) |
1395 | goto leave; | 1395 | goto leave; |
1396 | 1396 | ||
1397 | /* Now we can encrypt DATA to CIPH. */ | 1397 | /* Now we can encrypt DATA to CIPH. */ |
1398 | ciph = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*ciph)); | 1398 | ciph = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*ciph)); |
1399 | rc = pubkey_encrypt (module->mod_id, ciph, data, pkey, flags); | 1399 | rc = pubkey_encrypt (module->mod_id, ciph, data, pkey, flags); |
1400 | mpi_free (data); | 1400 | mpi_free (data); |
1401 | data = NULL; | 1401 | data = NULL; |
1402 | if (rc) | 1402 | if (rc) |
1403 | goto leave; | 1403 | goto leave; |
1404 | 1404 | ||
1405 | /* We did it. Now build the return list */ | 1405 | /* We did it. Now build the return list */ |
1406 | { | 1406 | { |
1407 | char *string, *p; | 1407 | char *string, *p; |
1408 | int i; | 1408 | int i; |
1409 | size_t nelem = strlen (algo_elems); | 1409 | size_t nelem = strlen (algo_elems); |
1410 | size_t needed = 19 + strlen (algo_name) + (nelem * 5); | 1410 | size_t needed = 19 + strlen (algo_name) + (nelem * 5); |
1411 | void **arg_list; | 1411 | void **arg_list; |
1412 | 1412 | ||
1413 | /* Build the string. */ | 1413 | /* Build the string. */ |
1414 | string = p = gcry_xmalloc (needed); | 1414 | string = p = gcry_xmalloc (needed); |
1415 | p = stpcpy ( p, "(enc-val(" ); | 1415 | p = stpcpy ( p, "(enc-val(" ); |
1416 | p = stpcpy ( p, algo_name ); | 1416 | p = stpcpy ( p, algo_name ); |
1417 | for (i=0; algo_elems[i]; i++ ) | 1417 | for (i=0; algo_elems[i]; i++ ) |
1418 | { | 1418 | { |
1419 | *p++ = '('; | 1419 | *p++ = '('; |
1420 | *p++ = algo_elems[i]; | 1420 | *p++ = algo_elems[i]; |
1421 | p = stpcpy ( p, "%m)" ); | 1421 | p = stpcpy ( p, "%m)" ); |
1422 | } | 1422 | } |
1423 | strcpy ( p, "))" ); | 1423 | strcpy ( p, "))" ); |
1424 | 1424 | ||
1425 | /* And now the ugly part: We don't have a function to pass an | 1425 | /* And now the ugly part: We don't have a function to pass an |
1426 | * array to a format string, so we have to do it this way :-(. */ | 1426 | * array to a format string, so we have to do it this way :-(. */ |
1427 | /* FIXME: There is now such a format spefier, so we can could | 1427 | /* FIXME: There is now such a format spefier, so we can could |
1428 | change the code to be more clear. */ | 1428 | change the code to be more clear. */ |
1429 | arg_list = malloc (nelem * sizeof *arg_list); | 1429 | arg_list = malloc (nelem * sizeof *arg_list); |
1430 | if (!arg_list) | 1430 | if (!arg_list) |
1431 | { | 1431 | { |
1432 | rc = gpg_err_code_from_errno (errno); | 1432 | rc = gpg_err_code_from_errno (errno); |
1433 | goto leave; | 1433 | goto leave; |
1434 | } | 1434 | } |
1435 | 1435 | ||
1436 | for (i = 0; i < nelem; i++) | 1436 | for (i = 0; i < nelem; i++) |
1437 | arg_list[i] = ciph + i; | 1437 | arg_list[i] = ciph + i; |
1438 | 1438 | ||
1439 | rc = gcry_sexp_build_array (r_ciph, NULL, string, arg_list); | 1439 | rc = gcry_sexp_build_array (r_ciph, NULL, string, arg_list); |
1440 | free (arg_list); | 1440 | free (arg_list); |
1441 | if (rc) | 1441 | if (rc) |
1442 | BUG (); | 1442 | BUG (); |
1443 | gcry_free (string); | 1443 | gcry_free (string); |
1444 | } | 1444 | } |
1445 | 1445 | ||
1446 | leave: | 1446 | leave: |
1447 | if (pkey) | 1447 | if (pkey) |
1448 | { | 1448 | { |
1449 | release_mpi_array (pkey); | 1449 | release_mpi_array (pkey); |
1450 | gcry_free (pkey); | 1450 | gcry_free (pkey); |
1451 | } | 1451 | } |
1452 | 1452 | ||
1453 | if (ciph) | 1453 | if (ciph) |
1454 | { | 1454 | { |
1455 | release_mpi_array (ciph); | 1455 | release_mpi_array (ciph); |
1456 | gcry_free (ciph); | 1456 | gcry_free (ciph); |
1457 | } | 1457 | } |
1458 | 1458 | ||
1459 | if (module) | 1459 | if (module) |
1460 | { | 1460 | { |
1461 | ath_mutex_lock (&pubkeys_registered_lock); | 1461 | ath_mutex_lock (&pubkeys_registered_lock); |
1462 | _gcry_module_release (module); | 1462 | _gcry_module_release (module); |
1463 | ath_mutex_unlock (&pubkeys_registered_lock); | 1463 | ath_mutex_unlock (&pubkeys_registered_lock); |
1464 | } | 1464 | } |
1465 | 1465 | ||
1466 | return gcry_error (rc); | 1466 | return gcry_error (rc); |
1467 | } | 1467 | } |
1468 | 1468 | ||
1469 | /* | 1469 | /* |
1470 | Do a PK decrypt operation | 1470 | Do a PK decrypt operation |
1471 | 1471 | ||
1472 | Caller has to provide a secret key as the SEXP skey and data in a | 1472 | Caller has to provide a secret key as the SEXP skey and data in a |
1473 | format as created by gcry_pk_encrypt. For historic reasons the | 1473 | format as created by gcry_pk_encrypt. For historic reasons the |
1474 | function returns simply an MPI as an S-expression part; this is | 1474 | function returns simply an MPI as an S-expression part; this is |
1475 | deprecated and the new method should be used which returns a real | 1475 | deprecated and the new method should be used which returns a real |
1476 | S-expressionl this is selected by adding at least an empty flags | 1476 | S-expressionl this is selected by adding at least an empty flags |
1477 | list to S_DATA. | 1477 | list to S_DATA. |
1478 | 1478 | ||
1479 | Returns: 0 or an errorcode. | 1479 | Returns: 0 or an errorcode. |
1480 | 1480 | ||
1481 | s_data = (enc-val | 1481 | s_data = (enc-val |
1482 | [(flags)] | 1482 | [(flags)] |
1483 | (<algo> | 1483 | (<algo> |
1484 | (<param_name1> <mpi>) | 1484 | (<param_name1> <mpi>) |
1485 | ... | 1485 | ... |
1486 | (<param_namen> <mpi>) | 1486 | (<param_namen> <mpi>) |
1487 | )) | 1487 | )) |
1488 | s_skey = <key-as-defined-in-sexp_to_key> | 1488 | s_skey = <key-as-defined-in-sexp_to_key> |
1489 | r_plain= Either an incomplete S-expression without the parentheses | 1489 | r_plain= Either an incomplete S-expression without the parentheses |
1490 | or if the flags list is used (even if empty) a real S-expression: | 1490 | or if the flags list is used (even if empty) a real S-expression: |
1491 | (value PLAIN). | 1491 | (value PLAIN). |
1492 | */ | 1492 | */ |
1493 | gcry_error_t | 1493 | gcry_error_t |
1494 | gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) | 1494 | gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) |
1495 | { | 1495 | { |
1496 | gcry_mpi_t *skey = NULL, *data = NULL, plain = NULL; | 1496 | gcry_mpi_t *skey = NULL, *data = NULL, plain = NULL; |
1497 | int modern, want_pkcs1, flags; | 1497 | int modern, want_pkcs1, flags; |
1498 | gcry_err_code_t rc; | 1498 | gcry_err_code_t rc; |
1499 | gcry_module_t module_enc = NULL, module_key = NULL; | 1499 | gcry_module_t module_enc = NULL, module_key = NULL; |
1500 | gcry_pk_spec_t *pubkey = NULL; | 1500 | gcry_pk_spec_t *pubkey = NULL; |
1501 | 1501 | ||
1502 | REGISTER_DEFAULT_PUBKEYS; | 1502 | REGISTER_DEFAULT_PUBKEYS; |
1503 | 1503 | ||
1504 | *r_plain = NULL; | 1504 | *r_plain = NULL; |
1505 | rc = sexp_to_key (s_skey, 1, &skey, &module_key); | 1505 | rc = sexp_to_key (s_skey, 1, &skey, &module_key); |
1506 | if (rc) | 1506 | if (rc) |
1507 | goto leave; | 1507 | goto leave; |
1508 | 1508 | ||
1509 | rc = sexp_to_enc (s_data, &data, &module_enc, &modern, &want_pkcs1, &flags); | 1509 | rc = sexp_to_enc (s_data, &data, &module_enc, &modern, &want_pkcs1, &flags); |
1510 | if (rc) | 1510 | if (rc) |
1511 | goto leave; | 1511 | goto leave; |
1512 | 1512 | ||
1513 | if (module_key->mod_id != module_enc->mod_id) | 1513 | if (module_key->mod_id != module_enc->mod_id) |
1514 | { | 1514 | { |
1515 | rc = GPG_ERR_CONFLICT; /* Key algo does not match data algo. */ | 1515 | rc = GPG_ERR_CONFLICT; /* Key algo does not match data algo. */ |
1516 | goto leave; | 1516 | goto leave; |
1517 | } | 1517 | } |
1518 | 1518 | ||
1519 | pubkey = (gcry_pk_spec_t *) module_key->spec; | 1519 | pubkey = (gcry_pk_spec_t *) module_key->spec; |
1520 | 1520 | ||
1521 | rc = pubkey_decrypt (module_key->mod_id, &plain, data, skey, flags); | 1521 | rc = pubkey_decrypt (module_key->mod_id, &plain, data, skey, flags); |
1522 | if (rc) | 1522 | if (rc) |
1523 | goto leave; | 1523 | goto leave; |
1524 | 1524 | ||
1525 | if (gcry_sexp_build (r_plain, NULL, modern? "(value %m)" : "%m", plain)) | 1525 | if (gcry_sexp_build (r_plain, NULL, modern? "(value %m)" : "%m", plain)) |
1526 | BUG (); | 1526 | BUG (); |
1527 | 1527 | ||
1528 | leave: | 1528 | leave: |
1529 | if (skey) | 1529 | if (skey) |
1530 | { | 1530 | { |
1531 | release_mpi_array (skey); | 1531 | release_mpi_array (skey); |
1532 | gcry_free (skey); | 1532 | gcry_free (skey); |
1533 | } | 1533 | } |
1534 | 1534 | ||
1535 | if (plain) | 1535 | if (plain) |
1536 | mpi_free (plain); | 1536 | mpi_free (plain); |
1537 | 1537 | ||
1538 | if (data) | 1538 | if (data) |
1539 | { | 1539 | { |
1540 | release_mpi_array (data); | 1540 | release_mpi_array (data); |
1541 | gcry_free (data); | 1541 | gcry_free (data); |
1542 | } | 1542 | } |
1543 | 1543 | ||
1544 | if (module_key || module_enc) | 1544 | if (module_key || module_enc) |
1545 | { | 1545 | { |
1546 | ath_mutex_lock (&pubkeys_registered_lock); | 1546 | ath_mutex_lock (&pubkeys_registered_lock); |
1547 | if (module_key) | 1547 | if (module_key) |
1548 | _gcry_module_release (module_key); | 1548 | _gcry_module_release (module_key); |
1549 | if (module_enc) | 1549 | if (module_enc) |
1550 | _gcry_module_release (module_enc); | 1550 | _gcry_module_release (module_enc); |
1551 | ath_mutex_unlock (&pubkeys_registered_lock); | 1551 | ath_mutex_unlock (&pubkeys_registered_lock); |
1552 | } | 1552 | } |
1553 | 1553 | ||
1554 | return gcry_error (rc); | 1554 | return gcry_error (rc); |
1555 | } | 1555 | } |
1556 | 1556 | ||
1557 | 1557 | ||
1558 | 1558 | ||
1559 | /* | 1559 | /* |
1560 | Create a signature. | 1560 | Create a signature. |
1561 | 1561 | ||
1562 | Caller has to provide a secret key as the SEXP skey and data | 1562 | Caller has to provide a secret key as the SEXP skey and data |
1563 | expressed as a SEXP list hash with only one element which should | 1563 | expressed as a SEXP list hash with only one element which should |
1564 | instantly be available as a MPI. Alternatively the structure given | 1564 | instantly be available as a MPI. Alternatively the structure given |
1565 | below may be used for S_HASH, it provides the abiliy to pass flags | 1565 | below may be used for S_HASH, it provides the abiliy to pass flags |
1566 | to the operation; the only flag defined by now is "pkcs1" which | 1566 | to the operation; the only flag defined by now is "pkcs1" which |
1567 | does PKCS#1 block type 1 style padding. | 1567 | does PKCS#1 block type 1 style padding. |
1568 | 1568 | ||
1569 | Returns: 0 or an errorcode. | 1569 | Returns: 0 or an errorcode. |
1570 | In case of 0 the function returns a new SEXP with the | 1570 | In case of 0 the function returns a new SEXP with the |
1571 | signature value; the structure of this signature depends on the | 1571 | signature value; the structure of this signature depends on the |
1572 | other arguments but is always suitable to be passed to | 1572 | other arguments but is always suitable to be passed to |
1573 | gcry_pk_verify | 1573 | gcry_pk_verify |
1574 | 1574 | ||
1575 | s_hash = See comment for sexp_data_to_mpi | 1575 | s_hash = See comment for sexp_data_to_mpi |
1576 | 1576 | ||
1577 | s_skey = <key-as-defined-in-sexp_to_key> | 1577 | s_skey = <key-as-defined-in-sexp_to_key> |
1578 | r_sig = (sig-val | 1578 | r_sig = (sig-val |
1579 | (<algo> | 1579 | (<algo> |
1580 | (<param_name1> <mpi>) | 1580 | (<param_name1> <mpi>) |
1581 | ... | 1581 | ... |
1582 | (<param_namen> <mpi>))) | 1582 | (<param_namen> <mpi>))) |
1583 | */ | 1583 | */ |
1584 | gcry_error_t | 1584 | gcry_error_t |
1585 | gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) | 1585 | gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) |
1586 | { | 1586 | { |
1587 | gcry_mpi_t *skey = NULL, hash = NULL, *result = NULL; | 1587 | gcry_mpi_t *skey = NULL, hash = NULL, *result = NULL; |
1588 | gcry_pk_spec_t *pubkey = NULL; | 1588 | gcry_pk_spec_t *pubkey = NULL; |
1589 | gcry_module_t module = NULL; | 1589 | gcry_module_t module = NULL; |
1590 | const char *algo_name, *algo_elems; | 1590 | const char *algo_name, *algo_elems; |
1591 | int i; | 1591 | int i; |
1592 | gcry_err_code_t rc; | 1592 | gcry_err_code_t rc; |
1593 | 1593 | ||
1594 | REGISTER_DEFAULT_PUBKEYS; | 1594 | REGISTER_DEFAULT_PUBKEYS; |
1595 | 1595 | ||
1596 | *r_sig = NULL; | 1596 | *r_sig = NULL; |
1597 | rc = sexp_to_key (s_skey, 1, &skey, &module); | 1597 | rc = sexp_to_key (s_skey, 1, &skey, &module); |
1598 | if (rc) | 1598 | if (rc) |
1599 | goto leave; | 1599 | goto leave; |
1600 | 1600 | ||
1601 | assert (module); | 1601 | assert (module); |
1602 | pubkey = (gcry_pk_spec_t *) module->spec; | 1602 | pubkey = (gcry_pk_spec_t *) module->spec; |
1603 | algo_name = pubkey->aliases? *pubkey->aliases : NULL; | 1603 | algo_name = pubkey->aliases? *pubkey->aliases : NULL; |
1604 | if (!algo_name || !*algo_name) | 1604 | if (!algo_name || !*algo_name) |
1605 | algo_name = pubkey->name; | 1605 | algo_name = pubkey->name; |
1606 | 1606 | ||
1607 | algo_elems = pubkey->elements_sig; | 1607 | algo_elems = pubkey->elements_sig; |
1608 | 1608 | ||
1609 | /* Get the stuff we want to sign. Note that pk_get_nbits does also | 1609 | /* Get the stuff we want to sign. Note that pk_get_nbits does also |
1610 | work on a private key. */ | 1610 | work on a private key. */ |
1611 | rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey), | 1611 | rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey), |
1612 | &hash, 0, NULL); | 1612 | &hash, 0, NULL); |
1613 | if (rc) | 1613 | if (rc) |
1614 | goto leave; | 1614 | goto leave; |
1615 | 1615 | ||
1616 | result = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*result)); | 1616 | result = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*result)); |
1617 | rc = pubkey_sign (module->mod_id, result, hash, skey); | 1617 | rc = pubkey_sign (module->mod_id, result, hash, skey); |
1618 | if (rc) | 1618 | if (rc) |
1619 | goto leave; | 1619 | goto leave; |
1620 | 1620 | ||
1621 | { | 1621 | { |
1622 | char *string, *p; | 1622 | char *string, *p; |
1623 | size_t nelem, needed = strlen (algo_name) + 20; | 1623 | size_t nelem, needed = strlen (algo_name) + 20; |
1624 | void **arg_list; | 1624 | void **arg_list; |
1625 | 1625 | ||
1626 | nelem = strlen (algo_elems); | 1626 | nelem = strlen (algo_elems); |
1627 | 1627 | ||
1628 | /* Count elements, so that we can allocate enough space. */ | 1628 | /* Count elements, so that we can allocate enough space. */ |
1629 | needed += 10 * nelem; | 1629 | needed += 10 * nelem; |
1630 | 1630 | ||
1631 | /* Build the string. */ | 1631 | /* Build the string. */ |
1632 | string = p = gcry_xmalloc (needed); | 1632 | string = p = gcry_xmalloc (needed); |
1633 | p = stpcpy (p, "(sig-val("); | 1633 | p = stpcpy (p, "(sig-val("); |
1634 | p = stpcpy (p, algo_name); | 1634 | p = stpcpy (p, algo_name); |
1635 | for (i = 0; algo_elems[i]; i++) | 1635 | for (i = 0; algo_elems[i]; i++) |
1636 | { | 1636 | { |
1637 | *p++ = '('; | 1637 | *p++ = '('; |
1638 | *p++ = algo_elems[i]; | 1638 | *p++ = algo_elems[i]; |
1639 | p = stpcpy (p, "%m)"); | 1639 | p = stpcpy (p, "%m)"); |
1640 | } | 1640 | } |
1641 | strcpy (p, "))"); | 1641 | strcpy (p, "))"); |
1642 | 1642 | ||
1643 | arg_list = malloc (nelem * sizeof *arg_list); | 1643 | arg_list = malloc (nelem * sizeof *arg_list); |
1644 | if (!arg_list) | 1644 | if (!arg_list) |
1645 | { | 1645 | { |
1646 | rc = gpg_err_code_from_errno (errno); | 1646 | rc = gpg_err_code_from_errno (errno); |
1647 | goto leave; | 1647 | goto leave; |
1648 | } | 1648 | } |
1649 | 1649 | ||
1650 | for (i = 0; i < nelem; i++) | 1650 | for (i = 0; i < nelem; i++) |
1651 | arg_list[i] = result + i; | 1651 | arg_list[i] = result + i; |
1652 | 1652 | ||
1653 | rc = gcry_sexp_build_array (r_sig, NULL, string, arg_list); | 1653 | rc = gcry_sexp_build_array (r_sig, NULL, string, arg_list); |
1654 | free (arg_list); | 1654 | free (arg_list); |
1655 | if (rc) | 1655 | if (rc) |
1656 | BUG (); | 1656 | BUG (); |
1657 | gcry_free (string); | 1657 | gcry_free (string); |
1658 | } | 1658 | } |
1659 | 1659 | ||
1660 | leave: | 1660 | leave: |
1661 | if (skey) | 1661 | if (skey) |
1662 | { | 1662 | { |
1663 | release_mpi_array (skey); | 1663 | release_mpi_array (skey); |
1664 | gcry_free (skey); | 1664 | gcry_free (skey); |
1665 | } | 1665 | } |
1666 | 1666 | ||
1667 | if (hash) | 1667 | if (hash) |
1668 | mpi_free (hash); | 1668 | mpi_free (hash); |
1669 | 1669 | ||
1670 | if (result) | 1670 | if (result) |
1671 | { | 1671 | { |
1672 | release_mpi_array (result); | 1672 | release_mpi_array (result); |
1673 | gcry_free (result); | 1673 | gcry_free (result); |
1674 | } | 1674 | } |
1675 | 1675 | ||
1676 | return gcry_error (rc); | 1676 | return gcry_error (rc); |
1677 | } | 1677 | } |
1678 | 1678 | ||
1679 | 1679 | ||
1680 | /* | 1680 | /* |
1681 | Verify a signature. | 1681 | Verify a signature. |
1682 | 1682 | ||
1683 | Caller has to supply the public key pkey, the signature sig and his | 1683 | Caller has to supply the public key pkey, the signature sig and his |
1684 | hashvalue data. Public key has to be a standard public key given | 1684 | hashvalue data. Public key has to be a standard public key given |
1685 | as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data | 1685 | as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data |
1686 | must be an S-Exp like the one in sign too. */ | 1686 | must be an S-Exp like the one in sign too. */ |
1687 | gcry_error_t | 1687 | gcry_error_t |
1688 | gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) | 1688 | gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) |
1689 | { | 1689 | { |
1690 | gcry_module_t module_key = NULL, module_sig = NULL; | 1690 | gcry_module_t module_key = NULL, module_sig = NULL; |
1691 | gcry_mpi_t *pkey = NULL, hash = NULL, *sig = NULL; | 1691 | gcry_mpi_t *pkey = NULL, hash = NULL, *sig = NULL; |
1692 | gcry_err_code_t rc; | 1692 | gcry_err_code_t rc; |
1693 | 1693 | ||
1694 | REGISTER_DEFAULT_PUBKEYS; | 1694 | REGISTER_DEFAULT_PUBKEYS; |
1695 | 1695 | ||
1696 | rc = sexp_to_key (s_pkey, 0, &pkey, &module_key); | 1696 | rc = sexp_to_key (s_pkey, 0, &pkey, &module_key); |
1697 | if (rc) | 1697 | if (rc) |
1698 | goto leave; | 1698 | goto leave; |
1699 | 1699 | ||
1700 | rc = sexp_to_sig (s_sig, &sig, &module_sig); | 1700 | rc = sexp_to_sig (s_sig, &sig, &module_sig); |
1701 | if (rc) | 1701 | if (rc) |
1702 | goto leave; | 1702 | goto leave; |
1703 | 1703 | ||
1704 | if (module_key->mod_id != module_sig->mod_id) | 1704 | if (module_key->mod_id != module_sig->mod_id) |
1705 | { | 1705 | { |
1706 | rc = GPG_ERR_CONFLICT; | 1706 | rc = GPG_ERR_CONFLICT; |
1707 | goto leave; | 1707 | goto leave; |
1708 | } | 1708 | } |
1709 | 1709 | ||
1710 | rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0, 0); | 1710 | rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0, 0); |
1711 | if (rc) | 1711 | if (rc) |
1712 | goto leave; | 1712 | goto leave; |
1713 | 1713 | ||
1714 | rc = pubkey_verify (module_key->mod_id, hash, sig, pkey, NULL, NULL); | 1714 | rc = pubkey_verify (module_key->mod_id, hash, sig, pkey, NULL, NULL); |
1715 | 1715 | ||
1716 | leave: | 1716 | leave: |
1717 | if (pkey) | 1717 | if (pkey) |
1718 | { | 1718 | { |
1719 | release_mpi_array (pkey); | 1719 | release_mpi_array (pkey); |
1720 | gcry_free (pkey); | 1720 | gcry_free (pkey); |
1721 | } | 1721 | } |
1722 | if (sig) | 1722 | if (sig) |
1723 | { | 1723 | { |
1724 | release_mpi_array (sig); | 1724 | release_mpi_array (sig); |
1725 | gcry_free (sig); | 1725 | gcry_free (sig); |
1726 | } | 1726 | } |
1727 | if (hash) | 1727 | if (hash) |
1728 | mpi_free (hash); | 1728 | mpi_free (hash); |
1729 | 1729 | ||
1730 | if (module_key || module_sig) | 1730 | if (module_key || module_sig) |
1731 | { | 1731 | { |
1732 | ath_mutex_lock (&pubkeys_registered_lock); | 1732 | ath_mutex_lock (&pubkeys_registered_lock); |
1733 | if (module_key) | 1733 | if (module_key) |
1734 | _gcry_module_release (module_key); | 1734 | _gcry_module_release (module_key); |
1735 | if (module_sig) | 1735 | if (module_sig) |
1736 | _gcry_module_release (module_sig); | 1736 | _gcry_module_release (module_sig); |
1737 | ath_mutex_unlock (&pubkeys_registered_lock); | 1737 | ath_mutex_unlock (&pubkeys_registered_lock); |
1738 | } | 1738 | } |
1739 | 1739 | ||
1740 | return gcry_error (rc); | 1740 | return gcry_error (rc); |
1741 | } | 1741 | } |
1742 | 1742 | ||
1743 | 1743 | ||
1744 | /* | 1744 | /* |
1745 | Test a key. | 1745 | Test a key. |
1746 | 1746 | ||
1747 | This may be used either for a public or a secret key to see whether | 1747 | This may be used either for a public or a secret key to see whether |
1748 | internal structre is valid. | 1748 | internal structre is valid. |
1749 | 1749 | ||
1750 | Returns: 0 or an errorcode. | 1750 | Returns: 0 or an errorcode. |
1751 | 1751 | ||
1752 | s_key = <key-as-defined-in-sexp_to_key> */ | 1752 | s_key = <key-as-defined-in-sexp_to_key> */ |
1753 | gcry_error_t | 1753 | gcry_error_t |
1754 | gcry_pk_testkey (gcry_sexp_t s_key) | 1754 | gcry_pk_testkey (gcry_sexp_t s_key) |
1755 | { | 1755 | { |
1756 | gcry_module_t module = NULL; | 1756 | gcry_module_t module = NULL; |
1757 | gcry_mpi_t *key = NULL; | 1757 | gcry_mpi_t *key = NULL; |
1758 | gcry_err_code_t rc; | 1758 | gcry_err_code_t rc; |
1759 | 1759 | ||
1760 | REGISTER_DEFAULT_PUBKEYS; | 1760 | REGISTER_DEFAULT_PUBKEYS; |
1761 | 1761 | ||
1762 | /* Note we currently support only secret key checking. */ | 1762 | /* Note we currently support only secret key checking. */ |
1763 | rc = sexp_to_key (s_key, 1, &key, &module); | 1763 | rc = sexp_to_key (s_key, 1, &key, &module); |
1764 | if (! rc) | 1764 | if (! rc) |
1765 | { | 1765 | { |
1766 | rc = pubkey_check_secret_key (module->mod_id, key); | 1766 | rc = pubkey_check_secret_key (module->mod_id, key); |
1767 | release_mpi_array (key); | 1767 | release_mpi_array (key); |
1768 | gcry_free (key); | 1768 | gcry_free (key); |
1769 | } | 1769 | } |
1770 | return gcry_error (rc); | 1770 | return gcry_error (rc); |
1771 | } | 1771 | } |
1772 | 1772 | ||
1773 | 1773 | ||
1774 | /* | 1774 | /* |
1775 | Create a public key pair and return it in r_key. | 1775 | Create a public key pair and return it in r_key. |
1776 | How the key is created depends on s_parms: | 1776 | How the key is created depends on s_parms: |
1777 | (genkey | 1777 | (genkey |
1778 | (algo | 1778 | (algo |
1779 | (parameter_name_1 ....) | 1779 | (parameter_name_1 ....) |
1780 | .... | 1780 | .... |
1781 | (parameter_name_n ....) | 1781 | (parameter_name_n ....) |
1782 | )) | 1782 | )) |
1783 | The key is returned in a format depending on the | 1783 | The key is returned in a format depending on the |
1784 | algorithm. Both, private and secret keys are returned | 1784 | algorithm. Both, private and secret keys are returned |
1785 | and optionally some additional informatin. | 1785 | and optionally some additional informatin. |
1786 | For elgamal we return this structure: | 1786 | For elgamal we return this structure: |
1787 | (key-data | 1787 | (key-data |
1788 | (public-key | 1788 | (public-key |
1789 | (elg | 1789 | (elg |
1790 | (p <mpi>) | 1790 | (p <mpi>) |
1791 | (g <mpi>) | 1791 | (g <mpi>) |
1792 | (y <mpi>) | 1792 | (y <mpi>) |
1793 | ) | 1793 | ) |
1794 | ) | 1794 | ) |
1795 | (private-key | 1795 | (private-key |
1796 | (elg | 1796 | (elg |
1797 | (p <mpi>) | 1797 | (p <mpi>) |
1798 | (g <mpi>) | 1798 | (g <mpi>) |
1799 | (y <mpi>) | 1799 | (y <mpi>) |
1800 | (x <mpi>) | 1800 | (x <mpi>) |
1801 | ) | 1801 | ) |
1802 | ) | 1802 | ) |
1803 | (misc-key-info | 1803 | (misc-key-info |
1804 | (pm1-factors n1 n2 ... nn) | 1804 | (pm1-factors n1 n2 ... nn) |
1805 | )) | 1805 | )) |
1806 | */ | 1806 | */ |
1807 | gcry_error_t | 1807 | gcry_error_t |
1808 | gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) | 1808 | gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) |
1809 | { | 1809 | { |
1810 | gcry_pk_spec_t *pubkey = NULL; | 1810 | gcry_pk_spec_t *pubkey = NULL; |
1811 | gcry_module_t module = NULL; | 1811 | gcry_module_t module = NULL; |
1812 | gcry_sexp_t list = NULL, l2 = NULL; | 1812 | gcry_sexp_t list = NULL, l2 = NULL; |
1813 | const char *name; | 1813 | const char *name; |
1814 | size_t n; | 1814 | size_t n; |
1815 | gcry_err_code_t rc = GPG_ERR_NO_ERROR; | 1815 | gcry_err_code_t rc = GPG_ERR_NO_ERROR; |
1816 | int i; | 1816 | int i; |
1817 | const char *algo_name = NULL; | 1817 | const char *algo_name = NULL; |
1818 | int algo; | 1818 | int algo; |
1819 | const char *sec_elems = NULL, *pub_elems = NULL; | 1819 | const char *sec_elems = NULL, *pub_elems = NULL; |
1820 | gcry_mpi_t skey[10], *factors = NULL; | 1820 | gcry_mpi_t skey[10], *factors = NULL; |
1821 | unsigned int nbits = 0; | 1821 | unsigned int nbits = 0; |
1822 | unsigned long use_e = 0; | 1822 | unsigned long use_e = 0; |
1823 | char *name_terminated; | 1823 | char *name_terminated; |
1824 | 1824 | ||
1825 | REGISTER_DEFAULT_PUBKEYS; | 1825 | REGISTER_DEFAULT_PUBKEYS; |
1826 | 1826 | ||
1827 | skey[0] = NULL; | 1827 | skey[0] = NULL; |
1828 | *r_key = NULL; | 1828 | *r_key = NULL; |
1829 | 1829 | ||
1830 | list = gcry_sexp_find_token (s_parms, "genkey", 0); | 1830 | list = gcry_sexp_find_token (s_parms, "genkey", 0); |
1831 | if (!list) | 1831 | if (!list) |
1832 | { | 1832 | { |
1833 | rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */ | 1833 | rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */ |
1834 | goto leave; | 1834 | goto leave; |
1835 | } | 1835 | } |
1836 | 1836 | ||
1837 | l2 = gcry_sexp_cadr (list); | 1837 | l2 = gcry_sexp_cadr (list); |
1838 | gcry_sexp_release (list); | 1838 | gcry_sexp_release (list); |
1839 | list = l2; | 1839 | list = l2; |
1840 | l2 = NULL; | 1840 | l2 = NULL; |
1841 | if (! list) | 1841 | if (! list) |
1842 | { | 1842 | { |
1843 | rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */ | 1843 | rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */ |
1844 | goto leave; | 1844 | goto leave; |
1845 | } | 1845 | } |
1846 | 1846 | ||
1847 | name = gcry_sexp_nth_data (list, 0, &n); | 1847 | name = gcry_sexp_nth_data (list, 0, &n); |
1848 | if (! name) | 1848 | if (! name) |
1849 | { | 1849 | { |
1850 | rc = GPG_ERR_INV_OBJ; /* Algo string missing. */ | 1850 | rc = GPG_ERR_INV_OBJ; /* Algo string missing. */ |
1851 | goto leave; | 1851 | goto leave; |
1852 | } | 1852 | } |
1853 | 1853 | ||
1854 | name_terminated = gcry_xmalloc (n + 1); | 1854 | name_terminated = gcry_xmalloc (n + 1); |
1855 | memcpy (name_terminated, name, n); | 1855 | memcpy (name_terminated, name, n); |
1856 | name_terminated[n] = 0; | 1856 | name_terminated[n] = 0; |
1857 | ath_mutex_lock (&pubkeys_registered_lock); | 1857 | ath_mutex_lock (&pubkeys_registered_lock); |
1858 | module = gcry_pk_lookup_name (name_terminated); | 1858 | module = gcry_pk_lookup_name (name_terminated); |
1859 | ath_mutex_unlock (&pubkeys_registered_lock); | 1859 | ath_mutex_unlock (&pubkeys_registered_lock); |
1860 | gcry_free (name_terminated); | 1860 | gcry_free (name_terminated); |
1861 | 1861 | ||
1862 | if (! module) | 1862 | if (! module) |
1863 | { | 1863 | { |
1864 | rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ | 1864 | rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ |
1865 | goto leave; | 1865 | goto leave; |
1866 | } | 1866 | } |
1867 | 1867 | ||
1868 | pubkey = (gcry_pk_spec_t *) module->spec; | 1868 | pubkey = (gcry_pk_spec_t *) module->spec; |
1869 | algo = module->mod_id; | 1869 | algo = module->mod_id; |
1870 | algo_name = pubkey->aliases? *pubkey->aliases : NULL; | 1870 | algo_name = pubkey->aliases? *pubkey->aliases : NULL; |
1871 | if (!algo_name || !*algo_name) | 1871 | if (!algo_name || !*algo_name) |
1872 | algo_name = pubkey->name; | 1872 | algo_name = pubkey->name; |
1873 | pub_elems = pubkey->elements_pkey; | 1873 | pub_elems = pubkey->elements_pkey; |
1874 | sec_elems = pubkey->elements_skey; | 1874 | sec_elems = pubkey->elements_skey; |
1875 | 1875 | ||
1876 | /* Handle the optional rsa-use-e element. */ | 1876 | /* Handle the optional rsa-use-e element. */ |
1877 | l2 = gcry_sexp_find_token (list, "rsa-use-e", 0); | 1877 | l2 = gcry_sexp_find_token (list, "rsa-use-e", 0); |
1878 | if (l2) | 1878 | if (l2) |
1879 | { | 1879 | { |
1880 | char buf[50]; | 1880 | char buf[50]; |
1881 | 1881 | ||
1882 | name = gcry_sexp_nth_data (l2, 1, &n); | 1882 | name = gcry_sexp_nth_data (l2, 1, &n); |
1883 | if ((! name) || (n >= DIM (buf) - 1)) | 1883 | if ((! name) || (n >= DIM (buf) - 1)) |
1884 | { | 1884 | { |
1885 | rc = GPG_ERR_INV_OBJ; /* No value or value too large. */ | 1885 | rc = GPG_ERR_INV_OBJ; /* No value or value too large. */ |
1886 | goto leave; | 1886 | goto leave; |
1887 | } | 1887 | } |
1888 | memcpy (buf, name, n); | 1888 | memcpy (buf, name, n); |
1889 | buf[n] = 0; | 1889 | buf[n] = 0; |
1890 | use_e = strtoul (buf, NULL, 0); | 1890 | use_e = strtoul (buf, NULL, 0); |
1891 | gcry_sexp_release (l2); | 1891 | gcry_sexp_release (l2); |
1892 | l2 = NULL; | 1892 | l2 = NULL; |
1893 | } | 1893 | } |
1894 | else | 1894 | else |
1895 | use_e = 65537; /* Not given, use the value generated by old versions. */ | 1895 | use_e = 65537; /* Not given, use the value generated by old versions. */ |
1896 | 1896 | ||
1897 | l2 = gcry_sexp_find_token (list, "nbits", 0); | 1897 | l2 = gcry_sexp_find_token (list, "nbits", 0); |
1898 | gcry_sexp_release (list); | 1898 | gcry_sexp_release (list); |
1899 | list = l2; | 1899 | list = l2; |
1900 | l2 = NULL; | 1900 | l2 = NULL; |
1901 | 1901 | ||
1902 | if (! list) | 1902 | if (! list) |
1903 | { | 1903 | { |
1904 | rc = GPG_ERR_NO_OBJ; /* No nbits parameter. */ | 1904 | rc = GPG_ERR_NO_OBJ; /* No nbits parameter. */ |
1905 | goto leave; | 1905 | goto leave; |
1906 | } | 1906 | } |
1907 | 1907 | ||
1908 | name = gcry_sexp_nth_data (list, 1, &n); | 1908 | name = gcry_sexp_nth_data (list, 1, &n); |
1909 | if (! name) | 1909 | if (! name) |
1910 | { | 1910 | { |
1911 | rc = GPG_ERR_INV_OBJ; /* nbits without a cdr. */ | 1911 | rc = GPG_ERR_INV_OBJ; /* nbits without a cdr. */ |
1912 | goto leave; | 1912 | goto leave; |
1913 | } | 1913 | } |
1914 | 1914 | ||
1915 | name_terminated = gcry_xmalloc (n + 1); | 1915 | name_terminated = gcry_xmalloc (n + 1); |
1916 | memcpy (name_terminated, name, n); | 1916 | memcpy (name_terminated, name, n); |
1917 | name_terminated[n] = 0; | 1917 | name_terminated[n] = 0; |
1918 | nbits = (unsigned int) strtoul (name_terminated, NULL, 0); | 1918 | nbits = (unsigned int) strtoul (name_terminated, NULL, 0); |
1919 | gcry_free (name_terminated); | 1919 | gcry_free (name_terminated); |
1920 | 1920 | ||
1921 | rc = pubkey_generate (module->mod_id, nbits, use_e, skey, &factors); | 1921 | rc = pubkey_generate (module->mod_id, nbits, use_e, skey, &factors); |
1922 | if (rc) | 1922 | if (rc) |
1923 | goto leave; | 1923 | goto leave; |
1924 | 1924 | ||
1925 | { | 1925 | { |
1926 | char *string, *p; | 1926 | char *string, *p; |
1927 | size_t nelem=0, nelem_cp = 0, needed=0; | 1927 | size_t nelem=0, nelem_cp = 0, needed=0; |
1928 | gcry_mpi_t mpis[30]; | 1928 | gcry_mpi_t mpis[30]; |
1929 | 1929 | ||
1930 | nelem = strlen (pub_elems) + strlen (sec_elems); | 1930 | nelem = strlen (pub_elems) + strlen (sec_elems); |
1931 | for (i = 0; factors[i]; i++) | 1931 | for (i = 0; factors[i]; i++) |
1932 | nelem++; | 1932 | nelem++; |
1933 | nelem_cp = nelem; | 1933 | nelem_cp = nelem; |
1934 | 1934 | ||
1935 | needed += nelem * 10; | 1935 | needed += nelem * 10; |
1936 | needed += 2 * strlen (algo_name) + 300; | 1936 | needed += 2 * strlen (algo_name) + 300; |
1937 | if (nelem > DIM (mpis)) | 1937 | if (nelem > DIM (mpis)) |
1938 | BUG (); | 1938 | BUG (); |
1939 | 1939 | ||
1940 | /* Build the string. */ | 1940 | /* Build the string. */ |
1941 | nelem = 0; | 1941 | nelem = 0; |
1942 | string = p = gcry_xmalloc (needed); | 1942 | string = p = gcry_xmalloc (needed); |
1943 | p = stpcpy (p, "(key-data"); | 1943 | p = stpcpy (p, "(key-data"); |
1944 | p = stpcpy (p, "(public-key("); | 1944 | p = stpcpy (p, "(public-key("); |
1945 | p = stpcpy (p, algo_name); | 1945 | p = stpcpy (p, algo_name); |
1946 | for(i = 0; pub_elems[i]; i++) | 1946 | for(i = 0; pub_elems[i]; i++) |
1947 | { | 1947 | { |
1948 | *p++ = '('; | 1948 | *p++ = '('; |
1949 | *p++ = pub_elems[i]; | 1949 | *p++ = pub_elems[i]; |
1950 | p = stpcpy (p, "%m)"); | 1950 | p = stpcpy (p, "%m)"); |
1951 | mpis[nelem++] = skey[i]; | 1951 | mpis[nelem++] = skey[i]; |
1952 | } | 1952 | } |
1953 | p = stpcpy (p, "))"); | 1953 | p = stpcpy (p, "))"); |
1954 | p = stpcpy (p, "(private-key("); | 1954 | p = stpcpy (p, "(private-key("); |
1955 | p = stpcpy (p, algo_name); | 1955 | p = stpcpy (p, algo_name); |
1956 | for (i = 0; sec_elems[i]; i++) | 1956 | for (i = 0; sec_elems[i]; i++) |
1957 | { | 1957 | { |
1958 | *p++ = '('; | 1958 | *p++ = '('; |
1959 | *p++ = sec_elems[i]; | 1959 | *p++ = sec_elems[i]; |
1960 | p = stpcpy (p, "%m)"); | 1960 | p = stpcpy (p, "%m)"); |
1961 | mpis[nelem++] = skey[i]; | 1961 | mpis[nelem++] = skey[i]; |
1962 | } | 1962 | } |
1963 | p = stpcpy (p, "))"); | 1963 | p = stpcpy (p, "))"); |
1964 | 1964 | ||
1965 | /* Very ugly hack to make release_mpi_array() work FIXME */ | 1965 | /* Very ugly hack to make release_mpi_array() work FIXME */ |
1966 | skey[i] = NULL; | 1966 | skey[i] = NULL; |
1967 | 1967 | ||
1968 | p = stpcpy (p, "(misc-key-info(pm1-factors"); | 1968 | p = stpcpy (p, "(misc-key-info(pm1-factors"); |
1969 | for(i = 0; factors[i]; i++) | 1969 | for(i = 0; factors[i]; i++) |
1970 | { | 1970 | { |
1971 | p = stpcpy (p, "%m"); | 1971 | p = stpcpy (p, "%m"); |
1972 | mpis[nelem++] = factors[i]; | 1972 | mpis[nelem++] = factors[i]; |
1973 | } | 1973 | } |
1974 | strcpy (p, ")))"); | 1974 | strcpy (p, ")))"); |
1975 | 1975 | ||
1976 | while (nelem < DIM (mpis)) | 1976 | while (nelem < DIM (mpis)) |
1977 | mpis[nelem++] = NULL; | 1977 | mpis[nelem++] = NULL; |
1978 | 1978 | ||
1979 | { | 1979 | { |
1980 | int elem_n = strlen (pub_elems) + strlen (sec_elems); | 1980 | int elem_n = strlen (pub_elems) + strlen (sec_elems); |
1981 | void **arg_list; | 1981 | void **arg_list; |
1982 | 1982 | ||
1983 | arg_list = malloc (nelem_cp * sizeof *arg_list); | 1983 | arg_list = malloc (nelem_cp * sizeof *arg_list); |
1984 | if (!arg_list) | 1984 | if (!arg_list) |
1985 | { | 1985 | { |
1986 | rc = gpg_err_code_from_errno (errno); | 1986 | rc = gpg_err_code_from_errno (errno); |
1987 | goto leave; | 1987 | goto leave; |
1988 | } | 1988 | } |
1989 | for (i = 0; i < elem_n; i++) | 1989 | for (i = 0; i < elem_n; i++) |
1990 | arg_list[i] = mpis + i; | 1990 | arg_list[i] = mpis + i; |
1991 | for (; i < nelem_cp; i++) | 1991 | for (; i < nelem_cp; i++) |
1992 | arg_list[i] = factors + i - elem_n; | 1992 | arg_list[i] = factors + i - elem_n; |
1993 | 1993 | ||
1994 | rc = gcry_sexp_build_array (r_key, NULL, string, arg_list); | 1994 | rc = gcry_sexp_build_array (r_key, NULL, string, arg_list); |
1995 | free (arg_list); | 1995 | free (arg_list); |
1996 | if (rc) | 1996 | if (rc) |
1997 | BUG (); | 1997 | BUG (); |
1998 | assert (DIM (mpis) == 30); /* Reminder to make sure that the | 1998 | assert (DIM (mpis) == 30); /* Reminder to make sure that the |
1999 | array gets increased if new | 1999 | array gets increased if new |
2000 | parameters are added. */ | 2000 | parameters are added. */ |
2001 | } | 2001 | } |
2002 | gcry_free (string); | 2002 | gcry_free (string); |
2003 | } | 2003 | } |
2004 | 2004 | ||
2005 | leave: | 2005 | leave: |
2006 | release_mpi_array (skey); | 2006 | release_mpi_array (skey); |
2007 | /* Don't free SKEY itself, it is a static array. */ | 2007 | /* Don't free SKEY itself, it is a static array. */ |
2008 | 2008 | ||
2009 | if (factors) | 2009 | if (factors) |
2010 | { | 2010 | { |
2011 | release_mpi_array ( factors ); | 2011 | release_mpi_array ( factors ); |
2012 | gcry_free (factors); | 2012 | gcry_free (factors); |
2013 | } | 2013 | } |
2014 | 2014 | ||
2015 | if (l2) | 2015 | if (l2) |
2016 | gcry_sexp_release (l2); | 2016 | gcry_sexp_release (l2); |
2017 | if (list) | 2017 | if (list) |
2018 | gcry_sexp_release (list); | 2018 | gcry_sexp_release (list); |
2019 | 2019 | ||
2020 | if (module) | 2020 | if (module) |
2021 | { | 2021 | { |
2022 | ath_mutex_lock (&pubkeys_registered_lock); | 2022 | ath_mutex_lock (&pubkeys_registered_lock); |
2023 | _gcry_module_release (module); | 2023 | _gcry_module_release (module); |
2024 | ath_mutex_unlock (&pubkeys_registered_lock); | 2024 | ath_mutex_unlock (&pubkeys_registered_lock); |
2025 | } | 2025 | } |
2026 | 2026 | ||
2027 | return gcry_error (rc); | 2027 | return gcry_error (rc); |
2028 | } | 2028 | } |
2029 | 2029 | ||
2030 | 2030 | ||
2031 | /* | 2031 | /* |
2032 | Get the number of nbits from the public key. | 2032 | Get the number of nbits from the public key. |
2033 | 2033 | ||
2034 | Hmmm: Should we have really this function or is it better to have a | 2034 | Hmmm: Should we have really this function or is it better to have a |
2035 | more general function to retrieve different propoerties of the key? */ | 2035 | more general function to retrieve different propoerties of the key? */ |
2036 | unsigned int | 2036 | unsigned int |
2037 | gcry_pk_get_nbits (gcry_sexp_t key) | 2037 | gcry_pk_get_nbits (gcry_sexp_t key) |
2038 | { | 2038 | { |
2039 | gcry_module_t module = NULL; | 2039 | gcry_module_t module = NULL; |
2040 | gcry_pk_spec_t *pubkey; | 2040 | gcry_pk_spec_t *pubkey; |
2041 | gcry_mpi_t *keyarr = NULL; | 2041 | gcry_mpi_t *keyarr = NULL; |
2042 | unsigned int nbits = 0; | 2042 | unsigned int nbits = 0; |
2043 | gcry_err_code_t rc; | 2043 | gcry_err_code_t rc; |
2044 | 2044 | ||
2045 | REGISTER_DEFAULT_PUBKEYS; | 2045 | REGISTER_DEFAULT_PUBKEYS; |
2046 | 2046 | ||
2047 | rc = sexp_to_key (key, 0, &keyarr, &module); | 2047 | rc = sexp_to_key (key, 0, &keyarr, &module); |
2048 | if (rc == GPG_ERR_INV_OBJ) | 2048 | if (rc == GPG_ERR_INV_OBJ) |
2049 | rc = sexp_to_key (key, 1, &keyarr, &module); | 2049 | rc = sexp_to_key (key, 1, &keyarr, &module); |
2050 | if (rc) | 2050 | if (rc) |
2051 | return 0; /* Error - 0 is a suitable indication for that. */ | 2051 | return 0; /* Error - 0 is a suitable indication for that. */ |
2052 | 2052 | ||
2053 | pubkey = (gcry_pk_spec_t *) module->spec; | 2053 | pubkey = (gcry_pk_spec_t *) module->spec; |
2054 | nbits = (*pubkey->get_nbits) (module->mod_id, keyarr); | 2054 | nbits = (*pubkey->get_nbits) (module->mod_id, keyarr); |
2055 | 2055 | ||
2056 | ath_mutex_lock (&pubkeys_registered_lock); | 2056 | ath_mutex_lock (&pubkeys_registered_lock); |
2057 | _gcry_module_release (module); | 2057 | _gcry_module_release (module); |
2058 | ath_mutex_unlock (&pubkeys_registered_lock); | 2058 | ath_mutex_unlock (&pubkeys_registered_lock); |
2059 | 2059 | ||
2060 | release_mpi_array (keyarr); | 2060 | release_mpi_array (keyarr); |
2061 | gcry_free (keyarr); | 2061 | gcry_free (keyarr); |
2062 | 2062 | ||
2063 | return nbits; | 2063 | return nbits; |
2064 | } | 2064 | } |
2065 | 2065 | ||
2066 | 2066 | ||
2067 | /* Return the so called KEYGRIP which is the SHA-1 hash of the public | 2067 | /* Return the so called KEYGRIP which is the SHA-1 hash of the public |
2068 | key parameters expressed in a way depended on the algorithm. | 2068 | key parameters expressed in a way depended on the algorithm. |
2069 | 2069 | ||
2070 | ARRAY must either be 20 bytes long or NULL; in the latter case a | 2070 | ARRAY must either be 20 bytes long or NULL; in the latter case a |
2071 | newly allocated array of that size is returned, otherwise ARRAY or | 2071 | newly allocated array of that size is returned, otherwise ARRAY or |
2072 | NULL is returned to indicate an error which is most likely an | 2072 | NULL is returned to indicate an error which is most likely an |
2073 | unknown algorithm. The function accepts public or secret keys. */ | 2073 | unknown algorithm. The function accepts public or secret keys. */ |
2074 | unsigned char * | 2074 | unsigned char * |
2075 | gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) | 2075 | gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) |
2076 | { | 2076 | { |
2077 | gcry_sexp_t list = NULL, l2 = NULL; | 2077 | gcry_sexp_t list = NULL, l2 = NULL; |
2078 | gcry_pk_spec_t *pubkey = NULL; | 2078 | gcry_pk_spec_t *pubkey = NULL; |
2079 | gcry_module_t module = NULL; | 2079 | gcry_module_t module = NULL; |
2080 | const char *s, *name; | 2080 | const char *s, *name; |
2081 | size_t n; | 2081 | size_t n; |
2082 | int idx; | 2082 | int idx; |
2083 | int is_rsa; | 2083 | int is_rsa; |
2084 | const char *elems; | 2084 | const char *elems; |
2085 | gcry_md_hd_t md = NULL; | 2085 | gcry_md_hd_t md = NULL; |
2086 | 2086 | ||
2087 | REGISTER_DEFAULT_PUBKEYS; | 2087 | REGISTER_DEFAULT_PUBKEYS; |
2088 | 2088 | ||
2089 | /* Check that the first element is valid. */ | 2089 | /* Check that the first element is valid. */ |
2090 | list = gcry_sexp_find_token (key, "public-key", 0); | 2090 | list = gcry_sexp_find_token (key, "public-key", 0); |
2091 | if (!list) | 2091 | if (!list) |
2092 | list = gcry_sexp_find_token (key, "private-key", 0); | 2092 | list = gcry_sexp_find_token (key, "private-key", 0); |
2093 | if (!list) | 2093 | if (!list) |
2094 | list = gcry_sexp_find_token (key, "protected-private-key", 0); | 2094 | list = gcry_sexp_find_token (key, "protected-private-key", 0); |
2095 | if (!list) | 2095 | if (!list) |
2096 | list = gcry_sexp_find_token (key, "shadowed-private-key", 0); | 2096 | list = gcry_sexp_find_token (key, "shadowed-private-key", 0); |
2097 | if (!list) | 2097 | if (!list) |
2098 | return NULL; /* No public- or private-key object. */ | 2098 | return NULL; /* No public- or private-key object. */ |
2099 | 2099 | ||
2100 | l2 = gcry_sexp_cadr (list); | 2100 | l2 = gcry_sexp_cadr (list); |
2101 | gcry_sexp_release (list); | 2101 | gcry_sexp_release (list); |
2102 | list = l2; | 2102 | list = l2; |
2103 | l2 = NULL; | 2103 | l2 = NULL; |
2104 | 2104 | ||
2105 | name = gcry_sexp_nth_data (list, 0, &n); | 2105 | name = gcry_sexp_nth_data (list, 0, &n); |
2106 | if (! name) | 2106 | if (! name) |
2107 | goto fail; /* Invalid structure of object. */ | 2107 | goto fail; /* Invalid structure of object. */ |
2108 | 2108 | ||
2109 | { | 2109 | { |
2110 | char *name_terminated = gcry_xmalloc (n + 1); | 2110 | char *name_terminated = gcry_xmalloc (n + 1); |
2111 | memcpy (name_terminated, name, n); | 2111 | memcpy (name_terminated, name, n); |
2112 | name_terminated[n] = 0; | 2112 | name_terminated[n] = 0; |
2113 | ath_mutex_lock (&pubkeys_registered_lock); | 2113 | ath_mutex_lock (&pubkeys_registered_lock); |
2114 | module = gcry_pk_lookup_name (name_terminated); | 2114 | module = gcry_pk_lookup_name (name_terminated); |
2115 | ath_mutex_unlock (&pubkeys_registered_lock); | 2115 | ath_mutex_unlock (&pubkeys_registered_lock); |
2116 | gcry_free (name_terminated); | 2116 | gcry_free (name_terminated); |
2117 | } | 2117 | } |
2118 | 2118 | ||
2119 | if (! module) | 2119 | if (! module) |
2120 | goto fail; /* unknown algorithm */ | 2120 | goto fail; /* unknown algorithm */ |
2121 | 2121 | ||
2122 | pubkey = (gcry_pk_spec_t *) module->spec; | 2122 | pubkey = (gcry_pk_spec_t *) module->spec; |
2123 | 2123 | ||
2124 | /* FIXME, special handling should be implemented by the algorithms, | 2124 | /* FIXME, special handling should be implemented by the algorithms, |
2125 | not by the libgcrypt core. */ | 2125 | not by the libgcrypt core. */ |
2126 | is_rsa = module->mod_id == GCRY_PK_RSA; | 2126 | is_rsa = module->mod_id == GCRY_PK_RSA; |
2127 | elems = pubkey->elements_grip; | 2127 | elems = pubkey->elements_grip; |
2128 | if (! elems) | 2128 | if (! elems) |
2129 | goto fail; /* no grip parameter */ | 2129 | goto fail; /* no grip parameter */ |
2130 | 2130 | ||
2131 | if (gcry_md_open (&md, GCRY_MD_SHA1, 0)) | 2131 | if (gcry_md_open (&md, GCRY_MD_SHA1, 0)) |
2132 | goto fail; | 2132 | goto fail; |
2133 | 2133 | ||
2134 | for (idx = 0, s = elems; *s; s++, idx++) | 2134 | for (idx = 0, s = elems; *s; s++, idx++) |
2135 | { | 2135 | { |
2136 | const char *data; | 2136 | const char *data; |
2137 | size_t datalen; | 2137 | size_t datalen; |
2138 | 2138 | ||
2139 | l2 = gcry_sexp_find_token (list, s, 1); | 2139 | l2 = gcry_sexp_find_token (list, s, 1); |
2140 | if (! l2) | 2140 | if (! l2) |
2141 | goto fail; | 2141 | goto fail; |
2142 | data = gcry_sexp_nth_data (l2, 1, &datalen); | 2142 | data = gcry_sexp_nth_data (l2, 1, &datalen); |
2143 | if (! data) | 2143 | if (! data) |
2144 | goto fail; | 2144 | goto fail; |
2145 | if (!is_rsa) | 2145 | if (!is_rsa) |
2146 | { | 2146 | { |
2147 | char buf[30]; | 2147 | char buf[30]; |
2148 | 2148 | ||
2149 | sprintf (buf, "(1:%c%u:", *s, (unsigned int)datalen); | 2149 | sprintf (buf, "(1:%c%u:", *s, (unsigned int)datalen); |
2150 | gcry_md_write (md, buf, strlen (buf)); | 2150 | gcry_md_write (md, buf, strlen (buf)); |
2151 | } | 2151 | } |
2152 | 2152 | ||
2153 | /* PKCS-15 says that for RSA only the modulus should be hashed - | 2153 | /* PKCS-15 says that for RSA only the modulus should be hashed - |
2154 | however, it is not clear wether this is meant to has the raw | 2154 | however, it is not clear wether this is meant to has the raw |
2155 | bytes assuming this is an unsigned integer or whether the DER | 2155 | bytes assuming this is an unsigned integer or whether the DER |
2156 | required 0 should be prefixed. We hash the raw bytes. For | 2156 | required 0 should be prefixed. We hash the raw bytes. For |
2157 | non-RSA we hash S-expressions. */ | 2157 | non-RSA we hash S-expressions. */ |
2158 | gcry_md_write (md, data, datalen); | 2158 | gcry_md_write (md, data, datalen); |
2159 | gcry_sexp_release (l2); | 2159 | gcry_sexp_release (l2); |
2160 | if (!is_rsa) | 2160 | if (!is_rsa) |
2161 | gcry_md_write (md, ")", 1); | 2161 | gcry_md_write (md, ")", 1); |
2162 | } | 2162 | } |
2163 | 2163 | ||
2164 | if (!array) | 2164 | if (!array) |
2165 | { | 2165 | { |
2166 | array = gcry_malloc (20); | 2166 | array = gcry_malloc (20); |
2167 | if (! array) | 2167 | if (! array) |
2168 | goto fail; | 2168 | goto fail; |
2169 | } | 2169 | } |
2170 | 2170 | ||
2171 | memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20); | 2171 | memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20); |
2172 | gcry_md_close (md); | 2172 | gcry_md_close (md); |
2173 | gcry_sexp_release (list); | 2173 | gcry_sexp_release (list); |
2174 | return array; | 2174 | return array; |
2175 | 2175 | ||
2176 | fail: | 2176 | fail: |
2177 | if (l2) | 2177 | if (l2) |
2178 | gcry_sexp_release (l2); | 2178 | gcry_sexp_release (l2); |
2179 | if (md) | 2179 | if (md) |
2180 | gcry_md_close (md); | 2180 | gcry_md_close (md); |
2181 | gcry_sexp_release (list); | 2181 | gcry_sexp_release (list); |
2182 | return NULL; | 2182 | return NULL; |
2183 | } | 2183 | } |
2184 | 2184 | ||
2185 | 2185 | ||
2186 | gcry_error_t | 2186 | gcry_error_t |
2187 | gcry_pk_ctl (int cmd, void *buffer, size_t buflen) | 2187 | gcry_pk_ctl (int cmd, void *buffer, size_t buflen) |
2188 | { | 2188 | { |
2189 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 2189 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
2190 | 2190 | ||
2191 | REGISTER_DEFAULT_PUBKEYS; | 2191 | REGISTER_DEFAULT_PUBKEYS; |
2192 | 2192 | ||
2193 | switch (cmd) | 2193 | switch (cmd) |
2194 | { | 2194 | { |
2195 | case GCRYCTL_DISABLE_ALGO: | 2195 | case GCRYCTL_DISABLE_ALGO: |
2196 | /* This one expects a buffer pointing to an integer with the | 2196 | /* This one expects a buffer pointing to an integer with the |
2197 | algo number. */ | 2197 | algo number. */ |
2198 | if ((! buffer) || (buflen != sizeof (int))) | 2198 | if ((! buffer) || (buflen != sizeof (int))) |
2199 | err = GPG_ERR_INV_ARG; | 2199 | err = GPG_ERR_INV_ARG; |
2200 | else | 2200 | else |
2201 | disable_pubkey_algo (*((int *) buffer)); | 2201 | disable_pubkey_algo (*((int *) buffer)); |
2202 | break; | 2202 | break; |
2203 | 2203 | ||
2204 | default: | 2204 | default: |
2205 | err = GPG_ERR_INV_OP; | 2205 | err = GPG_ERR_INV_OP; |
2206 | } | 2206 | } |
2207 | 2207 | ||
2208 | return gcry_error (err); | 2208 | return gcry_error (err); |
2209 | } | 2209 | } |
2210 | 2210 | ||
2211 | 2211 | ||
2212 | /* | 2212 | /* |
2213 | Return information about the given algorithm | 2213 | Return information about the given algorithm |
2214 | WHAT select the kind of information returned: | 2214 | WHAT select the kind of information returned: |
2215 | GCRYCTL_TEST_ALGO: | 2215 | GCRYCTL_TEST_ALGO: |
2216 | Returns 0 when the specified algorithm is available for use. | 2216 | Returns 0 when the specified algorithm is available for use. |
2217 | Buffer must be NULL, nbytes may have the address of a variable | 2217 | Buffer must be NULL, nbytes may have the address of a variable |
2218 | with the required usage of the algorithm. It may be 0 for don't | 2218 | with the required usage of the algorithm. It may be 0 for don't |
2219 | care or a combination of the GCRY_PK_USAGE_xxx flags; | 2219 | care or a combination of the GCRY_PK_USAGE_xxx flags; |
2220 | GCRYCTL_GET_ALGO_USAGE: | 2220 | GCRYCTL_GET_ALGO_USAGE: |
2221 | Return the usage glafs for the give algo. An invalid alog | 2221 | Return the usage glafs for the give algo. An invalid alog |
2222 | does return 0. Disabled algos are ignored here becuase we | 2222 | does return 0. Disabled algos are ignored here becuase we |
2223 | only want to know whether the algo is at all capable of | 2223 | only want to know whether the algo is at all capable of |
2224 | the usage. | 2224 | the usage. |
2225 | 2225 | ||
2226 | Note: Because this function is in most cases used to return an | 2226 | Note: Because this function is in most cases used to return an |
2227 | integer value, we can make it easier for the caller to just look at | 2227 | integer value, we can make it easier for the caller to just look at |
2228 | the return value. The caller will in all cases consult the value | 2228 | the return value. The caller will in all cases consult the value |
2229 | and thereby detecting whether a error occured or not (i.e. while | 2229 | and thereby detecting whether a error occured or not (i.e. while |
2230 | checking the block size) */ | 2230 | checking the block size) */ |
2231 | gcry_error_t | 2231 | gcry_error_t |
2232 | gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes) | 2232 | gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes) |
2233 | { | 2233 | { |
2234 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 2234 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
2235 | 2235 | ||
2236 | switch (what) | 2236 | switch (what) |
2237 | { | 2237 | { |
2238 | case GCRYCTL_TEST_ALGO: | 2238 | case GCRYCTL_TEST_ALGO: |
2239 | { | 2239 | { |
2240 | int use = nbytes ? *nbytes : 0; | 2240 | int use = nbytes ? *nbytes : 0; |
2241 | if (buffer) | 2241 | if (buffer) |
2242 | err = GPG_ERR_INV_ARG; | 2242 | err = GPG_ERR_INV_ARG; |
2243 | else if (check_pubkey_algo (algorithm, use)) | 2243 | else if (check_pubkey_algo (algorithm, use)) |
2244 | err = GPG_ERR_PUBKEY_ALGO; | 2244 | err = GPG_ERR_PUBKEY_ALGO; |
2245 | break; | 2245 | break; |
2246 | } | 2246 | } |
2247 | 2247 | ||
2248 | case GCRYCTL_GET_ALGO_USAGE: | 2248 | case GCRYCTL_GET_ALGO_USAGE: |
2249 | { | 2249 | { |
2250 | gcry_module_t pubkey; | 2250 | gcry_module_t pubkey; |
2251 | int use = 0; | 2251 | int use = 0; |
2252 | 2252 | ||
2253 | REGISTER_DEFAULT_PUBKEYS; | 2253 | REGISTER_DEFAULT_PUBKEYS; |
2254 | 2254 | ||
2255 | ath_mutex_lock (&pubkeys_registered_lock); | 2255 | ath_mutex_lock (&pubkeys_registered_lock); |
2256 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 2256 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
2257 | if (pubkey) | 2257 | if (pubkey) |
2258 | { | 2258 | { |
2259 | use = ((gcry_pk_spec_t *) pubkey->spec)->use; | 2259 | use = ((gcry_pk_spec_t *) pubkey->spec)->use; |
2260 | _gcry_module_release (pubkey); | 2260 | _gcry_module_release (pubkey); |
2261 | } | 2261 | } |
2262 | ath_mutex_unlock (&pubkeys_registered_lock); | 2262 | ath_mutex_unlock (&pubkeys_registered_lock); |
2263 | 2263 | ||
2264 | /* FIXME? */ | 2264 | /* FIXME? */ |
2265 | *nbytes = use; | 2265 | *nbytes = use; |
2266 | } | 2266 | } |
2267 | 2267 | ||
2268 | case GCRYCTL_GET_ALGO_NPKEY: | 2268 | case GCRYCTL_GET_ALGO_NPKEY: |
2269 | { | 2269 | { |
2270 | /* FIXME? */ | 2270 | /* FIXME? */ |
2271 | int npkey = pubkey_get_npkey (algorithm); | 2271 | int npkey = pubkey_get_npkey (algorithm); |
2272 | *nbytes = npkey; | 2272 | *nbytes = npkey; |
2273 | break; | 2273 | break; |
2274 | } | 2274 | } |
2275 | case GCRYCTL_GET_ALGO_NSKEY: | 2275 | case GCRYCTL_GET_ALGO_NSKEY: |
2276 | { | 2276 | { |
2277 | /* FIXME? */ | 2277 | /* FIXME? */ |
2278 | int nskey = pubkey_get_nskey (algorithm); | 2278 | int nskey = pubkey_get_nskey (algorithm); |
2279 | *nbytes = nskey; | 2279 | *nbytes = nskey; |
2280 | break; | 2280 | break; |
2281 | } | 2281 | } |
2282 | case GCRYCTL_GET_ALGO_NSIGN: | 2282 | case GCRYCTL_GET_ALGO_NSIGN: |
2283 | { | 2283 | { |
2284 | /* FIXME? */ | 2284 | /* FIXME? */ |
2285 | int nsign = pubkey_get_nsig (algorithm); | 2285 | int nsign = pubkey_get_nsig (algorithm); |
2286 | *nbytes = nsign; | 2286 | *nbytes = nsign; |
2287 | break; | 2287 | break; |
2288 | } | 2288 | } |
2289 | case GCRYCTL_GET_ALGO_NENCR: | 2289 | case GCRYCTL_GET_ALGO_NENCR: |
2290 | { | 2290 | { |
2291 | /* FIXME? */ | 2291 | /* FIXME? */ |
2292 | int nencr = pubkey_get_nenc (algorithm); | 2292 | int nencr = pubkey_get_nenc (algorithm); |
2293 | *nbytes = nencr; | 2293 | *nbytes = nencr; |
2294 | break; | 2294 | break; |
2295 | } | 2295 | } |
2296 | 2296 | ||
2297 | default: | 2297 | default: |
2298 | err = GPG_ERR_INV_OP; | 2298 | err = GPG_ERR_INV_OP; |
2299 | } | 2299 | } |
2300 | 2300 | ||
2301 | return gcry_error (err); | 2301 | return gcry_error (err); |
2302 | } | 2302 | } |
2303 | 2303 | ||
2304 | 2304 | ||
2305 | gcry_err_code_t | 2305 | gcry_err_code_t |
2306 | _gcry_pk_init (void) | 2306 | _gcry_pk_init (void) |
2307 | { | 2307 | { |
2308 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 2308 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
2309 | 2309 | ||
2310 | REGISTER_DEFAULT_PUBKEYS; | 2310 | REGISTER_DEFAULT_PUBKEYS; |
2311 | 2311 | ||
2312 | return err; | 2312 | return err; |
2313 | } | 2313 | } |
2314 | 2314 | ||
2315 | 2315 | ||
2316 | gcry_err_code_t | 2316 | gcry_err_code_t |
2317 | _gcry_pk_module_lookup (int algorithm, gcry_module_t *module) | 2317 | _gcry_pk_module_lookup (int algorithm, gcry_module_t *module) |
2318 | { | 2318 | { |
2319 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 2319 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
2320 | gcry_module_t pubkey; | 2320 | gcry_module_t pubkey; |
2321 | 2321 | ||
2322 | REGISTER_DEFAULT_PUBKEYS; | 2322 | REGISTER_DEFAULT_PUBKEYS; |
2323 | 2323 | ||
2324 | ath_mutex_lock (&pubkeys_registered_lock); | 2324 | ath_mutex_lock (&pubkeys_registered_lock); |
2325 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); | 2325 | pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); |
2326 | if (pubkey) | 2326 | if (pubkey) |
2327 | *module = pubkey; | 2327 | *module = pubkey; |
2328 | else | 2328 | else |
2329 | err = GPG_ERR_PUBKEY_ALGO; | 2329 | err = GPG_ERR_PUBKEY_ALGO; |
2330 | ath_mutex_unlock (&pubkeys_registered_lock); | 2330 | ath_mutex_unlock (&pubkeys_registered_lock); |
2331 | 2331 | ||
2332 | return err; | 2332 | return err; |
2333 | } | 2333 | } |
2334 | 2334 | ||
2335 | 2335 | ||
2336 | void | 2336 | void |
2337 | _gcry_pk_module_release (gcry_module_t module) | 2337 | _gcry_pk_module_release (gcry_module_t module) |
2338 | { | 2338 | { |
2339 | ath_mutex_lock (&pubkeys_registered_lock); | 2339 | ath_mutex_lock (&pubkeys_registered_lock); |
2340 | _gcry_module_release (module); | 2340 | _gcry_module_release (module); |
2341 | ath_mutex_unlock (&pubkeys_registered_lock); | 2341 | ath_mutex_unlock (&pubkeys_registered_lock); |
2342 | } | 2342 | } |
2343 | 2343 | ||
2344 | /* Get a list consisting of the IDs of the loaded pubkey modules. If | 2344 | /* Get a list consisting of the IDs of the loaded pubkey modules. If |
2345 | LIST is zero, write the number of loaded pubkey modules to | 2345 | LIST is zero, write the number of loaded pubkey modules to |
2346 | LIST_LENGTH and return. If LIST is non-zero, the first | 2346 | LIST_LENGTH and return. If LIST is non-zero, the first |
2347 | *LIST_LENGTH algorithm IDs are stored in LIST, which must be of | 2347 | *LIST_LENGTH algorithm IDs are stored in LIST, which must be of |
2348 | according size. In case there are less pubkey modules than | 2348 | according size. In case there are less pubkey modules than |
2349 | *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */ | 2349 | *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */ |
2350 | gcry_error_t | 2350 | gcry_error_t |
2351 | gcry_pk_list (int *list, int *list_length) | 2351 | gcry_pk_list (int *list, int *list_length) |
2352 | { | 2352 | { |
2353 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 2353 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
2354 | 2354 | ||
2355 | ath_mutex_lock (&pubkeys_registered_lock); | 2355 | ath_mutex_lock (&pubkeys_registered_lock); |
2356 | err = _gcry_module_list (pubkeys_registered, list, list_length); | 2356 | err = _gcry_module_list (pubkeys_registered, list, list_length); |
2357 | ath_mutex_unlock (&pubkeys_registered_lock); | 2357 | ath_mutex_unlock (&pubkeys_registered_lock); |
2358 | 2358 | ||
2359 | return err; | 2359 | return err; |
2360 | } | 2360 | } |