Coverage Report

Created: 2026-06-28 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/md5/md5.cc
Line
Count
Source
1
// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/md5.h>
16
17
#include <string.h>
18
19
#include <openssl/mem.h>
20
#include <openssl/span.h>
21
22
#include "../fipsmodule/digest/md32_common.h"
23
#include "../internal.h"
24
#include "internal.h"
25
26
27
using namespace bssl;
28
29
0
uint8_t *MD5(const uint8_t *data, size_t len, uint8_t out[MD5_DIGEST_LENGTH]) {
30
0
  MD5_CTX ctx;
31
0
  MD5_Init(&ctx);
32
0
  MD5_Update(&ctx, data, len);
33
0
  MD5_Final(out, &ctx);
34
35
0
  return out;
36
0
}
37
38
51.1k
int MD5_Init(MD5_CTX *md5) {
39
51.1k
  OPENSSL_memset(md5, 0, sizeof(MD5_CTX));
40
51.1k
  md5->h[0] = 0x67452301UL;
41
51.1k
  md5->h[1] = 0xefcdab89UL;
42
51.1k
  md5->h[2] = 0x98badcfeUL;
43
51.1k
  md5->h[3] = 0x10325476UL;
44
51.1k
  return 1;
45
51.1k
}
46
47
#if defined(MD5_ASM)
48
253k
#define md5_block_data_order md5_block_asm_data_order
49
#else
50
static void md5_block_data_order(uint32_t *state, const uint8_t *data,
51
                                 size_t num);
52
#endif
53
54
0
void MD5_Transform(MD5_CTX *c, const uint8_t data[MD5_CBLOCK]) {
55
0
  md5_block_data_order(c->h, data, 1);
56
0
}
57
58
namespace {
59
struct MD5Traits {
60
  using HashContext = MD5_CTX;
61
  static constexpr size_t kBlockSize = MD5_CBLOCK;
62
  static constexpr bool kLengthIsBigEndian = false;
63
  static void HashBlocks(uint32_t *state, const uint8_t *data,
64
253k
                         size_t num_blocks) {
65
253k
    md5_block_data_order(state, data, num_blocks);
66
253k
  }
67
};
68
}  // namespace
69
70
290k
int MD5_Update(MD5_CTX *c, const void *data, size_t len) {
71
290k
  crypto_md32_update<MD5Traits>(c,
72
290k
                                Span(static_cast<const uint8_t *>(data), len));
73
290k
  return 1;
74
290k
}
75
76
157k
int MD5_Final(uint8_t out[MD5_DIGEST_LENGTH], MD5_CTX *c) {
77
157k
  crypto_md32_final<MD5Traits>(c);
78
157k
  CRYPTO_store_u32_le(out, c->h[0]);
79
157k
  CRYPTO_store_u32_le(out + 4, c->h[1]);
80
157k
  CRYPTO_store_u32_le(out + 8, c->h[2]);
81
157k
  CRYPTO_store_u32_le(out + 12, c->h[3]);
82
157k
  return 1;
83
157k
}
84
85
// As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
86
// simplified to the code below.  Wei attributes these optimizations
87
// to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
88
#define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d))
89
#define G(b, c, d) ((((b) ^ (c)) & (d)) ^ (c))
90
#define H(b, c, d) ((b) ^ (c) ^ (d))
91
#define I(b, c, d) (((~(d)) | (b)) ^ (c))
92
93
#define R0(a, b, c, d, k, s, t)            \
94
  do {                                     \
95
    (a) += ((k) + (t) + F((b), (c), (d))); \
96
    (a) = CRYPTO_rotl_u32(a, s);           \
97
    (a) += (b);                            \
98
  } while (0)
99
100
#define R1(a, b, c, d, k, s, t)            \
101
  do {                                     \
102
    (a) += ((k) + (t) + G((b), (c), (d))); \
103
    (a) = CRYPTO_rotl_u32(a, s);           \
104
    (a) += (b);                            \
105
  } while (0)
106
107
#define R2(a, b, c, d, k, s, t)            \
108
  do {                                     \
109
    (a) += ((k) + (t) + H((b), (c), (d))); \
110
    (a) = CRYPTO_rotl_u32(a, s);           \
111
    (a) += (b);                            \
112
  } while (0)
113
114
#define R3(a, b, c, d, k, s, t)            \
115
  do {                                     \
116
    (a) += ((k) + (t) + I((b), (c), (d))); \
117
    (a) = CRYPTO_rotl_u32(a, s);           \
118
    (a) += (b);                            \
119
  } while (0)
120
121
#ifndef MD5_ASM
122
#ifdef X
123
#undef X
124
#endif
125
static void md5_block_data_order(uint32_t *state, const uint8_t *data,
126
                                 size_t num) {
127
  uint32_t A, B, C, D;
128
  uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12,
129
      XX13, XX14, XX15;
130
#define X(i) XX##i
131
132
  A = state[0];
133
  B = state[1];
134
  C = state[2];
135
  D = state[3];
136
137
  for (; num--;) {
138
    X(0) = CRYPTO_load_u32_le(data);
139
    data += 4;
140
    X(1) = CRYPTO_load_u32_le(data);
141
    data += 4;
142
    // Round 0
143
    R0(A, B, C, D, X(0), 7, 0xd76aa478L);
144
    X(2) = CRYPTO_load_u32_le(data);
145
    data += 4;
146
    R0(D, A, B, C, X(1), 12, 0xe8c7b756L);
147
    X(3) = CRYPTO_load_u32_le(data);
148
    data += 4;
149
    R0(C, D, A, B, X(2), 17, 0x242070dbL);
150
    X(4) = CRYPTO_load_u32_le(data);
151
    data += 4;
152
    R0(B, C, D, A, X(3), 22, 0xc1bdceeeL);
153
    X(5) = CRYPTO_load_u32_le(data);
154
    data += 4;
155
    R0(A, B, C, D, X(4), 7, 0xf57c0fafL);
156
    X(6) = CRYPTO_load_u32_le(data);
157
    data += 4;
158
    R0(D, A, B, C, X(5), 12, 0x4787c62aL);
159
    X(7) = CRYPTO_load_u32_le(data);
160
    data += 4;
161
    R0(C, D, A, B, X(6), 17, 0xa8304613L);
162
    X(8) = CRYPTO_load_u32_le(data);
163
    data += 4;
164
    R0(B, C, D, A, X(7), 22, 0xfd469501L);
165
    X(9) = CRYPTO_load_u32_le(data);
166
    data += 4;
167
    R0(A, B, C, D, X(8), 7, 0x698098d8L);
168
    X(10) = CRYPTO_load_u32_le(data);
169
    data += 4;
170
    R0(D, A, B, C, X(9), 12, 0x8b44f7afL);
171
    X(11) = CRYPTO_load_u32_le(data);
172
    data += 4;
173
    R0(C, D, A, B, X(10), 17, 0xffff5bb1L);
174
    X(12) = CRYPTO_load_u32_le(data);
175
    data += 4;
176
    R0(B, C, D, A, X(11), 22, 0x895cd7beL);
177
    X(13) = CRYPTO_load_u32_le(data);
178
    data += 4;
179
    R0(A, B, C, D, X(12), 7, 0x6b901122L);
180
    X(14) = CRYPTO_load_u32_le(data);
181
    data += 4;
182
    R0(D, A, B, C, X(13), 12, 0xfd987193L);
183
    X(15) = CRYPTO_load_u32_le(data);
184
    data += 4;
185
    R0(C, D, A, B, X(14), 17, 0xa679438eL);
186
    R0(B, C, D, A, X(15), 22, 0x49b40821L);
187
    // Round 1
188
    R1(A, B, C, D, X(1), 5, 0xf61e2562L);
189
    R1(D, A, B, C, X(6), 9, 0xc040b340L);
190
    R1(C, D, A, B, X(11), 14, 0x265e5a51L);
191
    R1(B, C, D, A, X(0), 20, 0xe9b6c7aaL);
192
    R1(A, B, C, D, X(5), 5, 0xd62f105dL);
193
    R1(D, A, B, C, X(10), 9, 0x02441453L);
194
    R1(C, D, A, B, X(15), 14, 0xd8a1e681L);
195
    R1(B, C, D, A, X(4), 20, 0xe7d3fbc8L);
196
    R1(A, B, C, D, X(9), 5, 0x21e1cde6L);
197
    R1(D, A, B, C, X(14), 9, 0xc33707d6L);
198
    R1(C, D, A, B, X(3), 14, 0xf4d50d87L);
199
    R1(B, C, D, A, X(8), 20, 0x455a14edL);
200
    R1(A, B, C, D, X(13), 5, 0xa9e3e905L);
201
    R1(D, A, B, C, X(2), 9, 0xfcefa3f8L);
202
    R1(C, D, A, B, X(7), 14, 0x676f02d9L);
203
    R1(B, C, D, A, X(12), 20, 0x8d2a4c8aL);
204
    // Round 2
205
    R2(A, B, C, D, X(5), 4, 0xfffa3942L);
206
    R2(D, A, B, C, X(8), 11, 0x8771f681L);
207
    R2(C, D, A, B, X(11), 16, 0x6d9d6122L);
208
    R2(B, C, D, A, X(14), 23, 0xfde5380cL);
209
    R2(A, B, C, D, X(1), 4, 0xa4beea44L);
210
    R2(D, A, B, C, X(4), 11, 0x4bdecfa9L);
211
    R2(C, D, A, B, X(7), 16, 0xf6bb4b60L);
212
    R2(B, C, D, A, X(10), 23, 0xbebfbc70L);
213
    R2(A, B, C, D, X(13), 4, 0x289b7ec6L);
214
    R2(D, A, B, C, X(0), 11, 0xeaa127faL);
215
    R2(C, D, A, B, X(3), 16, 0xd4ef3085L);
216
    R2(B, C, D, A, X(6), 23, 0x04881d05L);
217
    R2(A, B, C, D, X(9), 4, 0xd9d4d039L);
218
    R2(D, A, B, C, X(12), 11, 0xe6db99e5L);
219
    R2(C, D, A, B, X(15), 16, 0x1fa27cf8L);
220
    R2(B, C, D, A, X(2), 23, 0xc4ac5665L);
221
    // Round 3
222
    R3(A, B, C, D, X(0), 6, 0xf4292244L);
223
    R3(D, A, B, C, X(7), 10, 0x432aff97L);
224
    R3(C, D, A, B, X(14), 15, 0xab9423a7L);
225
    R3(B, C, D, A, X(5), 21, 0xfc93a039L);
226
    R3(A, B, C, D, X(12), 6, 0x655b59c3L);
227
    R3(D, A, B, C, X(3), 10, 0x8f0ccc92L);
228
    R3(C, D, A, B, X(10), 15, 0xffeff47dL);
229
    R3(B, C, D, A, X(1), 21, 0x85845dd1L);
230
    R3(A, B, C, D, X(8), 6, 0x6fa87e4fL);
231
    R3(D, A, B, C, X(15), 10, 0xfe2ce6e0L);
232
    R3(C, D, A, B, X(6), 15, 0xa3014314L);
233
    R3(B, C, D, A, X(13), 21, 0x4e0811a1L);
234
    R3(A, B, C, D, X(4), 6, 0xf7537e82L);
235
    R3(D, A, B, C, X(11), 10, 0xbd3af235L);
236
    R3(C, D, A, B, X(2), 15, 0x2ad7d2bbL);
237
    R3(B, C, D, A, X(9), 21, 0xeb86d391L);
238
239
    A = state[0] += A;
240
    B = state[1] += B;
241
    C = state[2] += C;
242
    D = state[3] += D;
243
  }
244
}
245
#undef X
246
#endif
247
248
#undef F
249
#undef G
250
#undef H
251
#undef I
252
#undef R0
253
#undef R1
254
#undef R2
255
#undef R3