pkcs5.c
Go to the documentation of this file.
1 /**
2  * @file pkcs5.c
3  * @brief PKCS #5 (Password-Based Cryptography Standard)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/crypto.h"
34 #include "kdf/pkcs5.h"
35 #include "mac/hmac.h"
36 
37 //Check crypto library configuration
38 #if (PKCS5_SUPPORT == ENABLED)
39 
40 //PKCS #5 OID (1.2.840.113549.1.5)
41 const uint8_t PKCS5_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05};
42 //PBKDF2 OID (1.2.840.113549.1.5.12)
43 const uint8_t PBKDF2_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0C};
44 
45 
46 /**
47  * @brief PBKDF1 key derivation function
48  *
49  * PBKDF1 applies a hash function, which shall be MD2, MD5 or SHA-1, to derive
50  * keys. The length of the derived key is bounded by the length of the hash
51  * function output, which is 16 octets for MD2 and MD5 and 20 octets for SHA-1
52  *
53  * @param[in] hash Underlying hash function (MD2, MD5 or SHA-1)
54  * @param[in] p Password, an octet string
55  * @param[in] pLen Length in octets of password
56  * @param[in] s Salt, an octet string
57  * @param[in] sLen Length in octets of salt
58  * @param[in] c Iteration count
59  * @param[out] dk Derived key
60  * @param[in] dkLen Intended length in octets of the derived key
61  * @return Error code
62  **/
63 
64 error_t pbkdf1(const HashAlgo *hash, const uint8_t *p, size_t pLen,
65  const uint8_t *s, size_t sLen, uint_t c, uint8_t *dk, size_t dkLen)
66 {
67  uint_t i;
68  HashContext *hashContext;
69  uint8_t t[MAX_HASH_DIGEST_SIZE];
70 
71  //Check parameters
72  if(hash == NULL || p == NULL || s == NULL || dk == NULL)
74 
75  //The iteration count must be a positive integer
76  if(c < 1)
78 
79  //Check the intended length of the derived key
80  if(dkLen > hash->digestSize)
81  return ERROR_INVALID_LENGTH;
82 
83  //Allocate a memory buffer to hold the hash context
84  hashContext = cryptoAllocMem(hash->contextSize);
85  //Failed to allocate memory?
86  if(hashContext == NULL)
87  return ERROR_OUT_OF_MEMORY;
88 
89  //Apply the hash function to the concatenation of P and S
90  hash->init(hashContext);
91  hash->update(hashContext, p, pLen);
92  hash->update(hashContext, s, sLen);
93  hash->final(hashContext, t);
94 
95  //Iterate as many times as required
96  for(i = 1; i < c; i++)
97  {
98  //Apply the hash function to T(i - 1)
99  hash->init(hashContext);
100  hash->update(hashContext, t, hash->digestSize);
101  hash->final(hashContext, t);
102  }
103 
104  //Output the derived key DK
105  cryptoMemcpy(dk, t, dkLen);
106 
107  //Free previously allocated memory
108  cryptoFreeMem(hashContext);
109 
110  //Successful processing
111  return NO_ERROR;
112 }
113 
114 
115 /**
116  * @brief PBKDF2 key derivation function
117  *
118  * PBKDF2 applies a pseudorandom function to derive keys. The
119  * length of the derived key is essentially unbounded
120  *
121  * @param[in] hash Hash algorithm used by the underlying PRF
122  * @param[in] p Password, an octet string
123  * @param[in] pLen Length in octets of password
124  * @param[in] s Salt, an octet string
125  * @param[in] sLen Length in octets of salt
126  * @param[in] c Iteration count
127  * @param[out] dk Derived key
128  * @param[in] dkLen Intended length in octets of the derived key
129  * @return Error code
130  **/
131 
132 error_t pbkdf2(const HashAlgo *hash, const uint8_t *p, size_t pLen,
133  const uint8_t *s, size_t sLen, uint_t c, uint8_t *dk, size_t dkLen)
134 {
135  uint_t i;
136  uint_t j;
137  uint_t k;
138  HmacContext *hashContext;
139  uint8_t a[4];
140  uint8_t t[MAX_HASH_DIGEST_SIZE];
141  uint8_t u[MAX_HASH_DIGEST_SIZE];
142 
143  //Check parameters
144  if(hash == NULL || p == NULL || s == NULL || dk == NULL)
146 
147  //The iteration count must be a positive integer
148  if(c < 1)
150 
151  //Allocate a memory buffer to hold the HMAC context
152  hashContext = cryptoAllocMem(sizeof(HmacContext));
153  //Failed to allocate memory?
154  if(hashContext == NULL)
155  return ERROR_OUT_OF_MEMORY;
156 
157  //For each block of the derived key apply the function F
158  for(i = 1; dkLen > 0; i++)
159  {
160  //Calculate the 4-octet encoding of the integer i (MSB first)
161  STORE32BE(i, a);
162 
163  //Compute U1 = PRF(P, S || INT(i))
164  hmacInit(hashContext, hash, p, pLen);
165  hmacUpdate(hashContext, s, sLen);
166  hmacUpdate(hashContext, a, 4);
167  hmacFinal(hashContext, u);
168 
169  //Save the resulting HMAC value
170  cryptoMemcpy(t, u, hash->digestSize);
171 
172  //Iterate as many times as required
173  for(j = 1; j < c; j++)
174  {
175  //Compute U(j) = PRF(P, U(j-1))
176  hmacInit(hashContext, hash, p, pLen);
177  hmacUpdate(hashContext, u, hash->digestSize);
178  hmacFinal(hashContext, u);
179 
180  //Compute T = U(1) xor U(2) xor ... xor U(c)
181  for(k = 0; k < hash->digestSize; k++)
182  {
183  t[k] ^= u[k];
184  }
185  }
186 
187  //Number of octets in the current block
188  k = MIN(dkLen, hash->digestSize);
189  //Save the resulting block
190  cryptoMemcpy(dk, t, k);
191 
192  //Point to the next block
193  dk += k;
194  dkLen -= k;
195  }
196 
197  //Free previously allocated memory
198  cryptoFreeMem(hashContext);
199 
200  //Successful processing
201  return NO_ERROR;
202 }
203 
204 #endif
const uint8_t PKCS5_OID[8]
Definition: pkcs5.c:41
const uint8_t PBKDF2_OID[9]
Definition: pkcs5.c:43
uint8_t c
Definition: ndp.h:510
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:590
#define cryptoFreeMem(p)
Definition: crypto.h:578
PKCS #5 (Password-Based Cryptography Standard)
uint8_t hash
Definition: tls.h:1363
uint8_t p
Definition: ndp.h:295
#define cryptoAllocMem(size)
Definition: crypto.h:573
General definitions for cryptographic algorithms.
void hmacFinal(HmacContext *context, uint8_t *digest)
Finish the HMAC calculation.
Definition: hmac.c:183
Invalid parameter.
Definition: error.h:45
#define MAX_HASH_DIGEST_SIZE
Definition: crypto.h:747
Generic hash algorithm context.
Definition: crypto.h:1044
error_t pbkdf1(const HashAlgo *hash, const uint8_t *p, size_t pLen, const uint8_t *s, size_t sLen, uint_t c, uint8_t *dk, size_t dkLen)
PBKDF1 key derivation function.
Definition: pkcs5.c:64
uint8_t a
Definition: ndp.h:407
error_t pbkdf2(const HashAlgo *hash, const uint8_t *p, size_t pLen, const uint8_t *s, size_t sLen, uint_t c, uint8_t *dk, size_t dkLen)
PBKDF2 key derivation function.
Definition: pkcs5.c:132
HMAC algorithm context.
Definition: hmac.h:180
HMAC (Keyed-Hashing for Message Authentication)
#define STORE32BE(a, p)
Definition: cpu_endian.h:268
#define MIN(a, b)
Definition: os_port.h:60
uint8_t s
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
void hmacInit(HmacContext *context, const HashAlgo *hash, const void *key, size_t keyLen)
Initialize HMAC calculation.
Definition: hmac.c:116
void hmacUpdate(HmacContext *context, const void *data, size_t length)
Update the HMAC context with a portion of the message being hashed.
Definition: hmac.c:166
Common interface for hash algorithms.
Definition: crypto.h:1054