Coverage Report

Created: 2026-10-27 07:01

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