1 /* ==================================================================== 2 * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * 3. All advertising materials mentioning features or use of this 17 * software must display the following acknowledgment: 18 * "This product includes software developed by the OpenSSL Project 19 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 20 * 21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22 * endorse or promote products derived from this software without 23 * prior written permission. For written permission, please contact 24 * licensing (at) OpenSSL.org. 25 * 26 * 5. Products derived from this software may not be called "OpenSSL" 27 * nor may "OpenSSL" appear in their names without prior written 28 * permission of the OpenSSL Project. 29 * 30 * 6. Redistributions of any form whatsoever must retain the following 31 * acknowledgment: 32 * "This product includes software developed by the OpenSSL Project 33 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46 * OF THE POSSIBILITY OF SUCH DAMAGE. 47 * ==================================================================== */ 48 49 #ifndef OPENSSL_HEADER_MD32_COMMON_H 50 #define OPENSSL_HEADER_MD32_COMMON_H 51 52 #include <openssl/base.h> 53 54 #include <assert.h> 55 56 #if defined(__cplusplus) 57 extern "C" { 58 #endif 59 60 61 /* This is a generic 32-bit "collector" for message digest algorithms. It 62 * collects input character stream into chunks of 32-bit values and invokes the 63 * block function that performs the actual hash calculations. To make use of 64 * this mechanism, the following macros must be defined before including 65 * md32_common.h. 66 * 67 * One of |DATA_ORDER_IS_BIG_ENDIAN| or |DATA_ORDER_IS_LITTLE_ENDIAN| must be 68 * defined to specify the byte order of the input stream. 69 * 70 * |HASH_CBLOCK| must be defined as the integer block size, in bytes. 71 * 72 * |HASH_CTX| must be defined as the name of the context structure, which must 73 * have at least the following members: 74 * 75 * typedef struct <name>_state_st { 76 * uint32_t h[<chaining length> / sizeof(uint32_t)]; 77 * uint32_t Nl, Nh; 78 * uint8_t data[HASH_CBLOCK]; 79 * unsigned num; 80 * ... 81 * } <NAME>_CTX; 82 * 83 * <chaining length> is the output length of the hash in bytes, before 84 * any truncation (e.g. 64 for SHA-224 and SHA-256, 128 for SHA-384 and 85 * SHA-512). 86 * 87 * |HASH_UPDATE| must be defined as the name of the "Update" function to 88 * generate. 89 * 90 * |HASH_TRANSFORM| must be defined as the the name of the "Transform" 91 * function to generate. 92 * 93 * |HASH_FINAL| must be defined as the name of "Final" function to generate. 94 * 95 * |HASH_BLOCK_DATA_ORDER| must be defined as the name of the "Block" function. 96 * That function must be implemented manually. It must be capable of operating 97 * on *unaligned* input data in its original (data) byte order. It must have 98 * this signature: 99 * 100 * void HASH_BLOCK_DATA_ORDER(uint32_t *state, const uint8_t *data, 101 * size_t num); 102 * 103 * It must update the hash state |state| with |num| blocks of data from |data|, 104 * where each block is |HASH_CBLOCK| bytes; i.e. |data| points to a array of 105 * |HASH_CBLOCK * num| bytes. |state| points to the |h| member of a |HASH_CTX|, 106 * and so will have |<chaining length> / sizeof(uint32_t)| elements. 107 * 108 * |HASH_MAKE_STRING(c, s)| must be defined as a block statement that converts 109 * the hash state |c->h| into the output byte order, storing the result in |s|. 110 */ 111 112 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) 113 #error "DATA_ORDER must be defined!" 114 #endif 115 116 #ifndef HASH_CBLOCK 117 #error "HASH_CBLOCK must be defined!" 118 #endif 119 #ifndef HASH_CTX 120 #error "HASH_CTX must be defined!" 121 #endif 122 123 #ifndef HASH_UPDATE 124 #error "HASH_UPDATE must be defined!" 125 #endif 126 #ifndef HASH_TRANSFORM 127 #error "HASH_TRANSFORM must be defined!" 128 #endif 129 #ifndef HASH_FINAL 130 #error "HASH_FINAL must be defined!" 131 #endif 132 133 #ifndef HASH_BLOCK_DATA_ORDER 134 #error "HASH_BLOCK_DATA_ORDER must be defined!" 135 #endif 136 137 #ifndef HASH_MAKE_STRING 138 #error "HASH_MAKE_STRING must be defined!" 139 #endif 140 141 #if defined(DATA_ORDER_IS_BIG_ENDIAN) 142 143 #if !defined(PEDANTIC) && defined(__GNUC__) && __GNUC__ >= 2 && \ 144 !defined(OPENSSL_NO_ASM) 145 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) 146 /* The first macro gives a ~30-40% performance improvement in SHA-256 compiled 147 * with gcc on P4. This can only be done on x86, where unaligned data fetches 148 * are possible. */ 149 #define HOST_c2l(c, l) \ 150 (void)({ \ 151 uint32_t r = *((const uint32_t *)(c)); \ 152 __asm__("bswapl %0" : "=r"(r) : "0"(r)); \ 153 (c) += 4; \ 154 (l) = r; \ 155 }) 156 #define HOST_l2c(l, c) \ 157 (void)({ \ 158 uint32_t r = (l); \ 159 __asm__("bswapl %0" : "=r"(r) : "0"(r)); \ 160 *((uint32_t *)(c)) = r; \ 161 (c) += 4; \ 162 r; \ 163 }) 164 #elif defined(__aarch64__) && defined(__BYTE_ORDER__) 165 #if defined(__ORDER_LITTLE_ENDIAN__) && \ 166 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 167 #define HOST_c2l(c, l) \ 168 (void)({ \ 169 uint32_t r; \ 170 __asm__("rev %w0, %w1" : "=r"(r) : "r"(*((const uint32_t *)(c)))); \ 171 (c) += 4; \ 172 (l) = r; \ 173 }) 174 #define HOST_l2c(l, c) \ 175 (void)({ \ 176 uint32_t r; \ 177 __asm__("rev %w0, %w1" : "=r"(r) : "r"((uint32_t)(l))); \ 178 *((uint32_t *)(c)) = r; \ 179 (c) += 4; \ 180 r; \ 181 }) 182 #elif defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 183 #define HOST_c2l(c, l) (void)((l) = *((const uint32_t *)(c)), (c) += 4) 184 #define HOST_l2c(l, c) (*((uint32_t *)(c)) = (l), (c) += 4, (l)) 185 #endif /* __aarch64__ && __BYTE_ORDER__ */ 186 #endif /* ARCH */ 187 #endif /* !PEDANTIC && GNUC && !NO_ASM */ 188 189 #ifndef HOST_c2l 190 #define HOST_c2l(c, l) \ 191 (void)(l = (((uint32_t)(*((c)++))) << 24), \ 192 l |= (((uint32_t)(*((c)++))) << 16), \ 193 l |= (((uint32_t)(*((c)++))) << 8), l |= (((uint32_t)(*((c)++))))) 194 #endif 195 196 #ifndef HOST_l2c 197 #define HOST_l2c(l, c) \ 198 (void)(*((c)++) = (uint8_t)(((l) >> 24) & 0xff), \ 199 *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ 200 *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ 201 *((c)++) = (uint8_t)(((l)) & 0xff)) 202 #endif 203 204 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) 205 206 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) 207 /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */ 208 #define HOST_c2l(c, l) (void)((l) = *((const uint32_t *)(c)), (c) += 4) 209 #define HOST_l2c(l, c) (void)(*((uint32_t *)(c)) = (l), (c) += 4, l) 210 #endif /* OPENSSL_X86 || OPENSSL_X86_64 */ 211 212 #ifndef HOST_c2l 213 #define HOST_c2l(c, l) \ 214 (void)(l = (((uint32_t)(*((c)++)))), l |= (((uint32_t)(*((c)++))) << 8), \ 215 l |= (((uint32_t)(*((c)++))) << 16), \ 216 l |= (((uint32_t)(*((c)++))) << 24)) 217 #endif 218 219 #ifndef HOST_l2c 220 #define HOST_l2c(l, c) \ 221 (void)(*((c)++) = (uint8_t)(((l)) & 0xff), \ 222 *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ 223 *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ 224 *((c)++) = (uint8_t)(((l) >> 24) & 0xff)) 225 #endif 226 227 #endif /* DATA_ORDER */ 228 229 int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) { 230 const uint8_t *data = data_; 231 232 if (len == 0) { 233 return 1; 234 } 235 236 uint32_t l = c->Nl + (((uint32_t)len) << 3); 237 if (l < c->Nl) { 238 /* Handle carries. */ 239 c->Nh++; 240 } 241 c->Nh += (uint32_t)(len >> 29); 242 c->Nl = l; 243 244 size_t n = c->num; 245 if (n != 0) { 246 if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) { 247 memcpy(c->data + n, data, HASH_CBLOCK - n); 248 HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); 249 n = HASH_CBLOCK - n; 250 data += n; 251 len -= n; 252 c->num = 0; 253 /* Keep |c->data| zeroed when unused. */ 254 memset(c->data, 0, HASH_CBLOCK); 255 } else { 256 memcpy(c->data + n, data, len); 257 c->num += (unsigned)len; 258 return 1; 259 } 260 } 261 262 n = len / HASH_CBLOCK; 263 if (n > 0) { 264 HASH_BLOCK_DATA_ORDER(c->h, data, n); 265 n *= HASH_CBLOCK; 266 data += n; 267 len -= n; 268 } 269 270 if (len != 0) { 271 c->num = (unsigned)len; 272 memcpy(c->data, data, len); 273 } 274 return 1; 275 } 276 277 278 void HASH_TRANSFORM(HASH_CTX *c, const uint8_t *data) { 279 HASH_BLOCK_DATA_ORDER(c->h, data, 1); 280 } 281 282 283 int HASH_FINAL(uint8_t *md, HASH_CTX *c) { 284 /* |c->data| always has room for at least one byte. A full block would have 285 * been consumed. */ 286 size_t n = c->num; 287 assert(n < HASH_CBLOCK); 288 c->data[n] = 0x80; 289 n++; 290 291 /* Fill the block with zeros if there isn't room for a 64-bit length. */ 292 if (n > (HASH_CBLOCK - 8)) { 293 memset(c->data + n, 0, HASH_CBLOCK - n); 294 n = 0; 295 HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); 296 } 297 memset(c->data + n, 0, HASH_CBLOCK - 8 - n); 298 299 /* Append a 64-bit length to the block and process it. */ 300 uint8_t *p = c->data + HASH_CBLOCK - 8; 301 #if defined(DATA_ORDER_IS_BIG_ENDIAN) 302 HOST_l2c(c->Nh, p); 303 HOST_l2c(c->Nl, p); 304 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) 305 HOST_l2c(c->Nl, p); 306 HOST_l2c(c->Nh, p); 307 #endif 308 assert(p == c->data + HASH_CBLOCK); 309 HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); 310 c->num = 0; 311 memset(c->data, 0, HASH_CBLOCK); 312 313 HASH_MAKE_STRING(c, md); 314 return 1; 315 } 316 317 318 #if defined(__cplusplus) 319 } /* extern C */ 320 #endif 321 322 #endif /* OPENSSL_HEADER_MD32_COMMON_H */ 323