Changeset d7dadcb4 in mainline for uspace/lib/crypto/crypto.c
- Timestamp:
- 2015-04-08T10:54:31Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 053fc2b
- Parents:
- 1dcc0b9
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/crypto/crypto.c
r1dcc0b9 rd7dadcb4 40 40 #include "crypto.h" 41 41 42 typedef int (*HASH_FUNC)(uint8_t*, size_t, uint8_t*); 43 42 /* Hash function procedure definition. */ 43 typedef void (*HASH_FUNC)(uint32_t*, uint32_t*); 44 45 /* Length of HMAC block. */ 46 #define HMAC_BLOCK_LENGTH 64 47 48 /* Ceiling for UINT32. */ 44 49 #define ceil_uint32(val) (((val) - (uint32_t)(val)) > 0 ? \ 45 50 (uint32_t)((val) + 1) : (uint32_t)(val)) 51 52 /* Floor for UINT32. */ 46 53 #define floor_uint32(val) (((val) - (uint32_t)(val)) < 0 ? \ 47 54 (uint32_t)((val) - 1) : (uint32_t)(val)) 55 56 /* Left rotation for UINT32. */ 48 57 #define rotl_uint32(val, shift) (((val) << shift) | ((val) >> (32 - shift))) 58 59 /* Pick value at specified index from array or zero if out of bounds. */ 49 60 #define get_at(input, size, i) (i < size ? input[i] : 0) 50 61 51 /** 52 * Setup hash function properties for use in crypto functions. 53 * 62 /* Init values used in SHA1 and MD5 functions. */ 63 static const uint32_t hash_init[] = { 64 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 65 }; 66 67 /* Shift amount array for MD5 algorithm. */ 68 static const uint32_t md5_shift[] = { 69 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 70 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 71 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 72 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 73 }; 74 75 /* Substitution box for MD5 algorithm. */ 76 static const uint32_t md5_sbox[] = { 77 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 78 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 79 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 80 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 81 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 82 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 83 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 84 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 85 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 86 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 87 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 88 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 89 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 90 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 91 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 92 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 93 }; 94 95 /** 96 * Working procedure of MD5 cryptographic hash function. 97 * 98 * @param h Working array with interim hash parts values. 99 * @param sched_arr Input array with scheduled values from input string. 100 */ 101 static void md5_proc(uint32_t *h, uint32_t *sched_arr) 102 { 103 uint32_t f, g, temp; 104 uint32_t w[HASH_MD5/4]; 105 106 memcpy(w, h, (HASH_MD5/4) * sizeof(uint32_t)); 107 108 for(size_t k = 0; k < 64; k++) { 109 if(k < 16) { 110 f = (w[1] & w[2]) | (~w[1] & w[3]); 111 g = k; 112 } else if(k >= 16 && k < 32) { 113 f = (w[1] & w[3]) | (w[2] & ~w[3]); 114 g = (5*k + 1) % 16; 115 } else if(k >= 32 && k < 48) { 116 f = w[1] ^ w[2] ^ w[3]; 117 g = (3*k + 5) % 16; 118 } else { 119 f = w[2] ^ (w[1] | ~w[3]); 120 g = 7*k % 16; 121 } 122 temp = w[3]; 123 w[3] = w[2]; 124 w[2] = w[1]; 125 w[1] += rotl_uint32(w[0] + f + md5_sbox[k] + 126 uint32_t_byteorder_swap(sched_arr[g]), 127 md5_shift[k]); 128 w[0] = temp; 129 } 130 131 for(uint8_t k = 0; k < HASH_MD5/4; k++) 132 h[k] += w[k]; 133 } 134 135 /** 136 * Working procedure of SHA-1 cryptographic hash function. 137 * 138 * @param h Working array with interim hash parts values. 139 * @param sched_arr Input array with scheduled values from input string. 140 */ 141 static void sha1_proc(uint32_t *h, uint32_t *sched_arr) 142 { 143 uint32_t f, cf, temp; 144 uint32_t w[HASH_SHA1/4]; 145 146 for(size_t k = 16; k < 80; k++) { 147 sched_arr[k] = rotl_uint32( 148 sched_arr[k-3] ^ 149 sched_arr[k-8] ^ 150 sched_arr[k-14] ^ 151 sched_arr[k-16], 152 1); 153 } 154 155 memcpy(w, h, (HASH_SHA1/4) * sizeof(uint32_t)); 156 157 for(size_t k = 0; k < 80; k++) { 158 if(k < 20) { 159 f = (w[1] & w[2]) | (~w[1] & w[3]); 160 cf = 0x5A827999; 161 } else if(k >= 20 && k < 40) { 162 f = w[1] ^ w[2] ^ w[3]; 163 cf = 0x6ED9EBA1; 164 } else if(k >= 40 && k < 60) { 165 f = (w[1] & w[2]) | (w[1] & w[3]) | (w[2] & w[3]); 166 cf = 0x8F1BBCDC; 167 } else { 168 f = w[1] ^ w[2] ^ w[3]; 169 cf = 0xCA62C1D6; 170 } 171 172 temp = rotl_uint32(w[0], 5) + f + w[4] + cf + sched_arr[k]; 173 174 w[4] = w[3]; 175 w[3] = w[2]; 176 w[2] = rotl_uint32(w[1], 30); 177 w[1] = w[0]; 178 w[0] = temp; 179 } 180 181 for(uint8_t k = 0; k < HASH_SHA1/4; k++) 182 h[k] += w[k]; 183 } 184 185 /** 186 * Create hash based on selected algorithm. 187 * 188 * @param input Input message byte sequence. 189 * @param input_size Size of message sequence. 190 * @param output Result hash byte sequence. 54 191 * @param hash_sel Hash function selector. 55 * @param hash_func Output parameter where hash function pointer is stored. 56 * @param hash_length Output parameter for setup result hash length. 57 */ 58 static void config_hash_func(hash_func_t hash_sel, HASH_FUNC *hash_func, 59 size_t *hash_length) 60 { 61 switch(hash_sel) { 62 case HASH_MD5: 63 if(hash_func) *hash_func = md5; 64 *hash_length = MD5_HASH_LENGTH; 65 break; 66 case HASH_SHA1: 67 if(hash_func) *hash_func = sha1; 68 *hash_length = SHA1_HASH_LENGTH; 69 break; 70 } 71 } 72 73 /** 74 * MD5 cryptographic hash function. 75 * 76 * @param input Input sequence to be encrypted. 77 * @param input_size Size of input sequence. 78 * @param hash Output parameter for result hash (32 byte value). 79 * 80 * @return EINVAL when input not specified, ENOMEM when pointer for output 81 * hash result is not allocated, otherwise EOK. 82 */ 83 int md5(uint8_t *input, size_t input_size, uint8_t *hash) 192 * 193 * @return EINVAL when input not specified, ENOMEM when pointer for 194 * output hash result is not allocated, otherwise EOK. 195 */ 196 int create_hash(uint8_t *input, size_t input_size, uint8_t *output, 197 hash_func_t hash_sel) 84 198 { 85 199 if(!input) 86 200 return EINVAL; 87 201 88 if(! hash)202 if(!output) 89 203 return ENOMEM; 90 204 91 // TODO 92 93 return EOK; 94 } 95 96 /** 97 * SHA-1 cryptographic hash function. 98 * 99 * @param input Input sequence to be encrypted. 100 * @param input_size Size of input sequence. 101 * @param hash Output parameter for result hash (20 byte value). 102 * 103 * @return EINVAL when input not specified, ENOMEM when pointer for output 104 * hash result is not allocated, otherwise EOK. 105 */ 106 int sha1(uint8_t *input, size_t input_size, uint8_t *hash) 107 { 108 if(!input) 109 return EINVAL; 110 111 if(!hash) 112 return ENOMEM; 113 114 uint32_t a, b, c, d, e, f, cf, temp; 115 uint32_t h[5] = { 116 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 117 }; 118 205 HASH_FUNC hash_func = (hash_sel == HASH_MD5) ? md5_proc : sha1_proc; 206 207 /* Prepare scheduled input. */ 119 208 uint8_t work_input[input_size + 1]; 120 209 memcpy(work_input, input, input_size); … … 122 211 123 212 size_t blocks = ceil_uint32((((double)input_size + 1) / 4 + 2) / 16); 124 125 uint32_t work_arr[blocks * 16 * sizeof(uint32_t)]; 213 uint32_t work_arr[blocks * 16]; 126 214 for(size_t i = 0; i < blocks; i++) { 127 215 for(size_t j = 0; j < 16; j++) { … … 134 222 } 135 223 136 work_arr[(blocks - 1) * 16 + 14] = (uint64_t)(input_size * 8) >> 32; 137 work_arr[(blocks - 1) * 16 + 15] = (input_size * 8) & 0xFFFFFFFF; 138 139 uint32_t sched_arr[80 * sizeof(uint32_t)]; 224 uint64_t bits_size = (uint64_t)(input_size * 8); 225 if(hash_sel == HASH_MD5) 226 bits_size = uint64_t_byteorder_swap(bits_size); 227 228 work_arr[(blocks - 1) * 16 + 14] = bits_size >> 32; 229 work_arr[(blocks - 1) * 16 + 15] = bits_size & 0xFFFFFFFF; 230 231 /* Hash computation. */ 232 uint32_t h[hash_sel/4]; 233 memcpy(h, hash_init, (hash_sel/4) * sizeof(uint32_t)); 234 uint32_t sched_arr[80]; 140 235 for(size_t i = 0; i < blocks; i++) { 141 236 for(size_t k = 0; k < 16; k++) { … … 143 238 } 144 239 145 for(size_t k = 16; k < 80; k++) { 146 sched_arr[k] = 147 rotl_uint32( 148 sched_arr[k-3] ^ 149 sched_arr[k-8] ^ 150 sched_arr[k-14] ^ 151 sched_arr[k-16], 152 1); 153 } 154 155 a = h[0]; b = h[1]; c = h[2]; d = h[3]; e = h[4]; 156 157 for(size_t k = 0; k < 80; k++) { 158 if(k < 20) { 159 f = (b & c) | (~b & d); 160 cf = 0x5A827999; 161 } else if(k >= 20 && k < 40) { 162 f = b ^ c ^ d; 163 cf = 0x6ED9EBA1; 164 } else if(k >= 40 && k < 60) { 165 f = (b & c) | (b & d) | (c & d); 166 cf = 0x8F1BBCDC; 167 } else { 168 f = b ^ c ^ d; 169 cf = 0xCA62C1D6; 170 } 171 172 temp = (rotl_uint32(a, 5) + f + e + cf + sched_arr[k]) & 173 0xFFFFFFFF; 174 175 e = d; 176 d = c; 177 c = rotl_uint32(b, 30); 178 b = a; 179 a = temp; 180 } 181 182 h[0] = (h[0] + a) & 0xFFFFFFFF; 183 h[1] = (h[1] + b) & 0xFFFFFFFF; 184 h[2] = (h[2] + c) & 0xFFFFFFFF; 185 h[3] = (h[3] + d) & 0xFFFFFFFF; 186 h[4] = (h[4] + e) & 0xFFFFFFFF; 187 } 188 189 for(size_t i = 0; i < 5; i++) { 190 h[i] = uint32_t_be2host(h[i]); 191 memcpy(hash + i*sizeof(uint32_t), &h[i], sizeof(uint32_t)); 240 hash_func(h, sched_arr); 241 } 242 243 /* Copy hash parts into final result. */ 244 for(size_t i = 0; i < hash_sel/4; i++) { 245 if(hash_sel == HASH_SHA1) 246 h[i] = uint32_t_byteorder_swap(h[i]); 247 memcpy(output + i*sizeof(uint32_t), &h[i], sizeof(uint32_t)); 192 248 } 193 249 … … 217 273 return ENOMEM; 218 274 219 size_t hash_length = 0;220 HASH_FUNC hash_func = NULL;221 config_hash_func(hash_sel, &hash_func, &hash_length);222 223 275 uint8_t work_key[HMAC_BLOCK_LENGTH]; 224 276 uint8_t o_key_pad[HMAC_BLOCK_LENGTH]; 225 277 uint8_t i_key_pad[HMAC_BLOCK_LENGTH]; 226 uint8_t temp_hash[hash_ length];278 uint8_t temp_hash[hash_sel]; 227 279 memset(work_key, 0, HMAC_BLOCK_LENGTH); 228 280 229 281 if(key_size > HMAC_BLOCK_LENGTH) { 230 hash_func(key, key_size, work_key);282 create_hash(key, key_size, work_key, hash_sel); 231 283 } else { 232 284 memcpy(work_key, key, key_size); … … 242 294 memcpy(temp_work + HMAC_BLOCK_LENGTH, msg, msg_size); 243 295 244 hash_func(temp_work, HMAC_BLOCK_LENGTH + msg_size, temp_hash); 296 create_hash(temp_work, HMAC_BLOCK_LENGTH + msg_size, temp_hash, 297 hash_sel); 245 298 246 299 memcpy(temp_work, o_key_pad, HMAC_BLOCK_LENGTH); 247 memcpy(temp_work + HMAC_BLOCK_LENGTH, temp_hash, hash_ length);248 249 hash_func(temp_work, HMAC_BLOCK_LENGTH + hash_length, hash);300 memcpy(temp_work + HMAC_BLOCK_LENGTH, temp_hash, hash_sel); 301 302 create_hash(temp_work, HMAC_BLOCK_LENGTH + hash_sel, hash, hash_sel); 250 303 251 304 return EOK; … … 276 329 return ENOMEM; 277 330 278 size_t hash_length = 0;279 config_hash_func(hash_sel, NULL, &hash_length);280 281 331 uint8_t work_salt[salt_size + sizeof(uint32_t)]; 282 332 memcpy(work_salt, salt, salt_size); 283 uint8_t work_hmac[hash_ length];284 uint8_t temp_hmac[hash_ length];285 uint8_t xor_hmac[hash_ length];286 uint8_t temp_hash[hash_ length*2];333 uint8_t work_hmac[hash_sel]; 334 uint8_t temp_hmac[hash_sel]; 335 uint8_t xor_hmac[hash_sel]; 336 uint8_t temp_hash[hash_sel*2]; 287 337 288 338 for(size_t i = 0; i < 2; i++) { … … 291 341 hmac(pass, pass_size, work_salt, salt_size + sizeof(uint32_t), 292 342 work_hmac, hash_sel); 293 memcpy(xor_hmac, work_hmac, hash_ length);343 memcpy(xor_hmac, work_hmac, hash_sel); 294 344 for(size_t k = 1; k < 4096; k++) { 295 memcpy(temp_hmac, work_hmac, hash_ length);296 hmac(pass, pass_size, temp_hmac, hash_ length,345 memcpy(temp_hmac, work_hmac, hash_sel); 346 hmac(pass, pass_size, temp_hmac, hash_sel, 297 347 work_hmac, hash_sel); 298 for(size_t t = 0; t < hash_ length; t++) {348 for(size_t t = 0; t < hash_sel; t++) { 299 349 xor_hmac[t] ^= work_hmac[t]; 300 350 } 301 351 } 302 memcpy(temp_hash + i*hash_ length, xor_hmac, hash_length);352 memcpy(temp_hash + i*hash_sel, xor_hmac, hash_sel); 303 353 } 304 354
Note:
See TracChangeset
for help on using the changeset viewer.