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