xref: /freebsd/sys/crypto/openssl/ossl_hash.h (revision 2e3f49888ec8851bafb22011533217487764fdb0)
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
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
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