This is a port of cyaSSL 2.7.0.

Dependents:   CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet

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-2013 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 #include <cyassl/ctaocrypt/pwdbased.h>
00031 #include <cyassl/ctaocrypt/hmac.h>
00032 #include <cyassl/ctaocrypt/integer.h>
00033 #include <cyassl/ctaocrypt/ctaoerror2.h>
00034 #if defined(CYASSL_SHA512) || defined(CYASSL_SHA384)
00035     #include <cyassl/ctaocrypt/sha512.h>
00036 #endif
00037 
00038 #ifdef NO_INLINE
00039     #include <cyassl/ctaocrypt/misc.h>
00040 #else
00041     #include <ctaocrypt/src/misc.c>
00042 #endif
00043 
00044 
00045 #ifndef min
00046 
00047     static INLINE word32 min(word32 a, word32 b)
00048     {
00049         return a > b ? b : a;
00050     }
00051 
00052 #endif /* min */
00053 
00054 
00055 int PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
00056            int sLen, int iterations, int kLen, int hashType)
00057 {
00058     Md5  md5;
00059     Sha  sha;
00060     int  hLen = (hashType == MD5) ? (int)MD5_DIGEST_SIZE : (int)SHA_DIGEST_SIZE;
00061     int  i;
00062     byte buffer[SHA_DIGEST_SIZE];  /* max size */
00063 
00064     if (hashType != MD5 && hashType != SHA)
00065         return BAD_FUNC_ARG;
00066 
00067     if (kLen > hLen)
00068         return BAD_FUNC_ARG;
00069 
00070     if (iterations < 1)
00071         return BAD_FUNC_ARG;
00072 
00073     if (hashType == MD5) {
00074         InitMd5(&md5);
00075         Md5Update(&md5, passwd, pLen);
00076         Md5Update(&md5, salt,   sLen);
00077         Md5Final(&md5,  buffer);
00078     }
00079     else {
00080         InitSha(&sha);
00081         ShaUpdate(&sha, passwd, pLen);
00082         ShaUpdate(&sha, salt,   sLen);
00083         ShaFinal(&sha,  buffer);
00084     }
00085 
00086     for (i = 1; i < iterations; i++) {
00087         if (hashType == MD5) {
00088             Md5Update(&md5, buffer, hLen);
00089             Md5Final(&md5,  buffer);
00090         }
00091         else {
00092             ShaUpdate(&sha, buffer, hLen);
00093             ShaFinal(&sha,  buffer);
00094         }
00095     }
00096     XMEMCPY(output, buffer, kLen);
00097 
00098     return 0;
00099 }
00100 
00101 
00102 int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
00103            int sLen, int iterations, int kLen, int hashType)
00104 {
00105     word32 i = 1;
00106     int    hLen;
00107     int    j;
00108     Hmac   hmac;
00109 #ifdef CYASSL_SHA512
00110     byte   buffer[SHA512_DIGEST_SIZE];
00111 #else
00112     byte   buffer[INNER_HASH_SIZE];  /* max size, doesn't handle 512 yet */
00113 #endif
00114 
00115     if (hashType == MD5) {
00116         hLen = MD5_DIGEST_SIZE;
00117     }
00118     else if (hashType == SHA) {
00119         hLen = SHA_DIGEST_SIZE;
00120     }
00121 #ifndef NO_SHA256
00122     else if (hashType == SHA256) {
00123         hLen = SHA256_DIGEST_SIZE;
00124     }
00125 #endif
00126 #ifdef CYASSL_SHA512
00127     else if (hashType == SHA512) {
00128         hLen = SHA512_DIGEST_SIZE;
00129     }
00130 #endif
00131     else
00132         return BAD_FUNC_ARG;
00133 
00134     HmacSetKey(&hmac, hashType, passwd, pLen);
00135 
00136     while (kLen) {
00137         int currentLen;
00138         HmacUpdate(&hmac, salt, sLen);
00139 
00140         /* encode i */
00141         for (j = 0; j < 4; j++) {
00142             byte b = (byte)(i >> ((3-j) * 8));
00143             HmacUpdate(&hmac, &b, 1);
00144         }
00145         HmacFinal(&hmac, buffer);
00146 
00147         currentLen = min(kLen, hLen);
00148         XMEMCPY(output, buffer, currentLen);
00149 
00150         for (j = 1; j < iterations; j++) {
00151             HmacUpdate(&hmac, buffer, hLen);
00152             HmacFinal(&hmac, buffer);
00153             xorbuf(output, buffer, currentLen);
00154         }
00155 
00156         output += currentLen;
00157         kLen   -= currentLen;
00158         i++;
00159     }
00160 
00161     return 0;
00162 }
00163 
00164 
00165 int PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt,
00166                  int saltLen, int iterations, int kLen, int hashType, int id)
00167 {
00168     /* all in bytes instead of bits */
00169     word32 u, v, dLen, pLen, iLen, sLen, totalLen;
00170     int    dynamic = 0;
00171     int    ret = 0;
00172     int    i;
00173     byte   *D, *S, *P, *I;
00174     byte   staticBuffer[1024];
00175     byte*  buffer = staticBuffer;
00176 #ifdef CYASSL_SHA512
00177     byte   Ai[SHA512_DIGEST_SIZE];
00178     byte   B[SHA512_BLOCK_SIZE];
00179 #elif !defined(NO_SHA256)
00180     byte   Ai[SHA256_DIGEST_SIZE];
00181     byte   B[SHA256_BLOCK_SIZE];
00182 #else
00183     byte   Ai[SHA_DIGEST_SIZE];
00184     byte   B[SHA_BLOCK_SIZE];
00185 #endif
00186 
00187     if (!iterations)
00188         iterations = 1;
00189 
00190     if (hashType == MD5) {
00191         v = MD5_BLOCK_SIZE;
00192         u = MD5_DIGEST_SIZE;
00193     }
00194     else if (hashType == SHA) {
00195         v = SHA_BLOCK_SIZE;
00196         u = SHA_DIGEST_SIZE;
00197     }
00198 #ifndef NO_SHA256
00199     else if (hashType == SHA256) {
00200         v = SHA256_BLOCK_SIZE;
00201         u = SHA256_DIGEST_SIZE;
00202     }
00203 #endif
00204 #ifdef CYASSL_SHA512
00205     else if (hashType == SHA512) {
00206         v = SHA512_BLOCK_SIZE;
00207         u = SHA512_DIGEST_SIZE;
00208     }
00209 #endif
00210     else
00211         return BAD_FUNC_ARG; 
00212 
00213     dLen = v;
00214     sLen =  v * ((saltLen + v - 1) / v);
00215     if (passLen)
00216         pLen = v * ((passLen + v - 1) / v);
00217     else
00218         pLen = 0;
00219     iLen = sLen + pLen;
00220 
00221     totalLen = dLen + sLen + pLen;
00222 
00223     if (totalLen > sizeof(staticBuffer)) {
00224         buffer = (byte*)XMALLOC(totalLen, 0, DYNAMIC_TYPE_KEY);
00225         if (buffer == NULL) return MEMORY_E;
00226         dynamic = 1;
00227     } 
00228 
00229     D = buffer;
00230     S = D + dLen;
00231     P = S + sLen;
00232     I = S;
00233 
00234     XMEMSET(D, id, dLen);
00235 
00236     for (i = 0; i < (int)sLen; i++)
00237         S[i] = salt[i % saltLen];
00238     for (i = 0; i < (int)pLen; i++)
00239         P[i] = passwd[i % passLen];
00240 
00241     while (kLen > 0) {
00242         word32 currentLen;
00243         mp_int B1;
00244 
00245         if (hashType == MD5) {
00246             Md5 md5;
00247 
00248             InitMd5(&md5);
00249             Md5Update(&md5, buffer, totalLen);
00250             Md5Final(&md5, Ai);
00251 
00252             for (i = 1; i < iterations; i++) {
00253                 Md5Update(&md5, Ai, u);
00254                 Md5Final(&md5, Ai);
00255             }
00256         }
00257         else if (hashType == SHA) {
00258             Sha sha;
00259 
00260             InitSha(&sha);
00261             ShaUpdate(&sha, buffer, totalLen);
00262             ShaFinal(&sha, Ai);
00263 
00264             for (i = 1; i < iterations; i++) {
00265                 ShaUpdate(&sha, Ai, u);
00266                 ShaFinal(&sha, Ai);
00267             }
00268         }
00269 #ifndef NO_SHA256
00270         else if (hashType == SHA256) {
00271             Sha256 sha256;
00272 
00273             InitSha256(&sha256);
00274             Sha256Update(&sha256, buffer, totalLen);
00275             Sha256Final(&sha256, Ai);
00276 
00277             for (i = 1; i < iterations; i++) {
00278                 Sha256Update(&sha256, Ai, u);
00279                 Sha256Final(&sha256, Ai);
00280             }
00281         }
00282 #endif
00283 #ifdef CYASSL_SHA512
00284         else if (hashType == SHA512) {
00285             Sha512 sha512;
00286 
00287             InitSha512(&sha512);
00288             Sha512Update(&sha512, buffer, totalLen);
00289             Sha512Final(&sha512, Ai);
00290 
00291             for (i = 1; i < iterations; i++) {
00292                 Sha512Update(&sha512, Ai, u);
00293                 Sha512Final(&sha512, Ai);
00294             }
00295         }
00296 #endif
00297 
00298         for (i = 0; i < (int)v; i++)
00299             B[i] = Ai[i % u];
00300 
00301         if (mp_init(&B1) != MP_OKAY)
00302             ret = MP_INIT_E;
00303         else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
00304             ret = MP_READ_E;
00305         else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
00306             ret = MP_ADD_E;
00307 
00308         if (ret != 0) {
00309             mp_clear(&B1);
00310             break;
00311         }
00312 
00313         for (i = 0; i < (int)iLen; i += v) {
00314             int    outSz;
00315             mp_int i1;
00316             mp_int res;
00317 
00318             if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
00319                 ret = MP_INIT_E;
00320                 break;
00321             }
00322             if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
00323                 ret = MP_READ_E;
00324             else if (mp_add(&i1, &B1, &res) != MP_OKAY)
00325                 ret = MP_ADD_E;
00326             else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
00327                 ret = MP_TO_E;
00328             else {
00329                 if (outSz > (int)v) {
00330                     /* take off MSB */
00331                     byte  tmp[129];
00332                     mp_to_unsigned_bin(&res, tmp);
00333                     XMEMCPY(I + i, tmp + 1, v);
00334                 }
00335                 else if (outSz < (int)v) {
00336                     XMEMSET(I + i, 0, v - outSz);
00337                     mp_to_unsigned_bin(&res, I + i + v - outSz);
00338                 }
00339                 else
00340                     mp_to_unsigned_bin(&res, I + i);
00341             }
00342 
00343             mp_clear(&i1);
00344             mp_clear(&res);
00345             if (ret < 0) break;
00346         }
00347 
00348         currentLen = min(kLen, (int)u);
00349         XMEMCPY(output, Ai, currentLen);
00350         output += currentLen;
00351         kLen   -= currentLen;
00352         mp_clear(&B1);
00353     }
00354 
00355     if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY);
00356     return ret;
00357 }
00358 
00359 #endif /* NO_PWDBASED */
00360