1 /* $OpenBSD: md32_common.h,v 1.19 2014/10/20 13:06:54 bcook Exp $ */
2 /* ====================================================================
3  * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    licensing@OpenSSL.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  */
51 
52 /*
53  * This is a generic 32 bit "collector" for message digest algorithms.
54  * Whenever needed it collects input character stream into chunks of
55  * 32 bit values and invokes a block function that performs actual hash
56  * calculations.
57  *
58  * Porting guide.
59  *
60  * Obligatory macros:
61  *
62  * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
63  *	this macro defines byte order of input stream.
64  * HASH_CBLOCK
65  *	size of a unit chunk HASH_BLOCK operates on.
66  * HASH_LONG
67  *	has to be at least 32 bit wide.
68  * HASH_CTX
69  *	context structure that at least contains following
70  *	members:
71  *		typedef struct {
72  *			...
73  *			HASH_LONG	Nl,Nh;
74  *			either {
75  *			HASH_LONG	data[HASH_LBLOCK];
76  *			unsigned char	data[HASH_CBLOCK];
77  *			};
78  *			unsigned int	num;
79  *			...
80  *			} HASH_CTX;
81  *	data[] vector is expected to be zeroed upon first call to
82  *	HASH_UPDATE.
83  * HASH_UPDATE
84  *	name of "Update" function, implemented here.
85  * HASH_TRANSFORM
86  *	name of "Transform" function, implemented here.
87  * HASH_FINAL
88  *	name of "Final" function, implemented here.
89  * HASH_BLOCK_DATA_ORDER
90  *	name of "block" function capable of treating *unaligned* input
91  *	message in original (data) byte order, implemented externally.
92  * HASH_MAKE_STRING
93  *	macro convering context variables to an ASCII hash string.
94  *
95  * MD5 example:
96  *
97  *	#define DATA_ORDER_IS_LITTLE_ENDIAN
98  *
99  *	#define HASH_LONG		MD5_LONG
100  *	#define HASH_CTX		MD5_CTX
101  *	#define HASH_CBLOCK		MD5_CBLOCK
102  *	#define HASH_UPDATE		MD5_Update
103  *	#define HASH_TRANSFORM		MD5_Transform
104  *	#define HASH_FINAL		MD5_Final
105  *	#define HASH_BLOCK_DATA_ORDER	md5_block_data_order
106  *
107  *					<appro@fy.chalmers.se>
108  */
109 
110 #include <stdint.h>
111 
112 #include <openssl/opensslconf.h>
113 
114 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
115 #error "DATA_ORDER must be defined!"
116 #endif
117 
118 #ifndef HASH_CBLOCK
119 #error "HASH_CBLOCK must be defined!"
120 #endif
121 #ifndef HASH_LONG
122 #error "HASH_LONG must be defined!"
123 #endif
124 #ifndef HASH_CTX
125 #error "HASH_CTX must be defined!"
126 #endif
127 
128 #ifndef HASH_UPDATE
129 #error "HASH_UPDATE must be defined!"
130 #endif
131 #ifndef HASH_TRANSFORM
132 #error "HASH_TRANSFORM must be defined!"
133 #endif
134 #if !defined(HASH_FINAL) && !defined(HASH_NO_FINAL)
135 #error "HASH_FINAL or HASH_NO_FINAL must be defined!"
136 #endif
137 
138 #ifndef HASH_BLOCK_DATA_ORDER
139 #error "HASH_BLOCK_DATA_ORDER must be defined!"
140 #endif
141 
142 /*
143  * This common idiom is recognized by the compiler and turned into a
144  * CPU-specific intrinsic as appropriate.
145  * e.g. GCC optimizes to roll on amd64 at -O0
146  */
147 static inline uint32_t ROTATE(uint32_t a, uint32_t n)
148 {
149 	return (a<<n)|(a>>(32-n));
150 }
151 
152 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
153 
154 #if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
155 # if ((defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)) || \
156       (defined(__x86_64) || defined(__x86_64__))
157     /*
158      * This gives ~30-40% performance improvement in SHA-256 compiled
159      * with gcc [on P4]. Well, first macro to be frank. We can pull
160      * this trick on x86* platforms only, because these CPUs can fetch
161      * unaligned data without raising an exception.
162      */
163 #  define HOST_c2l(c,l)	({ unsigned int r=*((const unsigned int *)(c));	\
164 				   asm ("bswapl %0":"=r"(r):"0"(r));	\
165 				   (c)+=4; (l)=r;			})
166 #  define HOST_l2c(l,c)	({ unsigned int r=(l);			\
167 				   asm ("bswapl %0":"=r"(r):"0"(r));	\
168 				   *((unsigned int *)(c))=r; (c)+=4;	})
169 # endif
170 #endif
171 #if defined(__s390__) || defined(__s390x__)
172 # define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4)
173 # define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4)
174 #endif
175 
176 #ifndef HOST_c2l
177 #define HOST_c2l(c,l) do {l =(((unsigned long)(*((c)++)))<<24);	\
178 			  l|=(((unsigned long)(*((c)++)))<<16);	\
179 			  l|=(((unsigned long)(*((c)++)))<< 8);	\
180 			  l|=(((unsigned long)(*((c)++)))    );	\
181 		      } while (0)
182 #endif
183 #ifndef HOST_l2c
184 #define HOST_l2c(l,c) do {*((c)++)=(unsigned char)(((l)>>24)&0xff);	\
185 			  *((c)++)=(unsigned char)(((l)>>16)&0xff);	\
186 			  *((c)++)=(unsigned char)(((l)>> 8)&0xff);	\
187 			  *((c)++)=(unsigned char)(((l)    )&0xff);	\
188 		      } while (0)
189 #endif
190 
191 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
192 
193 #if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
194 # if defined(__s390x__)
195 #  define HOST_c2l(c,l)	({ asm ("lrv	%0,%1"			\
196 				   :"=d"(l) :"m"(*(const unsigned int *)(c)));\
197 				   (c)+=4; 				})
198 #  define HOST_l2c(l,c)	({ asm ("strv	%1,%0"			\
199 				   :"=m"(*(unsigned int *)(c)) :"d"(l));\
200 				   (c)+=4; 				})
201 # endif
202 #endif
203 #if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
204 #  define HOST_c2l(c,l)	((l)=*((const unsigned int *)(c)), (c)+=4)
205 #  define HOST_l2c(l,c)	(*((unsigned int *)(c))=(l), (c)+=4)
206 #endif
207 
208 #ifndef HOST_c2l
209 #define HOST_c2l(c,l) do {l =(((unsigned long)(*((c)++)))    );	\
210 			  l|=(((unsigned long)(*((c)++)))<< 8);	\
211 			  l|=(((unsigned long)(*((c)++)))<<16);	\
212 			  l|=(((unsigned long)(*((c)++)))<<24);	\
213 		      } while (0)
214 #endif
215 #ifndef HOST_l2c
216 #define HOST_l2c(l,c) do {*((c)++)=(unsigned char)(((l)    )&0xff);	\
217 			  *((c)++)=(unsigned char)(((l)>> 8)&0xff);	\
218 			  *((c)++)=(unsigned char)(((l)>>16)&0xff);	\
219 			  *((c)++)=(unsigned char)(((l)>>24)&0xff);	\
220 		      } while (0)
221 #endif
222 
223 #endif
224 
225 /*
226  * Time for some action:-)
227  */
228 
229 int
230 HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len)
231 {
232 	const unsigned char *data = data_;
233 	unsigned char *p;
234 	HASH_LONG l;
235 	size_t n;
236 
237 	if (len == 0)
238 		return 1;
239 
240 	l = (c->Nl + (((HASH_LONG)len) << 3))&0xffffffffUL;
241 	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
242 	 * Wei Dai <weidai@eskimo.com> for pointing it out. */
243 	if (l < c->Nl) /* overflow */
244 		c->Nh++;
245 	c->Nh+=(HASH_LONG)(len>>29);	/* might cause compiler warning on 16-bit */
246 	c->Nl = l;
247 
248 	n = c->num;
249 	if (n != 0) {
250 		p = (unsigned char *)c->data;
251 
252 		if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) {
253 			memcpy (p + n, data, HASH_CBLOCK - n);
254 			HASH_BLOCK_DATA_ORDER (c, p, 1);
255 			n = HASH_CBLOCK - n;
256 			data += n;
257 			len -= n;
258 			c->num = 0;
259 			memset (p,0,HASH_CBLOCK);	/* keep it zeroed */
260 		} else {
261 			memcpy (p + n, data, len);
262 			c->num += (unsigned int)len;
263 			return 1;
264 		}
265 	}
266 
267 	n = len/HASH_CBLOCK;
268 	if (n > 0) {
269 		HASH_BLOCK_DATA_ORDER (c, data, n);
270 		n    *= HASH_CBLOCK;
271 		data += n;
272 		len -= n;
273 	}
274 
275 	if (len != 0) {
276 		p = (unsigned char *)c->data;
277 		c->num = (unsigned int)len;
278 		memcpy (p, data, len);
279 	}
280 	return 1;
281 }
282 
283 
284 void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
285 {
286 	HASH_BLOCK_DATA_ORDER (c, data, 1);
287 }
288 
289 
290 #ifndef HASH_NO_FINAL
291 int HASH_FINAL (unsigned char *md, HASH_CTX *c)
292 {
293 	unsigned char *p = (unsigned char *)c->data;
294 	size_t n = c->num;
295 
296 	p[n] = 0x80; /* there is always room for one */
297 	n++;
298 
299 	if (n > (HASH_CBLOCK - 8)) {
300 		memset (p + n, 0, HASH_CBLOCK - n);
301 		n = 0;
302 		HASH_BLOCK_DATA_ORDER (c, p, 1);
303 	}
304 	memset (p + n, 0, HASH_CBLOCK - 8 - n);
305 
306 	p += HASH_CBLOCK - 8;
307 #if   defined(DATA_ORDER_IS_BIG_ENDIAN)
308 	HOST_l2c(c->Nh, p);
309 	HOST_l2c(c->Nl, p);
310 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
311 	HOST_l2c(c->Nl, p);
312 	HOST_l2c(c->Nh, p);
313 #endif
314 	p -= HASH_CBLOCK;
315 	HASH_BLOCK_DATA_ORDER (c, p, 1);
316 	c->num = 0;
317 	memset (p, 0, HASH_CBLOCK);
318 
319 #ifndef HASH_MAKE_STRING
320 #error "HASH_MAKE_STRING must be defined!"
321 #else
322 	HASH_MAKE_STRING(c, md);
323 #endif
324 
325 	return 1;
326 }
327 #endif
328 
329 #ifndef MD32_REG_T
330 #if defined(__alpha) || defined(__sparcv9) || defined(__mips)
331 #define MD32_REG_T long
332 /*
333  * This comment was originaly written for MD5, which is why it
334  * discusses A-D. But it basically applies to all 32-bit digests,
335  * which is why it was moved to common header file.
336  *
337  * In case you wonder why A-D are declared as long and not
338  * as MD5_LONG. Doing so results in slight performance
339  * boost on LP64 architectures. The catch is we don't
340  * really care if 32 MSBs of a 64-bit register get polluted
341  * with eventual overflows as we *save* only 32 LSBs in
342  * *either* case. Now declaring 'em long excuses the compiler
343  * from keeping 32 MSBs zeroed resulting in 13% performance
344  * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
345  * Well, to be honest it should say that this *prevents*
346  * performance degradation.
347  *				<appro@fy.chalmers.se>
348  */
349 #else
350 /*
351  * Above is not absolute and there are LP64 compilers that
352  * generate better code if MD32_REG_T is defined int. The above
353  * pre-processor condition reflects the circumstances under which
354  * the conclusion was made and is subject to further extension.
355  *				<appro@fy.chalmers.se>
356  */
357 #define MD32_REG_T int
358 #endif
359 #endif
360