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