Coverage Report

Created: 2024-02-25 06:34

/src/htslib/md5.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Trivial amendments by James Bonfield <jkb@sanger.ac.uk> to provide an
3
 * HTSlib interface. 2015.
4
 *
5
 * Externally our API uses an opaque hts_md5_context structure.
6
 *
7
 * Internally either this gets defined and used with the routines here
8
 * or it remains incomplete and is cast to the OpenSSL MD5_CTX structure
9
 * and used by routines from OpenSSL.
10
 */
11
12
/*
13
 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
14
 * MD5 Message-Digest Algorithm (RFC 1321).
15
 *
16
 * Homepage:
17
 * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
18
 *
19
 * Author:
20
 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
21
 *
22
 * This software was written by Alexander Peslyak in 2001.  No copyright is
23
 * claimed, and the software is hereby placed in the public domain.
24
 * In case this attempt to disclaim copyright and place the software in the
25
 * public domain is deemed null and void, then the software is
26
 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
27
 * general public under the following terms:
28
 *
29
 * Redistribution and use in source and binary forms, with or without
30
 * modification, are permitted.
31
 *
32
 * There's ABSOLUTELY NO WARRANTY, express or implied.
33
 *
34
 * (This is a heavily cut-down "BSD license".)
35
 *
36
 * This differs from Colin Plumb's older public domain implementation in that
37
 * no exactly 32-bit integer data type is required (any 32-bit or wider
38
 * unsigned integer data type will do), there's no compile-time endianness
39
 * configuration, and the function prototypes match OpenSSL's.  No code from
40
 * Colin Plumb's implementation has been reused; this comment merely compares
41
 * the properties of the two independent implementations.
42
 *
43
 * The primary goals of this implementation are portability and ease of use.
44
 * It is meant to be fast, but not as fast as possible.  Some known
45
 * optimizations are not included to reduce source code size and avoid
46
 * compile-time configuration.
47
 */
48
49
#define HTS_BUILDING_LIBRARY // Enables HTSLIB_EXPORT, see htslib/hts_defs.h
50
#include <config.h>
51
52
#include <stdlib.h>
53
#include "htslib/hts.h"
54
#include "htslib/hts_endian.h"
55
56
#ifndef HAVE_OPENSSL
57
58
#include <string.h>
59
60
/* Any 32-bit or wider unsigned integer data type will do */
61
typedef unsigned int hts_md5_u32plus;
62
63
struct hts_md5_context {
64
  hts_md5_u32plus lo, hi;
65
  hts_md5_u32plus a, b, c, d;
66
  unsigned char buffer[64];
67
  hts_md5_u32plus block[16];
68
};
69
70
/*
71
 * The basic MD5 functions.
72
 *
73
 * F and G are optimized compared to their RFC 1321 definitions for
74
 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
75
 * implementation.
76
 */
77
255M
#define F(x, y, z)      ((z) ^ ((x) & ((y) ^ (z))))
78
255M
#define G(x, y, z)      ((y) ^ ((z) & ((x) ^ (y))))
79
127M
#define H(x, y, z)      (((x) ^ (y)) ^ (z))
80
127M
#define H2(x, y, z)     ((x) ^ ((y) ^ (z)))
81
255M
#define I(x, y, z)      ((y) ^ ((x) | ~(z)))
82
83
/*
84
 * The MD5 transformation for all four rounds.
85
 */
86
#define STEP(f, a, b, c, d, x, t, s) \
87
1.02G
  (a) += f((b), (c), (d)) + (x) + (t); \
88
1.02G
  (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
89
1.02G
  (a) += (b);
90
91
/*
92
 * SET reads 4 input bytes in little-endian byte order and stores them
93
 * in a properly aligned word in host byte order.
94
 *
95
 * The check for little-endian architectures that tolerate unaligned
96
 * memory accesses is just an optimization.  Nothing will break if it
97
 * doesn't work.
98
 */
99
#if defined(HTS_LITTLE_ENDIAN) && HTS_ALLOW_UNALIGNED != 0
100
#define SET(n) \
101
  (*(hts_md5_u32plus *)&ptr[(n) * 4])
102
#define GET(n) \
103
  SET(n)
104
#else
105
#define SET(n) \
106
  (ctx->block[(n)] = \
107
  (hts_md5_u32plus)ptr[(n) * 4] | \
108
  ((hts_md5_u32plus)ptr[(n) * 4 + 1] << 8) | \
109
  ((hts_md5_u32plus)ptr[(n) * 4 + 2] << 16) | \
110
  ((hts_md5_u32plus)ptr[(n) * 4 + 3] << 24))
111
#define GET(n) \
112
  (ctx->block[(n)])
113
#endif
114
115
/*
116
 * This processes one or more 64-byte data blocks, but does NOT update
117
 * the bit counters.  There are no alignment requirements.
118
 */
119
static const void *body(hts_md5_context *ctx, const void *data, unsigned long size)
120
25.8k
{
121
25.8k
  const unsigned char *ptr;
122
25.8k
  hts_md5_u32plus a, b, c, d;
123
25.8k
  hts_md5_u32plus saved_a, saved_b, saved_c, saved_d;
124
125
25.8k
  ptr = (const unsigned char *)data;
126
127
25.8k
  a = ctx->a;
128
25.8k
  b = ctx->b;
129
25.8k
  c = ctx->c;
130
25.8k
  d = ctx->d;
131
132
15.9M
  do {
133
15.9M
    saved_a = a;
134
15.9M
    saved_b = b;
135
15.9M
    saved_c = c;
136
15.9M
    saved_d = d;
137
138
/* Round 1 */
139
15.9M
    STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
140
15.9M
    STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
141
15.9M
    STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
142
15.9M
    STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
143
15.9M
    STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
144
15.9M
    STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
145
15.9M
    STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
146
15.9M
    STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
147
15.9M
    STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
148
15.9M
    STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
149
15.9M
    STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
150
15.9M
    STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
151
15.9M
    STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
152
15.9M
    STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
153
15.9M
    STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
154
15.9M
    STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
155
156
/* Round 2 */
157
15.9M
    STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
158
15.9M
    STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
159
15.9M
    STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
160
15.9M
    STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
161
15.9M
    STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
162
15.9M
    STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
163
15.9M
    STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
164
15.9M
    STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
165
15.9M
    STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
166
15.9M
    STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
167
15.9M
    STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
168
15.9M
    STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
169
15.9M
    STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
170
15.9M
    STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
171
15.9M
    STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
172
15.9M
    STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
173
174
/* Round 3 */
175
15.9M
    STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
176
15.9M
    STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
177
15.9M
    STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
178
15.9M
    STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
179
15.9M
    STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
180
15.9M
    STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
181
15.9M
    STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
182
15.9M
    STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
183
15.9M
    STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
184
15.9M
    STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
185
15.9M
    STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
186
15.9M
    STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
187
15.9M
    STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
188
15.9M
    STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
189
15.9M
    STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
190
15.9M
    STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
191
192
/* Round 4 */
193
15.9M
    STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
194
15.9M
    STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
195
15.9M
    STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
196
15.9M
    STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
197
15.9M
    STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
198
15.9M
    STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
199
15.9M
    STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
200
15.9M
    STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
201
15.9M
    STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
202
15.9M
    STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
203
15.9M
    STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
204
15.9M
    STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
205
15.9M
    STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
206
15.9M
    STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
207
15.9M
    STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
208
15.9M
    STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
209
210
15.9M
    a += saved_a;
211
15.9M
    b += saved_b;
212
15.9M
    c += saved_c;
213
15.9M
    d += saved_d;
214
215
15.9M
    ptr += 64;
216
15.9M
  } while (size -= 64);
217
218
25.8k
  ctx->a = a;
219
25.8k
  ctx->b = b;
220
25.8k
  ctx->c = c;
221
25.8k
  ctx->d = d;
222
223
25.8k
  return ptr;
224
25.8k
}
225
226
void hts_md5_reset(hts_md5_context *ctx)
227
24.4k
{
228
24.4k
  ctx->a = 0x67452301;
229
24.4k
  ctx->b = 0xefcdab89;
230
24.4k
  ctx->c = 0x98badcfe;
231
24.4k
  ctx->d = 0x10325476;
232
233
24.4k
  ctx->lo = 0;
234
24.4k
  ctx->hi = 0;
235
24.4k
}
236
237
void hts_md5_update(hts_md5_context *ctx, const void *data, unsigned long size)
238
24.4k
{
239
24.4k
  hts_md5_u32plus saved_lo;
240
24.4k
  unsigned long used, available;
241
242
24.4k
  saved_lo = ctx->lo;
243
24.4k
  if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
244
0
    ctx->hi++;
245
24.4k
  ctx->hi += size >> 29;
246
247
24.4k
  used = saved_lo & 0x3f;
248
249
24.4k
  if (used) {
250
0
    available = 64 - used;
251
252
0
    if (size < available) {
253
0
      memcpy(&ctx->buffer[used], data, size);
254
0
      return;
255
0
    }
256
257
0
    memcpy(&ctx->buffer[used], data, available);
258
0
    data = (const unsigned char *)data + available;
259
0
    size -= available;
260
0
    body(ctx, ctx->buffer, 64);
261
0
  }
262
263
24.4k
  if (size >= 64) {
264
1.25k
    data = body(ctx, data, size & ~(unsigned long)0x3f);
265
1.25k
    size &= 0x3f;
266
1.25k
  }
267
268
24.4k
  memcpy(ctx->buffer, data, size);
269
24.4k
}
270
271
void hts_md5_final(unsigned char *result, hts_md5_context *ctx)
272
24.4k
{
273
24.4k
  unsigned long used, available;
274
275
24.4k
  used = ctx->lo & 0x3f;
276
277
24.4k
  ctx->buffer[used++] = 0x80;
278
279
24.4k
  available = 64 - used;
280
281
24.4k
  if (available < 8) {
282
159
    memset(&ctx->buffer[used], 0, available);
283
159
    body(ctx, ctx->buffer, 64);
284
159
    used = 0;
285
159
    available = 64;
286
159
  }
287
288
24.4k
  memset(&ctx->buffer[used], 0, available - 8);
289
290
24.4k
  ctx->lo <<= 3;
291
24.4k
  ctx->buffer[56] = ctx->lo;
292
24.4k
  ctx->buffer[57] = ctx->lo >> 8;
293
24.4k
  ctx->buffer[58] = ctx->lo >> 16;
294
24.4k
  ctx->buffer[59] = ctx->lo >> 24;
295
24.4k
  ctx->buffer[60] = ctx->hi;
296
24.4k
  ctx->buffer[61] = ctx->hi >> 8;
297
24.4k
  ctx->buffer[62] = ctx->hi >> 16;
298
24.4k
  ctx->buffer[63] = ctx->hi >> 24;
299
300
24.4k
  body(ctx, ctx->buffer, 64);
301
302
24.4k
  result[0] = ctx->a;
303
24.4k
  result[1] = ctx->a >> 8;
304
24.4k
  result[2] = ctx->a >> 16;
305
24.4k
  result[3] = ctx->a >> 24;
306
24.4k
  result[4] = ctx->b;
307
24.4k
  result[5] = ctx->b >> 8;
308
24.4k
  result[6] = ctx->b >> 16;
309
24.4k
  result[7] = ctx->b >> 24;
310
24.4k
  result[8] = ctx->c;
311
24.4k
  result[9] = ctx->c >> 8;
312
24.4k
  result[10] = ctx->c >> 16;
313
24.4k
  result[11] = ctx->c >> 24;
314
24.4k
  result[12] = ctx->d;
315
24.4k
  result[13] = ctx->d >> 8;
316
24.4k
  result[14] = ctx->d >> 16;
317
24.4k
  result[15] = ctx->d >> 24;
318
319
24.4k
  memset(ctx, 0, sizeof(*ctx));
320
24.4k
}
321
322
323
hts_md5_context *hts_md5_init(void)
324
24.4k
{
325
24.4k
    hts_md5_context *ctx = malloc(sizeof(*ctx));
326
24.4k
    if (!ctx)
327
0
        return NULL;
328
329
24.4k
    hts_md5_reset(ctx);
330
24.4k
    return ctx;
331
24.4k
}
332
333
#else
334
335
#include <openssl/md5.h>
336
#include <assert.h>
337
338
/*
339
 * Wrappers around the OpenSSL libcrypto.so MD5 implementation.
340
 *
341
 * These are here to ensure they end up in the symbol table of the
342
 * library regardless of the static inline in the headers.
343
 */
344
hts_md5_context *hts_md5_init(void)
345
{
346
    MD5_CTX *ctx = malloc(sizeof(*ctx));
347
    if (!ctx)
348
        return NULL;
349
350
    MD5_Init(ctx);
351
352
    return (hts_md5_context *)ctx;
353
}
354
355
void hts_md5_reset(hts_md5_context *ctx)
356
{
357
    MD5_Init((MD5_CTX *)ctx);
358
}
359
360
void hts_md5_update(hts_md5_context *ctx, const void *data, unsigned long size)
361
{
362
    MD5_Update((MD5_CTX *)ctx, data, size);
363
}
364
365
void hts_md5_final(unsigned char *result, hts_md5_context *ctx)
366
{
367
    MD5_Final(result, (MD5_CTX *)ctx);
368
}
369
370
#endif
371
372
void hts_md5_destroy(hts_md5_context *ctx)
373
24.4k
{
374
24.4k
    if (!ctx)
375
0
        return;
376
377
24.4k
    free(ctx);
378
24.4k
}
379
380
void hts_md5_hex(char *hex, const unsigned char *digest)
381
0
{
382
0
    int i;
383
0
    for (i = 0; i < 16; i++) {
384
0
        hex[i*2+0] = "0123456789abcdef"[(digest[i]>>4)&0xf];
385
0
        hex[i*2+1] = "0123456789abcdef"[digest[i]&0xf];
386
0
    }
387
0
    hex[32] = 0;
388
0
}