Coverage Report

Created: 2025-12-31 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mupdf/source/fitz/crypt-sha2.c
Line
Count
Source
1
/*
2
This code is based on the code found from 7-Zip, which has a modified
3
version of the SHA-256 found from Crypto++ <http://www.cryptopp.com/>.
4
The code was modified a little to fit into liblzma and fitz.
5
6
This file has been put into the public domain.
7
You can do whatever you want with this file.
8
9
SHA-384 and SHA-512 were also taken from Crypto++ and adapted for fitz.
10
*/
11
12
#include "mupdf/fitz.h"
13
14
#include <string.h>
15
16
static inline int isbigendian(void)
17
0
{
18
0
  static const int one = 1;
19
0
  return *(char*)&one == 0;
20
0
}
21
22
static inline unsigned int bswap32(unsigned int num)
23
0
{
24
0
  return  ( (((num) << 24))
25
0
    | (((num) << 8) & 0x00FF0000)
26
0
    | (((num) >> 8) & 0x0000FF00)
27
0
    | (((num) >> 24)) );
28
0
}
29
30
static inline uint64_t bswap64(uint64_t num)
31
0
{
32
0
  return ( (((num) << 56))
33
0
    | (((num) << 40) & 0x00FF000000000000ULL)
34
0
    | (((num) << 24) & 0x0000FF0000000000ULL)
35
0
    | (((num) << 8) & 0x000000FF00000000ULL)
36
0
    | (((num) >> 8) & 0x00000000FF000000ULL)
37
0
    | (((num) >> 24) & 0x0000000000FF0000ULL)
38
0
    | (((num) >> 40) & 0x000000000000FF00ULL)
39
0
    | (((num) >> 56)) );
40
0
}
41
42
/* At least on x86, GCC is able to optimize this to a rotate instruction. */
43
0
#define rotr(num, amount) ((num) >> (amount) | (num) << (8 * sizeof(num) - (amount)))
44
45
0
#define blk0(i) (W[i] = data[i])
46
0
#define blk2(i) (W[i & 15] += s1(W[(i - 2) & 15]) + W[(i - 7) & 15] \
47
0
    + s0(W[(i - 15) & 15]))
48
49
0
#define Ch(x, y, z) (z ^ (x & (y ^ z)))
50
0
#define Maj(x, y, z) ((x & y) | (z & (x | y)))
51
52
0
#define a(i) T[(0 - i) & 7]
53
0
#define b(i) T[(1 - i) & 7]
54
0
#define c(i) T[(2 - i) & 7]
55
0
#define d(i) T[(3 - i) & 7]
56
0
#define e(i) T[(4 - i) & 7]
57
0
#define f(i) T[(5 - i) & 7]
58
0
#define g(i) T[(6 - i) & 7]
59
0
#define h(i) T[(7 - i) & 7]
60
61
#define R(i) \
62
0
  h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + K[i + j] \
63
0
    + (j ? blk2(i) : blk0(i)); \
64
0
  d(i) += h(i); \
65
0
  h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
66
67
/* For SHA256 */
68
69
0
#define S0(x) (rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22))
70
0
#define S1(x) (rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25))
71
0
#define s0(x) (rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3))
72
0
#define s1(x) (rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10))
73
74
static const unsigned int SHA256_K[64] = {
75
  0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
76
  0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
77
  0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
78
  0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
79
  0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
80
  0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
81
  0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
82
  0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
83
  0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
84
  0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
85
  0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
86
  0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
87
  0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
88
  0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
89
  0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
90
  0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
91
};
92
93
static void
94
transform256(unsigned int state[8], unsigned int data[16])
95
0
{
96
0
  const unsigned int *K = SHA256_K;
97
0
  unsigned int W[16];
98
0
  unsigned int T[8];
99
0
  unsigned int j;
100
101
  /* ensure big-endian integers */
102
0
  if (!isbigendian())
103
0
    for (j = 0; j < 16; j++)
104
0
      data[j] = bswap32(data[j]);
105
106
  /* Copy state[] to working vars. */
107
0
  memcpy(T, state, sizeof(T));
108
109
  /* 64 operations, partially loop unrolled */
110
0
  for (j = 0; j < 64; j += 16) {
111
0
    R( 0); R( 1); R( 2); R( 3);
112
0
    R( 4); R( 5); R( 6); R( 7);
113
0
    R( 8); R( 9); R(10); R(11);
114
0
    R(12); R(13); R(14); R(15);
115
0
  }
116
117
  /* Add the working vars back into state[]. */
118
0
  state[0] += a(0);
119
0
  state[1] += b(0);
120
0
  state[2] += c(0);
121
0
  state[3] += d(0);
122
0
  state[4] += e(0);
123
0
  state[5] += f(0);
124
0
  state[6] += g(0);
125
0
  state[7] += h(0);
126
0
}
127
128
#undef S0
129
#undef S1
130
#undef s0
131
#undef s1
132
133
void fz_sha256_init(fz_sha256 *context)
134
0
{
135
0
  context->count[0] = context->count[1] = 0;
136
137
0
  context->state[0] = 0x6A09E667;
138
0
  context->state[1] = 0xBB67AE85;
139
0
  context->state[2] = 0x3C6EF372;
140
0
  context->state[3] = 0xA54FF53A;
141
0
  context->state[4] = 0x510E527F;
142
0
  context->state[5] = 0x9B05688C;
143
0
  context->state[6] = 0x1F83D9AB;
144
0
  context->state[7] = 0x5BE0CD19;
145
0
}
146
147
void fz_sha256_update(fz_sha256 *context, const unsigned char *input, size_t inlen)
148
0
{
149
  /* Copy the input data into a properly aligned temporary buffer.
150
   * This way we can be called with arbitrarily sized buffers
151
   * (no need to be multiple of 64 bytes), and the code works also
152
   * on architectures that don't allow unaligned memory access. */
153
0
  while (inlen > 0)
154
0
  {
155
0
    const unsigned int copy_start = context->count[0] & 0x3F;
156
0
    unsigned int copy_size = 64 - copy_start;
157
0
    if (copy_size > inlen)
158
0
      copy_size = (unsigned int)inlen;
159
160
0
    memcpy(context->buffer.u8 + copy_start, input, copy_size);
161
162
0
    input += copy_size;
163
0
    inlen -= copy_size;
164
0
    context->count[0] += copy_size;
165
    /* carry overflow from low to high */
166
0
    if (context->count[0] < copy_size)
167
0
      context->count[1]++;
168
169
0
    if ((context->count[0] & 0x3F) == 0)
170
0
      transform256(context->state, context->buffer.u32);
171
0
  }
172
0
}
173
174
void fz_sha256_final(fz_sha256 *context, unsigned char digest[32])
175
0
{
176
  /* Add padding as described in RFC 3174 (it describes SHA-1 but
177
   * the same padding style is used for SHA-256 too). */
178
0
  unsigned int j = context->count[0] & 0x3F;
179
0
  context->buffer.u8[j++] = 0x80;
180
181
0
  while (j != 56)
182
0
  {
183
0
    if (j == 64)
184
0
    {
185
0
      transform256(context->state, context->buffer.u32);
186
0
      j = 0;
187
0
    }
188
0
    context->buffer.u8[j++] = 0x00;
189
0
  }
190
191
  /* Convert the message size from bytes to bits. */
192
0
  context->count[1] = (context->count[1] << 3) + (context->count[0] >> 29);
193
0
  context->count[0] = context->count[0] << 3;
194
195
0
  if (!isbigendian())
196
0
  {
197
0
    context->buffer.u32[14] = bswap32(context->count[1]);
198
0
    context->buffer.u32[15] = bswap32(context->count[0]);
199
0
  }
200
0
  else
201
0
  {
202
0
    context->buffer.u32[14] = context->count[1];
203
0
    context->buffer.u32[15] = context->count[0];
204
0
  }
205
0
  transform256(context->state, context->buffer.u32);
206
207
0
  if (!isbigendian())
208
0
    for (j = 0; j < 8; j++)
209
0
      context->state[j] = bswap32(context->state[j]);
210
211
0
  memcpy(digest, &context->state[0], 32);
212
0
  memset(context, 0, sizeof(fz_sha256));
213
0
}
214
215
/* For SHA512 */
216
217
0
#define S0(x) (rotr(x, 28) ^ rotr(x, 34) ^ rotr(x, 39))
218
0
#define S1(x) (rotr(x, 14) ^ rotr(x, 18) ^ rotr(x, 41))
219
0
#define s0(x) (rotr(x, 1) ^ rotr(x, 8) ^ (x >> 7))
220
0
#define s1(x) (rotr(x, 19) ^ rotr(x, 61) ^ (x >> 6))
221
222
static const uint64_t SHA512_K[80] = {
223
  0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL,
224
  0xB5C0FBCFEC4D3B2FULL, 0xE9B5DBA58189DBBCULL,
225
  0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL,
226
  0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL,
227
  0xD807AA98A3030242ULL, 0x12835B0145706FBEULL,
228
  0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
229
  0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL,
230
  0x9BDC06A725C71235ULL, 0xC19BF174CF692694ULL,
231
  0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL,
232
  0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL,
233
  0x2DE92C6F592B0275ULL, 0x4A7484AA6EA6E483ULL,
234
  0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
235
  0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL,
236
  0xB00327C898FB213FULL, 0xBF597FC7BEEF0EE4ULL,
237
  0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL,
238
  0x06CA6351E003826FULL, 0x142929670A0E6E70ULL,
239
  0x27B70A8546D22FFCULL, 0x2E1B21385C26C926ULL,
240
  0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
241
  0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL,
242
  0x81C2C92E47EDAEE6ULL, 0x92722C851482353BULL,
243
  0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL,
244
  0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL,
245
  0xD192E819D6EF5218ULL, 0xD69906245565A910ULL,
246
  0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
247
  0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL,
248
  0x2748774CDF8EEB99ULL, 0x34B0BCB5E19B48A8ULL,
249
  0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL,
250
  0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL,
251
  0x748F82EE5DEFB2FCULL, 0x78A5636F43172F60ULL,
252
  0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
253
  0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL,
254
  0xBEF9A3F7B2C67915ULL, 0xC67178F2E372532BULL,
255
  0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL,
256
  0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL,
257
  0x06F067AA72176FBAULL, 0x0A637DC5A2C898A6ULL,
258
  0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
259
  0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL,
260
  0x3C9EBE0A15C9BEBCULL, 0x431D67C49C100D4CULL,
261
  0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL,
262
  0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL,
263
};
264
265
static void
266
transform512(uint64_t state[8], uint64_t data[16])
267
0
{
268
0
  const uint64_t *K = SHA512_K;
269
0
  uint64_t W[16];
270
0
  uint64_t T[8];
271
0
  unsigned int j;
272
273
  /* ensure big-endian integers */
274
0
  if (!isbigendian())
275
0
    for (j = 0; j < 16; j++)
276
0
      data[j] = bswap64(data[j]);
277
278
  /* Copy state[] to working vars. */
279
0
  memcpy(T, state, sizeof(T));
280
281
  /* 80 operations, partially loop unrolled */
282
0
  for (j = 0; j < 80; j+= 16) {
283
0
    R( 0); R( 1); R( 2); R( 3);
284
0
    R( 4); R( 5); R( 6); R( 7);
285
0
    R( 8); R( 9); R(10); R(11);
286
0
    R(12); R(13); R(14); R(15);
287
0
  }
288
289
  /* Add the working vars back into state[]. */
290
0
  state[0] += a(0);
291
0
  state[1] += b(0);
292
0
  state[2] += c(0);
293
0
  state[3] += d(0);
294
0
  state[4] += e(0);
295
0
  state[5] += f(0);
296
0
  state[6] += g(0);
297
0
  state[7] += h(0);
298
0
}
299
300
#undef S0
301
#undef S1
302
#undef s0
303
#undef s1
304
305
void fz_sha512_init(fz_sha512 *context)
306
0
{
307
0
  context->count[0] = context->count[1] = 0;
308
309
0
  context->state[0] = 0x6A09E667F3BCC908ull;
310
0
  context->state[1] = 0xBB67AE8584CAA73Bull;
311
0
  context->state[2] = 0x3C6EF372FE94F82Bull;
312
0
  context->state[3] = 0xA54FF53A5F1D36F1ull;
313
0
  context->state[4] = 0x510E527FADE682D1ull;
314
0
  context->state[5] = 0x9B05688C2B3E6C1Full;
315
0
  context->state[6] = 0x1F83D9ABFB41BD6Bull;
316
0
  context->state[7] = 0x5BE0CD19137E2179ull;
317
0
}
318
319
void fz_sha512_update(fz_sha512 *context, const unsigned char *input, size_t inlen)
320
0
{
321
  /* Copy the input data into a properly aligned temporary buffer.
322
   * This way we can be called with arbitrarily sized buffers
323
   * (no need to be multiple of 128 bytes), and the code works also
324
   * on architectures that don't allow unaligned memory access. */
325
0
  while (inlen > 0)
326
0
  {
327
0
    const unsigned int copy_start = context->count[0] & 0x7F;
328
0
    unsigned int copy_size = 128 - copy_start;
329
0
    if (copy_size > inlen)
330
0
      copy_size = (unsigned int)inlen;
331
332
0
    memcpy(context->buffer.u8 + copy_start, input, copy_size);
333
334
0
    input += copy_size;
335
0
    inlen -= copy_size;
336
0
    context->count[0] += copy_size;
337
    /* carry overflow from low to high */
338
0
    if (context->count[0] < copy_size)
339
0
      context->count[1]++;
340
341
0
    if ((context->count[0] & 0x7F) == 0)
342
0
      transform512(context->state, context->buffer.u64);
343
0
  }
344
0
}
345
346
void fz_sha512_final(fz_sha512 *context, unsigned char digest[64])
347
0
{
348
  /* Add padding as described in RFC 3174 (it describes SHA-1 but
349
   * the same padding style is used for SHA-512 too). */
350
0
  unsigned int j = context->count[0] & 0x7F;
351
0
  context->buffer.u8[j++] = 0x80;
352
353
0
  while (j != 112)
354
0
  {
355
0
    if (j == 128)
356
0
    {
357
0
      transform512(context->state, context->buffer.u64);
358
0
      j = 0;
359
0
    }
360
0
    context->buffer.u8[j++] = 0x00;
361
0
  }
362
363
  /* Convert the message size from bytes to bits. */
364
0
  context->count[1] = (context->count[1] << 3) + (context->count[0] >> 29);
365
0
  context->count[0] = context->count[0] << 3;
366
367
0
  if (!isbigendian())
368
0
  {
369
0
    context->buffer.u64[14] = bswap64(context->count[1]);
370
0
    context->buffer.u64[15] = bswap64(context->count[0]);
371
0
  }
372
0
  else
373
0
  {
374
0
    context->buffer.u64[14] = context->count[1];
375
0
    context->buffer.u64[15] = context->count[0];
376
0
  }
377
0
  transform512(context->state, context->buffer.u64);
378
379
0
  if (!isbigendian())
380
0
    for (j = 0; j < 8; j++)
381
0
      context->state[j] = bswap64(context->state[j]);
382
383
0
  memcpy(digest, &context->state[0], 64);
384
0
  memset(context, 0, sizeof(fz_sha512));
385
0
}
386
387
void fz_sha384_init(fz_sha384 *context)
388
0
{
389
0
  context->count[0] = context->count[1] = 0;
390
391
0
  context->state[0] = 0xCBBB9D5DC1059ED8ull;
392
0
  context->state[1] = 0x629A292A367CD507ull;
393
0
  context->state[2] = 0x9159015A3070DD17ull;
394
0
  context->state[3] = 0x152FECD8F70E5939ull;
395
0
  context->state[4] = 0x67332667FFC00B31ull;
396
0
  context->state[5] = 0x8EB44A8768581511ull;
397
0
  context->state[6] = 0xDB0C2E0D64F98FA7ull;
398
0
  context->state[7] = 0x47B5481DBEFA4FA4ull;
399
0
}
400
401
void fz_sha384_update(fz_sha384 *context, const unsigned char *input, size_t inlen)
402
0
{
403
0
  fz_sha512_update(context, input, inlen);
404
0
}
405
406
void fz_sha384_final(fz_sha384 *context, unsigned char digest[64])
407
0
{
408
0
  fz_sha512_final(context, digest);
409
0
}