Coverage Report

Created: 2023-09-25 06:05

/src/e2fsprogs/lib/ext2fs/sha512.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * sha512.c --- The sha512 algorithm
3
 *
4
 * Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
5
 * (copied from libtomcrypt and then relicensed under GPLv2)
6
 *
7
 * %Begin-Header%
8
 * This file may be redistributed under the terms of the GNU Library
9
 * General Public License, version 2.
10
 * %End-Header%
11
 */
12
13
14
#include "config.h"
15
#if HAVE_SYS_TYPES_H
16
#include <sys/types.h>
17
#endif
18
#include "ext2fs.h"
19
20
/* the K array */
21
0
#define CONST64(n) n
22
static const __u64 K[80] = {
23
  CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
24
  CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
25
  CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
26
  CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
27
  CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
28
  CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
29
  CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
30
  CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
31
  CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
32
  CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
33
  CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
34
  CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
35
  CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
36
  CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
37
  CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
38
  CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
39
  CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
40
  CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
41
  CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
42
  CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
43
  CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
44
  CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
45
  CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
46
  CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
47
  CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
48
  CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
49
  CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
50
  CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
51
  CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
52
  CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
53
  CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
54
  CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
55
  CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
56
  CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
57
  CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
58
  CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
59
  CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
60
  CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
61
  CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
62
  CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
63
};
64
0
#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
65
0
#define Maj(x,y,z)      (((x | y) & z) | (x & y))
66
0
#define S(x, n)         ROR64c(x, n)
67
0
#define R(x, n)         (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((__u64)n))
68
0
#define Sigma0(x)       (S(x, 28) ^ S(x, 34) ^ S(x, 39))
69
0
#define Sigma1(x)       (S(x, 14) ^ S(x, 18) ^ S(x, 41))
70
0
#define Gamma0(x)       (S(x, 1) ^ S(x, 8) ^ R(x, 7))
71
0
#define Gamma1(x)       (S(x, 19) ^ S(x, 61) ^ R(x, 6))
72
#define RND(a,b,c,d,e,f,g,h,i)\
73
0
    t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];\
74
0
    t1 = Sigma0(a) + Maj(a, b, c);\
75
0
    d += t0;\
76
0
    h  = t0 + t1;
77
#define STORE64H(x, y) \
78
0
  do { \
79
0
    (y)[0] = (unsigned char)(((x)>>56)&255);\
80
0
    (y)[1] = (unsigned char)(((x)>>48)&255);\
81
0
    (y)[2] = (unsigned char)(((x)>>40)&255);\
82
0
    (y)[3] = (unsigned char)(((x)>>32)&255);\
83
0
    (y)[4] = (unsigned char)(((x)>>24)&255);\
84
0
    (y)[5] = (unsigned char)(((x)>>16)&255);\
85
0
    (y)[6] = (unsigned char)(((x)>>8)&255);\
86
0
    (y)[7] = (unsigned char)((x)&255); } while(0)
87
88
#define LOAD64H(x, y)\
89
0
  do {x = \
90
0
    (((__u64)((y)[0] & 255)) << 56) |\
91
0
    (((__u64)((y)[1] & 255)) << 48) |\
92
0
    (((__u64)((y)[2] & 255)) << 40) |\
93
0
    (((__u64)((y)[3] & 255)) << 32) |\
94
0
    (((__u64)((y)[4] & 255)) << 24) |\
95
0
    (((__u64)((y)[5] & 255)) << 16) |\
96
0
    (((__u64)((y)[6] & 255)) << 8) |\
97
0
    (((__u64)((y)[7] & 255)));\
98
0
  } while(0)
99
100
#define ROR64c(x, y) \
101
0
    ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((__u64)(y)&CONST64(63))) | \
102
0
      ((x)<<((__u64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
103
104
struct sha512_state {
105
  __u64  length, state[8];
106
  unsigned long curlen;
107
  unsigned char buf[128];
108
};
109
110
/* This is a highly simplified version from libtomcrypt */
111
struct hash_state {
112
  struct sha512_state sha512;
113
};
114
115
static void sha512_compress(struct hash_state * md, const unsigned char *buf)
116
0
{
117
0
  __u64 S[8], W[80], t0, t1;
118
0
  int i;
119
120
  /* copy state into S */
121
0
  for (i = 0; i < 8; i++) {
122
0
    S[i] = md->sha512.state[i];
123
0
  }
124
125
  /* copy the state into 1024-bits into W[0..15] */
126
0
  for (i = 0; i < 16; i++) {
127
0
    LOAD64H(W[i], buf + (8*i));
128
0
  }
129
130
  /* fill W[16..79] */
131
0
  for (i = 16; i < 80; i++) {
132
0
    W[i] = Gamma1(W[i - 2]) + W[i - 7] +
133
0
      Gamma0(W[i - 15]) + W[i - 16];
134
0
  }
135
136
0
  for (i = 0; i < 80; i += 8) {
137
0
    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
138
0
    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
139
0
    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
140
0
    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
141
0
    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
142
0
    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
143
0
    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
144
0
    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
145
0
  }
146
147
   /* feedback */
148
0
  for (i = 0; i < 8; i++) {
149
0
    md->sha512.state[i] = md->sha512.state[i] + S[i];
150
0
  }
151
0
}
152
153
static void sha512_init(struct hash_state * md)
154
0
{
155
0
  md->sha512.curlen = 0;
156
0
  md->sha512.length = 0;
157
0
  md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
158
0
  md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
159
0
  md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
160
0
  md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
161
0
  md->sha512.state[4] = CONST64(0x510e527fade682d1);
162
0
  md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
163
0
  md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
164
0
  md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
165
0
}
166
167
static void sha512_done(struct hash_state * md, unsigned char *out)
168
0
{
169
0
  int i;
170
171
  /* increase the length of the message */
172
0
  md->sha512.length += md->sha512.curlen * CONST64(8);
173
174
  /* append the '1' bit */
175
0
  md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;
176
177
  /* if the length is currently above 112 bytes we append zeros then
178
   * compress. Then we can fall back to padding zeros and length encoding
179
   * like normal. */
180
0
  if (md->sha512.curlen > 112) {
181
0
    while (md->sha512.curlen < 128) {
182
0
      md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
183
0
    }
184
0
    sha512_compress(md, md->sha512.buf);
185
0
    md->sha512.curlen = 0;
186
0
  }
187
188
  /* pad up to 120 bytes of zeroes note: that from 112 to 120 is the 64 MSB
189
   * of the length. We assume that you won't hash > 2^64 bits of data. */
190
0
  while (md->sha512.curlen < 120) {
191
0
    md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
192
0
  }
193
194
  /* store length */
195
0
  STORE64H(md->sha512.length, md->sha512.buf + 120);
196
0
  sha512_compress(md, md->sha512.buf);
197
198
  /* copy output */
199
0
  for (i = 0; i < 8; i++) {
200
0
    STORE64H(md->sha512.state[i], out+(8 * i));
201
0
  }
202
0
}
203
204
0
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
205
0
#define SHA512_BLOCKSIZE 128
206
static void sha512_process(struct hash_state * md,
207
         const unsigned char *in,
208
         unsigned long inlen)
209
0
{
210
0
  unsigned long n;
211
212
0
  while (inlen > 0) {
213
0
    if (md->sha512.curlen == 0 && inlen >= SHA512_BLOCKSIZE) {
214
0
      sha512_compress(md, in);
215
0
      md->sha512.length += SHA512_BLOCKSIZE * 8;
216
0
      in += SHA512_BLOCKSIZE;
217
0
      inlen -= SHA512_BLOCKSIZE;
218
0
    } else {
219
0
      n = MIN(inlen, (SHA512_BLOCKSIZE - md->sha512.curlen));
220
0
      memcpy(md->sha512.buf + md->sha512.curlen,
221
0
             in, (size_t)n);
222
0
      md->sha512.curlen += n;
223
0
      in += n;
224
0
      inlen -= n;
225
0
      if (md->sha512.curlen == SHA512_BLOCKSIZE) {
226
0
        sha512_compress(md, md->sha512.buf);
227
0
        md->sha512.length += SHA512_BLOCKSIZE * 8;
228
0
        md->sha512.curlen = 0;
229
0
      }
230
0
    }
231
0
  }
232
0
}
233
234
void ext2fs_sha512(const unsigned char *in, unsigned long in_size,
235
       unsigned char out[EXT2FS_SHA512_LENGTH])
236
0
{
237
0
  struct hash_state md;
238
239
0
  sha512_init(&md);
240
0
  sha512_process(&md, in, in_size);
241
0
  sha512_done(&md, out);
242
0
}
243
244
#ifdef UNITTEST
245
static const struct {
246
  char *msg;
247
  unsigned char hash[64];
248
} tests[] = {
249
  { "",
250
    { 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
251
      0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
252
      0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
253
      0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
254
      0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
255
      0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
256
      0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
257
      0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e }
258
  },
259
  { "abc",
260
    { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
261
      0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
262
      0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
263
      0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
264
      0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
265
      0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
266
      0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
267
      0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
268
  },
269
  { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
270
    { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
271
      0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
272
      0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
273
      0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
274
      0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
275
      0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
276
      0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
277
      0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
278
  },
279
};
280
281
int main(int argc, char **argv)
282
{
283
  int i;
284
  int errors = 0;
285
  unsigned char tmp[64];
286
287
  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
288
    unsigned char *msg = (unsigned char *) tests[i].msg;
289
    int len = strlen(tests[i].msg);
290
291
    ext2fs_sha512(msg, len, tmp);
292
    printf("SHA512 test message %d: ", i);
293
    if (memcmp(tmp, tests[i].hash, 64) != 0) {
294
      printf("FAILED\n");
295
      errors++;
296
    } else
297
      printf("OK\n");
298
  }
299
  return errors;
300
}
301
302
#endif /* UNITTEST */