~xnox/debian/sid/cryptsetup/ubuntu

« back to all changes in this revision

Viewing changes to lib/crypto_backend/pbkdf2_generic.c

  • Committer: Package Import Robot
  • Author(s): Jonas Meurer, Milan Broz, Steve Langasek, Jonas Meurer
  • Date: 2013-06-28 12:10:41 UTC
  • mfrom: (0.2.11)
  • Revision ID: package-import@ubuntu.com-20130628121041-ek9rtel19yehj31t
Tags: 2:1.6.1-1
[ Milan Broz ]
* new upstream version. (closes: #704827, 707997)
  - default LUKS encryption mode is XTS (aes-xts-plain64) (closes: #714331)
  - adds native support for Truecrypt and compatible on-disk format
  - adds benchmark command
  - adds cryptsetup-reencrypt, a tool to offline reencrypt LUKS device
  - adds veritysetup, a tool for dm-verity block device verification module
* install docs/examples into docs at cryptsetup-dev package.
* fix compilation warnings in askpass.c.

[ Steve Langasek ]
* fix upstart jobs to not cause boot hangs when actually used in
  conjunction with startpar.  (closes: #694499, #677712).
* in connection with the above, make the cryptdisks-early job explicitly
  wait for 'umountfs' on shutdown just like cryptdisks does; otherwise,
  the teardown of the cryptdisks upstart job may cause the cryptdisks-early
  init script run before we're done unmounting filesystems.

[ Jonas Meurer ]
* minor wording fixes to README.initramfs, suggested by intrigeri and Adam
  D. Barrett.
* add bash-completion script for cryptdisks_{start,stop}. Thanks to Claudius
  Hubig for providing a patch. (closes: #700777)
* support specifying key-slot in crypttab. Thanks to Kevin Locke for the
  patch. (closes: #704470)
* remove evms support code from cryptroot initramfs script. (closes: #713918)
* fix location of keyscripts in initramfs documentation. (closes: #697446)
* fix a typo in decrypt_ssl script that prevented stdout from beeing
  redirected to /dev/null. (closes: #700285)
* give full path to blkid in crytproot initramfs script. (closes: #697155)
* export number of previous tries from cryptroot and cryptdisks to
  keyscript. Thanks to Laurens Blankers for the idea. Opens the possibility
  to fallback after a given number of tries for keyscripts. (closes: #438481,
  #471729, #697455)
* improve check for cpu hardware encryption support in initramfs cryptroot
  hook. (closes: #714326)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Implementation of Password-Based Cryptography as per PKCS#5
 
3
 * Copyright (C) 2002,2003 Simon Josefsson
 
4
 * Copyright (C) 2004 Free Software Foundation
 
5
 *
 
6
 * cryptsetup related changes
 
7
 * Copyright (C) 2012, Red Hat, Inc. All rights reserved.
 
8
 *
 
9
 * This file is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU Lesser General Public
 
11
 * License as published by the Free Software Foundation; either
 
12
 * version 2.1 of the License, or (at your option) any later version.
 
13
 *
 
14
 * This file is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
 * Lesser General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU Lesser General Public
 
20
 * License along with this file; if not, write to the Free Software
 
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
22
 *
 
23
 */
 
24
 
 
25
#include <errno.h>
 
26
#include <alloca.h>
 
27
#include "crypto_backend.h"
 
28
 
 
29
/*
 
30
 * 5.2 PBKDF2
 
31
 *
 
32
 *  PBKDF2 applies a pseudorandom function (see Appendix B.1 for an
 
33
 *  example) to derive keys. The length of the derived key is essentially
 
34
 *  unbounded. (However, the maximum effective search space for the
 
35
 *  derived key may be limited by the structure of the underlying
 
36
 *  pseudorandom function. See Appendix B.1 for further discussion.)
 
37
 *  PBKDF2 is recommended for new applications.
 
38
 *
 
39
 *  PBKDF2 (P, S, c, dkLen)
 
40
 *
 
41
 *  Options:        PRF        underlying pseudorandom function (hLen
 
42
 *                             denotes the length in octets of the
 
43
 *                             pseudorandom function output)
 
44
 *
 
45
 *  Input:          P          password, an octet string (ASCII or UTF-8)
 
46
 *                  S          salt, an octet string
 
47
 *                  c          iteration count, a positive integer
 
48
 *                  dkLen      intended length in octets of the derived
 
49
 *                             key, a positive integer, at most
 
50
 *                             (2^32 - 1) * hLen
 
51
 *
 
52
 *  Output:         DK         derived key, a dkLen-octet string
 
53
 */
 
54
 
 
55
#define MAX_PRF_BLOCK_LEN 80
 
56
 
 
57
int pkcs5_pbkdf2(const char *hash,
 
58
                        const char *P, size_t Plen,
 
59
                        const char *S, size_t Slen,
 
60
                        unsigned int c, unsigned int dkLen,
 
61
                        char *DK)
 
62
{
 
63
        struct crypt_hmac *hmac;
 
64
        char U[MAX_PRF_BLOCK_LEN];
 
65
        char T[MAX_PRF_BLOCK_LEN];
 
66
        int i, k, rc = -EINVAL;
 
67
        unsigned int u, hLen, l, r;
 
68
        size_t tmplen = Slen + 4;
 
69
        char *tmp;
 
70
 
 
71
        tmp = alloca(tmplen);
 
72
        if (tmp == NULL)
 
73
                return -ENOMEM;
 
74
 
 
75
        hLen = crypt_hmac_size(hash);
 
76
        if (hLen == 0 || hLen > MAX_PRF_BLOCK_LEN)
 
77
                return -EINVAL;
 
78
 
 
79
        if (c == 0)
 
80
                return -EINVAL;
 
81
 
 
82
        if (dkLen == 0)
 
83
                return -EINVAL;
 
84
 
 
85
        /*
 
86
         *
 
87
         *  Steps:
 
88
         *
 
89
         *     1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
 
90
         *        stop.
 
91
         */
 
92
 
 
93
        if (dkLen > 4294967295U)
 
94
                return -EINVAL;
 
95
 
 
96
        /*
 
97
         *     2. Let l be the number of hLen-octet blocks in the derived key,
 
98
         *        rounding up, and let r be the number of octets in the last
 
99
         *        block:
 
100
         *
 
101
         *                  l = CEIL (dkLen / hLen) ,
 
102
         *                  r = dkLen - (l - 1) * hLen .
 
103
         *
 
104
         *        Here, CEIL (x) is the "ceiling" function, i.e. the smallest
 
105
         *        integer greater than, or equal to, x.
 
106
         */
 
107
 
 
108
        l = dkLen / hLen;
 
109
        if (dkLen % hLen)
 
110
                l++;
 
111
        r = dkLen - (l - 1) * hLen;
 
112
 
 
113
        /*
 
114
         *     3. For each block of the derived key apply the function F defined
 
115
         *        below to the password P, the salt S, the iteration count c, and
 
116
         *        the block index to compute the block:
 
117
         *
 
118
         *                  T_1 = F (P, S, c, 1) ,
 
119
         *                  T_2 = F (P, S, c, 2) ,
 
120
         *                  ...
 
121
         *                  T_l = F (P, S, c, l) ,
 
122
         *
 
123
         *        where the function F is defined as the exclusive-or sum of the
 
124
         *        first c iterates of the underlying pseudorandom function PRF
 
125
         *        applied to the password P and the concatenation of the salt S
 
126
         *        and the block index i:
 
127
         *
 
128
         *                  F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
 
129
         *
 
130
         *        where
 
131
         *
 
132
         *                  U_1 = PRF (P, S || INT (i)) ,
 
133
         *                  U_2 = PRF (P, U_1) ,
 
134
         *                  ...
 
135
         *                  U_c = PRF (P, U_{c-1}) .
 
136
         *
 
137
         *        Here, INT (i) is a four-octet encoding of the integer i, most
 
138
         *        significant octet first.
 
139
         *
 
140
         *     4. Concatenate the blocks and extract the first dkLen octets to
 
141
         *        produce a derived key DK:
 
142
         *
 
143
         *                  DK = T_1 || T_2 ||  ...  || T_l<0..r-1>
 
144
         *
 
145
         *     5. Output the derived key DK.
 
146
         *
 
147
         *  Note. The construction of the function F follows a "belt-and-
 
148
         *  suspenders" approach. The iterates U_i are computed recursively to
 
149
         *  remove a degree of parallelism from an opponent; they are exclusive-
 
150
         *  ored together to reduce concerns about the recursion degenerating
 
151
         *  into a small set of values.
 
152
         *
 
153
         */
 
154
 
 
155
        if (crypt_hmac_init(&hmac, hash, P, Plen))
 
156
                return -EINVAL;
 
157
 
 
158
        for (i = 1; (unsigned int) i <= l; i++) {
 
159
                memset(T, 0, hLen);
 
160
 
 
161
                for (u = 1; u <= c ; u++) {
 
162
                        if (u == 1) {
 
163
                                memcpy(tmp, S, Slen);
 
164
                                tmp[Slen + 0] = (i & 0xff000000) >> 24;
 
165
                                tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
 
166
                                tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
 
167
                                tmp[Slen + 3] = (i & 0x000000ff) >> 0;
 
168
 
 
169
                                if (crypt_hmac_write(hmac, tmp, tmplen))
 
170
                                        goto out;
 
171
                        } else {
 
172
                                if (crypt_hmac_write(hmac, U, hLen))
 
173
                                        goto out;
 
174
                        }
 
175
 
 
176
                        if (crypt_hmac_final(hmac, U, hLen))
 
177
                                goto out;
 
178
 
 
179
                        for (k = 0; (unsigned int) k < hLen; k++)
 
180
                                T[k] ^= U[k];
 
181
                }
 
182
 
 
183
                memcpy(DK + (i - 1) * hLen, T, (unsigned int) i == l ? r : hLen);
 
184
        }
 
185
        rc = 0;
 
186
out:
 
187
        crypt_hmac_destroy(hmac);
 
188
        return rc;
 
189
}