Coverage Report

Created: 2023-12-08 07:00

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