]> git.proxmox.com Git - grub2.git/blame - grub-core/lib/crypto.c
core: use GRUB_TERM_ definitions when handling term characters
[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;
94f701a8 208 grub_size_t blocksize;
fbf62978
VS
209 if (!cipher->cipher->decrypt)
210 return GPG_ERR_NOT_SUPPORTED;
94f701a8
VS
211 blocksize = cipher->cipher->blocksize;
212 if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
213 || ((size & (blocksize - 1)) != 0))
fbf62978 214 return GPG_ERR_INV_ARG;
76a2a430 215 end = (const grub_uint8_t *) in + size;
d944246c 216 for (inptr = in, outptr = out; inptr < end;
94f701a8 217 inptr += blocksize, outptr += blocksize)
d944246c 218 cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
fbf62978 219 return GPG_ERR_NO_ERROR;
d944246c
VS
220}
221
fbf62978 222gcry_err_code_t
d944246c 223grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
1bc7cc1b 224 void *out, const void *in, grub_size_t size)
d944246c 225{
76a2a430
VS
226 const grub_uint8_t *inptr, *end;
227 grub_uint8_t *outptr;
94f701a8 228 grub_size_t blocksize;
fbf62978
VS
229 if (!cipher->cipher->encrypt)
230 return GPG_ERR_NOT_SUPPORTED;
94f701a8
VS
231 blocksize = cipher->cipher->blocksize;
232 if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
233 || ((size & (blocksize - 1)) != 0))
fbf62978 234 return GPG_ERR_INV_ARG;
76a2a430 235 end = (const grub_uint8_t *) in + size;
d944246c 236 for (inptr = in, outptr = out; inptr < end;
94f701a8 237 inptr += blocksize, outptr += blocksize)
d944246c 238 cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
fbf62978 239 return GPG_ERR_NO_ERROR;
d944246c
VS
240}
241
fbf62978 242gcry_err_code_t
d944246c 243grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
76a2a430 244 void *out, const void *in, grub_size_t size,
d944246c
VS
245 void *iv_in)
246{
76a2a430
VS
247 grub_uint8_t *outptr;
248 const grub_uint8_t *inptr, *end;
d944246c 249 void *iv;
94f701a8
VS
250 grub_size_t blocksize;
251 if (!cipher->cipher->encrypt)
fbf62978 252 return GPG_ERR_NOT_SUPPORTED;
94f701a8
VS
253 blocksize = cipher->cipher->blocksize;
254 if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
255 || ((size & (blocksize - 1)) != 0))
fbf62978 256 return GPG_ERR_INV_ARG;
76a2a430 257 end = (const grub_uint8_t *) in + size;
d944246c
VS
258 iv = iv_in;
259 for (inptr = in, outptr = out; inptr < end;
94f701a8 260 inptr += blocksize, outptr += blocksize)
d944246c 261 {
94f701a8 262 grub_crypto_xor (outptr, inptr, iv, blocksize);
d944246c
VS
263 cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
264 iv = outptr;
265 }
94f701a8 266 grub_memcpy (iv_in, iv, blocksize);
fbf62978 267 return GPG_ERR_NO_ERROR;
d944246c
VS
268}
269
fbf62978 270gcry_err_code_t
d944246c 271grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
1a1f408f 272 void *out, const void *in, grub_size_t size,
d944246c
VS
273 void *iv)
274{
76a2a430
VS
275 const grub_uint8_t *inptr, *end;
276 grub_uint8_t *outptr;
4b85f122 277 grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
94f701a8 278 grub_size_t blocksize;
fbf62978
VS
279 if (!cipher->cipher->decrypt)
280 return GPG_ERR_NOT_SUPPORTED;
94f701a8
VS
281 blocksize = cipher->cipher->blocksize;
282 if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
283 || ((size & (blocksize - 1)) != 0))
fbf62978 284 return GPG_ERR_INV_ARG;
94f701a8 285 if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
4b85f122 286 return GPG_ERR_INV_ARG;
76a2a430 287 end = (const grub_uint8_t *) in + size;
d944246c 288 for (inptr = in, outptr = out; inptr < end;
94f701a8 289 inptr += blocksize, outptr += blocksize)
d944246c 290 {
94f701a8 291 grub_memcpy (ivt, inptr, blocksize);
d944246c 292 cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
94f701a8
VS
293 grub_crypto_xor (outptr, outptr, iv, blocksize);
294 grub_memcpy (iv, ivt, blocksize);
d944246c 295 }
fbf62978
VS
296 return GPG_ERR_NO_ERROR;
297}
298
6e7d9194
VS
299/* Based on gcry/cipher/md.c. */
300struct grub_crypto_hmac_handle *
301grub_crypto_hmac_init (const struct gcry_md_spec *md,
302 const void *key, grub_size_t keylen)
303{
304 grub_uint8_t *helpkey = NULL;
305 grub_uint8_t *ipad = NULL, *opad = NULL;
306 void *ctx = NULL;
307 struct grub_crypto_hmac_handle *ret = NULL;
308 unsigned i;
309
310 if (md->mdlen > md->blocksize)
311 return NULL;
312
313 ctx = grub_malloc (md->contextsize);
314 if (!ctx)
315 goto err;
316
317 if ( keylen > md->blocksize )
318 {
319 helpkey = grub_malloc (md->mdlen);
320 if (!helpkey)
321 goto err;
322 grub_crypto_hash (md, helpkey, key, keylen);
323
324 key = helpkey;
325 keylen = md->mdlen;
326 }
327
328 ipad = grub_zalloc (md->blocksize);
329 if (!ipad)
330 goto err;
331
332 opad = grub_zalloc (md->blocksize);
333 if (!opad)
334 goto err;
335
336 grub_memcpy ( ipad, key, keylen );
337 grub_memcpy ( opad, key, keylen );
338 for (i=0; i < md->blocksize; i++ )
339 {
340 ipad[i] ^= 0x36;
341 opad[i] ^= 0x5c;
342 }
343 grub_free (helpkey);
344 helpkey = NULL;
345
346 md->init (ctx);
347
348 md->write (ctx, ipad, md->blocksize); /* inner pad */
349 grub_memset (ipad, 0, md->blocksize);
350 grub_free (ipad);
351 ipad = NULL;
352
353 ret = grub_malloc (sizeof (*ret));
354 if (!ret)
355 goto err;
356
357 ret->md = md;
358 ret->ctx = ctx;
359 ret->opad = opad;
360
361 return ret;
362
363 err:
364 grub_free (helpkey);
365 grub_free (ctx);
366 grub_free (ipad);
367 grub_free (opad);
368 return NULL;
369}
370
371void
848c83e7
VS
372grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
373 const void *data,
6e7d9194
VS
374 grub_size_t datalen)
375{
376 hnd->md->write (hnd->ctx, data, datalen);
377}
378
379gcry_err_code_t
380grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
381{
382 grub_uint8_t *p;
383 grub_uint8_t *ctx2;
384
385 ctx2 = grub_malloc (hnd->md->contextsize);
386 if (!ctx2)
387 return GPG_ERR_OUT_OF_MEMORY;
388
389 hnd->md->final (hnd->ctx);
390 hnd->md->read (hnd->ctx);
391 p = hnd->md->read (hnd->ctx);
392
393 hnd->md->init (ctx2);
394 hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
395 hnd->md->write (ctx2, p, hnd->md->mdlen);
396 hnd->md->final (ctx2);
397 grub_memset (hnd->opad, 0, hnd->md->blocksize);
398 grub_free (hnd->opad);
399 grub_memset (hnd->ctx, 0, hnd->md->contextsize);
400 grub_free (hnd->ctx);
401
402 grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
403 grub_memset (ctx2, 0, hnd->md->contextsize);
404 grub_free (ctx2);
405
406 grub_memset (hnd, 0, sizeof (*hnd));
407 grub_free (hnd);
408
409 return GPG_ERR_NO_ERROR;
410}
411
412gcry_err_code_t
413grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
414 const void *key, grub_size_t keylen,
88ac3146 415 const void *data, grub_size_t datalen, void *out)
6e7d9194
VS
416{
417 struct grub_crypto_hmac_handle *hnd;
418
419 hnd = grub_crypto_hmac_init (md, key, keylen);
420 if (!hnd)
421 return GPG_ERR_OUT_OF_MEMORY;
422
423 grub_crypto_hmac_write (hnd, data, datalen);
424 return grub_crypto_hmac_fini (hnd, out);
425}
426
427
fbf62978
VS
428grub_err_t
429grub_crypto_gcry_error (gcry_err_code_t in)
430{
431 if (in == GPG_ERR_NO_ERROR)
432 return GRUB_ERR_NONE;
433 return GRUB_ACCESS_DENIED;
d944246c 434}
10e53efa
VS
435
436int
b391bdb2 437grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
10e53efa
VS
438{
439 register grub_size_t counter = 0;
b391bdb2 440 const grub_uint8_t *pa, *pb;
10e53efa
VS
441
442 for (pa = a, pb = b; n; pa++, pb++, n--)
443 {
444 if (*pa != *pb)
445 counter++;
446 }
447
448 return !!counter;
449}
b391bdb2 450
4a445f58
VS
451#ifndef GRUB_UTIL
452
b391bdb2
VS
453int
454grub_password_get (char buf[], unsigned buf_size)
455{
456 unsigned cur_len = 0;
457 int key;
458
459 while (1)
460 {
87fae34a 461 key = grub_getkey ();
b391bdb2
VS
462 if (key == '\n' || key == '\r')
463 break;
464
bdd89d23 465 if (key == GRUB_TERM_ESC)
b391bdb2
VS
466 {
467 cur_len = 0;
468 break;
469 }
470
471 if (key == '\b')
472 {
451d80e5
HMG
473 if (cur_len)
474 cur_len--;
b391bdb2
VS
475 continue;
476 }
477
478 if (!grub_isprint (key))
479 continue;
480
481 if (cur_len + 2 < buf_size)
482 buf[cur_len++] = key;
483 }
484
485 grub_memset (buf + cur_len, 0, buf_size - cur_len);
486
dfed5c6b 487 grub_xputs ("\n");
b391bdb2
VS
488 grub_refresh ();
489
bdd89d23 490 return (key != GRUB_TERM_ESC);
2cb55e6f 491}
4a445f58 492#endif
5e3b8dcb 493