Coverage Report

Created: 2026-02-16 07:12

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
18.1k
int MD4_Init(MD4_CTX *md4) {
40
18.1k
  OPENSSL_memset(md4, 0, sizeof(MD4_CTX));
41
18.1k
  md4->h[0] = 0x67452301UL;
42
18.1k
  md4->h[1] = 0xefcdab89UL;
43
18.1k
  md4->h[2] = 0x98badcfeUL;
44
18.1k
  md4->h[3] = 0x10325476UL;
45
18.1k
  return 1;
46
18.1k
}
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
18.4k
                         size_t num_blocks) {
62
18.4k
    md4_block_data_order(state, data, num_blocks);
63
18.4k
  }
64
};
65
}  // namespace
66
67
18.3k
int MD4_Update(MD4_CTX *c, const void *data, size_t len) {
68
18.3k
  crypto_md32_update<MD4Traits>(c,
69
18.3k
                                Span(static_cast<const uint8_t *>(data), len));
70
18.3k
  return 1;
71
18.3k
}
72
73
18.1k
int MD4_Final(uint8_t out[MD4_DIGEST_LENGTH], MD4_CTX *c) {
74
18.1k
  crypto_md32_final<MD4Traits>(c);
75
18.1k
  CRYPTO_store_u32_le(out, c->h[0]);
76
18.1k
  CRYPTO_store_u32_le(out + 4, c->h[1]);
77
18.1k
  CRYPTO_store_u32_le(out + 8, c->h[2]);
78
18.1k
  CRYPTO_store_u32_le(out + 12, c->h[3]);
79
18.1k
  return 1;
80
18.1k
}
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.33M
#define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d))
86
1.33M
#define G(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
87
1.33M
#define H(b, c, d) ((b) ^ (c) ^ (d))
88
89
#define R0(a, b, c, d, k, s, t)            \
90
1.33M
  do {                                     \
91
1.33M
    (a) += ((k) + (t) + F((b), (c), (d))); \
92
1.33M
    (a) = CRYPTO_rotl_u32(a, s);           \
93
1.33M
  } while (0)
94
95
#define R1(a, b, c, d, k, s, t)            \
96
1.33M
  do {                                     \
97
1.33M
    (a) += ((k) + (t) + G((b), (c), (d))); \
98
1.33M
    (a) = CRYPTO_rotl_u32(a, s);           \
99
1.33M
  } while (0)
100
101
#define R2(a, b, c, d, k, s, t)            \
102
1.33M
  do {                                     \
103
1.33M
    (a) += ((k) + (t) + H((b), (c), (d))); \
104
1.33M
    (a) = CRYPTO_rotl_u32(a, s);           \
105
1.33M
  } while (0)
106
107
static void md4_block_data_order(uint32_t *state, const uint8_t *data,
108
18.4k
                                 size_t num) {
109
18.4k
  uint32_t A, B, C, D;
110
18.4k
  uint32_t X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15;
111
112
18.4k
  A = state[0];
113
18.4k
  B = state[1];
114
18.4k
  C = state[2];
115
18.4k
  D = state[3];
116
117
101k
  for (; num--;) {
118
83.4k
    X0 = CRYPTO_load_u32_le(data);
119
83.4k
    data += 4;
120
83.4k
    X1 = CRYPTO_load_u32_le(data);
121
83.4k
    data += 4;
122
    // Round 0
123
83.4k
    R0(A, B, C, D, X0, 3, 0);
124
83.4k
    X2 = CRYPTO_load_u32_le(data);
125
83.4k
    data += 4;
126
83.4k
    R0(D, A, B, C, X1, 7, 0);
127
83.4k
    X3 = CRYPTO_load_u32_le(data);
128
83.4k
    data += 4;
129
83.4k
    R0(C, D, A, B, X2, 11, 0);
130
83.4k
    X4 = CRYPTO_load_u32_le(data);
131
83.4k
    data += 4;
132
83.4k
    R0(B, C, D, A, X3, 19, 0);
133
83.4k
    X5 = CRYPTO_load_u32_le(data);
134
83.4k
    data += 4;
135
83.4k
    R0(A, B, C, D, X4, 3, 0);
136
83.4k
    X6 = CRYPTO_load_u32_le(data);
137
83.4k
    data += 4;
138
83.4k
    R0(D, A, B, C, X5, 7, 0);
139
83.4k
    X7 = CRYPTO_load_u32_le(data);
140
83.4k
    data += 4;
141
83.4k
    R0(C, D, A, B, X6, 11, 0);
142
83.4k
    X8 = CRYPTO_load_u32_le(data);
143
83.4k
    data += 4;
144
83.4k
    R0(B, C, D, A, X7, 19, 0);
145
83.4k
    X9 = CRYPTO_load_u32_le(data);
146
83.4k
    data += 4;
147
83.4k
    R0(A, B, C, D, X8, 3, 0);
148
83.4k
    X10 = CRYPTO_load_u32_le(data);
149
83.4k
    data += 4;
150
83.4k
    R0(D, A, B, C, X9, 7, 0);
151
83.4k
    X11 = CRYPTO_load_u32_le(data);
152
83.4k
    data += 4;
153
83.4k
    R0(C, D, A, B, X10, 11, 0);
154
83.4k
    X12 = CRYPTO_load_u32_le(data);
155
83.4k
    data += 4;
156
83.4k
    R0(B, C, D, A, X11, 19, 0);
157
83.4k
    X13 = CRYPTO_load_u32_le(data);
158
83.4k
    data += 4;
159
83.4k
    R0(A, B, C, D, X12, 3, 0);
160
83.4k
    X14 = CRYPTO_load_u32_le(data);
161
83.4k
    data += 4;
162
83.4k
    R0(D, A, B, C, X13, 7, 0);
163
83.4k
    X15 = CRYPTO_load_u32_le(data);
164
83.4k
    data += 4;
165
83.4k
    R0(C, D, A, B, X14, 11, 0);
166
83.4k
    R0(B, C, D, A, X15, 19, 0);
167
    // Round 1
168
83.4k
    R1(A, B, C, D, X0, 3, 0x5A827999L);
169
83.4k
    R1(D, A, B, C, X4, 5, 0x5A827999L);
170
83.4k
    R1(C, D, A, B, X8, 9, 0x5A827999L);
171
83.4k
    R1(B, C, D, A, X12, 13, 0x5A827999L);
172
83.4k
    R1(A, B, C, D, X1, 3, 0x5A827999L);
173
83.4k
    R1(D, A, B, C, X5, 5, 0x5A827999L);
174
83.4k
    R1(C, D, A, B, X9, 9, 0x5A827999L);
175
83.4k
    R1(B, C, D, A, X13, 13, 0x5A827999L);
176
83.4k
    R1(A, B, C, D, X2, 3, 0x5A827999L);
177
83.4k
    R1(D, A, B, C, X6, 5, 0x5A827999L);
178
83.4k
    R1(C, D, A, B, X10, 9, 0x5A827999L);
179
83.4k
    R1(B, C, D, A, X14, 13, 0x5A827999L);
180
83.4k
    R1(A, B, C, D, X3, 3, 0x5A827999L);
181
83.4k
    R1(D, A, B, C, X7, 5, 0x5A827999L);
182
83.4k
    R1(C, D, A, B, X11, 9, 0x5A827999L);
183
83.4k
    R1(B, C, D, A, X15, 13, 0x5A827999L);
184
    // Round 2
185
83.4k
    R2(A, B, C, D, X0, 3, 0x6ED9EBA1L);
186
83.4k
    R2(D, A, B, C, X8, 9, 0x6ED9EBA1L);
187
83.4k
    R2(C, D, A, B, X4, 11, 0x6ED9EBA1L);
188
83.4k
    R2(B, C, D, A, X12, 15, 0x6ED9EBA1L);
189
83.4k
    R2(A, B, C, D, X2, 3, 0x6ED9EBA1L);
190
83.4k
    R2(D, A, B, C, X10, 9, 0x6ED9EBA1L);
191
83.4k
    R2(C, D, A, B, X6, 11, 0x6ED9EBA1L);
192
83.4k
    R2(B, C, D, A, X14, 15, 0x6ED9EBA1L);
193
83.4k
    R2(A, B, C, D, X1, 3, 0x6ED9EBA1L);
194
83.4k
    R2(D, A, B, C, X9, 9, 0x6ED9EBA1L);
195
83.4k
    R2(C, D, A, B, X5, 11, 0x6ED9EBA1L);
196
83.4k
    R2(B, C, D, A, X13, 15, 0x6ED9EBA1L);
197
83.4k
    R2(A, B, C, D, X3, 3, 0x6ED9EBA1L);
198
83.4k
    R2(D, A, B, C, X11, 9, 0x6ED9EBA1L);
199
83.4k
    R2(C, D, A, B, X7, 11, 0x6ED9EBA1L);
200
83.4k
    R2(B, C, D, A, X15, 15, 0x6ED9EBA1L);
201
202
83.4k
    A = state[0] += A;
203
83.4k
    B = state[1] += B;
204
83.4k
    C = state[2] += C;
205
83.4k
    D = state[3] += D;
206
83.4k
  }
207
18.4k
}