cyassl re-port with cellular comms, PSK test

Dependencies:   VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src

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