1 /*
2 * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 /*-
11 * This is a generic 32 bit "collector" for message digest algorithms.
12 * Whenever needed it collects input character stream into chunks of
13 * 32 bit values and invokes a block function that performs actual hash
14 * calculations.
15 *
16 * Porting guide.
17 *
18 * Obligatory macros:
19 *
20 * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
21 * this macro defines byte order of input stream.
22 * HASH_CBLOCK
23 * size of a unit chunk HASH_BLOCK operates on.
24 * HASH_LONG
25 * has to be at least 32 bit wide.
26 * HASH_CTX
27 * context structure that at least contains following
28 * members:
29 * typedef struct {
30 * ...
31 * HASH_LONG Nl,Nh;
32 * either {
33 * HASH_LONG data[HASH_LBLOCK];
34 * unsigned char data[HASH_CBLOCK];
35 * };
36 * unsigned int num;
37 * ...
38 * } HASH_CTX;
39 * data[] vector is expected to be zeroed upon first call to
40 * HASH_UPDATE.
41 * HASH_UPDATE
42 * name of "Update" function, implemented here.
43 * HASH_TRANSFORM
44 * name of "Transform" function, implemented here.
45 * HASH_FINAL
46 * name of "Final" function, implemented here.
47 * HASH_BLOCK_DATA_ORDER
48 * name of "block" function capable of treating *unaligned* input
49 * message in original (data) byte order, implemented externally.
50 * HASH_MAKE_STRING
51 * macro converting context variables to an ASCII hash string.
52 *
53 * MD5 example:
54 *
55 * #define DATA_ORDER_IS_LITTLE_ENDIAN
56 *
57 * #define HASH_LONG MD5_LONG
58 * #define HASH_CTX MD5_CTX
59 * #define HASH_CBLOCK MD5_CBLOCK
60 * #define HASH_UPDATE MD5_Update
61 * #define HASH_TRANSFORM MD5_Transform
62 * #define HASH_FINAL MD5_Final
63 * #define HASH_BLOCK_DATA_ORDER md5_block_data_order
64 */
65
66 #ifndef OSSL_CRYPTO_MD32_COMMON_H
67 #define OSSL_CRYPTO_MD32_COMMON_H
68 #pragma once
69
70 #include <openssl/crypto.h>
71
72 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
73 #error "DATA_ORDER must be defined!"
74 #endif
75
76 #ifndef HASH_CBLOCK
77 #error "HASH_CBLOCK must be defined!"
78 #endif
79 #ifndef HASH_LONG
80 #error "HASH_LONG must be defined!"
81 #endif
82 #ifndef HASH_CTX
83 #error "HASH_CTX must be defined!"
84 #endif
85
86 #ifndef HASH_UPDATE
87 #error "HASH_UPDATE must be defined!"
88 #endif
89 #ifndef HASH_TRANSFORM
90 #error "HASH_TRANSFORM must be defined!"
91 #endif
92 #ifndef HASH_FINAL
93 #error "HASH_FINAL must be defined!"
94 #endif
95
96 #ifndef HASH_BLOCK_DATA_ORDER
97 #error "HASH_BLOCK_DATA_ORDER must be defined!"
98 #endif
99
100 #define ROTATE(a, n) (((a) << (n)) | (((a) & 0xffffffff) >> (32 - (n))))
101
102 #ifndef PEDANTIC
103 #if defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
104 #if defined(__riscv_zbb) || defined(__riscv_zbkb)
105 #if __riscv_xlen == 64
106 #undef ROTATE
107 #define ROTATE(x, n) ({ MD32_REG_T ret; \
108 asm ("roriw %0, %1, %2" \
109 : "=r"(ret) \
110 : "r"(x), "i"(32 - (n))); ret; })
111 #endif
112 #if __riscv_xlen == 32
113 #undef ROTATE
114 #define ROTATE(x, n) ({ MD32_REG_T ret; \
115 asm ("rori %0, %1, %2" \
116 : "=r"(ret) \
117 : "r"(x), "i"(32 - (n))); ret; })
118 #endif
119 #endif
120 #endif
121 #endif
122
123 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
124
125 #define HOST_c2l(c, l) (l = (((unsigned long)(*((c)++))) << 24), \
126 l |= (((unsigned long)(*((c)++))) << 16), \
127 l |= (((unsigned long)(*((c)++))) << 8), \
128 l |= (((unsigned long)(*((c)++)))))
129 #define HOST_l2c(l, c) (*((c)++) = (unsigned char)(((l) >> 24) & 0xff), \
130 *((c)++) = (unsigned char)(((l) >> 16) & 0xff), \
131 *((c)++) = (unsigned char)(((l) >> 8) & 0xff), \
132 *((c)++) = (unsigned char)(((l)) & 0xff), \
133 l)
134
135 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
136
137 #define HOST_c2l(c, l) (l = (((unsigned long)(*((c)++)))), \
138 l |= (((unsigned long)(*((c)++))) << 8), \
139 l |= (((unsigned long)(*((c)++))) << 16), \
140 l |= (((unsigned long)(*((c)++))) << 24))
141 #define HOST_l2c(l, c) (*((c)++) = (unsigned char)(((l)) & 0xff), \
142 *((c)++) = (unsigned char)(((l) >> 8) & 0xff), \
143 *((c)++) = (unsigned char)(((l) >> 16) & 0xff), \
144 *((c)++) = (unsigned char)(((l) >> 24) & 0xff), \
145 l)
146
147 #endif
148
149 /*
150 * Time for some action :-)
151 */
152
HASH_UPDATE(HASH_CTX * c,const void * data_,size_t len)153 int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len)
154 {
155 const unsigned char *data = data_;
156 unsigned char *p;
157 HASH_LONG l;
158 size_t n;
159
160 if (len == 0)
161 return 1;
162
163 l = (c->Nl + (((HASH_LONG)len) << 3)) & 0xffffffffUL;
164 if (l < c->Nl) /* overflow */
165 c->Nh++;
166 c->Nh += (HASH_LONG)(len >> 29); /* might cause compiler warning on
167 * 16-bit */
168 c->Nl = l;
169
170 n = c->num;
171 if (n != 0) {
172 p = (unsigned char *)c->data;
173
174 if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) {
175 memcpy(p + n, data, HASH_CBLOCK - n);
176 HASH_BLOCK_DATA_ORDER(c, p, 1);
177 n = HASH_CBLOCK - n;
178 data += n;
179 len -= n;
180 c->num = 0;
181 /*
182 * We use memset rather than OPENSSL_cleanse() here deliberately.
183 * Using OPENSSL_cleanse() here could be a performance issue. It
184 * will get properly cleansed on finalisation so this isn't a
185 * security problem.
186 */
187 memset(p, 0, HASH_CBLOCK); /* keep it zeroed */
188 } else {
189 memcpy(p + n, data, len);
190 c->num += (unsigned int)len;
191 return 1;
192 }
193 }
194
195 n = len / HASH_CBLOCK;
196 if (n > 0) {
197 HASH_BLOCK_DATA_ORDER(c, data, n);
198 n *= HASH_CBLOCK;
199 data += n;
200 len -= n;
201 }
202
203 if (len != 0) {
204 p = (unsigned char *)c->data;
205 c->num = (unsigned int)len;
206 memcpy(p, data, len);
207 }
208 return 1;
209 }
210
HASH_TRANSFORM(HASH_CTX * c,const unsigned char * data)211 void HASH_TRANSFORM(HASH_CTX *c, const unsigned char *data)
212 {
213 HASH_BLOCK_DATA_ORDER(c, data, 1);
214 }
215
HASH_FINAL(unsigned char * md,HASH_CTX * c)216 int HASH_FINAL(unsigned char *md, HASH_CTX *c)
217 {
218 unsigned char *p = (unsigned char *)c->data;
219 size_t n = c->num;
220
221 p[n] = 0x80; /* there is always room for one */
222 n++;
223
224 if (n > (HASH_CBLOCK - 8)) {
225 memset(p + n, 0, HASH_CBLOCK - n);
226 n = 0;
227 HASH_BLOCK_DATA_ORDER(c, p, 1);
228 }
229 memset(p + n, 0, HASH_CBLOCK - 8 - n);
230
231 p += HASH_CBLOCK - 8;
232 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
233 (void)HOST_l2c(c->Nh, p);
234 (void)HOST_l2c(c->Nl, p);
235 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
236 (void)HOST_l2c(c->Nl, p);
237 (void)HOST_l2c(c->Nh, p);
238 #endif
239 p -= HASH_CBLOCK;
240 HASH_BLOCK_DATA_ORDER(c, p, 1);
241 c->num = 0;
242 OPENSSL_cleanse(p, HASH_CBLOCK);
243
244 #ifndef HASH_MAKE_STRING
245 #error "HASH_MAKE_STRING must be defined!"
246 #else
247 HASH_MAKE_STRING(c, md);
248 #endif
249
250 return 1;
251 }
252
253 #ifndef MD32_REG_T
254 #if defined(__alpha) || defined(__sparcv9) || defined(__mips)
255 #define MD32_REG_T long
256 /*
257 * This comment was originally written for MD5, which is why it
258 * discusses A-D. But it basically applies to all 32-bit digests,
259 * which is why it was moved to common header file.
260 *
261 * In case you wonder why A-D are declared as long and not
262 * as MD5_LONG. Doing so results in slight performance
263 * boost on LP64 architectures. The catch is we don't
264 * really care if 32 MSBs of a 64-bit register get polluted
265 * with eventual overflows as we *save* only 32 LSBs in
266 * *either* case. Now declaring 'em long excuses the compiler
267 * from keeping 32 MSBs zeroed resulting in 13% performance
268 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
269 * Well, to be honest it should say that this *prevents*
270 * performance degradation.
271 */
272 #else
273 /*
274 * Above is not absolute and there are LP64 compilers that
275 * generate better code if MD32_REG_T is defined int. The above
276 * pre-processor condition reflects the circumstances under which
277 * the conclusion was made and is subject to further extension.
278 */
279 #define MD32_REG_T int
280 #endif
281 #endif
282
283 #endif
284