A library for setting up Secure Socket Layer (SSL) connections and verifying remote hosts using certificates. Contains only the source files for mbed platform implementation of the library.

Dependents:   HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL

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-2014 wolfSSL Inc.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL 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  * CyaSSL 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-1301, USA
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023     #include <config.h>
00024 #endif
00025 
00026 #include <cyassl/ctaocrypt/settings.h>
00027 
00028 #ifndef NO_PWDBASED
00029 
00030 #ifdef CYASSL_PIC32MZ_HASH
00031 
00032 #define InitMd5   InitMd5_sw
00033 #define Md5Update Md5Update_sw
00034 #define Md5Final  Md5Final_sw
00035 
00036 #define InitSha   InitSha_sw
00037 #define ShaUpdate ShaUpdate_sw
00038 #define ShaFinal  ShaFinal_sw
00039 
00040 #define InitSha256   InitSha256_sw
00041 #define Sha256Update Sha256Update_sw
00042 #define Sha256Final  Sha256Final_sw
00043 
00044 #endif
00045 
00046 #include <cyassl/ctaocrypt/pwdbased.h>
00047 #include <cyassl/ctaocrypt/hmac.h>
00048 #include <cyassl/ctaocrypt/integer.h>
00049 #include <cyassl/ctaocrypt/error-crypt.h>
00050 #if defined(CYASSL_SHA512) || defined(CYASSL_SHA384)
00051     #include <cyassl/ctaocrypt/sha512.h>
00052 #endif
00053 
00054 #ifdef NO_INLINE
00055     #include <cyassl/ctaocrypt/misc.h>
00056 #else
00057     #include <ctaocrypt/src/misc.c>
00058 #endif
00059 
00060 
00061 #ifndef min
00062 
00063     static INLINE word32 min(word32 a, word32 b)
00064     {
00065         return a > b ? b : a;
00066     }
00067 
00068 #endif /* min */
00069 
00070 
00071 int PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
00072            int sLen, int iterations, int kLen, int hashType)
00073 {
00074     Md5  md5;
00075     Sha  sha;
00076     int  hLen = (hashType == MD5) ? (int)MD5_DIGEST_SIZE : (int)SHA_DIGEST_SIZE;
00077     int  i, ret = 0;
00078     byte buffer[SHA_DIGEST_SIZE];  /* max size */
00079 
00080     if (hashType != MD5 && hashType != SHA)
00081         return BAD_FUNC_ARG;
00082 
00083     if (kLen > hLen)
00084         return BAD_FUNC_ARG;
00085 
00086     if (iterations < 1)
00087         return BAD_FUNC_ARG;
00088 
00089     if (hashType == MD5) {
00090         InitMd5(&md5);
00091         Md5Update(&md5, passwd, pLen);
00092         Md5Update(&md5, salt,   sLen);
00093         Md5Final(&md5,  buffer);
00094     }
00095     else {
00096         ret = InitSha(&sha);
00097         if (ret != 0)
00098             return ret;
00099         ShaUpdate(&sha, passwd, pLen);
00100         ShaUpdate(&sha, salt,   sLen);
00101         ShaFinal(&sha,  buffer);
00102     }
00103 
00104     for (i = 1; i < iterations; i++) {
00105         if (hashType == MD5) {
00106             Md5Update(&md5, buffer, hLen);
00107             Md5Final(&md5,  buffer);
00108         }
00109         else {
00110             ShaUpdate(&sha, buffer, hLen);
00111             ShaFinal(&sha,  buffer);
00112         }
00113     }
00114     XMEMCPY(output, buffer, kLen);
00115 
00116     return 0;
00117 }
00118 
00119 
00120 int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
00121            int sLen, int iterations, int kLen, int hashType)
00122 {
00123     word32 i = 1;
00124     int    hLen;
00125     int    j, ret;
00126     Hmac   hmac;
00127 #ifdef CYASSL_SMALL_STACK
00128     byte*  buffer;
00129 #else
00130     byte   buffer[MAX_DIGEST_SIZE];
00131 #endif
00132 
00133     if (hashType == MD5) {
00134         hLen = MD5_DIGEST_SIZE;
00135     }
00136     else if (hashType == SHA) {
00137         hLen = SHA_DIGEST_SIZE;
00138     }
00139 #ifndef NO_SHA256
00140     else if (hashType == SHA256) {
00141         hLen = SHA256_DIGEST_SIZE;
00142     }
00143 #endif
00144 #ifdef CYASSL_SHA512
00145     else if (hashType == SHA512) {
00146         hLen = SHA512_DIGEST_SIZE;
00147     }
00148 #endif
00149     else
00150         return BAD_FUNC_ARG;
00151 
00152 #ifdef CYASSL_SMALL_STACK
00153     buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00154     if (buffer == NULL)
00155         return MEMORY_E;
00156 #endif
00157 
00158     ret = HmacSetKey(&hmac, hashType, passwd, pLen);
00159 
00160     if (ret == 0) {
00161         while (kLen) {
00162             int currentLen;
00163 
00164             ret = HmacUpdate(&hmac, salt, sLen);
00165             if (ret != 0)
00166                 break;
00167 
00168             /* encode i */
00169             for (j = 0; j < 4; j++) {
00170                 byte b = (byte)(i >> ((3-j) * 8));
00171 
00172                 ret = HmacUpdate(&hmac, &b, 1);
00173                 if (ret != 0)
00174                     break;
00175             }
00176 
00177             /* check ret from inside for loop */
00178             if (ret != 0)
00179                 break;
00180 
00181             ret = HmacFinal(&hmac, buffer);
00182             if (ret != 0)
00183                 break;
00184 
00185             currentLen = min(kLen, hLen);
00186             XMEMCPY(output, buffer, currentLen);
00187 
00188             for (j = 1; j < iterations; j++) {
00189                 ret = HmacUpdate(&hmac, buffer, hLen);
00190                 if (ret != 0)
00191                     break;
00192                 ret = HmacFinal(&hmac, buffer);
00193                 if (ret != 0)
00194                     break;
00195                 xorbuf(output, buffer, currentLen);
00196             }
00197 
00198             /* check ret from inside for loop */
00199             if (ret != 0)
00200                 break;
00201 
00202             output += currentLen;
00203             kLen   -= currentLen;
00204             i++;
00205         }
00206     }
00207 
00208 #ifdef CYASSL_SMALL_STACK
00209     XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00210 #endif
00211 
00212     return ret;
00213 }
00214 
00215 #ifdef CYASSL_SHA512
00216 #define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE
00217 #elif !defined(NO_SHA256)
00218 #define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE
00219 #else
00220 #define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE
00221 #endif
00222 
00223 int PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt,
00224                  int saltLen, int iterations, int kLen, int hashType, int id)
00225 {
00226     /* all in bytes instead of bits */
00227     word32 u, v, dLen, pLen, iLen, sLen, totalLen;
00228     int    dynamic = 0;
00229     int    ret = 0;
00230     int    i;
00231     byte   *D, *S, *P, *I;
00232 #ifdef CYASSL_SMALL_STACK
00233     byte   staticBuffer[1]; /* force dynamic usage */
00234 #else
00235     byte   staticBuffer[1024];
00236 #endif
00237     byte*  buffer = staticBuffer;
00238 
00239 #ifdef CYASSL_SMALL_STACK
00240     byte*  Ai;
00241     byte*  B;
00242 #else
00243     byte   Ai[PBKDF_DIGEST_SIZE];
00244     byte   B[PBKDF_DIGEST_SIZE];
00245 #endif
00246 
00247     if (!iterations)
00248         iterations = 1;
00249 
00250     if (hashType == MD5) {
00251         v = MD5_BLOCK_SIZE;
00252         u = MD5_DIGEST_SIZE;
00253     }
00254     else if (hashType == SHA) {
00255         v = SHA_BLOCK_SIZE;
00256         u = SHA_DIGEST_SIZE;
00257     }
00258 #ifndef NO_SHA256
00259     else if (hashType == SHA256) {
00260         v = SHA256_BLOCK_SIZE;
00261         u = SHA256_DIGEST_SIZE;
00262     }
00263 #endif
00264 #ifdef CYASSL_SHA512
00265     else if (hashType == SHA512) {
00266         v = SHA512_BLOCK_SIZE;
00267         u = SHA512_DIGEST_SIZE;
00268     }
00269 #endif
00270     else
00271         return BAD_FUNC_ARG;
00272 
00273 #ifdef CYASSL_SMALL_STACK
00274     Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00275     if (Ai == NULL)
00276         return MEMORY_E;
00277 
00278     B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00279     if (B == NULL) {
00280         XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00281         return MEMORY_E;
00282     }
00283 #endif
00284 
00285     dLen = v;
00286     sLen =  v * ((saltLen + v - 1) / v);
00287     if (passLen)
00288         pLen = v * ((passLen + v - 1) / v);
00289     else
00290         pLen = 0;
00291     iLen = sLen + pLen;
00292 
00293     totalLen = dLen + sLen + pLen;
00294 
00295     if (totalLen > sizeof(staticBuffer)) {
00296         buffer = (byte*)XMALLOC(totalLen, 0, DYNAMIC_TYPE_KEY);
00297         if (buffer == NULL) {
00298 #ifdef CYASSL_SMALL_STACK
00299             XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00300             XFREE(B,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
00301 #endif
00302             return MEMORY_E;
00303         }
00304         dynamic = 1;
00305     } 
00306 
00307     D = buffer;
00308     S = D + dLen;
00309     P = S + sLen;
00310     I = S;
00311 
00312     XMEMSET(D, id, dLen);
00313 
00314     for (i = 0; i < (int)sLen; i++)
00315         S[i] = salt[i % saltLen];
00316     for (i = 0; i < (int)pLen; i++)
00317         P[i] = passwd[i % passLen];
00318 
00319     while (kLen > 0) {
00320         word32 currentLen;
00321         mp_int B1;
00322 
00323         if (hashType == MD5) {
00324             Md5 md5;
00325 
00326             InitMd5(&md5);
00327             Md5Update(&md5, buffer, totalLen);
00328             Md5Final(&md5, Ai);
00329 
00330             for (i = 1; i < iterations; i++) {
00331                 Md5Update(&md5, Ai, u);
00332                 Md5Final(&md5, Ai);
00333             }
00334         }
00335         else if (hashType == SHA) {
00336             Sha sha;
00337 
00338             ret = InitSha(&sha);
00339             if (ret != 0)
00340                 break;
00341             ShaUpdate(&sha, buffer, totalLen);
00342             ShaFinal(&sha, Ai);
00343 
00344             for (i = 1; i < iterations; i++) {
00345                 ShaUpdate(&sha, Ai, u);
00346                 ShaFinal(&sha, Ai);
00347             }
00348         }
00349 #ifndef NO_SHA256
00350         else if (hashType == SHA256) {
00351             Sha256 sha256;
00352 
00353             ret = InitSha256(&sha256);
00354             if (ret != 0)
00355                 break;
00356 
00357             ret = Sha256Update(&sha256, buffer, totalLen);
00358             if (ret != 0)
00359                 break;
00360 
00361             ret = Sha256Final(&sha256, Ai);
00362             if (ret != 0)
00363                 break;
00364 
00365             for (i = 1; i < iterations; i++) {
00366                 ret = Sha256Update(&sha256, Ai, u);
00367                 if (ret != 0)
00368                     break;
00369 
00370                 ret = Sha256Final(&sha256, Ai);
00371                 if (ret != 0)
00372                     break;
00373             }
00374         }
00375 #endif
00376 #ifdef CYASSL_SHA512
00377         else if (hashType == SHA512) {
00378             Sha512 sha512;
00379 
00380             ret = InitSha512(&sha512);
00381             if (ret != 0)
00382                 break;
00383 
00384             ret = Sha512Update(&sha512, buffer, totalLen);
00385             if (ret != 0)
00386                 break;
00387 
00388             ret = Sha512Final(&sha512, Ai);
00389             if (ret != 0)
00390                 break;
00391 
00392             for (i = 1; i < iterations; i++) {
00393                 ret = Sha512Update(&sha512, Ai, u);
00394                 if (ret != 0)
00395                     break;
00396 
00397                 ret = Sha512Final(&sha512, Ai);
00398                 if (ret != 0)
00399                     break;
00400             }
00401         }
00402 #endif
00403 
00404         for (i = 0; i < (int)v; i++)
00405             B[i] = Ai[i % u];
00406 
00407         if (mp_init(&B1) != MP_OKAY)
00408             ret = MP_INIT_E;
00409         else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
00410             ret = MP_READ_E;
00411         else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
00412             ret = MP_ADD_E;
00413 
00414         if (ret != 0) {
00415             mp_clear(&B1);
00416             break;
00417         }
00418 
00419         for (i = 0; i < (int)iLen; i += v) {
00420             int    outSz;
00421             mp_int i1;
00422             mp_int res;
00423 
00424             if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
00425                 ret = MP_INIT_E;
00426                 break;
00427             }
00428             if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
00429                 ret = MP_READ_E;
00430             else if (mp_add(&i1, &B1, &res) != MP_OKAY)
00431                 ret = MP_ADD_E;
00432             else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
00433                 ret = MP_TO_E;
00434             else {
00435                 if (outSz > (int)v) {
00436                     /* take off MSB */
00437                     byte  tmp[129];
00438                     ret = mp_to_unsigned_bin(&res, tmp);
00439                     XMEMCPY(I + i, tmp + 1, v);
00440                 }
00441                 else if (outSz < (int)v) {
00442                     XMEMSET(I + i, 0, v - outSz);
00443                     ret = mp_to_unsigned_bin(&res, I + i + v - outSz);
00444                 }
00445                 else
00446                     ret = mp_to_unsigned_bin(&res, I + i);
00447             }
00448 
00449             mp_clear(&i1);
00450             mp_clear(&res);
00451             if (ret < 0) break;
00452         }
00453 
00454         currentLen = min(kLen, (int)u);
00455         XMEMCPY(output, Ai, currentLen);
00456         output += currentLen;
00457         kLen   -= currentLen;
00458         mp_clear(&B1);
00459     }
00460 
00461     if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY);
00462 
00463 #ifdef CYASSL_SMALL_STACK
00464     XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00465     XFREE(B,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
00466 #endif
00467 
00468     return ret;
00469 }
00470 
00471 #undef PBKDF_DIGEST_SIZE
00472 
00473 #endif /* NO_PWDBASED */
00474