Branch data Line data Source code
1 : : /* gc-pbkdf2-sha1.c --- Password-Based Key Derivation Function a'la PKCS#5
2 : : Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009, 2010 Free Software
3 : : Foundation, Inc.
4 : :
5 : : This program is free software; you can redistribute it and/or modify
6 : : it under the terms of the GNU General Public License as published by
7 : : the Free Software Foundation; either version 3, or (at your option)
8 : : any later version.
9 : :
10 : : This program is distributed in the hope that it will be useful,
11 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : : GNU General Public License for more details.
14 : :
15 : : You should have received a copy of the GNU General Public License
16 : : along with this program; if not, write to the Free Software Foundation,
17 : : Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 : :
19 : : /* Written by Simon Josefsson. */
20 : :
21 : : #include <config.h>
22 : :
23 : : #include "gc.h"
24 : :
25 : : #include <stdlib.h>
26 : : #include <string.h>
27 : :
28 : : /* Implement PKCS#5 PBKDF2 as per RFC 2898. The PRF to use is hard
29 : : coded to be HMAC-SHA1. Inputs are the password P of length PLEN,
30 : : the salt S of length SLEN, the iteration counter C (> 0), and the
31 : : desired derived output length DKLEN. Output buffer is DK which
32 : : must have room for at least DKLEN octets. The output buffer will
33 : : be filled with the derived data. */
34 : : Gc_rc
35 : 28 : gc_pbkdf2_sha1 (const char *P, size_t Plen,
36 : : const char *S, size_t Slen,
37 : : unsigned int c,
38 : : char *DK, size_t dkLen)
39 : : {
40 : 28 : unsigned int hLen = 20;
41 : : char U[20];
42 : : char T[20];
43 : : unsigned int u;
44 : : unsigned int l;
45 : : unsigned int r;
46 : : unsigned int i;
47 : : unsigned int k;
48 : : int rc;
49 : : char *tmp;
50 : 28 : size_t tmplen = Slen + 4;
51 : :
52 [ - + ]: 28 : if (c == 0)
53 : 0 : return GC_PKCS5_INVALID_ITERATION_COUNT;
54 : :
55 [ - + ]: 28 : if (dkLen == 0)
56 : 0 : return GC_PKCS5_INVALID_DERIVED_KEY_LENGTH;
57 : :
58 : : if (dkLen > 4294967295U)
59 : : return GC_PKCS5_DERIVED_KEY_TOO_LONG;
60 : :
61 : 28 : l = ((dkLen - 1) / hLen) + 1;
62 : 28 : r = dkLen - (l - 1) * hLen;
63 : :
64 : 28 : tmp = malloc (tmplen);
65 [ - + ]: 28 : if (tmp == NULL)
66 : 0 : return GC_MALLOC_ERROR;
67 : :
68 : 28 : memcpy (tmp, S, Slen);
69 : :
70 [ + + ]: 69 : for (i = 1; i <= l; i++)
71 : : {
72 : 41 : memset (T, 0, hLen);
73 : :
74 [ + + ]: 22487 : for (u = 1; u <= c; u++)
75 : : {
76 [ + + ]: 22446 : if (u == 1)
77 : : {
78 : 41 : tmp[Slen + 0] = (i & 0xff000000) >> 24;
79 : 41 : tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
80 : 41 : tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
81 : 41 : tmp[Slen + 3] = (i & 0x000000ff) >> 0;
82 : :
83 : 41 : rc = gc_hmac_sha1 (P, Plen, tmp, tmplen, U);
84 : : }
85 : : else
86 : 22405 : rc = gc_hmac_sha1 (P, Plen, U, hLen, U);
87 : :
88 [ - + ]: 22446 : if (rc != GC_OK)
89 : : {
90 : 0 : free (tmp);
91 : 0 : return rc;
92 : : }
93 : :
94 [ + + ]: 471366 : for (k = 0; k < hLen; k++)
95 : 448920 : T[k] ^= U[k];
96 : : }
97 : :
98 [ + + ]: 41 : memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen);
99 : : }
100 : :
101 : 28 : free (tmp);
102 : :
103 : 28 : return GC_OK;
104 : : }
|