0
|
1 /* hmac-sha1.c */ |
|
2 /* |
|
3 This file is part of the AVR-Crypto-Lib. |
|
4 Copyright (C) 2008 Daniel Otte ([email protected]) |
|
5 |
|
6 This program is free software: you can redistribute it and/or modify |
|
7 it under the terms of the GNU General Public License as published by |
|
8 the Free Software Foundation, either version 3 of the License, or |
|
9 (at your option) any later version. |
|
10 |
|
11 This program is distributed in the hope that it will be useful, |
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 GNU General Public License for more details. |
|
15 |
|
16 You should have received a copy of the GNU General Public License |
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
18 */ |
|
19 /** |
|
20 * |
|
21 * implementation of HMAC as described in RFC2104 |
|
22 * Author: Daniel Otte |
|
23 * email: [email protected] |
|
24 * License: GPLv3 or later |
|
25 **/ |
|
26 |
|
27 /* |
|
28 * hmac = hash ( k^opad , hash( k^ipad , msg)) |
|
29 */ |
|
30 |
|
31 #include <stdint.h> |
|
32 #include <string.h> |
|
33 #include "config.h" |
|
34 #include "sha1.h" |
|
35 #include "hmac-sha1.h" |
|
36 |
|
37 #define IPAD 0x36 |
|
38 #define OPAD 0x5C |
|
39 |
|
40 |
|
41 #ifndef HMAC_SHORTONLY |
|
42 |
|
43 void hmac_sha1_init(hmac_sha1_ctx_t *s, const void* key, uint16_t keylength_b){ |
|
44 uint8_t buffer[SHA1_BLOCK_BYTES]; |
|
45 uint8_t i; |
|
46 |
|
47 memset(buffer, 0, SHA1_BLOCK_BYTES); |
|
48 if (keylength_b > SHA1_BLOCK_BITS){ |
|
49 sha1((void*)buffer, key, keylength_b); |
|
50 } else { |
|
51 memcpy(buffer, key, (keylength_b+7)/8); |
|
52 } |
|
53 |
|
54 for (i=0; i<SHA1_BLOCK_BYTES; ++i){ |
|
55 buffer[i] ^= IPAD; |
|
56 } |
|
57 sha1_init(&(s->a)); |
|
58 sha1_nextBlock(&(s->a), buffer); |
|
59 |
|
60 for (i=0; i<SHA1_BLOCK_BYTES; ++i){ |
|
61 buffer[i] ^= IPAD^OPAD; |
|
62 } |
|
63 sha1_init(&(s->b)); |
|
64 sha1_nextBlock(&(s->b), buffer); |
|
65 |
|
66 |
|
67 #if defined SECURE_WIPE_BUFFER |
|
68 memset(buffer, 0, SHA1_BLOCK_BYTES); |
|
69 #endif |
|
70 } |
|
71 |
|
72 void hmac_sha1_nextBlock(hmac_sha1_ctx_t *s, const void* block){ |
|
73 sha1_nextBlock(&(s->a), block); |
|
74 } |
|
75 void hmac_sha1_lastBlock(hmac_sha1_ctx_t *s, const void* block, uint16_t length_b){ |
|
76 while(length_b>=SHA1_BLOCK_BITS){ |
|
77 sha1_nextBlock(&s->a, block); |
|
78 block = (uint8_t*)block + SHA1_BLOCK_BYTES; |
|
79 length_b -= SHA1_BLOCK_BITS; |
|
80 } |
|
81 sha1_lastBlock(&s->a, block, length_b); |
|
82 } |
|
83 |
|
84 void hmac_sha1_final(void* dest, hmac_sha1_ctx_t *s){ |
|
85 sha1_ctx2hash(dest, &s->a); |
|
86 sha1_lastBlock(&s->b, dest, SHA1_HASH_BITS); |
|
87 sha1_ctx2hash(dest, &(s->b)); |
|
88 } |
|
89 |
|
90 #endif |
|
91 |
|
92 /* |
|
93 * keylength in bits! |
|
94 * message length in bits! |
|
95 */ |
|
96 void hmac_sha1(void* dest, const void* key, uint16_t keylength_b, const void* msg, uint32_t msglength_b){ /* a one-shot*/ |
|
97 sha1_ctx_t s; |
|
98 uint8_t i; |
|
99 uint8_t buffer[SHA1_BLOCK_BYTES]; |
|
100 |
|
101 memset(buffer, 0, SHA1_BLOCK_BYTES); |
|
102 |
|
103 /* if key is larger than a block we have to hash it*/ |
|
104 if (keylength_b > SHA1_BLOCK_BITS){ |
|
105 sha1((void*)buffer, key, keylength_b); |
|
106 } else { |
|
107 memcpy(buffer, key, (keylength_b+7)/8); |
|
108 } |
|
109 |
|
110 for (i=0; i<SHA1_BLOCK_BYTES; ++i){ |
|
111 buffer[i] ^= IPAD; |
|
112 } |
|
113 sha1_init(&s); |
|
114 sha1_nextBlock(&s, buffer); |
|
115 while (msglength_b >= SHA1_BLOCK_BITS){ |
|
116 sha1_nextBlock(&s, msg); |
|
117 msg = (uint8_t*)msg + SHA1_BLOCK_BYTES; |
|
118 msglength_b -= SHA1_BLOCK_BITS; |
|
119 } |
|
120 sha1_lastBlock(&s, msg, msglength_b); |
|
121 /* since buffer still contains key xor ipad we can do ... */ |
|
122 for (i=0; i<SHA1_BLOCK_BYTES; ++i){ |
|
123 buffer[i] ^= IPAD ^ OPAD; |
|
124 } |
|
125 sha1_ctx2hash(dest, &s); /* save inner hash temporary to dest */ |
|
126 sha1_init(&s); |
|
127 sha1_nextBlock(&s, buffer); |
|
128 sha1_lastBlock(&s, dest, SHA1_HASH_BITS); |
|
129 sha1_ctx2hash(dest, &s); |
|
130 } |
|
131 |