/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  | }  |