aboutsummaryrefslogtreecommitdiffstats
path: root/include/mcl/op.hpp
blob: 549d93b79d0d368fc38d60bb50d5cc1134d6e3c2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
#pragma once
/**
    @file
    @brief definition of Op
    @author MITSUNARI Shigeo(@herumi)
    @license modified new BSD license
    http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/gmp_util.hpp>
#include <memory.h>
#include <mcl/array.hpp>

#ifndef MCL_MAX_BIT_SIZE
    #define MCL_MAX_BIT_SIZE 521
#endif
#if defined(__EMSCRIPTEN__) || defined(__wasm__)
    #define MCL_DONT_USE_XBYAK
    #define MCL_DONT_USE_OPENSSL
#endif
#if !defined(MCL_DONT_USE_XBYAK) && (defined(_WIN64) || defined(__x86_64__)) && (MCL_SIZEOF_UNIT == 8)
    #define MCL_USE_XBYAK
    #define MCL_XBYAK_DIRECT_CALL
#endif

#define MCL_MAX_HASH_BIT_SIZE 512

namespace mcl {

static const int version = 0x091; /* 0xABC = A.BC */

/*
    specifies available string format mode for X::setIoMode()
    // for Fp, Fp2, Fp6, Fp12
    default(0) : IoDec
    printable string(zero terminated, variable size)
    IoBin(2) | IoDec(10) | IoHex(16) | IoBinPrefix | IoHexPrefix

    byte string(not zero terminated, fixed size)
    IoArray | IoArrayRaw
    IoArray = IoSerialize

    // for Ec
    affine(0) | IoEcCompY | IoComp
    default : affine

    affine and IoEcCompY are available with ioMode for Fp
    IoSerialize ignores ioMode for Fp

    IoAuto
        dec or hex according to ios_base::fmtflags
    IoBin
        binary number([01]+)
    IoDec
        decimal number
    IoHex
        hexadecimal number([0-9a-fA-F]+)
    IoBinPrefix
        0b + <binary number>
    IoHexPrefix
        0x + <hexadecimal number>
    IoArray
        array of Unit(fixed size = Fp::getByteSize())
    IoArrayRaw
        array of Unit(fixed size = Fp::getByteSize()) without Montgomery conversion

    // for Ec::setIoMode()
    IoEcAffine(default)
    "0" ; infinity
    "1 <x> <y>" ; affine coordinate

    IoEcProj
    "4" <x> <y> <z> ; projective or jacobi coordinate

    IoEcCompY
        1-bit y prepresentation of elliptic curve
        "2 <x>" ; compressed for even y
        "3 <x>" ; compressed for odd y

    IoSerialize
        if isMSBserialize(): // p is not full bit
            size = Fp::getByteSize()
            use MSB of array of x for 1-bit y for prime p where (p % 8 != 0)
            [0] ; infinity
            <x> ; for even y
            <x>|1 ; for odd y ; |1 means set MSB of x
        else:
            size = Fp::getByteSize() + 1
            [0] ; infinity
            2 <x> ; for even y
            3 <x> ; for odd y
*/
enum IoMode {
    IoAuto = 0, // dec or hex according to ios_base::fmtflags
    IoBin = 2, // binary number without prefix
    IoDec = 10, // decimal number without prefix
    IoHex = 16, // hexadecimal number without prefix
    IoArray = 32, // array of Unit(fixed size)
    IoArrayRaw = 64, // raw array of Unit without Montgomery conversion
    IoPrefix = 128, // append '0b'(bin) or '0x'(hex)
    IoBinPrefix = IoBin | IoPrefix,
    IoHexPrefix = IoHex | IoPrefix,
    IoEcAffine = 0, // affine coordinate
    IoEcCompY = 256, // 1-bit y representation of elliptic curve
    IoSerialize = 512, // use MBS for 1-bit y
    IoFixedSizeByteSeq = IoSerialize, // obsolete
    IoEcProj = 1024, // projective or jacobi coordinate
    IoSerializeHexStr = 2048 // printable hex string
};

namespace fp {

const size_t UnitBitSize = sizeof(Unit) * 8;

const size_t maxUnitSize = (MCL_MAX_BIT_SIZE + UnitBitSize - 1) / UnitBitSize;
#define MCL_MAX_UNIT_SIZE ((MCL_MAX_BIT_SIZE + MCL_UNIT_BIT_SIZE - 1) / MCL_UNIT_BIT_SIZE)

struct FpGenerator;
struct Op;

typedef void (*void1u)(Unit*);
typedef void (*void2u)(Unit*, const Unit*);
typedef void (*void2uI)(Unit*, const Unit*, Unit);
typedef void (*void2uIu)(Unit*, const Unit*, Unit, const Unit*);
typedef void (*void2uOp)(Unit*, const Unit*, const Op&);
typedef void (*void3u)(Unit*, const Unit*, const Unit*);
typedef void (*void4u)(Unit*, const Unit*, const Unit*, const Unit*);
typedef int (*int2u)(Unit*, const Unit*);

typedef Unit (*u1uII)(Unit*, Unit, Unit);
typedef Unit (*u3u)(Unit*, const Unit*, const Unit*);

/*
    disable -Wcast-function-type
    the number of arguments of some JIT functions is smaller than that of T
*/
template<class T, class S>
T func_ptr_cast(S func)
{
    return reinterpret_cast<T>(reinterpret_cast<void*>(func));
}
struct Block {
    const Unit *p; // pointer to original FpT.v_
    size_t n;
    Unit v_[maxUnitSize];
};

enum Mode {
    FP_AUTO,
    FP_GMP,
    FP_GMP_MONT,
    FP_LLVM,
    FP_LLVM_MONT,
    FP_XBYAK
};

enum PrimeMode {
    PM_GENERIC = 0,
    PM_NIST_P192,
    PM_SECP256K1,
    PM_NIST_P521
};

enum MaskMode {
    NoMask = 0, // throw if greater or equal
    SmallMask = 1, // 1-bit smaller mask if greater or equal
    MaskAndMod = 2, // mask and substract if greater or equal
    Mod = 3 // mod p
};

struct Op {
    /*
        don't change the layout of rp and p
        asm code assumes &rp + 1 == p
    */
    Unit rp;
    Unit p[maxUnitSize];
    mpz_class mp;
    uint32_t pmod4;
    mcl::SquareRoot sq;
    mcl::Modp modp;
    Unit half[maxUnitSize]; // (p + 1) / 2
    Unit oneRep[maxUnitSize]; // 1(=inv R if Montgomery)
    /*
        for Montgomery
        one = 1
        R = (1 << (N * sizeof(Unit) * 8)) % p
        R2 = (R * R) % p
        R3 = RR^3
    */
    Unit one[maxUnitSize];
    Unit R2[maxUnitSize];
    Unit R3[maxUnitSize];
#ifdef MCL_USE_XBYAK
    FpGenerator *fg;
    mcl::Array<Unit> invTbl;
#endif
    void3u fp_addA_;
    void3u fp_subA_;
    void2u fp_negA_;
    void3u fp_mulA_;
    void2u fp_sqrA_;
    void3u fp2_addA_;
    void3u fp2_subA_;
    void2u fp2_negA_;
    void3u fp2_mulA_;
    void2u fp2_sqrA_;
    void3u fpDbl_addA_;
    void3u fpDbl_subA_;
    void3u fpDbl_mulPreA_;
    void2u fpDbl_sqrPreA_;
    void2u fpDbl_modA_;
    void3u fp2Dbl_mulPreA_;
    void2u fp2Dbl_sqrPreA_;
    size_t maxN;
    size_t N;
    size_t bitSize;
    bool (*fp_isZero)(const Unit*);
    void1u fp_clear;
    void2u fp_copy;
    void2u fp_shr1;
    void3u fp_neg;
    void4u fp_add;
    void4u fp_sub;
    void4u fp_mul;
    void3u fp_sqr;
    void2uOp fp_invOp;
    void2uIu fp_mulUnit; // fpN1_mod + fp_mulUnitPre

    void3u fpDbl_mulPre;
    void2u fpDbl_sqrPre;
    int2u fp_preInv;
    void2uI fp_mulUnitPre; // z[N + 1] = x[N] * y
    void3u fpN1_mod; // y[N] = x[N + 1] % p[N]

    void4u fpDbl_add;
    void4u fpDbl_sub;
    void3u fpDbl_mod;

    u3u fp_addPre; // without modulo p
    u3u fp_subPre; // without modulo p
    u3u fpDbl_addPre;
    u3u fpDbl_subPre;
    /*
        for Fp2 = F[u] / (u^2 + 1)
        x = a + bu
    */
    int xi_a; // xi = xi_a + u
    void4u fp2_mulNF;
    void2u fp2_inv;
    void2u fp2_mul_xiA_;
    uint32_t (*hash)(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);

    PrimeMode primeMode;
    bool isFullBit; // true if bitSize % uniSize == 0
    bool isMont; // true if use Montgomery
    bool isFastMod; // true if modulo is fast

    Op()
    {
        clear();
    }
    ~Op()
    {
#ifdef MCL_USE_XBYAK
        destroyFpGenerator(fg);
#endif
    }
    void clear()
    {
        rp = 0;
        memset(p, 0, sizeof(p));
        mp = 0;
        pmod4 = 0;
        sq.clear();
        // fg is not set
        memset(half, 0, sizeof(half));
        memset(oneRep, 0, sizeof(oneRep));
        memset(one, 0, sizeof(one));
        memset(R2, 0, sizeof(R2));
        memset(R3, 0, sizeof(R3));
#ifdef MCL_USE_XBYAK
        invTbl.clear();
#endif
        fp_addA_ = 0;
        fp_subA_ = 0;
        fp_negA_ = 0;
        fp_mulA_ = 0;
        fp_sqrA_ = 0;
        fp2_addA_ = 0;
        fp2_subA_ = 0;
        fp2_negA_ = 0;
        fp2_mulA_ = 0;
        fp2_sqrA_ = 0;
        fpDbl_addA_ = 0;
        fpDbl_subA_ = 0;
        fpDbl_mulPreA_ = 0;
        fpDbl_sqrPreA_ = 0;
        fpDbl_modA_ = 0;
        fp2Dbl_mulPreA_ = 0;
        fp2Dbl_sqrPreA_ = 0;
        maxN = 0;
        N = 0;
        bitSize = 0;
        fp_isZero = 0;
        fp_clear = 0;
        fp_copy = 0;
        fp_shr1 = 0;
        fp_neg = 0;
        fp_add = 0;
        fp_sub = 0;
        fp_mul = 0;
        fp_sqr = 0;
        fp_invOp = 0;
        fp_mulUnit = 0;

        fpDbl_mulPre = 0;
        fpDbl_sqrPre = 0;
        fp_preInv = 0;
        fp_mulUnitPre = 0;
        fpN1_mod = 0;

        fpDbl_add = 0;
        fpDbl_sub = 0;
        fpDbl_mod = 0;

        fp_addPre = 0;
        fp_subPre = 0;
        fpDbl_addPre = 0;
        fpDbl_subPre = 0;

        xi_a = 0;
        fp2_mulNF = 0;
        fp2_inv = 0;
        fp2_mul_xiA_ = 0;

        primeMode = PM_GENERIC;
        isFullBit = false;
        isMont = false;
        isFastMod = false;
        hash = 0;
    }
    void fromMont(Unit* y, const Unit *x) const
    {
        /*
            M(x, y) = xyR^-1
            y = M(x, 1) = xR^-1
        */
        fp_mul(y, x, one, p);
    }
    void toMont(Unit* y, const Unit *x) const
    {
        /*
            y = M(x, R2) = xR^2 R^-1 = xR
        */
        fp_mul(y, x, R2, p);
    }
    bool init(const mpz_class& p, size_t maxBitSize, int xi_a, Mode mode, size_t mclMaxBitSize = MCL_MAX_BIT_SIZE);
#ifdef MCL_USE_XBYAK
    static FpGenerator* createFpGenerator();
    static void destroyFpGenerator(FpGenerator *fg);
#endif
private:
    Op(const Op&);
    void operator=(const Op&);
};

inline const char* getIoSeparator(int ioMode)
{
    return (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) ? "" : " ";
}

inline void dump(const char *s, size_t n)
{
    for (size_t i = 0; i < n; i++) {
        printf("%02x ", (uint8_t)s[i]);
    }
    printf("\n");
}

#ifndef CYBOZU_DONT_USE_STRING
int detectIoMode(int ioMode, const std::ios_base& ios);

inline void dump(const std::string& s)
{
    dump(s.c_str(), s.size());
}
#endif

} } // mcl::fp