File: f_generic.c

package info (click to toggle)
haskell-cryptonite 0.26-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 3,160 kB
  • sloc: ansic: 21,001; haskell: 16,572; makefile: 8
file content (133 lines) | stat: -rw-r--r-- 4,362 bytes parent folder | download | duplicates (4)
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
/**
 * @file p448/f_generic.c
 * @author Mike Hamburg
 *
 * @copyright
 *   Copyright (c) 2015-2016 Cryptography Research, Inc.  \n
 *   Released under the MIT License.  See LICENSE.txt for license information.
 *
 * @brief Generic arithmetic which has to be compiled per field.
 *
 * @warning This file was automatically generated in Python.
 * Please do not edit it.
 */
#include "field.h"

static const gf MODULUS = {FIELD_LITERAL(
    0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff, 0xfffffffffffffe, 0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff
)};
    
#if P_MOD_8 == 5
    const gf SQRT_MINUS_ONE = {FIELD_LITERAL(
        /* NOPE */
    )};
#endif

/** Serialize to wire format. */
void cryptonite_gf_serialize (uint8_t serial[SER_BYTES], const gf x, int with_hibit) {
    gf red;
    cryptonite_gf_copy(red, x);
    cryptonite_gf_strong_reduce(red);
    if (!with_hibit) { assert(cryptonite_gf_hibit(red) == 0); }
    
    unsigned int j=0, fill=0;
    dword_t buffer = 0;
    UNROLL for (unsigned int i=0; i<(with_hibit ? X_SER_BYTES : SER_BYTES); i++) {
        if (fill < 8 && j < NLIMBS) {
            buffer |= ((dword_t)red->limb[LIMBPERM(j)]) << fill;
            fill += LIMB_PLACE_VALUE(LIMBPERM(j));
            j++;
        }
        serial[i] = buffer;
        fill -= 8;
        buffer >>= 8;
    }
}

/** Return high bit of x = low bit of 2x mod p */
mask_t cryptonite_gf_hibit(const gf x) {
    gf y;
    cryptonite_gf_add(y,x,x);
    cryptonite_gf_strong_reduce(y);
    return -(y->limb[0]&1);
}

/** Deserialize from wire format; return -1 on success and 0 on failure. */
mask_t cryptonite_gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) {
    unsigned int j=0, fill=0;
    dword_t buffer = 0;
    dsword_t scarry = 0;
    UNROLL for (unsigned int i=0; i<NLIMBS; i++) {
        UNROLL while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < (with_hibit ? X_SER_BYTES : SER_BYTES)) {
            buffer |= ((dword_t)serial[j]) << fill;
            fill += 8;
            j++;
        }
        x->limb[LIMBPERM(i)] = (i<NLIMBS-1) ? buffer & LIMB_MASK(LIMBPERM(i)) : buffer;
        fill -= LIMB_PLACE_VALUE(LIMBPERM(i));
        buffer >>= LIMB_PLACE_VALUE(LIMBPERM(i));
        scarry = (scarry + x->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)]) >> (8*sizeof(word_t));
    }
    mask_t succ = with_hibit ? -(mask_t)1 : ~cryptonite_gf_hibit(x);
    return succ & word_is_zero(buffer) & ~word_is_zero(scarry);
}

/** Reduce to canonical form. */
void cryptonite_gf_strong_reduce (gf a) {
    /* first, clear high */
    cryptonite_gf_weak_reduce(a); /* Determined to have negligible perf impact. */

    /* now the total is less than 2p */

    /* compute total_value - p.  No need to reduce mod p. */
    dsword_t scarry = 0;
    for (unsigned int i=0; i<NLIMBS; i++) {
        scarry = scarry + a->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)];
        a->limb[LIMBPERM(i)] = scarry & LIMB_MASK(LIMBPERM(i));
        scarry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
    }

    /* uncommon case: it was >= p, so now scarry = 0 and this = x
     * common case: it was < p, so now scarry = -1 and this = x - p + 2^255
     * so let's add back in p.  will carry back off the top for 2^255.
     */
    assert(word_is_zero(scarry) | word_is_zero(scarry+1));

    word_t scarry_0 = scarry;
    dword_t carry = 0;

    /* add it back */
    for (unsigned int i=0; i<NLIMBS; i++) {
        carry = carry + a->limb[LIMBPERM(i)] + (scarry_0 & MODULUS->limb[LIMBPERM(i)]);
        a->limb[LIMBPERM(i)] = carry & LIMB_MASK(LIMBPERM(i));
        carry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
    }

    assert(word_is_zero(carry + scarry_0));
}

/** Subtract two gf elements d=a-b */
void cryptonite_gf_sub (gf d, const gf a, const gf b) {
    cryptonite_gf_sub_RAW ( d, a, b );
    cryptonite_gf_bias( d, 2 );
    cryptonite_gf_weak_reduce ( d );
}

/** Add two field elements d = a+b */
void cryptonite_gf_add (gf d, const gf a, const gf b) {
    cryptonite_gf_add_RAW ( d, a, b );
    cryptonite_gf_weak_reduce ( d );
}

/** Compare a==b */
mask_t cryptonite_gf_eq(const gf a, const gf b) {
    gf c;
    cryptonite_gf_sub(c,a,b);
    cryptonite_gf_strong_reduce(c);
    mask_t ret=0;
    for (unsigned int i=0; i<NLIMBS; i++) {
        ret |= c->limb[LIMBPERM(i)];
    }

    return word_is_zero(ret);
}