/src/blst_normal/src/hash_to_field.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright Supranational LLC |
3 | | * Licensed under the Apache License, Version 2.0, see LICENSE for details. |
4 | | * SPDX-License-Identifier: Apache-2.0 |
5 | | */ |
6 | | |
7 | | #include "consts.h" |
8 | | #include "sha256.h" |
9 | | |
10 | | static const vec384 BLS12_381_RRRR = { /* RR^2 */ |
11 | | TO_LIMB_T(0xed48ac6bd94ca1e0), TO_LIMB_T(0x315f831e03a7adf8), |
12 | | TO_LIMB_T(0x9a53352a615e29dd), TO_LIMB_T(0x34c04e5e921e1761), |
13 | | TO_LIMB_T(0x2512d43565724728), TO_LIMB_T(0x0aa6346091755d4d) |
14 | | }; |
15 | | |
16 | | #ifdef expand_message_xmd |
17 | | void expand_message_xmd(unsigned char *bytes, size_t len_in_bytes, |
18 | | const unsigned char *aug, size_t aug_len, |
19 | | const unsigned char *msg, size_t msg_len, |
20 | | const unsigned char *DST, size_t DST_len); |
21 | | #else |
22 | | static void sha256_init_Zpad(SHA256_CTX *ctx) |
23 | 2.34k | { |
24 | 2.34k | ctx->h[0] = 0xda5698beU; |
25 | 2.34k | ctx->h[1] = 0x17b9b469U; |
26 | 2.34k | ctx->h[2] = 0x62335799U; |
27 | 2.34k | ctx->h[3] = 0x779fbecaU; |
28 | 2.34k | ctx->h[4] = 0x8ce5d491U; |
29 | 2.34k | ctx->h[5] = 0xc0d26243U; |
30 | 2.34k | ctx->h[6] = 0xbafef9eaU; |
31 | 2.34k | ctx->h[7] = 0x1837a9d8U; |
32 | 2.34k | ctx->N = 64; |
33 | 2.34k | vec_zero(ctx->buf, sizeof(ctx->buf)); |
34 | 2.34k | ctx->off = 0; |
35 | 2.34k | } |
36 | | |
37 | | static void vec_xor(void *restrict ret, const void *restrict a, |
38 | | const void *restrict b, size_t num) |
39 | 15.6k | { |
40 | 15.6k | limb_t *rp = (limb_t *)ret; |
41 | 15.6k | const limb_t *ap = (const limb_t *)a; |
42 | 15.6k | const limb_t *bp = (const limb_t *)b; |
43 | 15.6k | size_t i; |
44 | | |
45 | 15.6k | num /= sizeof(limb_t); |
46 | | |
47 | 78.3k | for (i = 0; i < num; i++) |
48 | 62.7k | rp[i] = ap[i] ^ bp[i]; |
49 | 15.6k | } |
50 | | |
51 | | static void expand_message_xmd(unsigned char *bytes, size_t len_in_bytes, |
52 | | const unsigned char *aug, size_t aug_len, |
53 | | const unsigned char *msg, size_t msg_len, |
54 | | const unsigned char *DST, size_t DST_len) |
55 | 2.34k | { |
56 | 2.34k | union { limb_t align; unsigned char c[32]; } b_0; |
57 | 2.34k | union { limb_t align; unsigned char c[33+256+31]; } b_i; |
58 | 2.34k | unsigned char *p; |
59 | 2.34k | size_t i, b_i_bits, b_i_blocks; |
60 | 2.34k | SHA256_CTX ctx; |
61 | | |
62 | | /* |
63 | | * compose template for 'strxor(b_0, b_(i-1)) || I2OSP(i, 1) || DST_prime' |
64 | | */ |
65 | 2.34k | if (DST_len > 255) { |
66 | 173 | sha256_init(&ctx); |
67 | 173 | sha256_update(&ctx, "H2C-OVERSIZE-DST-", 17); |
68 | 173 | sha256_update(&ctx, DST, DST_len); |
69 | 173 | sha256_final(b_0.c, &ctx); |
70 | 173 | DST = b_0.c, DST_len = 32; |
71 | 173 | } |
72 | 2.34k | b_i_blocks = ((33 + DST_len + 1 + 9) + 63) & -64; |
73 | 2.34k | vec_zero(b_i.c + b_i_blocks - 64, 64); |
74 | | |
75 | 2.34k | p = b_i.c + 33; |
76 | 48.3k | for (i = 0; i < DST_len; i++) |
77 | 45.9k | p[i] = DST[i]; |
78 | 2.34k | p[i++] = (unsigned char)DST_len; |
79 | 2.34k | p[i++] = 0x80; |
80 | 2.34k | p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = 0; |
81 | 2.34k | b_i_bits = (33 + DST_len + 1) * 8; |
82 | 2.34k | p = b_i.c + b_i_blocks; |
83 | 2.34k | p[-2] = (unsigned char)(b_i_bits >> 8); |
84 | 2.34k | p[-1] = (unsigned char)(b_i_bits); |
85 | | |
86 | 2.34k | sha256_init_Zpad(&ctx); /* Z_pad | */ |
87 | 2.34k | sha256_update(&ctx, aug, aug_len); /* | aug | */ |
88 | 2.34k | sha256_update(&ctx, msg, msg_len); /* | msg | */ |
89 | | /* | I2OSP(len_in_bytes, 2) || I2OSP(0, 1) || DST_prime */ |
90 | 2.34k | b_i.c[30] = (unsigned char)(len_in_bytes >> 8); |
91 | 2.34k | b_i.c[31] = (unsigned char)(len_in_bytes); |
92 | 2.34k | b_i.c[32] = 0; |
93 | 2.34k | sha256_update(&ctx, b_i.c + 30, 3 + DST_len + 1); |
94 | 2.34k | sha256_final(b_0.c, &ctx); |
95 | | |
96 | 2.34k | sha256_init_h(ctx.h); |
97 | 2.34k | vec_copy(b_i.c, b_0.c, 32); |
98 | 2.34k | ++b_i.c[32]; |
99 | 2.34k | sha256_block_data_order(ctx.h, b_i.c, b_i_blocks / 64); |
100 | 2.34k | sha256_emit(bytes, ctx.h); |
101 | | |
102 | 2.34k | len_in_bytes += 31; /* ell = ceil(len_in_bytes / b_in_bytes), with */ |
103 | 2.34k | len_in_bytes /= 32; /* caller being responsible for accordingly large |
104 | | * buffer. hash_to_field passes one with length |
105 | | * divisible by 64, remember? which works... */ |
106 | 18.0k | while (--len_in_bytes) { |
107 | 15.6k | sha256_init_h(ctx.h); |
108 | 15.6k | vec_xor(b_i.c, b_0.c, bytes, 32); |
109 | 15.6k | bytes += 32; |
110 | 15.6k | ++b_i.c[32]; |
111 | 15.6k | sha256_block_data_order(ctx.h, b_i.c, b_i_blocks / 64); |
112 | 15.6k | sha256_emit(bytes, ctx.h); |
113 | 15.6k | } |
114 | 2.34k | } |
115 | | #endif |
116 | | |
117 | | /* |
118 | | * |nelems| is 'count * m' from spec |
119 | | */ |
120 | | static void hash_to_field(vec384 elems[], size_t nelems, |
121 | | const unsigned char *aug, size_t aug_len, |
122 | | const unsigned char *msg, size_t msg_len, |
123 | | const unsigned char *DST, size_t DST_len) |
124 | 2.34k | { |
125 | 2.34k | size_t L = sizeof(vec384) + 128/8; /* ceil((ceil(log2(p)) + k) / 8) */ |
126 | 2.34k | size_t len_in_bytes = L * nelems; /* divisible by 64, hurray! */ |
127 | | #if !defined(__STDC_VERSION__) || __STDC_VERSION__<199901 \ |
128 | | || defined(__STDC_NO_VLA__) |
129 | | limb_t *pseudo_random = alloca(len_in_bytes); |
130 | | #else |
131 | 2.34k | limb_t pseudo_random[len_in_bytes/sizeof(limb_t)]; |
132 | 2.34k | #endif |
133 | 2.34k | unsigned char *bytes; |
134 | 2.34k | vec768 elem; |
135 | | |
136 | 2.34k | aug_len = aug!=NULL ? aug_len : 0; |
137 | 2.34k | DST_len = DST!=NULL ? DST_len : 0; |
138 | | |
139 | 2.34k | expand_message_xmd((unsigned char *)pseudo_random, len_in_bytes, |
140 | 2.34k | aug, aug_len, msg, msg_len, DST, DST_len); |
141 | | |
142 | 2.34k | vec_zero(elem, sizeof(elem)); |
143 | 2.34k | bytes = (unsigned char *)pseudo_random; |
144 | 11.3k | while (nelems--) { |
145 | 9.01k | limbs_from_be_bytes(elem, bytes, L); |
146 | 9.01k | bytes += L; |
147 | | /* |
148 | | * L-bytes block % P, output is in Montgomery domain... |
149 | | */ |
150 | 9.01k | redc_mont_384(elems[0], elem, BLS12_381_P, p0); |
151 | 9.01k | mul_mont_384(elems[0], elems[0], BLS12_381_RRRR, BLS12_381_P, p0); |
152 | 9.01k | elems++; |
153 | 9.01k | } |
154 | 2.34k | } |
155 | | |
156 | | void blst_expand_message_xmd(unsigned char *bytes, size_t len_in_bytes, |
157 | | const unsigned char *msg, size_t msg_len, |
158 | | const unsigned char *DST, size_t DST_len) |
159 | 0 | { |
160 | 0 | size_t buf_len = (len_in_bytes+31) & ((size_t)0-32); |
161 | 0 | unsigned char *buf_ptr = bytes; |
162 | |
|
163 | 0 | if (buf_len > 255*32) |
164 | 0 | return; |
165 | | |
166 | 0 | if (buf_len != len_in_bytes) |
167 | 0 | buf_ptr = alloca(buf_len); |
168 | |
|
169 | 0 | expand_message_xmd(buf_ptr, len_in_bytes, NULL, 0, msg, msg_len, |
170 | 0 | DST, DST_len); |
171 | 0 | if (buf_ptr != bytes) { |
172 | 0 | unsigned char *ptr = buf_ptr; |
173 | 0 | while (len_in_bytes--) |
174 | 0 | *bytes++ = *ptr++; |
175 | 0 | vec_zero(buf_ptr, buf_len); |
176 | 0 | } |
177 | 0 | } |