Coverage Report

Created: 2025-08-28 06:59

/src/boringssl/crypto/md4/md4.cc
Line
Count
Source (jump to first uncovered line)
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/md4.h>
16
17
#include <stdlib.h>
18
#include <string.h>
19
20
#include <openssl/span.h>
21
22
#include "../fipsmodule/digest/md32_common.h"
23
#include "../internal.h"
24
25
26
0
uint8_t *MD4(const uint8_t *data, size_t len, uint8_t out[MD4_DIGEST_LENGTH]) {
27
0
  MD4_CTX ctx;
28
0
  MD4_Init(&ctx);
29
0
  MD4_Update(&ctx, data, len);
30
0
  MD4_Final(out, &ctx);
31
32
0
  return out;
33
0
}
34
35
// Implemented from RFC 1186 The MD4 Message-Digest Algorithm.
36
37
28.4k
int MD4_Init(MD4_CTX *md4) {
38
28.4k
  OPENSSL_memset(md4, 0, sizeof(MD4_CTX));
39
28.4k
  md4->h[0] = 0x67452301UL;
40
28.4k
  md4->h[1] = 0xefcdab89UL;
41
28.4k
  md4->h[2] = 0x98badcfeUL;
42
28.4k
  md4->h[3] = 0x10325476UL;
43
28.4k
  return 1;
44
28.4k
}
45
46
static void md4_block_data_order(uint32_t *state, const uint8_t *data,
47
                                 size_t num);
48
49
0
void MD4_Transform(MD4_CTX *c, const uint8_t data[MD4_CBLOCK]) {
50
0
  md4_block_data_order(c->h, data, 1);
51
0
}
52
53
namespace {
54
struct MD4Traits {
55
  using HashContext = MD4_CTX;
56
  static constexpr size_t kBlockSize = MD4_CBLOCK;
57
  static constexpr bool kLengthIsBigEndian = false;
58
  static void HashBlocks(uint32_t *state, const uint8_t *data,
59
28.9k
                         size_t num_blocks) {
60
28.9k
    md4_block_data_order(state, data, num_blocks);
61
28.9k
  }
62
};
63
}  // namespace
64
65
28.7k
int MD4_Update(MD4_CTX *c, const void *data, size_t len) {
66
28.7k
  bssl::crypto_md32_update<MD4Traits>(
67
28.7k
      c, bssl::Span(static_cast<const uint8_t *>(data), len));
68
28.7k
  return 1;
69
28.7k
}
70
71
28.4k
int MD4_Final(uint8_t out[MD4_DIGEST_LENGTH], MD4_CTX *c) {
72
28.4k
  bssl::crypto_md32_final<MD4Traits>(c);
73
28.4k
  CRYPTO_store_u32_le(out, c->h[0]);
74
28.4k
  CRYPTO_store_u32_le(out + 4, c->h[1]);
75
28.4k
  CRYPTO_store_u32_le(out + 8, c->h[2]);
76
28.4k
  CRYPTO_store_u32_le(out + 12, c->h[3]);
77
28.4k
  return 1;
78
28.4k
}
79
80
// As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
81
// simplified to the code below.  Wei attributes these optimizations
82
// to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
83
1.58M
#define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d))
84
1.58M
#define G(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
85
1.58M
#define H(b, c, d) ((b) ^ (c) ^ (d))
86
87
#define R0(a, b, c, d, k, s, t)            \
88
1.58M
  do {                                     \
89
1.58M
    (a) += ((k) + (t) + F((b), (c), (d))); \
90
1.58M
    (a) = CRYPTO_rotl_u32(a, s);           \
91
1.58M
  } while (0)
92
93
#define R1(a, b, c, d, k, s, t)            \
94
1.58M
  do {                                     \
95
1.58M
    (a) += ((k) + (t) + G((b), (c), (d))); \
96
1.58M
    (a) = CRYPTO_rotl_u32(a, s);           \
97
1.58M
  } while (0)
98
99
#define R2(a, b, c, d, k, s, t)            \
100
1.58M
  do {                                     \
101
1.58M
    (a) += ((k) + (t) + H((b), (c), (d))); \
102
1.58M
    (a) = CRYPTO_rotl_u32(a, s);           \
103
1.58M
  } while (0)
104
105
static void md4_block_data_order(uint32_t *state, const uint8_t *data,
106
28.9k
                                 size_t num) {
107
28.9k
  uint32_t A, B, C, D;
108
28.9k
  uint32_t X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15;
109
110
28.9k
  A = state[0];
111
28.9k
  B = state[1];
112
28.9k
  C = state[2];
113
28.9k
  D = state[3];
114
115
127k
  for (; num--;) {
116
98.9k
    X0 = CRYPTO_load_u32_le(data);
117
98.9k
    data += 4;
118
98.9k
    X1 = CRYPTO_load_u32_le(data);
119
98.9k
    data += 4;
120
    // Round 0
121
98.9k
    R0(A, B, C, D, X0, 3, 0);
122
98.9k
    X2 = CRYPTO_load_u32_le(data);
123
98.9k
    data += 4;
124
98.9k
    R0(D, A, B, C, X1, 7, 0);
125
98.9k
    X3 = CRYPTO_load_u32_le(data);
126
98.9k
    data += 4;
127
98.9k
    R0(C, D, A, B, X2, 11, 0);
128
98.9k
    X4 = CRYPTO_load_u32_le(data);
129
98.9k
    data += 4;
130
98.9k
    R0(B, C, D, A, X3, 19, 0);
131
98.9k
    X5 = CRYPTO_load_u32_le(data);
132
98.9k
    data += 4;
133
98.9k
    R0(A, B, C, D, X4, 3, 0);
134
98.9k
    X6 = CRYPTO_load_u32_le(data);
135
98.9k
    data += 4;
136
98.9k
    R0(D, A, B, C, X5, 7, 0);
137
98.9k
    X7 = CRYPTO_load_u32_le(data);
138
98.9k
    data += 4;
139
98.9k
    R0(C, D, A, B, X6, 11, 0);
140
98.9k
    X8 = CRYPTO_load_u32_le(data);
141
98.9k
    data += 4;
142
98.9k
    R0(B, C, D, A, X7, 19, 0);
143
98.9k
    X9 = CRYPTO_load_u32_le(data);
144
98.9k
    data += 4;
145
98.9k
    R0(A, B, C, D, X8, 3, 0);
146
98.9k
    X10 = CRYPTO_load_u32_le(data);
147
98.9k
    data += 4;
148
98.9k
    R0(D, A, B, C, X9, 7, 0);
149
98.9k
    X11 = CRYPTO_load_u32_le(data);
150
98.9k
    data += 4;
151
98.9k
    R0(C, D, A, B, X10, 11, 0);
152
98.9k
    X12 = CRYPTO_load_u32_le(data);
153
98.9k
    data += 4;
154
98.9k
    R0(B, C, D, A, X11, 19, 0);
155
98.9k
    X13 = CRYPTO_load_u32_le(data);
156
98.9k
    data += 4;
157
98.9k
    R0(A, B, C, D, X12, 3, 0);
158
98.9k
    X14 = CRYPTO_load_u32_le(data);
159
98.9k
    data += 4;
160
98.9k
    R0(D, A, B, C, X13, 7, 0);
161
98.9k
    X15 = CRYPTO_load_u32_le(data);
162
98.9k
    data += 4;
163
98.9k
    R0(C, D, A, B, X14, 11, 0);
164
98.9k
    R0(B, C, D, A, X15, 19, 0);
165
    // Round 1
166
98.9k
    R1(A, B, C, D, X0, 3, 0x5A827999L);
167
98.9k
    R1(D, A, B, C, X4, 5, 0x5A827999L);
168
98.9k
    R1(C, D, A, B, X8, 9, 0x5A827999L);
169
98.9k
    R1(B, C, D, A, X12, 13, 0x5A827999L);
170
98.9k
    R1(A, B, C, D, X1, 3, 0x5A827999L);
171
98.9k
    R1(D, A, B, C, X5, 5, 0x5A827999L);
172
98.9k
    R1(C, D, A, B, X9, 9, 0x5A827999L);
173
98.9k
    R1(B, C, D, A, X13, 13, 0x5A827999L);
174
98.9k
    R1(A, B, C, D, X2, 3, 0x5A827999L);
175
98.9k
    R1(D, A, B, C, X6, 5, 0x5A827999L);
176
98.9k
    R1(C, D, A, B, X10, 9, 0x5A827999L);
177
98.9k
    R1(B, C, D, A, X14, 13, 0x5A827999L);
178
98.9k
    R1(A, B, C, D, X3, 3, 0x5A827999L);
179
98.9k
    R1(D, A, B, C, X7, 5, 0x5A827999L);
180
98.9k
    R1(C, D, A, B, X11, 9, 0x5A827999L);
181
98.9k
    R1(B, C, D, A, X15, 13, 0x5A827999L);
182
    // Round 2
183
98.9k
    R2(A, B, C, D, X0, 3, 0x6ED9EBA1L);
184
98.9k
    R2(D, A, B, C, X8, 9, 0x6ED9EBA1L);
185
98.9k
    R2(C, D, A, B, X4, 11, 0x6ED9EBA1L);
186
98.9k
    R2(B, C, D, A, X12, 15, 0x6ED9EBA1L);
187
98.9k
    R2(A, B, C, D, X2, 3, 0x6ED9EBA1L);
188
98.9k
    R2(D, A, B, C, X10, 9, 0x6ED9EBA1L);
189
98.9k
    R2(C, D, A, B, X6, 11, 0x6ED9EBA1L);
190
98.9k
    R2(B, C, D, A, X14, 15, 0x6ED9EBA1L);
191
98.9k
    R2(A, B, C, D, X1, 3, 0x6ED9EBA1L);
192
98.9k
    R2(D, A, B, C, X9, 9, 0x6ED9EBA1L);
193
98.9k
    R2(C, D, A, B, X5, 11, 0x6ED9EBA1L);
194
98.9k
    R2(B, C, D, A, X13, 15, 0x6ED9EBA1L);
195
98.9k
    R2(A, B, C, D, X3, 3, 0x6ED9EBA1L);
196
98.9k
    R2(D, A, B, C, X11, 9, 0x6ED9EBA1L);
197
98.9k
    R2(C, D, A, B, X7, 11, 0x6ED9EBA1L);
198
98.9k
    R2(B, C, D, A, X15, 15, 0x6ED9EBA1L);
199
200
98.9k
    A = state[0] += A;
201
98.9k
    B = state[1] += B;
202
98.9k
    C = state[2] += C;
203
98.9k
    D = state[3] += D;
204
98.9k
  }
205
28.9k
}