Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pwdbased.c Source File

pwdbased.c

00001 /* pwdbased.c
00002  *
00003  * Copyright (C) 2006-2016 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfssl/wolfcrypt/settings.h>
00028 
00029 #ifndef NO_PWDBASED
00030 
00031 #ifdef WOLFSSL_PIC32MZ_HASH
00032     #ifndef NO_MD5
00033         #define wc_InitMd5   wc_InitMd5_sw
00034         #define wc_Md5Update wc_Md5Update_sw
00035         #define wc_Md5Final  wc_Md5Final_sw
00036     #endif /* NO_MD5 */
00037 
00038     #define wc_InitSha   wc_InitSha_sw
00039     #define wc_ShaUpdate wc_ShaUpdate_sw
00040     #define wc_ShaFinal  wc_ShaFinal_sw
00041 
00042     #define wc_InitSha256   wc_InitSha256_sw
00043     #define wc_Sha256Update wc_Sha256Update_sw
00044     #define wc_Sha256Final  wc_Sha256Final_sw
00045 #endif
00046 
00047 #include <wolfssl/wolfcrypt/pwdbased.h>
00048 #include <wolfssl/wolfcrypt/hmac.h>
00049 #include <wolfssl/wolfcrypt/integer.h>
00050 #include <wolfssl/wolfcrypt/error-crypt.h>
00051 #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
00052     #include <wolfssl/wolfcrypt/sha512.h>
00053 #endif
00054 
00055 #ifdef NO_INLINE
00056     #include <wolfssl/wolfcrypt/misc.h>
00057 #else
00058     #include <wolfcrypt/src/misc.c>
00059 #endif
00060 
00061 #ifndef WOLFSSL_HAVE_MIN
00062 #define WOLFSSL_HAVE_MIN
00063 
00064     static INLINE word32 min(word32 a, word32 b)
00065     {
00066         return a > b ? b : a;
00067     }
00068 
00069 #endif /* WOLFSSL_HAVE_MIN */
00070 
00071 
00072 #ifndef NO_SHA
00073 /* PBKDF1 needs at least SHA available */
00074 int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
00075            int sLen, int iterations, int kLen, int hashType)
00076 {
00077     Sha  sha;
00078 #ifndef NO_MD5
00079     Md5  md5;
00080 #endif
00081     int  hLen = (int)SHA_DIGEST_SIZE;
00082     int  i, ret = 0;
00083     byte buffer[SHA_DIGEST_SIZE];  /* max size */
00084 
00085     if (hashType != MD5 && hashType != SHA)
00086         return BAD_FUNC_ARG;
00087 
00088 #ifndef NO_MD5
00089     if (hashType == MD5)
00090         hLen = (int)MD5_DIGEST_SIZE;
00091 #endif
00092 
00093     if (kLen > hLen)
00094         return BAD_FUNC_ARG;
00095 
00096     if (iterations < 1)
00097         return BAD_FUNC_ARG;
00098 
00099     switch (hashType) {
00100 #ifndef NO_MD5
00101         case MD5:
00102             wc_InitMd5(&md5);
00103             wc_Md5Update(&md5, passwd, pLen);
00104             wc_Md5Update(&md5, salt,   sLen);
00105             wc_Md5Final(&md5,  buffer);
00106             break;
00107 #endif /* NO_MD5 */
00108         case SHA:
00109         default:
00110             ret = wc_InitSha(&sha);
00111             if (ret != 0)
00112                 return ret;
00113             wc_ShaUpdate(&sha, passwd, pLen);
00114             wc_ShaUpdate(&sha, salt,   sLen);
00115             wc_ShaFinal(&sha,  buffer);
00116             break;
00117     }
00118 
00119     for (i = 1; i < iterations; i++) {
00120         if (hashType == SHA) {
00121             wc_ShaUpdate(&sha, buffer, hLen);
00122             wc_ShaFinal(&sha,  buffer);
00123         }
00124 #ifndef NO_MD5
00125         else {
00126             wc_Md5Update(&md5, buffer, hLen);
00127             wc_Md5Final(&md5,  buffer);
00128         }
00129 #endif
00130     }
00131     XMEMCPY(output, buffer, kLen);
00132 
00133     return 0;
00134 }
00135 #endif /* NO_SHA */
00136 
00137 
00138 int GetDigestSize(int hashType)
00139 {
00140     int hLen;
00141 
00142     switch (hashType) {
00143 #ifndef NO_MD5
00144         case MD5:
00145             hLen = MD5_DIGEST_SIZE;
00146             break;
00147 #endif
00148 #ifndef NO_SHA
00149         case SHA:
00150             hLen = SHA_DIGEST_SIZE;
00151             break;
00152 #endif
00153 #ifndef NO_SHA256
00154         case SHA256:
00155             hLen = SHA256_DIGEST_SIZE;
00156             break;
00157 #endif
00158 #ifdef WOLFSSL_SHA512
00159         case SHA512:
00160             hLen = SHA512_DIGEST_SIZE;
00161             break;
00162 #endif
00163         default:
00164             return BAD_FUNC_ARG;
00165     }
00166 
00167     return hLen;
00168 }
00169 
00170 
00171 int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
00172            int sLen, int iterations, int kLen, int hashType)
00173 {
00174     word32 i = 1;
00175     int    hLen;
00176     int    j, ret;
00177     Hmac   hmac;
00178 #ifdef WOLFSSL_SMALL_STACK
00179     byte*  buffer;
00180 #else
00181     byte   buffer[MAX_DIGEST_SIZE];
00182 #endif
00183 
00184     hLen = GetDigestSize(hashType);
00185     if (hLen < 0)
00186         return BAD_FUNC_ARG;
00187 
00188 #ifdef WOLFSSL_SMALL_STACK
00189     buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00190     if (buffer == NULL)
00191         return MEMORY_E;
00192 #endif
00193 
00194     ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen);
00195 
00196     if (ret == 0) {
00197         while (kLen) {
00198             int currentLen;
00199 
00200             ret = wc_HmacUpdate(&hmac, salt, sLen);
00201             if (ret != 0)
00202                 break;
00203 
00204             /* encode i */
00205             for (j = 0; j < 4; j++) {
00206                 byte b = (byte)(i >> ((3-j) * 8));
00207 
00208                 ret = wc_HmacUpdate(&hmac, &b, 1);
00209                 if (ret != 0)
00210                     break;
00211             }
00212 
00213             /* check ret from inside for loop */
00214             if (ret != 0)
00215                 break;
00216 
00217             ret = wc_HmacFinal(&hmac, buffer);
00218             if (ret != 0)
00219                 break;
00220 
00221             currentLen = min(kLen, hLen);
00222             XMEMCPY(output, buffer, currentLen);
00223 
00224             for (j = 1; j < iterations; j++) {
00225                 ret = wc_HmacUpdate(&hmac, buffer, hLen);
00226                 if (ret != 0)
00227                     break;
00228                 ret = wc_HmacFinal(&hmac, buffer);
00229                 if (ret != 0)
00230                     break;
00231                 xorbuf(output, buffer, currentLen);
00232             }
00233 
00234             /* check ret from inside for loop */
00235             if (ret != 0)
00236                 break;
00237 
00238             output += currentLen;
00239             kLen   -= currentLen;
00240             i++;
00241         }
00242     }
00243 
00244 #ifdef WOLFSSL_SMALL_STACK
00245     XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00246 #endif
00247 
00248     return ret;
00249 }
00250 
00251 #ifdef WOLFSSL_SHA512
00252     #define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE
00253 #elif !defined(NO_SHA256)
00254     #define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE
00255 #else
00256     #define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE
00257 #endif
00258 
00259 /* helper for wc_PKCS12_PBKDF(), sets block and digest sizes */
00260 int GetPKCS12HashSizes(int hashType, word32* v, word32* u)
00261 {
00262     if (!v || !u)
00263         return BAD_FUNC_ARG;
00264 
00265     switch (hashType) {
00266 #ifndef NO_MD5
00267         case MD5:
00268             *v = MD5_BLOCK_SIZE;
00269             *u = MD5_DIGEST_SIZE;
00270             break;
00271 #endif
00272 #ifndef NO_SHA
00273         case SHA:
00274             *v = SHA_BLOCK_SIZE;
00275             *u = SHA_DIGEST_SIZE;
00276             break;
00277 #endif
00278 #ifndef NO_SHA256
00279         case SHA256:
00280             *v = SHA256_BLOCK_SIZE;
00281             *u = SHA256_DIGEST_SIZE;
00282             break;
00283 #endif
00284 #ifdef WOLFSSL_SHA512
00285         case SHA512:
00286             *v = SHA512_BLOCK_SIZE;
00287             *u = SHA512_DIGEST_SIZE;
00288             break;
00289 #endif
00290         default:
00291             return BAD_FUNC_ARG;
00292     }
00293 
00294     return 0;
00295 }
00296 
00297 /* helper for PKCS12_PBKDF(), does hash operation */
00298 int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen,
00299                  byte* Ai, word32 u, int iterations)
00300 {
00301     int i;
00302     int ret = 0;
00303 
00304     if (buffer == NULL || Ai == NULL)
00305         return BAD_FUNC_ARG;
00306 
00307     switch (hashType) {
00308 #ifndef NO_MD5
00309         case MD5:
00310             {
00311                 Md5 md5;
00312                 wc_InitMd5(&md5);
00313                 wc_Md5Update(&md5, buffer, totalLen);
00314                 wc_Md5Final(&md5, Ai);
00315 
00316                 for (i = 1; i < iterations; i++) {
00317                     wc_Md5Update(&md5, Ai, u);
00318                     wc_Md5Final(&md5, Ai);
00319                 }
00320             }
00321             break;
00322 #endif /* NO_MD5 */
00323 #ifndef NO_SHA
00324         case SHA:
00325             {
00326                 Sha sha;
00327                 ret = wc_InitSha(&sha);
00328                 if (ret != 0)
00329                     break;
00330                 wc_ShaUpdate(&sha, buffer, totalLen);
00331                 wc_ShaFinal(&sha, Ai);
00332 
00333                 for (i = 1; i < iterations; i++) {
00334                     wc_ShaUpdate(&sha, Ai, u);
00335                     wc_ShaFinal(&sha, Ai);
00336                 }
00337             }
00338             break;
00339 #endif /* NO_SHA */
00340 #ifndef NO_SHA256
00341         case SHA256:
00342             {
00343                 Sha256 sha256;
00344                 ret = wc_InitSha256(&sha256);
00345                 if (ret != 0)
00346                     break;
00347 
00348                 ret = wc_Sha256Update(&sha256, buffer, totalLen);
00349                 if (ret != 0)
00350                     break;
00351 
00352                 ret = wc_Sha256Final(&sha256, Ai);
00353                 if (ret != 0)
00354                     break;
00355 
00356                 for (i = 1; i < iterations; i++) {
00357                     ret = wc_Sha256Update(&sha256, Ai, u);
00358                     if (ret != 0)
00359                         break;
00360 
00361                     ret = wc_Sha256Final(&sha256, Ai);
00362                     if (ret != 0)
00363                         break;
00364                 }
00365             }
00366             break;
00367 #endif /* NO_SHA256 */
00368 #ifdef WOLFSSL_SHA512
00369         case SHA512:
00370             {
00371                 Sha512 sha512;
00372                 ret = wc_InitSha512(&sha512);
00373                 if (ret != 0)
00374                     break;
00375 
00376                 ret = wc_Sha512Update(&sha512, buffer, totalLen);
00377                 if (ret != 0)
00378                     break;
00379 
00380                 ret = wc_Sha512Final(&sha512, Ai);
00381                 if (ret != 0)
00382                     break;
00383 
00384                 for (i = 1; i < iterations; i++) {
00385                     ret = wc_Sha512Update(&sha512, Ai, u);
00386                     if (ret != 0)
00387                         break;
00388 
00389                     ret = wc_Sha512Final(&sha512, Ai);
00390                     if (ret != 0)
00391                         break;
00392                 }
00393             }
00394             break;
00395 #endif /* WOLFSSL_SHA512 */
00396 
00397         default:
00398             ret = BAD_FUNC_ARG;
00399             break;
00400     }
00401 
00402     return ret;
00403 }
00404 
00405 int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt,
00406                  int saltLen, int iterations, int kLen, int hashType, int id)
00407 {
00408     /* all in bytes instead of bits */
00409     word32 u, v, dLen, pLen, iLen, sLen, totalLen;
00410     int    dynamic = 0;
00411     int    ret = 0;
00412     int    i;
00413     byte   *D, *S, *P, *I;
00414 #ifdef WOLFSSL_SMALL_STACK
00415     byte   staticBuffer[1]; /* force dynamic usage */
00416 #else
00417     byte   staticBuffer[1024];
00418 #endif
00419     byte*  buffer = staticBuffer;
00420 
00421 #ifdef WOLFSSL_SMALL_STACK
00422     byte*  Ai;
00423     byte*  B;
00424 #else
00425     byte   Ai[PBKDF_DIGEST_SIZE];
00426     byte   B[PBKDF_DIGEST_SIZE];
00427 #endif
00428 
00429     if (!iterations)
00430         iterations = 1;
00431 
00432     ret = GetPKCS12HashSizes(hashType, &v, &u);
00433     if (ret < 0)
00434         return BAD_FUNC_ARG;
00435 
00436 #ifdef WOLFSSL_SMALL_STACK
00437     Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00438     if (Ai == NULL)
00439         return MEMORY_E;
00440 
00441     B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00442     if (B == NULL) {
00443         XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00444         return MEMORY_E;
00445     }
00446 #endif
00447 
00448     XMEMSET(Ai, 0, PBKDF_DIGEST_SIZE);
00449     XMEMSET(B,  0, PBKDF_DIGEST_SIZE);
00450 
00451     dLen = v;
00452     sLen =  v * ((saltLen + v - 1) / v);
00453     if (passLen)
00454         pLen = v * ((passLen + v - 1) / v);
00455     else
00456         pLen = 0;
00457     iLen = sLen + pLen;
00458 
00459     totalLen = dLen + sLen + pLen;
00460 
00461     if (totalLen > sizeof(staticBuffer)) {
00462         buffer = (byte*)XMALLOC(totalLen, 0, DYNAMIC_TYPE_KEY);
00463         if (buffer == NULL) {
00464 #ifdef WOLFSSL_SMALL_STACK
00465             XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00466             XFREE(B,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
00467 #endif
00468             return MEMORY_E;
00469         }
00470         dynamic = 1;
00471     }
00472 
00473     D = buffer;
00474     S = D + dLen;
00475     P = S + sLen;
00476     I = S;
00477 
00478     XMEMSET(D, id, dLen);
00479 
00480     for (i = 0; i < (int)sLen; i++)
00481         S[i] = salt[i % saltLen];
00482     for (i = 0; i < (int)pLen; i++)
00483         P[i] = passwd[i % passLen];
00484 
00485     while (kLen > 0) {
00486         word32 currentLen;
00487         mp_int B1;
00488 
00489         ret = DoPKCS12Hash(hashType, buffer, totalLen, Ai, u, iterations);
00490         if (ret < 0)
00491             break;
00492 
00493         for (i = 0; i < (int)v; i++)
00494             B[i] = Ai[i % u];
00495 
00496         if (mp_init(&B1) != MP_OKAY)
00497             ret = MP_INIT_E;
00498         else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
00499             ret = MP_READ_E;
00500         else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
00501             ret = MP_ADD_E;
00502 
00503         if (ret != 0) {
00504             mp_clear(&B1);
00505             break;
00506         }
00507 
00508         for (i = 0; i < (int)iLen; i += v) {
00509             int    outSz;
00510             mp_int i1;
00511             mp_int res;
00512 
00513             if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
00514                 ret = MP_INIT_E;
00515                 break;
00516             }
00517             if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
00518                 ret = MP_READ_E;
00519             else if (mp_add(&i1, &B1, &res) != MP_OKAY)
00520                 ret = MP_ADD_E;
00521             else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
00522                 ret = MP_TO_E;
00523             else {
00524                 if (outSz > (int)v) {
00525                     /* take off MSB */
00526                     byte  tmp[129];
00527                     ret = mp_to_unsigned_bin(&res, tmp);
00528                     XMEMCPY(I + i, tmp + 1, v);
00529                 }
00530                 else if (outSz < (int)v) {
00531                     XMEMSET(I + i, 0, v - outSz);
00532                     ret = mp_to_unsigned_bin(&res, I + i + v - outSz);
00533                 }
00534                 else
00535                     ret = mp_to_unsigned_bin(&res, I + i);
00536             }
00537 
00538             mp_clear(&i1);
00539             mp_clear(&res);
00540             if (ret < 0) break;
00541         }
00542 
00543         currentLen = min(kLen, (int)u);
00544         XMEMCPY(output, Ai, currentLen);
00545         output += currentLen;
00546         kLen   -= currentLen;
00547         mp_clear(&B1);
00548     }
00549 
00550     if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY);
00551 
00552 #ifdef WOLFSSL_SMALL_STACK
00553     XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00554     XFREE(B,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
00555 #endif
00556 
00557     return ret;
00558 }
00559 
00560 #undef PBKDF_DIGEST_SIZE
00561 
00562 #endif /* NO_PWDBASED */
00563 
00564