~ubuntu-branches/ubuntu/trusty/grub2/trusty

« back to all changes in this revision

Viewing changes to grub-core/lib/libgcrypt/cipher/kdf.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2014-01-16 15:18:04 UTC
  • mfrom: (17.6.38 experimental)
  • Revision ID: package-import@ubuntu.com-20140116151804-3foouk7fpqcq3sxx
Tags: 2.02~beta2-2
* Convert patch handling to git-dpm.
* Add bi-endian support to ELF parser (Tomohiro B Berry).
* Adjust restore_mkdevicemap.patch to mark get_kfreebsd_version as static,
  to appease "gcc -Werror=missing-prototypes".
* Cherry-pick from upstream:
  - Change grub-macbless' manual page section to 8.
* Install grub-glue-efi, grub-macbless, grub-render-label, and
  grub-syslinux2cfg.
* grub-shell: Pass -no-pad to xorriso when building floppy images.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* kdf.c  - Key Derivation Functions
 
2
 * Copyright (C) 1998, 2011 Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of Libgcrypt.
 
5
 *
 
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
 
8
 * published by the Free Software Foundation; either version 2.1 of
 
9
 * the License, or (at your option) any later version.
 
10
 *
 
11
 * Libgcrypt 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 Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public
 
17
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <config.h>
 
21
#include <stdio.h>
 
22
#include <stdlib.h>
 
23
#include <string.h>
 
24
#include <errno.h>
 
25
 
 
26
#include "g10lib.h"
 
27
#include "cipher.h"
 
28
#include "ath.h"
 
29
 
 
30
 
 
31
/* Transform a passphrase into a suitable key of length KEYSIZE and
 
32
   store this key in the caller provided buffer KEYBUFFER.  The caller
 
33
   must provide an HASHALGO, a valid ALGO and depending on that algo a
 
34
   SALT of 8 bytes and the number of ITERATIONS.  Code taken from
 
35
   gnupg/agent/protect.c:hash_passphrase.  */
 
36
gpg_err_code_t
 
37
openpgp_s2k (const void *passphrase, size_t passphraselen,
 
38
             int algo, int hashalgo,
 
39
             const void *salt, size_t saltlen,
 
40
             unsigned long iterations,
 
41
             size_t keysize, void *keybuffer)
 
42
{
 
43
  gpg_err_code_t ec;
 
44
  gcry_md_hd_t md;
 
45
  char *key = keybuffer;
 
46
  int pass, i;
 
47
  int used = 0;
 
48
  int secmode;
 
49
 
 
50
  if ((algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K)
 
51
      && (!salt || saltlen != 8))
 
52
    return GPG_ERR_INV_VALUE;
 
53
 
 
54
  secmode = gcry_is_secure (passphrase) || gcry_is_secure (keybuffer);
 
55
 
 
56
  ec = gpg_err_code (gcry_md_open (&md, hashalgo,
 
57
                                   secmode? GCRY_MD_FLAG_SECURE : 0));
 
58
  if (ec)
 
59
    return ec;
 
60
 
 
61
  for (pass=0; used < keysize; pass++)
 
62
    {
 
63
      if (pass)
 
64
        {
 
65
          gcry_md_reset (md);
 
66
          for (i=0; i < pass; i++) /* Preset the hash context.  */
 
67
            gcry_md_putc (md, 0);
 
68
        }
 
69
 
 
70
      if (algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K)
 
71
        {
 
72
          int len2 = passphraselen + 8;
 
73
          unsigned long count = len2;
 
74
 
 
75
          if (algo == GCRY_KDF_ITERSALTED_S2K)
 
76
            {
 
77
              count = iterations;
 
78
              if (count < len2)
 
79
                count = len2;
 
80
            }
 
81
 
 
82
          while (count > len2)
 
83
            {
 
84
              gcry_md_write (md, salt, saltlen);
 
85
              gcry_md_write (md, passphrase, passphraselen);
 
86
              count -= len2;
 
87
            }
 
88
          if (count < saltlen)
 
89
            gcry_md_write (md, salt, count);
 
90
          else
 
91
            {
 
92
              gcry_md_write (md, salt, saltlen);
 
93
              count -= saltlen;
 
94
              gcry_md_write (md, passphrase, count);
 
95
            }
 
96
        }
 
97
      else
 
98
        gcry_md_write (md, passphrase, passphraselen);
 
99
 
 
100
      gcry_md_final (md);
 
101
      i = gcry_md_get_algo_dlen (hashalgo);
 
102
      if (i > keysize - used)
 
103
        i = keysize - used;
 
104
      memcpy (key+used, gcry_md_read (md, hashalgo), i);
 
105
      used += i;
 
106
    }
 
107
  gcry_md_close (md);
 
108
  return 0;
 
109
}
 
110
 
 
111
 
 
112
/* Transform a passphrase into a suitable key of length KEYSIZE and
 
113
   store this key in the caller provided buffer KEYBUFFER.  The caller
 
114
   must provide PRFALGO which indicates the pseudorandom function to
 
115
   use: This shall be the algorithms id of a hash algorithm; it is
 
116
   used in HMAC mode.  SALT is a salt of length SALTLEN and ITERATIONS
 
117
   gives the number of iterations.  */
 
118
gpg_err_code_t
 
119
pkdf2 (const void *passphrase, size_t passphraselen,
 
120
       int hashalgo,
 
121
       const void *salt, size_t saltlen,
 
122
       unsigned long iterations,
 
123
       size_t keysize, void *keybuffer)
 
124
{
 
125
  gpg_err_code_t ec;
 
126
  gcry_md_hd_t md;
 
127
  int secmode;
 
128
  unsigned int dklen = keysize;
 
129
  char *dk = keybuffer;
 
130
  unsigned int hlen;   /* Output length of the digest function.  */
 
131
  unsigned int l;      /* Rounded up number of blocks.  */
 
132
  unsigned int r;      /* Number of octets in the last block.  */
 
133
  char *sbuf;          /* Malloced buffer to concatenate salt and iter
 
134
                          as well as space to hold TBUF and UBUF.  */
 
135
  char *tbuf;          /* Buffer for T; ptr into SBUF, size is HLEN. */
 
136
  char *ubuf;          /* Buffer for U; ptr into SBUF, size is HLEN. */
 
137
  unsigned int lidx;   /* Current block number.  */
 
138
  unsigned long iter;  /* Current iteration number.  */
 
139
  unsigned int i;
 
140
 
 
141
  if (!salt || !saltlen || !iterations || !dklen)
 
142
    return GPG_ERR_INV_VALUE;
 
143
 
 
144
  hlen = gcry_md_get_algo_dlen (hashalgo);
 
145
  if (!hlen)
 
146
    return GPG_ERR_DIGEST_ALGO;
 
147
 
 
148
  secmode = gcry_is_secure (passphrase) || gcry_is_secure (keybuffer);
 
149
 
 
150
  /* We ignore step 1 from pksc5v2.1 which demands a check that dklen
 
151
     is not larger that 0xffffffff * hlen.  */
 
152
 
 
153
  /* Step 2 */
 
154
  l = ((dklen - 1)/ hlen) + 1;
 
155
  r = dklen - (l - 1) * hlen;
 
156
 
 
157
  /* Setup buffers and prepare a hash context.  */
 
158
  sbuf = (secmode
 
159
          ? gcry_malloc_secure (saltlen + 4 + hlen + hlen)
 
160
          : gcry_malloc (saltlen + 4 + hlen + hlen));
 
161
  if (!sbuf)
 
162
    return gpg_err_code_from_syserror ();
 
163
  tbuf = sbuf + saltlen + 4;
 
164
  ubuf = tbuf + hlen;
 
165
 
 
166
  ec = gpg_err_code (gcry_md_open (&md, hashalgo,
 
167
                                   (GCRY_MD_FLAG_HMAC
 
168
                                    | (secmode?GCRY_MD_FLAG_SECURE:0))));
 
169
  if (ec)
 
170
    {
 
171
      gcry_free (sbuf);
 
172
      return ec;
 
173
    }
 
174
 
 
175
  /* Step 3 and 4. */
 
176
  memcpy (sbuf, salt, saltlen);
 
177
  for (lidx = 1; lidx <= l; lidx++)
 
178
    {
 
179
      for (iter = 0; iter < iterations; iter++)
 
180
        {
 
181
          ec = gpg_err_code (gcry_md_setkey (md, passphrase, passphraselen));
 
182
          if (ec)
 
183
            {
 
184
              gcry_md_close (md);
 
185
              gcry_free (sbuf);
 
186
              return ec;
 
187
            }
 
188
          if (!iter) /* Compute U_1:  */
 
189
            {
 
190
              sbuf[saltlen]     = (lidx >> 24);
 
191
              sbuf[saltlen + 1] = (lidx >> 16);
 
192
              sbuf[saltlen + 2] = (lidx >> 8);
 
193
              sbuf[saltlen + 3] = lidx;
 
194
              gcry_md_write (md, sbuf, saltlen + 4);
 
195
              memcpy (ubuf, gcry_md_read (md, 0), hlen);
 
196
              memcpy (tbuf, ubuf, hlen);
 
197
            }
 
198
          else /* Compute U_(2..c):  */
 
199
            {
 
200
              gcry_md_write (md, ubuf, hlen);
 
201
              memcpy (ubuf, gcry_md_read (md, 0), hlen);
 
202
              for (i=0; i < hlen; i++)
 
203
                tbuf[i] ^= ubuf[i];
 
204
            }
 
205
        }
 
206
      if (lidx == l)  /* Last block.  */
 
207
        memcpy (dk, tbuf, r);
 
208
      else
 
209
        {
 
210
          memcpy (dk, tbuf, hlen);
 
211
          dk += hlen;
 
212
        }
 
213
    }
 
214
 
 
215
  gcry_md_close (md);
 
216
  gcry_free (sbuf);
 
217
  return 0;
 
218
}
 
219
 
 
220
 
 
221
/* Derive a key from a passphrase.  KEYSIZE gives the requested size
 
222
   of the keys in octets.  KEYBUFFER is a caller provided buffer
 
223
   filled on success with the derived key.  The input passphrase is
 
224
   taken from (PASSPHRASE,PASSPHRASELEN) which is an arbitrary memory
 
225
   buffer.  ALGO specifies the KDF algorithm to use; these are the
 
226
   constants GCRY_KDF_*.  SUBALGO specifies an algorithm used
 
227
   internally by the KDF algorithms; this is usually a hash algorithm
 
228
   but certain KDF algorithm may use it differently.  {SALT,SALTLEN}
 
229
   is a salt as needed by most KDF algorithms.  ITERATIONS is a
 
230
   positive integer parameter to most KDFs.  0 is returned on success,
 
231
   or an error code on failure.  */
 
232
gpg_error_t
 
233
gcry_kdf_derive (const void *passphrase, size_t passphraselen,
 
234
                 int algo, int subalgo,
 
235
                 const void *salt, size_t saltlen,
 
236
                 unsigned long iterations,
 
237
                 size_t keysize, void *keybuffer)
 
238
{
 
239
  gpg_err_code_t ec;
 
240
 
 
241
  if (!passphrase || (!passphraselen && algo != GCRY_KDF_PBKDF2))
 
242
    {
 
243
      ec = GPG_ERR_INV_DATA;
 
244
      goto leave;
 
245
    }
 
246
  if (!keybuffer || !keysize)
 
247
    {
 
248
      ec = GPG_ERR_INV_VALUE;
 
249
      goto leave;
 
250
    }
 
251
 
 
252
 
 
253
  switch (algo)
 
254
    {
 
255
    case GCRY_KDF_SIMPLE_S2K:
 
256
    case GCRY_KDF_SALTED_S2K:
 
257
    case GCRY_KDF_ITERSALTED_S2K:
 
258
      ec = openpgp_s2k (passphrase, passphraselen, algo, subalgo,
 
259
                        salt, saltlen, iterations, keysize, keybuffer);
 
260
      break;
 
261
 
 
262
    case GCRY_KDF_PBKDF1:
 
263
      ec = GPG_ERR_UNSUPPORTED_ALGORITHM;
 
264
      break;
 
265
 
 
266
    case GCRY_KDF_PBKDF2:
 
267
      ec = pkdf2 (passphrase, passphraselen, subalgo,
 
268
                  salt, saltlen, iterations, keysize, keybuffer);
 
269
      break;
 
270
 
 
271
    default:
 
272
      ec = GPG_ERR_UNKNOWN_ALGORITHM;
 
273
      break;
 
274
    }
 
275
 
 
276
 leave:
 
277
  return gpg_error (ec);
 
278
}