1/* $OpenBSD: xmss_hash.c,v 1.4 2023/12/20 00:06:25 jsg Exp $ */ 2/* 3hash.c version 20160722 4Andreas H��lsing 5Joost Rijneveld 6Public 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 23int core_hash_SHA2(unsigned char *, const unsigned int, const unsigned char *, 24 unsigned int, const unsigned char *, unsigned long long, unsigned int); 25 26unsigned 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 38int 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 */ 71int 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 */ 79int 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 */ 91int 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 116int 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