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