1 /* $OpenBSD: xmss_hash.c,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */ 2 /* 3 hash.c version 20160722 4 Andreas Hülsing 5 Joost Rijneveld 6 Public domain. 7 */ 8 9 #include "xmss_hash_address.h" 10 #include "xmss_commons.h" 11 #include "xmss_hash.h" 12 13 #include <stddef.h> 14 #include <stdint.h> 15 #include <stdio.h> 16 #include <string.h> 17 #include <openssl/sha.h> 18 #include <openssl/hmac.h> 19 #include <openssl/evp.h> 20 21 int core_hash_SHA2(unsigned char *, const unsigned int, const unsigned char *, 22 unsigned int, const unsigned char *, unsigned long long, unsigned int); 23 24 unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]){ 25 #if IS_LITTLE_ENDIAN==1 26 int i = 0; 27 for(i=0;i<8;i++) 28 to_byte(bytes+i*4, addr[i],4); 29 return bytes; 30 #else 31 memcpy(bytes, addr, 32); 32 return bytes; 33 #endif 34 } 35 36 int core_hash_SHA2(unsigned char *out, const unsigned int type, const unsigned char *key, unsigned int keylen, const unsigned char *in, unsigned long long inlen, unsigned int n){ 37 unsigned long long i = 0; 38 unsigned char buf[inlen + n + keylen]; 39 40 // Input is (toByte(X, 32) || KEY || M) 41 42 // set toByte 43 to_byte(buf, type, n); 44 45 for (i=0; i < keylen; i++) { 46 buf[i+n] = key[i]; 47 } 48 49 for (i=0; i < inlen; i++) { 50 buf[keylen + n + i] = in[i]; 51 } 52 53 if (n == 32) { 54 SHA256(buf, inlen + keylen + n, out); 55 return 0; 56 } 57 else { 58 if (n == 64) { 59 SHA512(buf, inlen + keylen + n, out); 60 return 0; 61 } 62 } 63 return 1; 64 } 65 66 /** 67 * Implements PRF 68 */ 69 int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen) 70 { 71 return core_hash_SHA2(out, 3, key, keylen, in, 32, keylen); 72 } 73 74 /* 75 * Implemts H_msg 76 */ 77 int h_msg(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int n) 78 { 79 if (keylen != 3*n){ 80 // H_msg takes 3n-bit keys, but n does not match the keylength of keylen 81 return -1; 82 } 83 return core_hash_SHA2(out, 2, key, keylen, in, inlen, n); 84 } 85 86 /** 87 * We assume the left half is in in[0]...in[n-1] 88 */ 89 int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n) 90 { 91 92 unsigned char buf[2*n]; 93 unsigned char key[n]; 94 unsigned char bitmask[2*n]; 95 unsigned char byte_addr[32]; 96 unsigned int i; 97 98 setKeyAndMask(addr, 0); 99 addr_to_byte(byte_addr, addr); 100 prf(key, byte_addr, pub_seed, n); 101 // Use MSB order 102 setKeyAndMask(addr, 1); 103 addr_to_byte(byte_addr, addr); 104 prf(bitmask, byte_addr, pub_seed, n); 105 setKeyAndMask(addr, 2); 106 addr_to_byte(byte_addr, addr); 107 prf(bitmask+n, byte_addr, pub_seed, n); 108 for (i = 0; i < 2*n; i++) { 109 buf[i] = in[i] ^ bitmask[i]; 110 } 111 return core_hash_SHA2(out, 1, key, n, buf, 2*n, n); 112 } 113 114 int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n) 115 { 116 unsigned char buf[n]; 117 unsigned char key[n]; 118 unsigned char bitmask[n]; 119 unsigned char byte_addr[32]; 120 unsigned int i; 121 122 setKeyAndMask(addr, 0); 123 addr_to_byte(byte_addr, addr); 124 prf(key, byte_addr, pub_seed, n); 125 126 setKeyAndMask(addr, 1); 127 addr_to_byte(byte_addr, addr); 128 prf(bitmask, byte_addr, pub_seed, n); 129 130 for (i = 0; i < n; i++) { 131 buf[i] = in[i] ^ bitmask[i]; 132 } 133 return core_hash_SHA2(out, 0, key, n, buf, n, n); 134 } 135