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