]> git.proxmox.com Git - grub2.git/blame - grub-core/lib/crypto.c
* grub-core/lib/crypto.c: Don't discard const attribute.
[grub2.git] / grub-core / lib / crypto.c
CommitLineData
d944246c
VS
1/*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
4 * 2007, 2008, 2009 Free Software Foundation, Inc.
5 *
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <grub/crypto.h>
21#include <grub/misc.h>
22#include <grub/mm.h>
b391bdb2 23#include <grub/term.h>
e745cf0c 24#include <grub/dl.h>
9c4b5c13 25#include <grub/i18n.h>
5e3b8dcb 26#include <grub/env.h>
e745cf0c
VS
27
28GRUB_MOD_LICENSE ("GPLv3+");
d944246c 29
6e7d9194
VS
30struct grub_crypto_hmac_handle
31{
32 const struct gcry_md_spec *md;
33 void *ctx;
34 void *opad;
35};
36
d944246c
VS
37static gcry_cipher_spec_t *grub_ciphers = NULL;
38static gcry_md_spec_t *grub_digests = NULL;
39
7316783f
VS
40void (*grub_crypto_autoload_hook) (const char *name) = NULL;
41
d944246c
VS
42/* Based on libgcrypt-1.4.4/src/misc.c. */
43void
44grub_burn_stack (grub_size_t size)
45{
46 char buf[64];
47
48 grub_memset (buf, 0, sizeof (buf));
49 if (size > sizeof (buf))
50 grub_burn_stack (size - sizeof (buf));
51}
52
5e3b8dcb
VS
53void
54_gcry_burn_stack (int size)
55{
56 grub_burn_stack (size);
57}
58
59void __attribute__ ((noreturn))
60_gcry_assert_failed (const char *expr, const char *file, int line,
61 const char *func)
62
63{
64 grub_fatal ("assertion %s at %s:%d (%s) failed\n", expr, file, line, func);
65}
66
67
68void _gcry_log_error (const char *fmt, ...)
69{
70 va_list args;
71 const char *debug = grub_env_get ("debug");
72
73 if (! debug)
74 return;
75
76 if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt"))
77 {
78 grub_printf ("gcrypt error: ");
79 va_start (args, fmt);
80 grub_vprintf (fmt, args);
81 va_end (args);
82 grub_refresh ();
83 }
84}
d944246c
VS
85
86void
87grub_cipher_register (gcry_cipher_spec_t *cipher)
88{
89 cipher->next = grub_ciphers;
90 grub_ciphers = cipher;
91}
92
93void
94grub_cipher_unregister (gcry_cipher_spec_t *cipher)
95{
96 gcry_cipher_spec_t **ciph;
97 for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next))
98 if (*ciph == cipher)
3851cc38
VS
99 {
100 *ciph = (*ciph)->next;
101 break;
102 }
d944246c
VS
103}
104
105void
106grub_md_register (gcry_md_spec_t *digest)
107{
108 digest->next = grub_digests;
109 grub_digests = digest;
110}
111
112void
113grub_md_unregister (gcry_md_spec_t *cipher)
114{
115 gcry_md_spec_t **ciph;
116 for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next))
117 if (*ciph == cipher)
3851cc38
VS
118 {
119 *ciph = (*ciph)->next;
120 break;
121 }
d944246c
VS
122}
123
124void
6e7d9194 125grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
d944246c
VS
126 grub_size_t inlen)
127{
7dd0a303
VS
128 GRUB_PROPERLY_ALIGNED_ARRAY (ctx, GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE);
129
130 if (hash->contextsize > sizeof (ctx))
131 grub_fatal ("Too large md context");
d944246c
VS
132 hash->init (&ctx);
133 hash->write (&ctx, in, inlen);
134 hash->final (&ctx);
135 grub_memcpy (out, hash->read (&ctx), hash->mdlen);
136}
137
138const gcry_md_spec_t *
139grub_crypto_lookup_md_by_name (const char *name)
140{
141 const gcry_md_spec_t *md;
7316783f
VS
142 int first = 1;
143 while (1)
144 {
145 for (md = grub_digests; md; md = md->next)
146 if (grub_strcasecmp (name, md->name) == 0)
147 return md;
148 if (grub_crypto_autoload_hook && first)
149 grub_crypto_autoload_hook (name);
150 else
151 return NULL;
152 first = 0;
153 }
d944246c
VS
154}
155
156const gcry_cipher_spec_t *
157grub_crypto_lookup_cipher_by_name (const char *name)
158{
159 const gcry_cipher_spec_t *ciph;
7316783f
VS
160 int first = 1;
161 while (1)
d944246c 162 {
7316783f
VS
163 for (ciph = grub_ciphers; ciph; ciph = ciph->next)
164 {
165 const char **alias;
166 if (grub_strcasecmp (name, ciph->name) == 0)
167 return ciph;
168 if (!ciph->aliases)
169 continue;
170 for (alias = ciph->aliases; *alias; alias++)
171 if (grub_strcasecmp (name, *alias) == 0)
172 return ciph;
173 }
174 if (grub_crypto_autoload_hook && first)
175 grub_crypto_autoload_hook (name);
176 else
177 return NULL;
178 first = 0;
d944246c 179 }
d944246c
VS
180}
181
182
183grub_crypto_cipher_handle_t
184grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher)
185{
186 grub_crypto_cipher_handle_t ret;
187 ret = grub_malloc (sizeof (*ret) + cipher->contextsize);
188 if (!ret)
189 return NULL;
190 ret->cipher = cipher;
191 return ret;
192}
193
194gcry_err_code_t
195grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
196 const unsigned char *key,
197 unsigned keylen)
198{
199 return cipher->cipher->setkey (cipher->ctx, key, keylen);
200}
201
fbf62978 202gcry_err_code_t
d944246c 203grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
1a1f408f 204 void *out, const void *in, grub_size_t size)
d944246c 205{
76a2a430
VS
206 const grub_uint8_t *inptr, *end;
207 grub_uint8_t *outptr;
fbf62978
VS
208 if (!cipher->cipher->decrypt)
209 return GPG_ERR_NOT_SUPPORTED;
d944246c 210 if (size % cipher->cipher->blocksize != 0)
fbf62978 211 return GPG_ERR_INV_ARG;
76a2a430 212 end = (const grub_uint8_t *) in + size;
d944246c
VS
213 for (inptr = in, outptr = out; inptr < end;
214 inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
215 cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
fbf62978 216 return GPG_ERR_NO_ERROR;
d944246c
VS
217}
218
fbf62978 219gcry_err_code_t
d944246c 220grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
1bc7cc1b 221 void *out, const void *in, grub_size_t size)
d944246c 222{
76a2a430
VS
223 const grub_uint8_t *inptr, *end;
224 grub_uint8_t *outptr;
fbf62978
VS
225 if (!cipher->cipher->encrypt)
226 return GPG_ERR_NOT_SUPPORTED;
d944246c 227 if (size % cipher->cipher->blocksize != 0)
fbf62978 228 return GPG_ERR_INV_ARG;
76a2a430 229 end = (const grub_uint8_t *) in + size;
d944246c
VS
230 for (inptr = in, outptr = out; inptr < end;
231 inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
232 cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
fbf62978 233 return GPG_ERR_NO_ERROR;
d944246c
VS
234}
235
fbf62978 236gcry_err_code_t
d944246c 237grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
76a2a430 238 void *out, const void *in, grub_size_t size,
d944246c
VS
239 void *iv_in)
240{
76a2a430
VS
241 grub_uint8_t *outptr;
242 const grub_uint8_t *inptr, *end;
d944246c 243 void *iv;
fbf62978
VS
244 if (!cipher->cipher->decrypt)
245 return GPG_ERR_NOT_SUPPORTED;
d944246c 246 if (size % cipher->cipher->blocksize != 0)
fbf62978 247 return GPG_ERR_INV_ARG;
76a2a430 248 end = (const grub_uint8_t *) in + size;
d944246c
VS
249 iv = iv_in;
250 for (inptr = in, outptr = out; inptr < end;
251 inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
252 {
253 grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize);
254 cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
255 iv = outptr;
256 }
257 grub_memcpy (iv_in, iv, cipher->cipher->blocksize);
fbf62978 258 return GPG_ERR_NO_ERROR;
d944246c
VS
259}
260
fbf62978 261gcry_err_code_t
d944246c 262grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
1a1f408f 263 void *out, const void *in, grub_size_t size,
d944246c
VS
264 void *iv)
265{
76a2a430
VS
266 const grub_uint8_t *inptr, *end;
267 grub_uint8_t *outptr;
4b85f122 268 grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
fbf62978
VS
269 if (!cipher->cipher->decrypt)
270 return GPG_ERR_NOT_SUPPORTED;
d944246c 271 if (size % cipher->cipher->blocksize != 0)
fbf62978 272 return GPG_ERR_INV_ARG;
4b85f122
VS
273 if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
274 return GPG_ERR_INV_ARG;
76a2a430 275 end = (const grub_uint8_t *) in + size;
d944246c
VS
276 for (inptr = in, outptr = out; inptr < end;
277 inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
278 {
279 grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
280 cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
281 grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
282 grub_memcpy (iv, ivt, cipher->cipher->blocksize);
283 }
fbf62978
VS
284 return GPG_ERR_NO_ERROR;
285}
286
6e7d9194
VS
287/* Based on gcry/cipher/md.c. */
288struct grub_crypto_hmac_handle *
289grub_crypto_hmac_init (const struct gcry_md_spec *md,
290 const void *key, grub_size_t keylen)
291{
292 grub_uint8_t *helpkey = NULL;
293 grub_uint8_t *ipad = NULL, *opad = NULL;
294 void *ctx = NULL;
295 struct grub_crypto_hmac_handle *ret = NULL;
296 unsigned i;
297
298 if (md->mdlen > md->blocksize)
299 return NULL;
300
301 ctx = grub_malloc (md->contextsize);
302 if (!ctx)
303 goto err;
304
305 if ( keylen > md->blocksize )
306 {
307 helpkey = grub_malloc (md->mdlen);
308 if (!helpkey)
309 goto err;
310 grub_crypto_hash (md, helpkey, key, keylen);
311
312 key = helpkey;
313 keylen = md->mdlen;
314 }
315
316 ipad = grub_zalloc (md->blocksize);
317 if (!ipad)
318 goto err;
319
320 opad = grub_zalloc (md->blocksize);
321 if (!opad)
322 goto err;
323
324 grub_memcpy ( ipad, key, keylen );
325 grub_memcpy ( opad, key, keylen );
326 for (i=0; i < md->blocksize; i++ )
327 {
328 ipad[i] ^= 0x36;
329 opad[i] ^= 0x5c;
330 }
331 grub_free (helpkey);
332 helpkey = NULL;
333
334 md->init (ctx);
335
336 md->write (ctx, ipad, md->blocksize); /* inner pad */
337 grub_memset (ipad, 0, md->blocksize);
338 grub_free (ipad);
339 ipad = NULL;
340
341 ret = grub_malloc (sizeof (*ret));
342 if (!ret)
343 goto err;
344
345 ret->md = md;
346 ret->ctx = ctx;
347 ret->opad = opad;
348
349 return ret;
350
351 err:
352 grub_free (helpkey);
353 grub_free (ctx);
354 grub_free (ipad);
355 grub_free (opad);
356 return NULL;
357}
358
359void
848c83e7
VS
360grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
361 const void *data,
6e7d9194
VS
362 grub_size_t datalen)
363{
364 hnd->md->write (hnd->ctx, data, datalen);
365}
366
367gcry_err_code_t
368grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
369{
370 grub_uint8_t *p;
371 grub_uint8_t *ctx2;
372
373 ctx2 = grub_malloc (hnd->md->contextsize);
374 if (!ctx2)
375 return GPG_ERR_OUT_OF_MEMORY;
376
377 hnd->md->final (hnd->ctx);
378 hnd->md->read (hnd->ctx);
379 p = hnd->md->read (hnd->ctx);
380
381 hnd->md->init (ctx2);
382 hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
383 hnd->md->write (ctx2, p, hnd->md->mdlen);
384 hnd->md->final (ctx2);
385 grub_memset (hnd->opad, 0, hnd->md->blocksize);
386 grub_free (hnd->opad);
387 grub_memset (hnd->ctx, 0, hnd->md->contextsize);
388 grub_free (hnd->ctx);
389
390 grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
391 grub_memset (ctx2, 0, hnd->md->contextsize);
392 grub_free (ctx2);
393
394 grub_memset (hnd, 0, sizeof (*hnd));
395 grub_free (hnd);
396
397 return GPG_ERR_NO_ERROR;
398}
399
400gcry_err_code_t
401grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
402 const void *key, grub_size_t keylen,
88ac3146 403 const void *data, grub_size_t datalen, void *out)
6e7d9194
VS
404{
405 struct grub_crypto_hmac_handle *hnd;
406
407 hnd = grub_crypto_hmac_init (md, key, keylen);
408 if (!hnd)
409 return GPG_ERR_OUT_OF_MEMORY;
410
411 grub_crypto_hmac_write (hnd, data, datalen);
412 return grub_crypto_hmac_fini (hnd, out);
413}
414
415
fbf62978
VS
416grub_err_t
417grub_crypto_gcry_error (gcry_err_code_t in)
418{
419 if (in == GPG_ERR_NO_ERROR)
420 return GRUB_ERR_NONE;
421 return GRUB_ACCESS_DENIED;
d944246c 422}
10e53efa
VS
423
424int
b391bdb2 425grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
10e53efa
VS
426{
427 register grub_size_t counter = 0;
b391bdb2 428 const grub_uint8_t *pa, *pb;
10e53efa
VS
429
430 for (pa = a, pb = b; n; pa++, pb++, n--)
431 {
432 if (*pa != *pb)
433 counter++;
434 }
435
436 return !!counter;
437}
b391bdb2 438
4a445f58
VS
439#ifndef GRUB_UTIL
440
b391bdb2
VS
441int
442grub_password_get (char buf[], unsigned buf_size)
443{
444 unsigned cur_len = 0;
445 int key;
446
447 while (1)
448 {
87fae34a 449 key = grub_getkey ();
b391bdb2
VS
450 if (key == '\n' || key == '\r')
451 break;
452
453 if (key == '\e')
454 {
455 cur_len = 0;
456 break;
457 }
458
459 if (key == '\b')
460 {
461 cur_len--;
462 continue;
463 }
464
465 if (!grub_isprint (key))
466 continue;
467
468 if (cur_len + 2 < buf_size)
469 buf[cur_len++] = key;
470 }
471
472 grub_memset (buf + cur_len, 0, buf_size - cur_len);
473
dfed5c6b 474 grub_xputs ("\n");
b391bdb2
VS
475 grub_refresh ();
476
477 return (key != '\e');
2cb55e6f 478}
4a445f58 479#endif
5e3b8dcb 480