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