1 /*
2 * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (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 * Derived from include/crypto/md32_common.h
12 *
13 * HASH_UPDATE and HASH_FINAL have been updated to work with the
14 * auth_hash interface.
15 */
16
17 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
18
19 # define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
20 l|=(((unsigned long)(*((c)++)))<<16), \
21 l|=(((unsigned long)(*((c)++)))<< 8), \
22 l|=(((unsigned long)(*((c)++))) ) )
23 # define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
24 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
25 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
26 *((c)++)=(unsigned char)(((l) )&0xff), \
27 l)
28
29 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
30
31 # define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
32 l|=(((unsigned long)(*((c)++)))<< 8), \
33 l|=(((unsigned long)(*((c)++)))<<16), \
34 l|=(((unsigned long)(*((c)++)))<<24) )
35 # define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
36 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
37 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
38 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
39 l)
40
41 #endif
42
43 /*
44 * Time for some action :-)
45 */
46
47 static int
HASH_UPDATE(void * c_,const void * data_,unsigned int len)48 HASH_UPDATE(void *c_, const void *data_, unsigned int len)
49 {
50 HASH_CTX *c = c_;
51 const unsigned char *data = data_;
52 unsigned char *p;
53 HASH_LONG l;
54 size_t n;
55
56 if (len == 0)
57 return 0;
58
59 l = (c->Nl + (((HASH_LONG) len) << 3)) & 0xffffffffUL;
60 if (l < c->Nl) /* overflow */
61 c->Nh++;
62 c->Nh += (HASH_LONG) (len >> 29); /* might cause compiler warning on
63 * 16-bit */
64 c->Nl = l;
65
66 n = c->num;
67 if (n != 0) {
68 p = (unsigned char *)c->data;
69
70 if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) {
71 memcpy(p + n, data, HASH_CBLOCK - n);
72 HASH_BLOCK_DATA_ORDER(c, p, 1);
73 n = HASH_CBLOCK - n;
74 data += n;
75 len -= n;
76 c->num = 0;
77 /*
78 * We use memset rather than OPENSSL_cleanse() here deliberately.
79 * Using OPENSSL_cleanse() here could be a performance issue. It
80 * will get properly cleansed on finalisation so this isn't a
81 * security problem.
82 */
83 memset(p, 0, HASH_CBLOCK); /* keep it zeroed */
84 } else {
85 memcpy(p + n, data, len);
86 c->num += (unsigned int)len;
87 return 0;
88 }
89 }
90
91 n = len / HASH_CBLOCK;
92 if (n > 0) {
93 HASH_BLOCK_DATA_ORDER(c, data, n);
94 n *= HASH_CBLOCK;
95 data += n;
96 len -= n;
97 }
98
99 if (len != 0) {
100 p = (unsigned char *)c->data;
101 c->num = (unsigned int)len;
102 memcpy(p, data, len);
103 }
104 return 0;
105 }
106
107 static void
HASH_FINAL(uint8_t * md,void * c_)108 HASH_FINAL(uint8_t *md, void *c_)
109 {
110 HASH_CTX *c = c_;
111 unsigned char *p = (unsigned char *)c->data;
112 size_t n = c->num;
113
114 p[n] = 0x80; /* there is always room for one */
115 n++;
116
117 if (n > (HASH_CBLOCK - 8)) {
118 memset(p + n, 0, HASH_CBLOCK - n);
119 n = 0;
120 HASH_BLOCK_DATA_ORDER(c, p, 1);
121 }
122 memset(p + n, 0, HASH_CBLOCK - 8 - n);
123
124 p += HASH_CBLOCK - 8;
125 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
126 (void)HOST_l2c(c->Nh, p);
127 (void)HOST_l2c(c->Nl, p);
128 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
129 (void)HOST_l2c(c->Nl, p);
130 (void)HOST_l2c(c->Nh, p);
131 #endif
132 p -= HASH_CBLOCK;
133 HASH_BLOCK_DATA_ORDER(c, p, 1);
134 c->num = 0;
135 OPENSSL_cleanse(p, HASH_CBLOCK);
136
137 #ifndef HASH_MAKE_STRING
138 # error "HASH_MAKE_STRING must be defined!"
139 #else
140 HASH_MAKE_STRING(c, md);
141 #endif
142
143 return;
144 }
145