source: azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/src/hmac.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 6.1 KB
Line 
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4/**************************** hmac.c ****************************/
5/******************** See RFC 4634 for details ******************/
6/*
7* Description:
8* This file implements the HMAC algorithm (Keyed-Hashing for
9* Message Authentication, RFC2104), expressed in terms of the
10* various SHA algorithms.
11*/
12
13#include "azure_c_shared_utility/sha.h"
14
15/*
16* hmac
17*
18* Description:
19* This function will compute an HMAC message digest.
20*
21* Parameters:
22* whichSha: [in]
23* One of SHA1, SHA224, SHA256, SHA384, SHA512
24* key: [in]
25* The secret shared key.
26* key_len: [in]
27* The length of the secret shared key.
28* message_array: [in]
29* An array of characters representing the message.
30* length: [in]
31* The length of the message in message_array
32* digest: [out]
33* Where the digest is returned.
34* NOTE: The length of the digest is determined by
35* the value of whichSha.
36*
37* Returns:
38* sha Error Code.
39*
40*/
41int hmac(SHAversion whichSha, const unsigned char *text, int text_len,
42 const unsigned char *key, int key_len,
43 uint8_t digest[USHAMaxHashSize])
44{
45 HMACContext ctx;
46 return hmacReset(&ctx, whichSha, key, key_len) ||
47 hmacInput(&ctx, text, text_len) ||
48 hmacResult(&ctx, digest);
49}
50
51/*
52* hmacReset
53*
54* Description:
55* This function will initialize the hmacContext in preparation
56* for computing a new HMAC message digest.
57*
58* Parameters:
59* context: [in/out]
60* The context to reset.
61* whichSha: [in]
62* One of SHA1, SHA224, SHA256, SHA384, SHA512
63* key: [in]
64* The secret shared key.
65* key_len: [in]
66* The length of the secret shared key.
67*
68* Returns:
69* sha Error Code.
70*
71*/
72int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
73 const unsigned char *key, int key_len)
74{
75 int i, blocksize, hashsize;
76
77 /* inner padding - key XORd with ipad */
78 unsigned char k_ipad[USHA_Max_Message_Block_Size];
79
80 /* temporary buffer when keylen > blocksize */
81 unsigned char tempkey[USHAMaxHashSize];
82
83 if (!ctx) return shaNull;
84
85 blocksize = ctx->blockSize = USHABlockSize(whichSha);
86 hashsize = ctx->hashSize = USHAHashSize(whichSha);
87
88 ctx->whichSha = whichSha;
89
90 /*
91 * If key is longer than the hash blocksize,
92 * reset it to key = HASH(key).
93 */
94 if (key_len > blocksize) {
95 USHAContext tctx;
96 int err = USHAReset(&tctx, whichSha) ||
97 USHAInput(&tctx, key, key_len) ||
98 USHAResult(&tctx, tempkey);
99 if (err != shaSuccess) return err;
100
101 key = tempkey;
102 key_len = hashsize;
103 }
104
105 /*
106 * The HMAC transform looks like:
107 *
108 * SHA(K XOR opad, SHA(K XOR ipad, text))
109 *
110 * where K is an n byte key.
111 * ipad is the byte 0x36 repeated blocksize times
112 * opad is the byte 0x5c repeated blocksize times
113 * and text is the data being protected.
114 */
115
116 /* store key into the pads, XOR'd with ipad and opad values */
117 for (i = 0; i < key_len; i++) {
118 k_ipad[i] = key[i] ^ 0x36;
119 ctx->k_opad[i] = key[i] ^ 0x5c;
120 }
121 /* remaining pad bytes are '\0' XOR'd with ipad and opad values */
122 for (; i < blocksize; i++) {
123 k_ipad[i] = 0x36;
124 ctx->k_opad[i] = 0x5c;
125 }
126
127 /* perform inner hash */
128 /* init context for 1st pass */
129 return USHAReset(&ctx->shaContext, whichSha) ||
130 /* and start with inner pad */
131 USHAInput(&ctx->shaContext, k_ipad, blocksize);
132}
133
134/*
135* hmacInput
136*
137* Description:
138* This function accepts an array of octets as the next portion
139* of the message.
140*
141* Parameters:
142* context: [in/out]
143* The HMAC context to update
144* message_array: [in]
145* An array of characters representing the next portion of
146* the message.
147* length: [in]
148* The length of the message in message_array
149*
150* Returns:
151* sha Error Code.
152*
153*/
154int hmacInput(HMACContext *ctx, const unsigned char *text,
155 int text_len)
156{
157 if (!ctx) return shaNull;
158 /* then text of datagram */
159 return USHAInput(&ctx->shaContext, text, text_len);
160}
161
162/*
163* HMACFinalBits
164*
165* Description:
166* This function will add in any final bits of the message.
167*
168* Parameters:
169* context: [in/out]
170* The HMAC context to update
171* message_bits: [in]
172* The final bits of the message, in the upper portion of the
173* byte. (Use 0b###00000 instead of 0b00000### to input the
174* three bits ###.)
175* length: [in]
176* The number of bits in message_bits, between 1 and 7.
177*
178* Returns:
179* sha Error Code.
180*/
181int hmacFinalBits(HMACContext *ctx,
182 const uint8_t bits,
183 unsigned int bitcount)
184{
185 if (!ctx) return shaNull;
186 /* then final bits of datagram */
187 return USHAFinalBits(&ctx->shaContext, bits, bitcount);
188}
189
190/*
191* HMACResult
192*
193* Description:
194* This function will return the N-byte message digest into the
195* Message_Digest array provided by the caller.
196* NOTE: The first octet of hash is stored in the 0th element,
197* the last octet of hash in the Nth element.
198*
199* Parameters:
200* context: [in/out]
201* The context to use to calculate the HMAC hash.
202* digest: [out]
203* Where the digest is returned.
204* NOTE 2: The length of the hash is determined by the value of
205* whichSha that was passed to hmacReset().
206*
207* Returns:
208* sha Error Code.
209*
210*/
211int hmacResult(HMACContext *ctx, uint8_t *digest)
212{
213 if (!ctx) return shaNull;
214
215 /* finish up 1st pass */
216 /* (Use digest here as a temporary buffer.) */
217 return USHAResult(&ctx->shaContext, digest) ||
218
219 /* perform outer SHA */
220 /* init context for 2nd pass */
221 USHAReset(&ctx->shaContext, (SHAversion)ctx->whichSha) ||
222
223 /* start with outer pad */
224 USHAInput(&ctx->shaContext, ctx->k_opad, ctx->blockSize) ||
225
226 /* then results of 1st hash */
227 USHAInput(&ctx->shaContext, digest, ctx->hashSize) ||
228
229 /* finish up 2nd pass */
230 USHAResult(&ctx->shaContext, digest);
231}
232
233
Note: See TracBrowser for help on using the repository browser.