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