File Coverage

md5.c
Criterion Covered Total %
statement 78 79 98.7
branch 27 28 96.4
condition n/a
subroutine n/a
pod n/a
total 105 107 98.1


line stmt bran cond sub pod time code
1             /*
2             * md5.c - MD5 implementation per RFC 1321.
3             *
4             * Plain C99, no external deps. Endian-agnostic (reads/writes go through
5             * byte-by-byte loaders/storers). Round constants and shift amounts come
6             * directly from the spec.
7             */
8              
9             #include "md5.h"
10             #include
11              
12             #define ROL32(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
13              
14             static const uint32_t MD5_K[64] = {
15             0xd76aa478u, 0xe8c7b756u, 0x242070dbu, 0xc1bdceeeu,
16             0xf57c0fafu, 0x4787c62au, 0xa8304613u, 0xfd469501u,
17             0x698098d8u, 0x8b44f7afu, 0xffff5bb1u, 0x895cd7beu,
18             0x6b901122u, 0xfd987193u, 0xa679438eu, 0x49b40821u,
19             0xf61e2562u, 0xc040b340u, 0x265e5a51u, 0xe9b6c7aau,
20             0xd62f105du, 0x02441453u, 0xd8a1e681u, 0xe7d3fbc8u,
21             0x21e1cde6u, 0xc33707d6u, 0xf4d50d87u, 0x455a14edu,
22             0xa9e3e905u, 0xfcefa3f8u, 0x676f02d9u, 0x8d2a4c8au,
23             0xfffa3942u, 0x8771f681u, 0x6d9d6122u, 0xfde5380cu,
24             0xa4beea44u, 0x4bdecfa9u, 0xf6bb4b60u, 0xbebfbc70u,
25             0x289b7ec6u, 0xeaa127fau, 0xd4ef3085u, 0x04881d05u,
26             0xd9d4d039u, 0xe6db99e5u, 0x1fa27cf8u, 0xc4ac5665u,
27             0xf4292244u, 0x432aff97u, 0xab9423a7u, 0xfc93a039u,
28             0x655b59c3u, 0x8f0ccc92u, 0xffeff47du, 0x85845dd1u,
29             0x6fa87e4fu, 0xfe2ce6e0u, 0xa3014314u, 0x4e0811a1u,
30             0xf7537e82u, 0xbd3af235u, 0x2ad7d2bbu, 0xeb86d391u
31             };
32              
33             static const unsigned MD5_S[64] = {
34             7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
35             5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
36             4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
37             6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
38             };
39              
40             static uint32_t
41 156000           load32_le(const unsigned char *p)
42             {
43 156000           return (uint32_t)p[0]
44 156000           | ((uint32_t)p[1] << 8)
45 156000           | ((uint32_t)p[2] << 16)
46 156000           | ((uint32_t)p[3] << 24);
47             }
48              
49             static void
50 64           store32_le(unsigned char *p, uint32_t v)
51             {
52 64           p[0] = (unsigned char)( v & 0xFFu);
53 64           p[1] = (unsigned char)((v >> 8) & 0xFFu);
54 64           p[2] = (unsigned char)((v >> 16) & 0xFFu);
55 64           p[3] = (unsigned char)((v >> 24) & 0xFFu);
56 64           }
57              
58             static void
59 9750           md5_compress(md5_ctx_t *ctx, const unsigned char *block)
60             {
61             uint32_t M[16];
62 9750           uint32_t a = ctx->state[0], b = ctx->state[1],
63 9750           c = ctx->state[2], d = ctx->state[3];
64             uint32_t f, g, t;
65             int i;
66              
67 165750 100         for (i = 0; i < 16; i++) M[i] = load32_le(block + i * 4);
68              
69 633750 100         for (i = 0; i < 64; i++) {
70 624000 100         if (i < 16) {
71 156000           f = (b & c) | (~b & d);
72 156000           g = (uint32_t)i;
73 468000 100         } else if (i < 32) {
74 156000           f = (d & b) | (~d & c);
75 156000           g = (uint32_t)(5 * i + 1) & 15u;
76 312000 100         } else if (i < 48) {
77 156000           f = b ^ c ^ d;
78 156000           g = (uint32_t)(3 * i + 5) & 15u;
79             } else {
80 156000           f = c ^ (b | ~d);
81 156000           g = (uint32_t)(7 * i) & 15u;
82             }
83 624000           t = d;
84 624000           d = c;
85 624000           c = b;
86 624000           b = b + ROL32(a + f + MD5_K[i] + M[g], MD5_S[i]);
87 624000           a = t;
88             }
89              
90 9750           ctx->state[0] += a;
91 9750           ctx->state[1] += b;
92 9750           ctx->state[2] += c;
93 9750           ctx->state[3] += d;
94 9750           }
95              
96             void
97 18           md5_init(md5_ctx_t *ctx)
98             {
99 18           ctx->state[0] = 0x67452301u;
100 18           ctx->state[1] = 0xefcdab89u;
101 18           ctx->state[2] = 0x98badcfeu;
102 18           ctx->state[3] = 0x10325476u;
103 18           ctx->bit_count = 0;
104 18           ctx->buffered = 0;
105 18           }
106              
107             void
108 53           md5_update(md5_ctx_t *ctx, const void *data, size_t len)
109             {
110 53           const unsigned char *p = (const unsigned char *)data;
111             size_t take;
112              
113 53           ctx->bit_count += (uint64_t)len << 3;
114              
115 53 100         if (ctx->buffered) {
116 29           take = MD5_BLOCK_SIZE - ctx->buffered;
117 29 100         if (take > len) take = len;
118 29           memcpy(ctx->buffer + ctx->buffered, p, take);
119 29           ctx->buffered += take;
120 29           p += take;
121 29           len -= take;
122 29 100         if (ctx->buffered == MD5_BLOCK_SIZE) {
123 16           md5_compress(ctx, ctx->buffer);
124 16           ctx->buffered = 0;
125             }
126             }
127 9787 100         while (len >= MD5_BLOCK_SIZE) {
128 9734           md5_compress(ctx, p);
129 9734           p += MD5_BLOCK_SIZE;
130 9734           len -= MD5_BLOCK_SIZE;
131             }
132 53 100         if (len) {
133 16           memcpy(ctx->buffer, p, len);
134 16           ctx->buffered = len;
135             }
136 53           }
137              
138             void
139 16           md5_final(md5_ctx_t *ctx, unsigned char out[MD5_DIGEST_SIZE])
140             {
141             /* Pad: append 0x80, zeros, then 64-bit little-endian length. */
142             unsigned char pad[MD5_BLOCK_SIZE];
143             unsigned char len_le[8];
144 16           uint64_t bits = ctx->bit_count;
145             size_t pad_len;
146             int i;
147              
148 16           pad[0] = 0x80;
149 1024 100         for (i = 1; i < MD5_BLOCK_SIZE; i++) pad[i] = 0;
150              
151             /* Need to land at offset 56 mod 64 after writing pad. */
152 16 50         if (ctx->buffered < 56)
153 16           pad_len = 56 - ctx->buffered;
154             else
155 0           pad_len = (MD5_BLOCK_SIZE + 56) - ctx->buffered;
156              
157 16           md5_update(ctx, pad, pad_len);
158              
159 144 100         for (i = 0; i < 8; i++) {
160 128           len_le[i] = (unsigned char)((bits >> (i * 8)) & 0xFFu);
161             }
162 16           md5_update(ctx, len_le, 8);
163              
164             /* bit_count was bumped twice by the padding update — that's fine,
165             * it's only consumed once during the very pad we just wrote. */
166 80 100         for (i = 0; i < 4; i++) store32_le(out + i * 4, ctx->state[i]);
167 16           }