File indexing completed on 2024-04-28 04:43:43
0001 /* pkcs5.c Partial Password-Based Cryptography (PKCS#5) implementation 0002 * Copyright (C) 2002 Free Software Foundation, Inc. 0003 * 0004 * This file is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Lesser General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2.1 of the License, or (at your option) any later version. 0008 * 0009 * This file is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Lesser General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Lesser General Public 0015 * License along with this file; if not, write to the Free Software 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 0017 * 0018 */ 0019 0020 #include "gcrypt.h" 0021 0022 /* 0023 * 5.2 PBKDF2 0024 * 0025 * PBKDF2 applies a pseudorandom function (see Appendix B.1 for an 0026 * example) to derive keys. The length of the derived key is essentially 0027 * unbounded. (However, the maximum effective search space for the 0028 * derived key may be limited by the structure of the underlying 0029 * pseudorandom function. See Appendix B.1 for further discussion.) 0030 * PBKDF2 is recommended for new applications. 0031 * 0032 * PBKDF2 (P, S, c, dkLen) 0033 * 0034 * Options: PRF underlying pseudorandom function (hLen 0035 * denotes the length in octets of the 0036 * pseudorandom function output) 0037 * 0038 * Input: P password, an octet string 0039 * S salt, an octet string 0040 * c iteration count, a positive integer 0041 * dkLen intended length in octets of the derived 0042 * key, a positive integer, at most 0043 * (2^32 - 1) * hLen 0044 * 0045 * Output: DK derived key, a dkLen-octet string 0046 */ 0047 0048 static gcry_error_t gcry_pbkdf2(int PRF, 0049 const char *P, 0050 size_t Plen, 0051 const char *S, 0052 size_t Slen, 0053 unsigned int c, 0054 unsigned int dkLen, 0055 char *DK) 0056 { 0057 gcry_md_hd_t prf; 0058 gcry_error_t rc; 0059 char *U; 0060 unsigned int u; 0061 unsigned int hLen; 0062 unsigned int l; 0063 unsigned int r; 0064 unsigned char *p; 0065 unsigned int i; 0066 unsigned int k; 0067 0068 hLen = gcry_md_get_algo_dlen(PRF); 0069 if (hLen == 0) 0070 return GPG_ERR_UNSUPPORTED_ALGORITHM; 0071 0072 if (c == 0) 0073 return GPG_ERR_INV_ARG; 0074 0075 if (dkLen == 0) 0076 return GPG_ERR_TOO_SHORT; 0077 0078 /* 0079 * 0080 * Steps: 0081 * 0082 * 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and 0083 * stop. 0084 */ 0085 0086 if (dkLen > 4294967295U) 0087 return GPG_ERR_TOO_LARGE; 0088 0089 /* 0090 * 2. Let l be the number of hLen-octet blocks in the derived key, 0091 * rounding up, and let r be the number of octets in the last 0092 * block: 0093 * 0094 * l = CEIL (dkLen / hLen) , 0095 * r = dkLen - (l - 1) * hLen . 0096 * 0097 * Here, CEIL (x) is the "ceiling" function, i.e. the smallest 0098 * integer greater than, or equal to, x. 0099 */ 0100 0101 l = dkLen / hLen; 0102 if (dkLen % hLen) 0103 l++; 0104 r = dkLen - (l - 1) * hLen; 0105 0106 /* 0107 * 3. For each block of the derived key apply the function F defined 0108 * below to the password P, the salt S, the iteration count c, and 0109 * the block index to compute the block: 0110 * 0111 * T_1 = F (P, S, c, 1) , 0112 * T_2 = F (P, S, c, 2) , 0113 * ... 0114 * T_l = F (P, S, c, l) , 0115 * 0116 * where the function F is defined as the exclusive-or sum of the 0117 * first c iterates of the underlying pseudorandom function PRF 0118 * applied to the password P and the concatenation of the salt S 0119 * and the block index i: 0120 * 0121 * F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c 0122 * 0123 * where 0124 * 0125 * U_1 = PRF (P, S || INT (i)) , 0126 * U_2 = PRF (P, U_1) , 0127 * ... 0128 * U_c = PRF (P, U_{c-1}) . 0129 * 0130 * Here, INT (i) is a four-octet encoding of the integer i, most 0131 * significant octet first. 0132 * 0133 * 4. Concatenate the blocks and extract the first dkLen octets to 0134 * produce a derived key DK: 0135 * 0136 * DK = T_1 || T_2 || ... || T_l<0..r-1> 0137 * 0138 * 5. Output the derived key DK. 0139 * 0140 * Note. The construction of the function F follows a "belt-and- 0141 * suspenders" approach. The iterates U_i are computed recursively to 0142 * remove a degree of parallelism from an opponent; they are exclusive- 0143 * ored together to reduce concerns about the recursion degenerating 0144 * into a small set of values. 0145 * 0146 */ 0147 rc = gcry_md_open(&prf, PRF, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE); 0148 if (rc != GPG_ERR_NO_ERROR) 0149 return rc; 0150 0151 U = (char *)gcry_malloc(hLen); 0152 if (!U) { 0153 rc = GPG_ERR_ENOMEM; 0154 goto done; 0155 } 0156 0157 for (i = 1; i <= l; i++) { 0158 memset(DK + (i - 1) * hLen, 0, i == l ? r : hLen); 0159 0160 for (u = 1; u <= c; u++) { 0161 gcry_md_reset(prf); 0162 0163 rc = gcry_md_setkey(prf, P, Plen); 0164 if (rc != GPG_ERR_NO_ERROR) { 0165 goto done; 0166 } 0167 if (u == 1) { 0168 char tmp[4]; 0169 gcry_md_write(prf, S, Slen); 0170 tmp[0] = (i & 0xff000000) >> 24; 0171 tmp[1] = (i & 0x00ff0000) >> 16; 0172 tmp[2] = (i & 0x0000ff00) >> 8; 0173 tmp[3] = (i & 0x000000ff) >> 0; 0174 gcry_md_write(prf, tmp, 4); 0175 } else 0176 gcry_md_write(prf, U, hLen); 0177 0178 p = gcry_md_read(prf, PRF); 0179 if (p == nullptr) { 0180 rc = GPG_ERR_CONFIGURATION; 0181 goto done; 0182 } 0183 0184 memcpy(U, p, hLen); 0185 for (k = 0; k < (i == l ? r : hLen); k++) 0186 DK[(i - 1) * hLen + k] ^= U[k]; 0187 } 0188 } 0189 0190 rc = GPG_ERR_NO_ERROR; 0191 done: 0192 gcry_md_close(prf); 0193 gcry_free(U); 0194 return rc; 0195 }