libcoap
4.3.5
Toggle main menu visibility
Loading...
Searching...
No Matches
coap_sha1.c
Go to the documentation of this file.
1
/*
2
* coap_sha1.c
3
*
4
* Full Copyright Statement RFC3174
5
*
6
* =======================================================================
7
*
8
* Copyright (C) The Internet Society (2001). All Rights Reserved.
9
*
10
* This document and translations of it may be copied and furnished to
11
* others, and derivative works that comment on or otherwise explain it
12
* or assist in its implementation may be prepared, copied, published
13
* and distributed, in whole or in part, without restriction of any
14
* kind, provided that the above copyright notice and this paragraph are
15
* included on all such copies and derivative works. However, this
16
* document itself may not be modified in any way, such as by removing
17
* the copyright notice or references to the Internet Society or other
18
* Internet organizations, except as needed for the purpose of
19
* developing Internet standards in which case the procedures for
20
* copyrights defined in the Internet Standards process must be
21
* followed, or as required to translate it into languages other than
22
* English.
23
*
24
* The limited permissions granted above are perpetual and will not be
25
* revoked by the Internet Society or its successors or assigns.
26
*
27
* This document and the information contained herein is provided on an
28
* "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
29
* TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
30
* BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
31
* HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
32
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
33
*
34
* =======================================================================
35
*
36
* Description:
37
* This file implements the Secure Hashing Algorithm 1 as
38
* defined in FIPS PUB 180-1 published April 17, 1995.
39
*
40
* The SHA-1, produces a 160-bit message digest for a given
41
* data stream. It should take about 2**n steps to find a
42
* message with the same digest as a given message and
43
* 2**(n/2) to find any two messages with the same digest,
44
* when n is the digest size in bits. Therefore, this
45
* algorithm can serve as a means of providing a
46
* "fingerprint" for a message.
47
*
48
* Portability Issues:
49
* SHA-1 is defined in terms of 32-bit "words". This code
50
* uses <stdint.h> (included via "sha1.h" to define 32 and 8
51
* bit unsigned integer types. If your C compiler does not
52
* support 32 bit unsigned integers, this code is not
53
* appropriate.
54
*
55
* Caveats:
56
* SHA-1 is designed to work with messages less than 2^64 bits
57
* long. Although SHA-1 allows a message digest to be generated
58
* for messages of any number of bits less than 2^64, this
59
* implementation only works with messages with a length that is
60
* a multiple of the size of an 8-bit character.
61
*
62
* Taken from https://datatracker.ietf.org/doc/html/rfc3174#section-7.2
63
* Reformatted as appropriate.
64
*/
65
66
#include "
coap3/coap_libcoap_build.h
"
67
68
#if COAP_WS_SUPPORT && !defined(COAP_WITH_LIBOPENSSL) && !defined(COAP_WITH_LIBGNUTLS) && !defined(COAP_WITH_LIBMBEDTLS) && !defined(COAP_WITH_LIBWOLFSSL)
69
/*
70
* Define the SHA1 circular left shift macro
71
*/
72
#define SHA1CircularShift(bits,word) \
73
(((word) << (bits)) | ((word) >> (32-(bits))))
74
75
/* Local Function Prototyptes */
76
void
SHA1PadMessage(
SHA1Context
*);
77
void
SHA1ProcessMessageBlock(
SHA1Context
*);
78
79
/*
80
* SHA1Reset
81
*
82
* Description:
83
* This function will initialize the SHA1Context in preparation
84
* for computing a new SHA1 message digest.
85
*
86
* Parameters:
87
* context: [in/out]
88
* The context to reset.
89
*
90
* Returns:
91
* sha Error Code.
92
*
93
*/
94
int
95
SHA1Reset
(
SHA1Context
*context) {
96
if
(!context) {
97
return
shaNull
;
98
}
99
100
context->
Length_Low
= 0;
101
context->
Length_High
= 0;
102
context->
Message_Block_Index
= 0;
103
104
context->
Intermediate_Hash
[0] = 0x67452301;
105
context->
Intermediate_Hash
[1] = 0xEFCDAB89;
106
context->
Intermediate_Hash
[2] = 0x98BADCFE;
107
context->
Intermediate_Hash
[3] = 0x10325476;
108
context->
Intermediate_Hash
[4] = 0xC3D2E1F0;
109
110
context->
Computed
= 0;
111
context->
Corrupted
= 0;
112
113
return
shaSuccess
;
114
}
115
116
/*
117
* SHA1Result
118
*
119
* Description:
120
* This function will return the 160-bit message digest into the
121
* Message_Digest array provided by the caller.
122
* NOTE: The first octet of hash is stored in the 0th element,
123
* the last octet of hash in the 19th element.
124
*
125
* Parameters:
126
* context: [in/out]
127
* The context to use to calculate the SHA-1 hash.
128
* Message_Digest: [out]
129
* Where the digest is returned.
130
*
131
* Returns:
132
* sha Error Code.
133
*
134
*/
135
int
136
SHA1Result
(
SHA1Context
*context,
137
uint8_t Message_Digest[
SHA1HashSize
]) {
138
int
i;
139
140
if
(!context || !Message_Digest) {
141
return
shaNull
;
142
}
143
144
if
(context->
Corrupted
) {
145
return
context->
Corrupted
;
146
}
147
148
if
(!context->
Computed
) {
149
SHA1PadMessage(context);
150
for
(i=0; i<64; ++i) {
151
/* message may be sensitive, clear it out */
152
context->
Message_Block
[i] = 0;
153
}
154
context->
Length_Low
= 0;
/* and clear length */
155
context->
Length_High
= 0;
156
context->
Computed
= 1;
157
}
158
159
for
(i = 0; i <
SHA1HashSize
; ++i) {
160
Message_Digest[i] = context->
Intermediate_Hash
[i>>2]
161
>> 8 * (3 - (i & 0x03));
162
}
163
164
return
shaSuccess
;
165
}
166
167
/*
168
* SHA1Input
169
*
170
* Description:
171
* This function accepts an array of octets as the next portion
172
* of the message.
173
*
174
* Parameters:
175
* context: [in/out]
176
* The SHA context to update
177
* message_array: [in]
178
* An array of characters representing the next portion of
179
* the message.
180
* length: [in]
181
* The length of the message in message_array
182
*
183
* Returns:
184
* sha Error Code.
185
*
186
*/
187
int
188
SHA1Input
(
SHA1Context
*context,
189
const
uint8_t *message_array,
190
unsigned
length) {
191
if
(!length) {
192
return
shaSuccess
;
193
}
194
195
if
(!context || !message_array) {
196
return
shaNull
;
197
}
198
199
if
(context->
Computed
) {
200
context->
Corrupted
=
shaStateError
;
201
return
shaStateError
;
202
}
203
204
if
(context->
Corrupted
) {
205
return
context->
Corrupted
;
206
}
207
while
(length-- && !context->
Corrupted
) {
208
context->
Message_Block
[context->
Message_Block_Index
++] =
209
(*message_array & 0xFF);
210
211
context->
Length_Low
+= 8;
212
if
(context->
Length_Low
== 0) {
213
context->
Length_High
++;
214
if
(context->
Length_High
== 0) {
215
/* Message is too long */
216
context->
Corrupted
= 1;
217
}
218
}
219
220
if
(context->
Message_Block_Index
== 64) {
221
SHA1ProcessMessageBlock(context);
222
}
223
224
message_array++;
225
}
226
227
return
shaSuccess
;
228
}
229
230
/*
231
* SHA1ProcessMessageBlock
232
*
233
* Description:
234
* This function will process the next 512 bits of the message
235
* stored in the Message_Block array.
236
*
237
* Parameters:
238
* None.
239
*
240
* Returns:
241
* Nothing.
242
*
243
* Comments:
244
* Many of the variable names in this code, especially the
245
* single character names, were used because those were the
246
* names used in the publication.
247
*
248
*
249
*/
250
void
251
SHA1ProcessMessageBlock(
SHA1Context
*context) {
252
const
uint32_t K[] = {
/* Constants defined in SHA-1 */
253
0x5A827999,
254
0x6ED9EBA1,
255
0x8F1BBCDC,
256
0xCA62C1D6
257
};
258
int
t;
/* Loop counter */
259
uint32_t temp;
/* Temporary word value */
260
uint32_t W[80];
/* Word sequence */
261
uint32_t A, B, C, D, E;
/* Word buffers */
262
263
/*
264
* Initialize the first 16 words in the array W
265
*/
266
for
(t = 0; t < 16; t++) {
267
W[t] = (uint32_t)(context->
Message_Block
[t * 4]) << 24;
268
W[t] |= (uint32_t)(context->
Message_Block
[t * 4 + 1]) << 16;
269
W[t] |= context->
Message_Block
[t * 4 + 2] << 8;
270
W[t] |= context->
Message_Block
[t * 4 + 3];
271
}
272
273
for
(t = 16; t < 80; t++) {
274
W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
275
}
276
277
A = context->
Intermediate_Hash
[0];
278
B = context->
Intermediate_Hash
[1];
279
C = context->
Intermediate_Hash
[2];
280
D = context->
Intermediate_Hash
[3];
281
E = context->
Intermediate_Hash
[4];
282
283
for
(t = 0; t < 20; t++) {
284
temp = SHA1CircularShift(5,A) +
285
((B & C) | ((~B) & D)) + E + W[t] + K[0];
286
E = D;
287
D = C;
288
C = SHA1CircularShift(30,B);
289
B = A;
290
A = temp;
291
}
292
293
for
(t = 20; t < 40; t++) {
294
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
295
E = D;
296
D = C;
297
C = SHA1CircularShift(30,B);
298
B = A;
299
A = temp;
300
}
301
302
for
(t = 40; t < 60; t++) {
303
temp = SHA1CircularShift(5,A) +
304
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
305
E = D;
306
D = C;
307
C = SHA1CircularShift(30,B);
308
B = A;
309
A = temp;
310
}
311
312
for
(t = 60; t < 80; t++) {
313
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
314
E = D;
315
D = C;
316
C = SHA1CircularShift(30,B);
317
B = A;
318
A = temp;
319
}
320
321
context->
Intermediate_Hash
[0] += A;
322
context->
Intermediate_Hash
[1] += B;
323
context->
Intermediate_Hash
[2] += C;
324
context->
Intermediate_Hash
[3] += D;
325
context->
Intermediate_Hash
[4] += E;
326
327
context->
Message_Block_Index
= 0;
328
}
329
330
331
/*
332
* SHA1PadMessage
333
*
334
* Description:
335
* According to the standard, the message must be padded to an even
336
* 512 bits. The first padding bit must be a '1'. The last 64
337
* bits represent the length of the original message. All bits in
338
* between should be 0. This function will pad the message
339
* according to those rules by filling the Message_Block array
340
* accordingly. It will also call the ProcessMessageBlock function
341
* provided appropriately. When it returns, it can be assumed that
342
* the message digest has been computed.
343
*
344
* Parameters:
345
* context: [in/out]
346
* The context to pad
347
* ProcessMessageBlock: [in]
348
* The appropriate SHA*ProcessMessageBlock function
349
* Returns:
350
* Nothing.
351
*
352
*/
353
354
void
355
SHA1PadMessage(
SHA1Context
*context) {
356
/*
357
* Check to see if the current message block is too small to hold
358
* the initial padding bits and length. If so, we will pad the
359
* block, process it, and then continue padding into a second
360
* block.
361
*/
362
if
(context->
Message_Block_Index
> 55) {
363
context->
Message_Block
[context->
Message_Block_Index
++] = 0x80;
364
while
(context->
Message_Block_Index
< 64) {
365
context->
Message_Block
[context->
Message_Block_Index
++] = 0;
366
}
367
368
SHA1ProcessMessageBlock(context);
369
370
while
(context->
Message_Block_Index
< 56) {
371
context->
Message_Block
[context->
Message_Block_Index
++] = 0;
372
}
373
}
else
{
374
context->
Message_Block
[context->
Message_Block_Index
++] = 0x80;
375
while
(context->
Message_Block_Index
< 56) {
376
context->
Message_Block
[context->
Message_Block_Index
++] = 0;
377
}
378
}
379
380
/*
381
* Store the message length as the last 8 octets
382
*/
383
context->
Message_Block
[56] = context->
Length_High
>> 24;
384
context->
Message_Block
[57] = context->
Length_High
>> 16;
385
context->
Message_Block
[58] = context->
Length_High
>> 8;
386
context->
Message_Block
[59] = context->
Length_High
;
387
context->
Message_Block
[60] = context->
Length_Low
>> 24;
388
context->
Message_Block
[61] = context->
Length_Low
>> 16;
389
context->
Message_Block
[62] = context->
Length_Low
>> 8;
390
context->
Message_Block
[63] = context->
Length_Low
;
391
392
SHA1ProcessMessageBlock(context);
393
}
394
#endif
/* COAP_WS_SUPPORT && !defined(COAP_WITH_LIBOPENSSL) && !defined(COAP_WITH_LIBGNUTLS) && !defined(COAP_WITH_LIBMBEDTLS) */
coap_libcoap_build.h
Library specific build wrapper for coap_internal.h.
shaSuccess
@ shaSuccess
Definition
coap_sha1_internal.h:74
shaNull
@ shaNull
Definition
coap_sha1_internal.h:75
shaStateError
@ shaStateError
Definition
coap_sha1_internal.h:77
SHA1Result
int SHA1Result(SHA1Context *, uint8_t Message_Digest[SHA1HashSize])
SHA1Reset
int SHA1Reset(SHA1Context *)
SHA1Input
int SHA1Input(SHA1Context *, const uint8_t *, unsigned int)
SHA1HashSize
#define SHA1HashSize
Definition
coap_sha1_internal.h:80
SHA1Context
Definition
coap_sha1_internal.h:86
SHA1Context::Length_High
uint32_t Length_High
Definition
coap_sha1_internal.h:90
SHA1Context::Computed
int Computed
Definition
coap_sha1_internal.h:96
SHA1Context::Intermediate_Hash
uint32_t Intermediate_Hash[SHA1HashSize/4]
Definition
coap_sha1_internal.h:87
SHA1Context::Message_Block
uint8_t Message_Block[64]
Definition
coap_sha1_internal.h:94
SHA1Context::Length_Low
uint32_t Length_Low
Definition
coap_sha1_internal.h:89
SHA1Context::Corrupted
int Corrupted
Definition
coap_sha1_internal.h:97
SHA1Context::Message_Block_Index
int_least16_t Message_Block_Index
Definition
coap_sha1_internal.h:93
src
coap_sha1.c
Generated on
for libcoap by
1.17.0