SURFEX v8.1
General documentation of Surfex
sha256_hash.c
Go to the documentation of this file.
1 /*
2  * SHA-256 hash in C and x86 assembly
3  *
4  * Copyright (c) 2014 Project Nayuki
5  * http://www.nayuki.io/page/fast-sha2-hashes-in-x86-assembly
6  *
7  * (MIT License)
8  * Permission is hereby granted, free of charge, to any person obtaining a copy of
9  * this software and associated documentation files (the "Software"), to deal in
10  * the Software without restriction, including without limitation the rights to
11  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12  * the Software, and to permit persons to whom the Software is furnished to do so,
13  * subject to the following conditions:
14  * - The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  * - The Software is provided "as is", without warranty of any kind, express or
17  * implied, including but not limited to the warranties of merchantability,
18  * fitness for a particular purpose and noninfringement. In no event shall the
19  * authors or copyright holders be liable for any claim, damages or other
20  * liability, whether in an action of contract, tort or otherwise, arising from,
21  * out of or in connection with the Software or the use or other dealings in the
22  * Software.
23  */
24 
25 // 2-Sep-2015 Alan Geer (ECMWF) Allow discontinuous streams of data
26 // 5-Aug-2016 Alan Geer (ECMWF) Fix undersized integers that allowed infinite loop
27 
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <time.h>
33 
34 extern void sha256_compress(uint32_t state[8], const uint8_t block[64]);
35 
36 /* Full message hasher */
37 
38 void sha256_hash(const uint8_t *message, uint64_t len, uint32_t hash[8],
39  uint8_t block[64], uint32_t *len_block, uint32_t action) {
40 
41 /* Actions (enumeration interoperabiltiy with fortran is iffy, so just use numbers):
42  * 0 - Complete message to be processed in one call
43  * 1 - Start processing incomplete message (state and len_state are kept by user between calls)
44  * 2 - Continue processing incomplete message
45  * 3 - Complete processing
46  */
47  uint64_t istart;
48  uint64_t rem;
49  uint64_t i;
50 
51  if (action <= 1) {
52 
53  // Initialise the hash
54  hash[0] = UINT32_C(0x6A09E667);
55  hash[1] = UINT32_C(0xBB67AE85);
56  hash[2] = UINT32_C(0x3C6EF372);
57  hash[3] = UINT32_C(0xA54FF53A);
58  hash[4] = UINT32_C(0x510E527F);
59  hash[5] = UINT32_C(0x9B05688C);
60  hash[6] = UINT32_C(0x1F83D9AB);
61  hash[7] = UINT32_C(0x5BE0CD19);
62  istart = 0;
63  *len_block = 0;
64  rem = len;
65 
66  } else {
67 
68  istart = 64 - *len_block;
69  rem = len - istart;
70  if( rem >= 0) {
71 
72  // We now have a full block to be hashed
73  memcpy(block+*len_block, message, istart);
74  sha256_compress(hash, block);
75  *len_block = 0;
76 
77  } else {
78 
79  // Only a partial block is available as yet
80  memcpy(block+*len_block, message, len);
81  *len_block += len;
82 
83  }
84 
85  }
86 
87  if(rem > 0) {
88 
89  // All complete blocks in the message
90  for (i = istart; len - i >= 64; i += 64)
91  sha256_compress(hash, message + i);
92 
93  // Remaining bit of message
94  rem = len - i;
95  memcpy(block, message + i, rem);
96  *len_block = rem;
97 
98  } else {
99 
100  rem = *len_block;
101 
102  }
103 
104  if (action==0 || action==3) {
105 
106  // Hash padding and completion
107  block[rem] = 0x80;
108  rem++;
109  if (64 - rem >= 8)
110  memset(block + rem, 0, 56 - rem);
111  else {
112  memset(block + rem, 0, 64 - rem);
113  sha256_compress(hash, block);
114  memset(block, 0, 56);
115  }
116 
117  uint64_t longLen = ((uint64_t)len) << 3;
118  for (i = 0; i < 8; i++)
119  block[64 - 1 - i] = (uint8_t)(longLen >> (i * 8));
120  sha256_compress(hash, block);
121 
122  }
123 }
124 
unsigned long uint64_t
Definition: bitbuff.c:10
void sha256_compress(uint32_t state[8], const uint8_t block[64])
Definition: sha256.c:28
void sha256_hash(const uint8_t *message, uint64_t len, uint32_t hash[8], uint8_t block[64], uint32_t *len_block, uint32_t action)
Definition: sha256_hash.c:38