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