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