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