1 /* gc-pbkdf2.c --- Password-Based Key Derivation Function a'la PKCS#5
2 Copyright (C) 2002-2006, 2009-2020 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Simon Josefsson. */
26 typedef Gc_rc (*gc_prf_func
) (const void *key
, size_t keylen
,
27 const void *in
, size_t inlen
, char *resbuf
);
30 gc_pbkdf2_prf (gc_prf_func prf
, size_t hLen
,
31 const char *P
, size_t Plen
,
32 const char *S
, size_t Slen
,
34 char *DK
, size_t dkLen
)
36 char U
[GC_MAX_DIGEST_SIZE
];
37 char T
[GC_MAX_DIGEST_SIZE
];
45 size_t tmplen
= Slen
+ 4;
48 return GC_PKCS5_INVALID_ITERATION_COUNT
;
51 return GC_PKCS5_INVALID_DERIVED_KEY_LENGTH
;
53 if (dkLen
> 4294967295U)
54 return GC_PKCS5_DERIVED_KEY_TOO_LONG
;
56 l
= ((dkLen
- 1) / hLen
) + 1;
57 r
= dkLen
- (l
- 1) * hLen
;
59 tmp
= malloc (tmplen
);
61 return GC_MALLOC_ERROR
;
63 memcpy (tmp
, S
, Slen
);
65 for (i
= 1; i
<= l
; i
++)
69 for (u
= 1; u
<= c
; u
++)
73 tmp
[Slen
+ 0] = (i
& 0xff000000) >> 24;
74 tmp
[Slen
+ 1] = (i
& 0x00ff0000) >> 16;
75 tmp
[Slen
+ 2] = (i
& 0x0000ff00) >> 8;
76 tmp
[Slen
+ 3] = (i
& 0x000000ff) >> 0;
78 rc
= prf (P
, Plen
, tmp
, tmplen
, U
);
81 rc
= prf (P
, Plen
, U
, hLen
, U
);
89 for (k
= 0; k
< hLen
; k
++)
93 memcpy (DK
+ (i
- 1) * hLen
, T
, i
== l
? r
: hLen
);
102 gc_pbkdf2_hmac (Gc_hash hash
,
103 const char *P
, size_t Plen
,
104 const char *S
, size_t Slen
,
105 unsigned int c
, char *DK
, size_t dkLen
)
112 #if GNULIB_GC_HMAC_SHA1
115 hLen
= GC_SHA1_DIGEST_SIZE
;
119 #if GNULIB_GC_HMAC_SHA256
121 prf
= gc_hmac_sha256
;
122 hLen
= GC_SHA256_DIGEST_SIZE
;
126 #if GNULIB_GC_HMAC_SHA512
128 prf
= gc_hmac_sha512
;
129 hLen
= GC_SHA512_DIGEST_SIZE
;
134 return GC_INVALID_HASH
;
137 return gc_pbkdf2_prf (prf
, hLen
, P
, Plen
, S
, Slen
, c
, DK
, dkLen
);