summaryrefslogtreecommitdiff
path: root/xmss_hash.c
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2018-02-23 15:58:37 +0000
committerDamien Miller <djm@mindrot.org>2018-02-26 11:40:41 +1100
commit1b11ea7c58cd5c59838b5fa574cd456d6047b2d4 (patch)
tree7e96cb41b5234b9d327f7c8f41392f09aed0994e /xmss_hash.c
parent7d330a1ac02076de98cfc8fda05353d57b603755 (diff)
upstream: Add experimental support for PQC XMSS keys (Extended
Hash-Based Signatures) The code is not compiled in by default (see WITH_XMSS in Makefile.inc) Joint work with stefan-lukas_gazdag at genua.eu See https://tools.ietf.org/html/draft-irtf-cfrg-xmss-hash-based-signatures-12 ok djm@ OpenBSD-Commit-ID: ef3eccb96762a5d6f135d7daeef608df7776a7ac
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}