Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pkcs5.c Source File

pkcs5.c

Go to the documentation of this file.
00001 /**
00002  * @file pkcs5.c
00003  * @brief PKCS #5 (Password-Based Cryptography Standard)
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneCrypto Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include <string.h>
00034 #include "crypto.h"
00035 #include "pkcs5.h"
00036 #include "hmac.h"
00037 
00038 //Check crypto library configuration
00039 #if (PKCS5_SUPPORT == ENABLED)
00040 
00041 //PKCS #5 OID (1.2.840.113549.1.5)
00042 const uint8_t PKCS5_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05};
00043 //PBKDF2 OID (1.2.840.113549.1.5.12)
00044 const uint8_t PBKDF2_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0C};
00045 
00046 
00047 /**
00048  * @brief PBKDF1 key derivation function
00049  *
00050  * PBKDF1 applies a hash function, which shall be MD2, MD5 or SHA-1, to derive
00051  * keys. The length of the derived key is bounded by the length of the hash
00052  * function output, which is 16 octets for MD2 and MD5 and 20 octets for SHA-1
00053  *
00054  * @param[in] hash Underlying hash function (MD2, MD5 or SHA-1)
00055  * @param[in] p Password, an octet string
00056  * @param[in] pLen Length in octets of password
00057  * @param[in] s Salt, an octet string
00058  * @param[in] sLen Length in octets of salt
00059  * @param[in] c Iteration count
00060  * @param[out] dk Derived key
00061  * @param[in] dkLen Intended length in octets of the derived key
00062  * @return Error code
00063  **/
00064 
00065 error_t pbkdf1(const HashAlgo *hash, const uint8_t *p, size_t pLen,
00066    const uint8_t *s, size_t sLen, uint_t c, uint8_t *dk, size_t dkLen)
00067 {
00068    uint_t i;
00069    uint8_t *t;
00070    HashContext *context;
00071 
00072    //Check input parameters
00073    if(c < 1 || dkLen > hash->digestSize)
00074       return ERROR_INVALID_PARAMETER;
00075 
00076    //Allocate a memory buffer to hold the hash context
00077    context = cryptoAllocMem(hash->contextSize);
00078    //Allocate a temporary buffer
00079    t = cryptoAllocMem(hash->digestSize);
00080 
00081    //Failed to allocate memory?
00082    if(!context || !t)
00083    {
00084       //Free previously allocated memory
00085       cryptoFreeMem(context);
00086       cryptoFreeMem(t);
00087 
00088       //Report an error
00089       return ERROR_OUT_OF_MEMORY;
00090    }
00091 
00092    //Apply the hash function to the concatenation of P and S
00093    hash->init(context);
00094    hash->update(context, p, pLen);
00095    hash->update(context, s, sLen);
00096    hash->final(context, t);
00097 
00098    //Iterate as many times as required
00099    for(i = 1; i < c; i++)
00100    {
00101       //Apply the hash function to T(i - 1)
00102       hash->init(context);
00103       hash->update(context, t, hash->digestSize);
00104       hash->final(context, t);
00105    }
00106 
00107    //Output the derived key DK
00108    memcpy(dk, t, dkLen);
00109 
00110    //Free previously allocated memory
00111    cryptoFreeMem(context);
00112    cryptoFreeMem(t);
00113 
00114    //Successful processing
00115    return NO_ERROR;
00116 }
00117 
00118 
00119 /**
00120  * @brief PBKDF2 key derivation function
00121  *
00122  * PBKDF2 applies a pseudorandom function to derive keys. The
00123  * length of the derived key is essentially unbounded
00124  *
00125  * @param[in] hash Hash algorithm used by the underlying PRF
00126  * @param[in] p Password, an octet string
00127  * @param[in] pLen Length in octets of password
00128  * @param[in] s Salt, an octet string
00129  * @param[in] sLen Length in octets of salt
00130  * @param[in] c Iteration count
00131  * @param[out] dk Derived key
00132  * @param[in] dkLen Intended length in octets of the derived key
00133  * @return Error code
00134  **/
00135 
00136 error_t pbkdf2(const HashAlgo *hash, const uint8_t *p, size_t pLen,
00137    const uint8_t *s, size_t sLen, uint_t c, uint8_t *dk, size_t dkLen)
00138 {
00139    uint_t i;
00140    uint_t j;
00141    uint_t k;
00142    uint8_t *u;
00143    uint8_t *t;
00144    HmacContext *context;
00145    uint8_t a[4];
00146 
00147    //Iteration count must be a positive integer
00148    if(c < 1)
00149       return ERROR_INVALID_PARAMETER;
00150 
00151    //Allocate a memory buffer to hold the HMAC context
00152    context = cryptoAllocMem(sizeof(HmacContext));
00153    //Allocate temporary buffers
00154    u = cryptoAllocMem(hash->digestSize);
00155    t = cryptoAllocMem(hash->digestSize);
00156 
00157    //Failed to allocate memory?
00158    if(!context || !u || !t)
00159    {
00160       //Free previously allocated memory
00161       cryptoFreeMem(context);
00162       cryptoFreeMem(u);
00163       cryptoFreeMem(t);
00164 
00165       //Report an error
00166       return ERROR_OUT_OF_MEMORY;
00167    }
00168 
00169    //For each block of the derived key apply the function F
00170    for(i = 1; dkLen > 0; i++)
00171    {
00172       //Calculate the 4-octet encoding of the integer i (MSB first)
00173       a[0] = (i >> 24) & 0xFF;
00174       a[1] = (i >> 16) & 0xFF;
00175       a[2] = (i >> 8) & 0xFF;
00176       a[3] = i & 0xFF;
00177 
00178       //Compute U1 = PRF(P, S || INT(i))
00179       hmacInit(context, hash, p, pLen);
00180       hmacUpdate(context, s, sLen);
00181       hmacUpdate(context, a, 4);
00182       hmacFinal(context, u);
00183 
00184       //Save the resulting HMAC value
00185       memcpy(t, u, hash->digestSize);
00186 
00187       //Iterate as many times as required
00188       for(j = 1; j < c; j++)
00189       {
00190          //Compute U(j) = PRF(P, U(j-1))
00191          hmacInit(context, hash, p, pLen);
00192          hmacUpdate(context, u, hash->digestSize);
00193          hmacFinal(context, u);
00194 
00195          //Compute T = U(1) xor U(2) xor ... xor U(c)
00196          for(k = 0; k < hash->digestSize; k++)
00197             t[k] ^= u[k];
00198       }
00199 
00200       //Number of octets in the current block
00201       k = MIN(dkLen, hash->digestSize);
00202       //Save the resulting block
00203       memcpy(dk, t, k);
00204 
00205       //Point to the next block
00206       dk += k;
00207       dkLen -= k;
00208    }
00209 
00210    //Free previously allocated memory
00211    cryptoFreeMem(context);
00212    cryptoFreeMem(u);
00213    cryptoFreeMem(t);
00214 
00215    //Successful processing
00216    return NO_ERROR;
00217 }
00218 
00219 #endif
00220