你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

新手接触嵌入式,感谢各路神仙热情帮助,分享一个EC算法

[复制链接]
lvfeng123 发布时间:2019-5-6 07:04
参考了micro-ecc部分代码。内联汇编尚未写完。 $ W2 @; f+ ]: K% {, y
代码在STM32L496上验证通过,计算时间是23毫秒。0 V* b: b3 V; Z& c* j% K5 X
只支持secp256k1曲线.  
$ V5 s; Z* m8 i" U% Y8 \(友情提供上sha256 MD算法);/ k; U4 c& k4 p- N- f) }
& i0 ]/ S7 i0 m( C' a
#include <stdint.h>
8 I5 I7 P% o+ T0 x# r$ l#include <stdio.h>
) K( K$ Q) S$ K6 i3 w1 _#include <string.h>% z- ^' r  d8 f) U7 V
#define EC_BYTES 32  ?1 t  R' D8 d& v8 m
#if __STDC_VERSION__ >= 199901L$ X% Z0 a2 d4 b$ ~* S
    #define RESTRICT restrict
! X' e; }3 j# Y5 @) d#else
2 T9 l" o7 h2 I$ L8 W5 L# p7 T    #define RESTRICT
' {1 z/ t1 D' R; [) N% Y#endif
3 b$ l7 q1 E6 S6 W+ Rtypedef uint32_t ec_word_t;9 u5 s( G* H  E  L0 [
typedef uint64_t ec_dword_t;
, q' Z2 j. w# M2 Wtypedef unsigned wordcount_t;$ A0 j; v' g" P4 F* O* N/ z

9 k6 H, }- {, v- }# c4 k5 ?#define HIGH_BIT_SET 0x80000000/ h2 b" t- E& C
#define ec_WORD_BITS 32- B( o$ h3 L2 n1 f0 T
#define ec_WORD_BITS_SHIFT 5' Y7 P5 L8 ]  _
#define ec_WORD_BITS_MASK 0x01F
  B/ W2 d" b; l# z  q# P. L9 B* j#define ec_WORDS 8* N( f" E$ U* C: d1 L& _
#define ec_N_WORDS 8, I# e* z. ]7 J1 |9 R
- J8 u! e' Z- N$ S- y3 u
#define vli_modSub_fast(result, left, right) vli_modSub((result), (left), (right), curve_p)
$ h; m9 G' \- x$ @( O6 c#define vli_modSquare_fast(result, left) vli_modMult_fast((result), (left), (left))8 \+ _8 v% l7 d
#define EVEN(vli) (!(vli[0] & 1))
& N0 y+ h6 m) ?* }. }6 z* h7 }7 Y7 C/ s, J
typedef struct EccPoint {( ~9 d. |4 O7 U/ G& ^
    ec_word_t x[ec_WORDS];0 n8 `# w( \. A. X8 C  ]" |
    ec_word_t y[ec_WORDS];+ @& N, T0 _: B+ I* Y
} EccPoint;
3 G2 Z8 W; f! \  B+ C6 C/ qstatic const ec_word_t curve_p[ec_WORDS] = {0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};) I, j5 t& f8 t$ I( C
//static const ec_word_t curve_b[ec_WORDS] = {0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};: I' o( C5 {" U- k0 i5 K
static const EccPoint curve_G = {{0x16F81798, 0x59F2815B, 0x2DCE28D9, 0x029BFCDB, 0xCE870B07, 0x55A06295, 0xF9DCBBAC, 0x79BE667E}, \
( N9 g0 g  f: A* t7 ]( M& u: g                                                                                                                                {0xFB10D4B8, 0x9C47D08F, 0xA6855419, 0xFD17B448, 0x0E1108A8, 0x5DA4FBFC, 0x26A3C465, 0x483ADA77}};4 n+ W$ I9 r/ W* l% b
static const ec_word_t curve_n[ec_N_WORDS] = {0xD0364141, 0xBFD25E8C, 0xAF48A03B, 0xBAAEDCE6, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
! k. V6 \- N* ]* S* ^8 t% X+ `9 o6 x) M7 @# H7 j: ^- m! }
static void vli_rshift1(ec_word_t *vli);
1 Y5 q; Z; `, T" D; Ystatic void vli2_rshift1(ec_word_t *vli);4 X  M( G/ r! L) [* V7 \
static void vli_set(ec_word_t *dest, const ec_word_t *src);7 A; D' T: e9 n
static void vli_clear(ec_word_t *vli);* H! v: I6 R: t* v
static void vli_bytesToNative(uint32_t *native, const uint8_t *bytes);0 {% g: Q0 q7 r! s6 q1 V; d6 f
static void vli_modMult_n(ec_word_t *result, const ec_word_t *left, const ec_word_t *right);/ Z% e5 o- D; V3 d
static void vli_mult(ec_word_t *result, const ec_word_t *left, const ec_word_t *right);) }. W0 q& |$ L$ S8 Q' U
static void vli_modSub(ec_word_t *result, const ec_word_t *left, const ec_word_t *right, const ec_word_t *mod);+ w5 }, W, j9 `
static void vli_modMult_fast(ec_word_t *result, const ec_word_t *left, const ec_word_t *right);5 W% N0 Q; y4 @( z
static void vli_modInv(ec_word_t *result, const ec_word_t *input, const ec_word_t *mod);
* s$ W: T: p2 g& [4 M, Fstatic void vli_modAdd(ec_word_t *result, const ec_word_t *left, const ec_word_t *right, const ec_word_t *mod);7 H; p3 m& [* D$ W' s5 u! m
static void vli_mmod_fast(ec_word_t *RESTRICT result, ec_word_t *RESTRICT product);
( d% p; }+ v+ q; {static int vli_equal(const ec_word_t *left, const ec_word_t *right);
$ {2 Q! X6 ?5 o4 @* R' J* c& bstatic ec_word_t vli_testBit(const ec_word_t *vli, int bit);
" Z. Y; Y- s6 }5 n4 Rstatic int vli_cmp(const ec_word_t *left, const ec_word_t *right);9 `% y4 ^. a5 y4 u. p& D
static ec_word_t vli_isZero(const ec_word_t *vli);
, m5 T, L  n: E  \2 `' i8 hstatic ec_word_t vli_sub(ec_word_t *result, const ec_word_t *left, const ec_word_t *right);( z% z1 W4 R$ y
static wordcount_t vli_numDigits(const ec_word_t *vli, wordcount_t max_words);  L) \. T8 c) X- _
static int vli_numBits(const ec_word_t *vli, wordcount_t max_words);4 @! l6 b" B8 A5 Z/ r
static int smax(int a, int b);1 J! f9 I6 q6 n2 L5 m7 r$ ~
static void apply_z(ec_word_t * RESTRICT X1, ec_word_t * RESTRICT Y1, const ec_word_t * RESTRICT Z);6 G* h, r% A! ~% V( f9 y
static void omega_mult(uint32_t * RESTRICT result, const uint32_t * RESTRICT right);: ]3 [" W# S9 p
static void muladd(ec_word_t a, ec_word_t b, ec_word_t *r0, ec_word_t *r1, ec_word_t *r2);& G1 U$ V) R2 t$ z4 Q! v$ t
static void XYcZ_add(ec_word_t * RESTRICT X1, ec_word_t * RESTRICT Y1, ec_word_t * RESTRICT X2, ec_word_t * RESTRICT Y2);
# d4 c# [7 o0 d) O- h5 h0 p% lstatic void EccPoint_double_jacobian(ec_word_t * RESTRICT X1, ec_word_t * RESTRICT Y1, ec_word_t * RESTRICT Z1);
; I! q$ P, ~0 N" \: J- u; j1 [3 R
int ec_verify(const uint8_t public_key[64], const uint8_t hash[32], const uint8_t signature[64]) {
) Z9 {, I, t& ]( a4 y6 ]    ec_word_t u1[ec_N_WORDS], u2[ec_N_WORDS];
% E1 ]! d1 |. z. k, J9 M) `    ec_word_t z[ec_N_WORDS];/ P- ]5 R* \8 f
    EccPoint public, sum;0 x2 @( S7 y& f1 D
    ec_word_t rx[ec_WORDS];
* d  s# [0 D6 b. O8 p) \    ec_word_t ry[ec_WORDS];
1 i; j3 e5 z/ e    ec_word_t tx[ec_WORDS];
0 O  h3 ]) s" J8 g- A    ec_word_t ty[ec_WORDS];
  c* d$ p; Q  p+ t- f    ec_word_t tz[ec_WORDS];
3 G) p: I4 n0 N: k; J/ D    const EccPoint *points[4];* h: M( T. M' M3 n* J2 t% A
    const EccPoint *point;
0 M9 D0 p5 N. H% l2 B    int numBits;
# s1 \+ l2 D4 K( z2 h. u    int i;
4 u( M1 |/ g+ G$ y    ec_word_t r[ec_N_WORDS], s[ec_N_WORDS];
, p( h) ]* `5 U# l  m    r[ec_N_WORDS - 1] = 0;
2 }7 h# y: f1 X- v  u    s[ec_N_WORDS - 1] = 0;6 t: Y! I- _* G8 i9 J/ K# m+ {5 v
) J: O  S6 u5 L- b* C$ j$ n
    vli_bytesToNative(public.x, public_key);
4 o/ I! ~+ M( e1 x  Q5 W    vli_bytesToNative(public.y, public_key + EC_BYTES);3 O. C$ ^, f% J/ X& D
    vli_bytesToNative(r, signature);
0 R* H( {9 ^3 j2 |    vli_bytesToNative(s, signature + EC_BYTES);
- L- y: |# ]% {5 ^
* ^& M; k4 g/ k; }, B( _( Y8 i    if (vli_isZero(r) || vli_isZero(s)) { /* r, s must not be 0. */9 ~$ y0 P  m% _* `1 l) k
        return 0;
4 J9 ]/ L5 `9 T; F    }
# k4 a6 p6 f) H        vli_modInv(z, s, curve_n);
, B* R- J: h- [( |. F8 I    u1[ec_N_WORDS - 1] = 0;$ H6 `8 M: m& L6 n- O/ f3 m
    vli_bytesToNative(u1, hash);
; J# G( k! e; t; [" w    vli_modMult_n(u1, u1, z); /* u1 = e/s */4 s" J! M6 O' H4 `7 z* |+ D
    vli_modMult_n(u2, r, z); /* u2 = r/s */
0 }# O0 I' F9 ?0 Q4 p1 t" U5 ~
# m) h8 J3 W" O. k+ n- B! ^$ f    /* Calculate sum = G + Q. */
" U# }% H, r. F2 y4 p    vli_set(sum.x, public.x);0 h; O! g4 x! w, X" T1 C. f
    vli_set(sum.y, public.y);/ _: C$ g  {: P8 S+ P, ~8 d
    vli_set(tx, curve_G.x);
- i  e8 X: q0 \9 b+ U* w6 l    vli_set(ty, curve_G.y);' r* ~% z8 b4 }
    vli_modSub_fast(z, sum.x, tx); /* Z = x2 - x1 */6 `; j1 \8 A/ v5 d! ^
    XYcZ_add(tx, ty, sum.x, sum.y);
% L7 G5 K  ]7 G. a( H- l    vli_modInv(z, z, curve_p); /* Z = 1/Z */
* N) k9 P, Y8 M* P    apply_z(sum.x, sum.y, z);
( n7 G0 @7 J7 Z( i) L: S& H$ {; r3 c& o- G; i. x8 V' X' {
    /* Use Shamir's trick to calculate u1*G + u2*Q */, O4 c1 ?; E8 q! w# |' g; a1 J
    points[0] = 0;1 u: w& v+ r2 t3 s
    points[1] = &curve_G;. W8 L. k* c! t3 U1 z
    points[2] = &public;
: [# K; h5 S6 a    points[3] = &sum;
, P/ f) B; r! y3 a    numBits = smax(vli_numBits(u1, ec_N_WORDS), vli_numBits(u2, ec_N_WORDS));
" C% z6 h3 @) X9 [9 z9 N" A" G
' G8 \1 n1 q9 _    point = points[(!!vli_testBit(u1, numBits - 1)) | ((!!vli_testBit(u2, numBits - 1)) << 1)];
5 U" t, h# M( O9 ^- |7 T3 c( Y    vli_set(rx, point->x);. h: Y2 ?3 E* u" i- ~
    vli_set(ry, point->y);4 a2 i& {; u& P; x7 J: b1 M
    vli_clear(z);% L, E" ]- p$ K0 y+ W  t
    z[0] = 1;
! g: @6 K# L5 ?" H" I! r4 D" h& A2 C; z
    for (i = numBits - 2; i >= 0; --i) {. N% d6 w9 |0 o. N/ \
        ec_word_t index;
; r# w  U( r' ]( Y3 G        EccPoint_double_jacobian(rx, ry, z);
+ P% o1 C5 U4 ~  e% g- Z. I9 L$ k: j7 P5 y+ [
        index = (!!vli_testBit(u1, i)) | ((!!vli_testBit(u2, i)) << 1);
+ h  a( k- N" W( d        point = points[index];
$ J" h' K/ \( C, B3 L        if (point) {& s. W; d2 K5 T5 ^) J, G  F! Z
            vli_set(tx, point->x);
$ F% L9 o/ j8 R; v+ r9 {; L            vli_set(ty, point->y);, |/ z7 _5 s0 G1 M% w* E/ }& E, P
            apply_z(tx, ty, z);( |( f6 I- |9 ?; q$ `) n+ S
            vli_modSub_fast(tz, rx, tx); /* Z = x2 - x1 */& y+ U! S! g0 X6 m/ M
            XYcZ_add(tx, ty, rx, ry);
9 I5 L# N' X4 p1 f5 R            vli_modMult_fast(z, z, tz);
- v4 v. K" x, r# R        }# M6 A6 v, e1 O. m8 v; @
    }. Y5 `8 ^7 K3 z& b2 h7 f
    vli_modInv(z, z, curve_p); /* Z = 1/Z */7 o3 p2 K, y# R- t7 Z$ l* \7 _* O
    apply_z(rx, ry, z);8 [0 l$ t" Z  v" S0 `
    return vli_equal(rx, r);; j- O/ K$ M  p1 o3 W. w
}
( W; {# q# [& m  qstatic int vli_equal(const ec_word_t *left, const ec_word_t *right) {
% |) G2 V2 U: X( x7 N    ec_word_t result = 0;! f9 }3 {" @) }- Z% V: y
    int i;
+ q3 _9 ^5 b, t, q( _    for (i = ec_WORDS - 1; i >= 0; --i) {* m; E7 x2 x( c  L+ j
        result |= (left[i] ^ right[i]);) ?7 H* X. n8 X4 Q  v
    }7 @; n9 u0 w& S% N7 X, k
    return (result == 0);7 H# g% {/ [% @& \
}
  M- e; I5 b' z* Zstatic ec_word_t vli_add(ec_word_t *result, const ec_word_t *left, const ec_word_t *right) {
. ^- ]* N9 L  Y6 ?  i    ec_word_t carry = 0;
. {' i7 {, {, F/ T' ]) A    wordcount_t i;
  W) _" F) Z& f# U' ~) d5 E    for (i = 0; i < ec_WORDS; ++i) {
  J; n4 v" H; e6 S; s        ec_word_t sum = left[i] + right[i] + carry;
5 Z( q! p) ~0 n) M$ s) D) a1 e        if (sum != left[i]) {
! y! m* L) Z3 r: Y$ N            carry = (sum < left[i]);2 k5 n* `2 r2 p+ R5 x
        }
# t( V$ [3 L, e$ i        result[i] = sum;
4 i8 P& @2 b$ x, W    }+ b2 I0 ?4 U/ p& r6 o& Q( i  J! o
    return carry;
' l* w& Y% [! Z) E; Q( K; F1 G}+ ~4 R5 L, r; X- D# B+ i
4 [, Q! R7 _5 f  ^/ G$ W
static void vli_bytesToNative(uint32_t *native, const uint8_t *bytes) {/ l! Y' u1 B' w
    unsigned i;
$ y2 U) P4 Q9 c2 A    for (i = 0; i < ec_WORDS; ++i) {
1 g$ \; W6 b* V3 d, E0 o        const uint8_t *digit = bytes + 4 * (ec_WORDS - 1 - i);# `: S! s4 C1 ?6 X" j( m+ V
        native[i] = ((uint32_t)digit[0] << 24) | ((uint32_t)digit[1] << 16) |1 B/ z: L8 c( z7 n
                    ((uint32_t)digit[2] << 8) | (uint32_t)digit[3];0 {# i8 a) E$ v% s# O5 E
    }3 y3 |+ G; x: c+ C, K  H  ?
}! t& \) d- L7 S) X- O! d3 @6 ]
static ec_word_t vli_isZero(const ec_word_t *vli) {# C6 T, B' |8 j7 U  }$ U1 L
    wordcount_t i;/ G6 w  p' k; s6 _: v6 w
    for (i = 0; i < ec_WORDS; ++i) {+ v* K/ [0 q# W  e+ G( m9 t8 U, O8 q
        if (vli[i]) {- q* E( H- x: i! {. q( p
            return 0;
; D0 T, h) Q: a+ D# ]( i0 j% J; S1 c! ?        }
8 w+ j  D8 H1 ]5 @# Z3 n1 J; u    }+ F: v# ]% Y$ E- v4 D
    return 1;
4 U# F2 \' `) q" s8 Y  M}/ R0 B/ A6 P3 h# |$ f0 z
static ec_word_t vli_sub(ec_word_t *result, const ec_word_t *left, const ec_word_t *right) {3 L' _5 D1 j) p! {7 g0 r) \+ W+ x
    ec_word_t borrow = 0;
, j. z" a- j, F/ K! I    wordcount_t i;( K. x+ U, }2 F) v+ A+ h
    for (i = 0; i < ec_WORDS; ++i) {" w9 l! H5 }( z, [
        ec_word_t diff = left[i] - right[i] - borrow;2 v4 z. l4 g8 S" {- |
        if (diff != left[i]) {5 l5 C; ^+ c1 L1 C
            borrow = (diff > left[i]);
/ V* k" T; x' h1 h3 _        }( z; }2 F6 l) L) i
        result[i] = diff;. ?( L3 u$ ^2 ~8 W5 r* W
    }+ t  w3 W) k& J4 w0 g3 w
    return borrow;
2 e! w; }; ?$ U8 I! B. S- N}. [* I( m) {* w' C

) U: b- X* s5 j8 Bstatic ec_word_t vli2_sub(ec_word_t *result,' G& S' X- Q9 K
                            const ec_word_t *left,
! ^! ?$ N8 U0 v2 m" C                            const ec_word_t *right) {
* u- ?/ t# E$ ]7 ^6 L    ec_word_t borrow = 0;
* }! ~1 M  M+ ]0 g9 s    wordcount_t i;5 [& L& P$ u) F  d. p
    for (i = 0; i < ec_WORDS * 2; ++i) {7 V  Z$ u& _0 r
        ec_word_t diff = left[i] - right[i] - borrow;
: |' u! a$ T" s/ A4 u        if (diff != left[i]) {
$ i8 Y$ A* H% o8 J- M# O            borrow = (diff > left[i]);
9 ]/ }( n& l4 G        }2 M8 F3 d" K* o3 x) ^; a3 f
        result[i] = diff;
3 k6 [  Q! f& F$ s2 M! o    }
. ^; u( \; k! \    return borrow;6 B, o- H4 E/ a' [, Y, h6 I
}
  o! s7 X) P# M; e3 m" G. V$ @
( D3 [4 Y! _/ E. m0 g' a' F/* Computes result = (left * right) % curve_n. */
7 a. c4 O' D6 U* Ystatic void vli_modMult_n(ec_word_t *result, const ec_word_t *left, const ec_word_t *right) {
: X* M; U2 ]- w$ E    ec_word_t product[2 * ec_WORDS];, w3 t5 b- }3 [
    ec_word_t modMultiple[2 * ec_WORDS];' a+ i) K) T: g' C
    ec_word_t tmp[2 * ec_WORDS];8 C. s4 A- b! ]* G+ w  i
    ec_word_t *v[2] = {tmp, product};: u. k  u* a- V+ J: P
    int i;
! k* U$ X( c6 q7 p    ec_word_t index = 1;; J/ |9 D( |# r5 {

- h" Q5 s$ Y. o$ ^. s4 {5 ~6 E* q    vli_mult(product, left, right);6 ]! g7 o3 v- l) W4 [
    vli_set(modMultiple + ec_WORDS, curve_n); /* works if curve_n has its highest bit set */% m" V5 i; C4 y6 i4 T0 |; K/ }
    vli_clear(modMultiple);- Q# V# `5 p* L( p9 V
1 v- V% j/ d, ?  Y  q4 {
    for (i = 0; i <= EC_BYTES * 8; ++i) {! j- \. C# b9 R2 y( v5 X7 b
        ec_word_t borrow = vli2_sub(v[1 - index], v[index], modMultiple);6 T5 B9 I4 K  p4 W( L- Z8 w# `: `- s
        index = !(index ^ borrow); /* Swap the index if there was no borrow */  |+ x2 O- N1 B8 {9 N- _" v
        vli2_rshift1(modMultiple);
5 y7 L+ t" r: s    }
( u6 C" V7 U' u; U  C( f    vli_set(result, v[index]);
+ M! b' ^+ G) _& _! R1 T  ^}
; }' u+ A& E: {1 v' d
* q9 j' Z0 P! v9 g2 r' O  I0 Ustatic void vli_mult(ec_word_t *result, const ec_word_t *left, const ec_word_t *right) {/ ~* R  f0 Y  p" H
    ec_word_t r0 = 0;
& o8 @+ b) r% a9 ~4 @    ec_word_t r1 = 0;7 `# D5 x3 Q4 m. Y7 m& E( r
    ec_word_t r2 = 0;
6 b2 i0 v6 e4 Y6 t% r' v" K6 }    wordcount_t i, k;: N. {4 i6 @( x' F3 P5 X

2 i0 J: L& v! [* ~5 \% @    /* Compute each digit of result in sequence, maintaining the carries. */) ]. L* o+ C$ z0 i% M
    for (k = 0; k < ec_WORDS; ++k) {# k1 D& V7 c1 c) z- n
        for (i = 0; i <= k; ++i) {' @( W- _+ c4 B4 H$ Q9 A
            muladd(left[i], right[k - i], &r0, &r1, &r2);4 s4 m4 q% }8 x# X# G. U) `: d5 q
        }" w) Q8 N5 m$ G; h
        result[k] = r0;+ S; X# t, D! s! R$ @
        r0 = r1;, `) l% o/ F: \. N, f! `
        r1 = r2;9 ~* S1 X' y3 H6 M3 h" X
        r2 = 0;$ g4 J  T. U$ x, I  y
    }& \' m5 Y8 _8 m. D7 F1 y
    for (k = ec_WORDS; k < ec_WORDS * 2 - 1; ++k) {% o2 G: j0 o. Z- ~5 X0 E
        for (i = (k + 1) - ec_WORDS; i < ec_WORDS; ++i) {
$ V: a) X; q8 z, x; J7 t2 l5 x3 ~3 C            muladd(left[i], right[k - i], &r0, &r1, &r2);
8 c; P; Z  C% \/ ~. W        }8 W+ e3 I4 ^7 u9 \+ O6 W
        result[k] = r0;& h$ k2 S% M; k2 c! ]
        r0 = r1;" \. S5 L0 J5 T
        r1 = r2;) Y& q+ T; v6 \5 W( r
        r2 = 0;
; R9 F7 ]+ d: H9 e2 q0 Y& [4 |. ~    }
0 x  X1 u; m% D: Z7 u) p& Q2 T    result[ec_WORDS * 2 - 1] = r0;
4 `) b9 w  d2 i( ^2 u2 H  T5 k) D2 h}
) p- I% S2 V4 r1 ?7 q; i0 K9 H" E. ~0 _" B) s
static void muladd(ec_word_t a, ec_word_t b, ec_word_t *r0, ec_word_t *r1, ec_word_t *r2) {
8 Q# E9 e! D; {& n. ~7 ~( @    ec_dword_t p = (ec_dword_t)a * b;
1 p2 ~8 a& t( _" I/ @    ec_dword_t r01 = ((ec_dword_t)(*r1) << ec_WORD_BITS) | *r0;
8 T5 \! A9 _# X  t1 J    r01 += p;
/ s( s1 P' J  j8 U    *r2 += (r01 < p);% S( O6 U; |& S- X8 \
    *r1 = r01 >> ec_WORD_BITS;
7 ^( q0 t" d- v6 o, K" {! K( u8 P    *r0 = (ec_word_t)r01;
8 G1 c* ]" V$ \- M+ g  }; e) L}
- C/ ]' ?$ @; ~2 v! l& e# e//#define muladd_exists 1
5 l5 x0 w& y5 B# U
) a! E; K. Y3 O& C; Jstatic void vli_rshift1(ec_word_t *vli) {
2 D" [5 y) o3 _1 D3 e& h' l    ec_word_t *end = vli;& U" }8 ^3 t$ j+ k* W; E( C
    ec_word_t carry = 0;
( X8 m+ b! l' p- O5 Q3 k4 t, W  t: z/ a- l  E5 I+ T3 S2 P  v$ F
    vli += ec_WORDS;/ O# `- H+ m& ^
    while (vli-- > end) {) v& `; ^# y% @( h( G
        ec_word_t temp = *vli;
3 R1 m  p- {/ Y3 \6 g' J; N        *vli = (temp >> 1) | carry;
4 X4 w% S8 C8 c        carry = temp << (ec_WORD_BITS - 1);6 o* B/ u4 U3 B' n1 n
    }
& u( A: E7 K+ ~}0 e$ c5 j' k4 x" E9 ]: ]5 a

; \# U% E4 o$ H9 a/ t5 fstatic void vli2_rshift1(ec_word_t *vli) {
. w) d$ P' ]; b# C7 ]& ?    vli_rshift1(vli);# f" H, t( g8 l9 a% m( l
    vli[ec_WORDS - 1] |= vli[ec_WORDS] << (ec_WORD_BITS - 1);2 }1 ~! u+ k0 B/ z
    vli_rshift1(vli + ec_WORDS);" W5 q/ E3 ?* S+ ^) Y
}
3 X' Z7 S- _/ _- W' h
4 F: p6 w3 g5 C9 @6 d5 U( @static void vli_modSub(ec_word_t *result, const ec_word_t *left, const ec_word_t *right, const ec_word_t *mod) {
- o5 i1 g% u0 l* i& O" n    ec_word_t l_borrow = vli_sub(result, left, right);+ y9 ?4 Y  a7 u$ m1 E/ D
    if (l_borrow) {. D8 Z2 _- k) Y: h
        /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
% W* M# @  s$ k: [$ P* l           we can get the correct result from result + mod (with overflow). */
4 S0 z( E& D1 @: S+ M7 ~+ z% L        vli_add(result, result, mod);; S! I8 ]/ R" q9 c& H
    }
. ~9 F- Z, U/ X' g. l0 f0 Q( t) Q}
5 O3 }6 c8 E+ f% [. `' hstatic void vli_set(ec_word_t *dest, const ec_word_t *src) {+ k( T! ?+ \, y/ e0 N% l/ m) R
    wordcount_t i;+ U: [: A" i% F
    for (i = 0; i < ec_WORDS; ++i) {2 s! r$ \7 J- p/ e: w
        dest[i] = src[i];4 Z8 s5 P+ s7 L" S8 i9 ^
    }
4 b: }2 p+ W! `3 @6 l}! p- s( A2 o( c; i2 D! y
- m$ `& L! K2 q1 X! z! [
static void XYcZ_add(ec_word_t * RESTRICT X1,
1 n( }) k. J6 u/ a' D9 y/ a) {                     ec_word_t * RESTRICT Y1,2 @. T# k' t' [5 d5 f. M5 g, L
                     ec_word_t * RESTRICT X2,
7 W7 s. Z8 k, m3 D1 u/ v/ k% t$ ]/ O                     ec_word_t * RESTRICT Y2) {5 F' V& L: ?3 U! p' `
    /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */- L' e$ Y$ {- M
    ec_word_t t5[ec_WORDS];
9 W1 ?' {! S% k" C8 b1 H$ `
- @( b5 x. j5 ~! i+ c    vli_modSub_fast(t5, X2, X1);  /* t5 = x2 - x1 */' J! J/ J8 K! I# G/ K5 J6 R
    vli_modSquare_fast(t5, t5);   /* t5 = (x2 - x1)^2 = A */
2 \( C; U2 j5 H4 b    vli_modMult_fast(X1, X1, t5); /* t1 = x1*A = B */
* r) B. a  n3 q- K3 y    vli_modMult_fast(X2, X2, t5); /* t3 = x2*A = C */
  v8 @0 B/ B2 J$ n/ N  h    vli_modSub_fast(Y2, Y2, Y1);  /* t4 = y2 - y1 */
( L6 C0 w7 e9 G    vli_modSquare_fast(t5, Y2);   /* t5 = (y2 - y1)^2 = D */  @+ I* [8 O* K/ m% q8 V* V$ y
, n# O  ~2 Q. Q) Q" a$ Y
    vli_modSub_fast(t5, t5, X1);  /* t5 = D - B */
2 d, j: W5 _  t5 {) t, I- v    vli_modSub_fast(t5, t5, X2);  /* t5 = D - B - C = x3 */
- U# {. X, n! W: t* d6 B; a    vli_modSub_fast(X2, X2, X1);  /* t3 = C - B */( N0 N/ z3 T2 v1 L2 V) h; {7 X
    vli_modMult_fast(Y1, Y1, X2); /* t2 = y1*(C - B) */
% `( _( l# J% Y/ _% c    vli_modSub_fast(X2, X1, t5);  /* t3 = B - x3 */* [7 B" y  G7 F7 h
    vli_modMult_fast(Y2, Y2, X2); /* t4 = (y2 - y1)*(B - x3) */
3 }6 ^2 l% O/ a2 d- h3 F    vli_modSub_fast(Y2, Y2, Y1);  /* t4 = y3 */- t1 {% G' Q, w. M
$ G& f* r  J9 Y0 W* `
    vli_set(X2, t5);) z& d$ r3 ^* Q* M+ r
}
! J& g; T' I/ }% Y9 p. ?$ V+ _) u5 s1 t2 v! a, u4 H/ m7 @
static void EccPoint_double_jacobian(ec_word_t * RESTRICT X1,4 d" _" p7 w" T; m8 P
                                     ec_word_t * RESTRICT Y1,
5 [  K+ m2 `; z' Z& S                                     ec_word_t * RESTRICT Z1) {
! H/ B$ `& O7 F% g    /* t1 = X, t2 = Y, t3 = Z */
  A& |# W& Y1 ~    ec_word_t t4[ec_WORDS];
  T. R1 H6 w8 L1 Z( H5 \    ec_word_t t5[ec_WORDS];
( G9 r0 o/ Y) r' r% ~; C5 b
9 {# J$ Z$ S, @. _' n9 {    if (vli_isZero(Z1)) {5 _* p' \$ E& `2 N+ s% L
        return;
5 ^. G/ J8 j+ W7 A    }2 u" f" N5 p* e3 P; m( J' v

+ w8 t4 `( J3 P: N1 k( c    vli_modSquare_fast(t5, Y1);   /* t5 = y1^2 */( C  L- l3 r" S- k
    vli_modMult_fast(t4, X1, t5); /* t4 = x1*y1^2 = A */
/ t7 \# I$ c3 [- J0 }$ A    vli_modSquare_fast(X1, X1);   /* t1 = x1^2 */9 T4 X6 O2 i  b4 z5 @6 b9 c
    vli_modSquare_fast(t5, t5);   /* t5 = y1^4 */. c5 o* f7 {) r6 C
    vli_modMult_fast(Z1, Y1, Z1); /* t3 = y1*z1 = z3 */
; x3 B" e7 W  R! N% ]! V+ t
1 ~; H- w2 \9 W: M    vli_modAdd(Y1, X1, X1, curve_p); /* t2 = 2*x1^2 */
/ j4 v; f$ X. F1 ~    vli_modAdd(Y1, Y1, X1, curve_p); /* t2 = 3*x1^2 */0 t$ J) S7 g9 R; q; G
    if (vli_testBit(Y1, 0)) {+ T& C6 l7 i# B
        ec_word_t carry = vli_add(Y1, Y1, curve_p);0 q) A% m/ H* t0 R* e
        vli_rshift1(Y1);
+ M) C1 S1 O3 R1 p        Y1[ec_WORDS - 1] |= carry << (ec_WORD_BITS - 1);
2 ]3 ?; F/ f6 [1 i. a0 @4 P    } else {! G! W6 w+ z9 [4 s
        vli_rshift1(Y1);
2 z2 A, }3 \6 o/ ^5 ~1 n( [    }
% Z" k; z; j+ s5 a3 e    /* t2 = 3/2*(x1^2) = B */
9 `/ {* w7 U$ h) M1 F: a& L# s' t/ M2 a# C: Q
    vli_modSquare_fast(X1, Y1);      /* t1 = B^2 */
' ]+ W7 r0 q0 h) i6 @- e& u2 L; m' j    vli_modSub(X1, X1, t4, curve_p); /* t1 = B^2 - A */
6 r/ @9 ]2 y1 v9 R0 i' o0 X2 k8 E    vli_modSub(X1, X1, t4, curve_p); /* t1 = B^2 - 2A = x3 */
4 N! s# w* B6 v- f+ E1 X2 u1 D( h# B+ k1 H6 G2 Y
    vli_modSub(t4, t4, X1, curve_p); /* t4 = A - x3 *// M1 X* C* m" i( p5 n# K$ Q# M9 ?7 P
    vli_modMult_fast(Y1, Y1, t4);    /* t2 = B * (A - x3) */* p  ~* J1 n* W$ L" s
    vli_modSub(Y1, Y1, t5, curve_p); /* t2 = B * (A - x3) - y1^4 = y3 */
2 k8 C: }0 P9 B& i/ y  M}
7 `. L' g1 U( n; x1 v: l0 A2 j1 ^static void vli_modMult_fast(ec_word_t *result,
" W6 ?6 p2 B1 Y& m2 G7 r% ?                             const ec_word_t *left,
' B. `+ b3 e0 a6 g! `! E                             const ec_word_t *right) {
4 B. o9 t: \, W& p% {5 `: s5 Y    ec_word_t product[2 * ec_WORDS];
" n: M" v, A7 W: Q" B    vli_mult(product, left, right);
1 s# l5 N( Z: f( ^' ^/ o3 v* a    vli_mmod_fast(result, product);
% g7 ^% G6 G' d! y! g/ B}
' f+ z: x* S& ustatic void vli_modInv(ec_word_t *result, const ec_word_t *input, const ec_word_t *mod) {
) v# a8 b' L& x. ~& j    ec_word_t a[ec_WORDS], b[ec_WORDS], u[ec_WORDS], v[ec_WORDS];4 q4 U) ?1 D7 J+ b6 L# E2 ]
    ec_word_t carry;
* O# |/ {; H- {6 k+ j    int cmpResult;3 J/ k0 ?4 j7 L, a! J# X  ?
( |. R  @* T- Z. p9 t, i
    if (vli_isZero(input)) {6 ?8 v' L2 `+ D/ [; p
        vli_clear(result);. i8 E! u, ?; b: R
        return;
  X" p$ r0 R/ h# _5 k2 s1 W3 |8 ?" H    }  Q+ i$ I: q% n

/ H  l% W. l: ]& t    vli_set(a, input);7 ]7 i$ ?4 V9 \0 _0 }% D
    vli_set(b, mod);8 r  }4 J/ U2 {8 M9 s1 d) _
    vli_clear(u);5 J" Q8 m  `: C$ J! S2 H7 b
    u[0] = 1;
: H5 P. A1 g" ^* f0 Q    vli_clear(v);
/ G' K1 b' U3 k( N. i, ]    while ((cmpResult = vli_cmp(a, b)) != 0) {6 ^2 |4 i2 V( j  I+ o
        carry = 0;
0 I. C2 n, f( ]8 J# e        if (EVEN(a)) {
' Q& l# `9 [7 |4 ^/ S$ J  j            vli_rshift1(a);8 @! q2 K) c) a: v5 J
            if (!EVEN(u)) {
) T- @  l' v  _: H5 m+ c$ o+ Z                carry = vli_add(u, u, mod);5 o- j' a; Z9 \' f8 ^
            }5 K( {% Y/ X+ N" f7 M* l! m
            vli_rshift1(u);* z; R- \, u6 Y5 r4 S
            if (carry) {3 X7 Q( K6 r5 o. B6 m+ x
                u[ec_WORDS - 1] |= HIGH_BIT_SET;
  D% }% r8 ]9 ~            }& k# A- F9 e1 j" @1 d# c4 O& K
        } else if (EVEN(b)) {/ T9 W( T0 |2 k
            vli_rshift1(b);
& {: h5 s* u9 [+ i& ]/ i            if (!EVEN(v)) {4 v1 m3 P5 `  n4 \& s# ]
                carry = vli_add(v, v, mod);
) x( H  I+ _# ?9 R8 A            }
  O4 a" i5 H, L' G. C            vli_rshift1(v);
3 z/ V8 l  R0 K, I" i            if (carry) {
3 x3 L5 ~% {" Q7 y0 [: x  |                v[ec_WORDS - 1] |= HIGH_BIT_SET;) {8 z/ q$ Q$ d" e2 h
            }. N  n' V& B, h2 N0 s5 t; I
        } else if (cmpResult > 0) {6 [* ?% f1 e2 [: n" U4 w/ H1 b
            vli_sub(a, a, b);
6 W2 E' K' o6 D  A" G% I            vli_rshift1(a);
- X7 t, ]( H* \, ~! B+ [( t* \            if (vli_cmp(u, v) < 0) {; J" N* q! @1 B; O! t; k
                vli_add(u, u, mod);, i) q! G& W2 [  k- r' ]) C: k
            }3 z& y% w, o) s* C
            vli_sub(u, u, v);
' f* F' i- k' H1 a1 o            if (!EVEN(u)) {
' z. C. e+ r7 ]9 {/ m                carry = vli_add(u, u, mod);% v# q' |1 H2 _6 s. r
            }
' G" P: K, ^# q# V. \            vli_rshift1(u);
3 w! \; r# h' @$ m$ Y            if (carry) {
/ x2 U3 F0 O4 V& O& `5 H* ^2 }& D                u[ec_WORDS - 1] |= HIGH_BIT_SET;2 y- f  n3 Q3 u* ]! @
            }, w+ _. a8 `/ D6 }
        } else {* r. v1 }1 Z' U8 C- w* C( _" g' _
            vli_sub(b, b, a);
2 o* _" ~& A# g4 j" M; X            vli_rshift1(b);
: n. }; }) N7 F# }5 O            if (vli_cmp(v, u) < 0) {0 }0 a  Z& b+ K% ?! d
                vli_add(v, v, mod);
6 W1 k) L: `+ X4 n  a+ o1 j* Y" h            }8 z% B- h( J2 C3 p% v2 G
            vli_sub(v, v, u);& A3 O7 z9 g3 x7 l( W, T7 F: n% y
            if (!EVEN(v)) {
8 [5 @& U! o& |3 l/ `                carry = vli_add(v, v, mod);
) |, U( A; E: i; ]/ e& b. z            }
- z2 o% ~3 `4 t* o* m  m, `. t0 p            vli_rshift1(v);# J& v) w+ W0 U3 g7 B
            if (carry) {2 k8 s. ]6 u* C. s% b: [" [0 ^5 N
                v[ec_WORDS - 1] |= HIGH_BIT_SET;
4 c  @) k! q( {4 J            }1 v7 V7 q+ @8 A% C4 [* R# K" t
        }; Y; k* V8 x/ U: V
    }
& `2 a& I* Z( V' o5 P    vli_set(result, u);
% c  r3 ~% y/ @. U! f8 v4 x}
. ]- k$ j3 I% _! W. T  b2 i! d; w% Q
static void apply_z(ec_word_t * RESTRICT X1,
# O. s0 w5 o4 c) O# i                    ec_word_t * RESTRICT Y1,: P9 r% D$ p' Q, j' k
                    const ec_word_t * RESTRICT Z) {! E1 r) i- K3 j) }, L/ j
    ec_word_t t1[ec_WORDS];" j* O/ L& f+ S# v

0 z% `% `3 q5 Y  N' T    vli_modSquare_fast(t1, Z);    /* z^2 */
! Y3 w! z7 p* W9 u- [$ R    vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */4 G" C7 r7 a5 I  ^
    vli_modMult_fast(t1, t1, Z);  /* z^3 */
# J6 N) f: {% z% {8 A; z    vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */9 |, ]% u2 M) z# E- N) R
}, r# l+ g. A; G$ ]% ?/ w

2 ^% Z# Q# `7 w% F; B  m  fstatic int vli_numBits(const ec_word_t *vli, wordcount_t max_words) {
  j/ c  W4 Y' ~    ec_word_t i;
2 M: J  Q6 Z" R  C! K! `. ], V    ec_word_t digit;
3 [5 P; m0 l7 F$ j  T
( [$ k# e0 x- t- Z3 L; W    wordcount_t num_digits = vli_numDigits(vli, max_words);8 ~4 Q" H  _" u
    if (num_digits == 0) {6 C* M( Y9 f( D
        return 0;# S+ ?* a* F& @4 `
    }
+ ^; g/ t- o- [: k8 ~5 a2 d; B; _6 J9 t6 m! B0 J: s3 f4 j
    digit = vli[num_digits - 1];% V2 l3 I+ ~8 Z3 ]7 g
    for (i = 0; digit; ++i) {
% A% W4 T/ J# w# ~5 l        digit >>= 1;1 e) h0 z" t% c/ L
    }
8 B8 ~# g" r+ W/ H2 i! j: D  `) [# J+ p7 k7 S( f2 v2 f
    return (((int)(num_digits - 1) << ec_WORD_BITS_SHIFT) + i);
% n$ S; n& g( S1 S% y' o9 F}
  J* A- x/ P" k* J: F' w) `' v
- ]( A- M2 N8 J$ K" `1 K8 cstatic wordcount_t vli_numDigits(const ec_word_t *vli, wordcount_t max_words) {
% R1 Z% @2 i' F4 ]  f; S5 `    int i;, [5 h) A3 u+ c( i# m
    /* Search from the end until we find a non-zero digit.
( h- ~; ~+ t5 F0 u( K       We do it in reverse because we expect that most digits will be nonzero. */6 G9 v0 x1 K- u+ V
    for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {- @" r* u, q& B- `
    }5 r/ A: f. F% a) B
8 Y3 O0 p+ Z5 w4 R+ J& e6 D
    return (i + 1);
/ C- z1 Q) M9 R' ?& z3 ]5 U" c}
+ f5 c) O/ F1 ]3 g2 y- o
8 Y9 G% |7 E2 g3 v. E8 Estatic ec_word_t vli_testBit(const ec_word_t *vli, int bit) {/ f2 n# ~7 {# [
    return (vli[bit >> ec_WORD_BITS_SHIFT] & ((ec_word_t)1 << (bit & ec_WORD_BITS_MASK)));4 [6 g( Z& Z+ R7 d$ T1 Y
}' o( n2 M: E2 f1 P; w

( @  S* s! S" y# istatic void vli_clear(ec_word_t *vli) {
8 m" s; r( f- C# y* G* W5 C# k    wordcount_t i;
! e+ F4 v" ?% u" E2 E( Y    for (i = 0; i < ec_WORDS; ++i) {. X7 V0 Y$ W5 l# `/ u- s
        vli[i] = 0;
' R0 G/ l7 k6 c    }
* B* k% u7 f) X' J& q# t, \}
$ F( [" L" r" ]5 v# ]+ B0 w  S$ M8 ?3 j1 C  b. U$ \5 t
static int smax(int a, int b) {
; u2 c8 |" c" u  w/ S  P- I    return (a > b ? a : b);6 k5 V/ @# Z  G1 o/ D" X5 P, K
}3 S$ ~6 E( e6 }; I) o9 i: W
4 H+ H5 C$ P2 ]1 s0 G& i% \
static int vli_cmp(const ec_word_t *left, const ec_word_t *right) {
6 r$ r3 w6 Z/ \% ]    int i;
  Y) [, [1 P, U) ~0 {* C    for (i = ec_WORDS - 1; i >= 0; --i) {7 U- g/ V/ ~* S9 V8 N2 M
        if (left[i] > right[i]) {
/ h- C2 v3 h6 `            return 1;. w( K) Z( l/ `2 s' I
        } else if (left[i] < right[i]) {
/ i  f2 u" `; Y' d6 l' P+ v1 F            return -1;3 W* p8 l8 ~' P
        }+ `0 M* }7 _% ^) u  N
    }
5 s) b+ _+ c) \) Q' F/ c/ b    return 0;
" |  G7 g! ]6 |/ |! m! P! I; [}
% O7 n; C/ f% e. n$ |! T! xstatic void vli_modAdd(ec_word_t *result, const ec_word_t *left, const ec_word_t *right, const ec_word_t *mod) {( ]8 J- l. k1 |4 T: V6 Y5 X
    ec_word_t carry = vli_add(result, left, right);
: z; A  P( _4 v7 W( z( u    if (carry || vli_cmp(result, mod) >= 0)
7 {/ j4 P  h' S3 Q) q) y        vli_sub(result, result, mod);
; M" e8 l: l: Y, r' C}$ c: w. o( F  l* l
" i& z  E9 ^/ `, z6 z6 Q( m4 o& }
static void vli_mmod_fast(ec_word_t *RESTRICT result, ec_word_t *RESTRICT product) {
- W/ p) v) z9 D( i2 T    ec_word_t tmp[2 * ec_WORDS];$ w. s4 \+ W3 [4 c" f/ Z
    ec_word_t carry;6 N( h! \" L" \6 v6 r0 }

3 A2 c2 d1 N6 a7 f3 ^1 k1 V% ~    vli_clear(tmp);5 U% G' Y/ R& l) O2 X
    vli_clear(tmp + ec_WORDS);
; B, R- i* P: w) w1 A& a5 _/ P. v+ f1 F6 U
    omega_mult(tmp, product + ec_WORDS); /* (Rq, q) = q * c */
# ?* N/ \# k$ T, Y% {4 ~3 G) J0 W9 V
    carry = vli_add(result, product, tmp); /* (C, r) = r + q       */
  g1 k: T/ r2 t3 O    vli_clear(product);
3 F) l: p2 i) ^: P) M    omega_mult(product, tmp + ec_WORDS); /* Rq*c */
# Y( H5 a, `) X    carry += vli_add(result, result, product); /* (C1, r) = r + Rq*c */
. E1 l1 E% e  X0 [" p1 t- I* H/ @+ o1 z& R8 E! @  v
    while (carry > 0) {
( {1 Y& @+ s' W/ {2 M        --carry;7 k0 j; O1 x$ h, W4 m5 Z1 |
        vli_sub(result, result, curve_p);) w. W9 d, H4 ~" |5 n; F3 M  v( w
    }+ u( F" o) N  S7 F- J
    if (vli_cmp(result, curve_p) > 0) {
0 r5 R% d( v7 w$ ?0 h        vli_sub(result, result, curve_p);
8 a& z# X3 K$ g! D: J    }
8 k. ~# v8 u( u* e* F6 y7 s( t}3 c. |  s# g+ b  D5 c# S, k

. i  l+ S7 d" |2 ?  lstatic void omega_mult(uint32_t * RESTRICT result, const uint32_t * RESTRICT right) {
" r: J7 ?; U, J' b, ?( Q1 ^    /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
( h5 c& [$ _7 y2 J& d    uint32_t carry = 0;
3 W0 u9 q; P- p6 I    wordcount_t k;0 \. b( V  ]4 u9 L5 [
; g- m( \( x0 K( h- I# @& E( J
    for (k = 0; k < ec_WORDS; ++k) {/ x- f1 g, X, }* V1 |6 ?& Q! I
        uint64_t p = (uint64_t)0x3D1 * right[k] + carry;- K; g% }4 D- P" {! V
        result[k] = (p & 0xffffffff);3 L  H. ]$ B& r+ ?- M! s% J
        carry = p >> 32;
2 p  \6 @4 p9 A- ~    }
4 ?, o" j; t& a* h6 H( t( P    result[ec_WORDS] = carry;
6 p7 s+ c# \' f, S! }2 v% A" \) a% |: d; S, C% S) J1 V
    result[1 + ec_WORDS] = vli_add(result + 1, result + 1, right); /* add the 2^32 multiple */
9 L! \8 c/ g& J! M$ H}3 v) s0 N4 h5 {# y3 M
, `; E: x) Z/ J: a' b4 l- }8 e0 T

& C2 {, ^* [: X; C, F$ A$ C; z: B/*************************************************************************/' W/ K9 M# h/ M3 s. z1 y
/*以下是sha256 算法 c语言实现*/
, u% F( M; z$ v% e9 B( z8 k" E/************************************************************************/
- y, I! L/ o8 `, n  f, `8 n7 I#define SHFR(x, n) (((x) >> (n)))+ }6 N( O6 L2 K- z3 `
#define ROTR(x, n) (((x) >> (n)) | ((x) << ((sizeof(x) << 3) - (n))))8 ^3 Y* q& j5 H6 G  e# a
#define ROTL(x, n) (((x) << (n)) | ((x) >> ((sizeof(x) << 3) - (n))))+ H" i8 e" A& |
( X) Q0 d9 T% q
#define CHX(x, y, z) (((x) &  (y)) ^ (~(x) & (z))): g3 R, K! h! E: E6 X$ B
#define MAJ(x, y, z) (((x) &  (y)) ^ ( (x) & (z)) ^ ((y) & (z)))+ F! f  b8 X; _, Y& f/ t, `
. x  ]  X  S; Y. h2 z
#define BSIG0(x) (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))% [+ ]  i* e; B" ]3 U' T
#define BSIG1(x) (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))% H# p# \3 d  ^! O" I
#define SSIG0(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))* |  [" |5 I- D+ k! m* U
#define SSIG1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))8 j& {1 l, Z3 V- Z- z
* v. w  T1 N3 z8 r' S
static uint32_t k[64] = {3 n' @% ^* w7 E! a7 a
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,8 m6 q. S- m' Y+ F  Q) t1 _( R5 Q
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
9 h% ]+ h* Q9 U4 ~    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,4 }3 i  s" J, ~. s9 v
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
* I* {/ q1 g" I& X6 o  ?  `    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
: x- y/ l) Y3 x$ |    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
% u4 p( |7 t6 E. W6 [    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
; y$ g, s! L- O9 n  Q$ C6 x    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f27 S+ v# }* {/ O. j  B7 P
};
6 v/ T# M( i5 B# W# i6 M! c1 c' F  L9 T. x( O
int dig(const uint8_t *msg, uint32_t *h){; V! J) A  D2 }+ F
    uint32_t w[64];, z4 U3 v- x1 f4 L; l) C  }
    uint32_t a0, b1, c2, d3, e4, f5, g6, h7;
; M4 g7 I8 p( O! F- J$ K    uint32_t t1, t2;
# H& ^7 x' C! u0 Q    int i = 0;/ G  h3 s5 a& D* L! w
    int j = 0;) ~8 ~5 W* a5 K8 A
    for (i=0; i<16; i++) {
) h/ V) C! _3 _! q' k# F' T        w[i] = msg[j]<<24 | msg[j+1]<<16 | msg[j+2]<<8 | msg[j+3];
" V' b6 O1 Z9 i. R        j += 4;( |5 B! s7 Z' V: W
    }
6 j- j$ c0 L. _5 Z3 M    for(i=16; i<64; i++)
9 O. j. g3 W: ~% J2 i        w[i] = SSIG1(w[i-2])+w[i-7]+SSIG0(w[i-15])+w[i-16];
' c9 O) f2 D7 Y$ }    a0 = h[0];
) A  @" b  p% c& N; K5 Y; U5 ?    b1 = h[1];
" p# t2 P9 R' ?0 h1 }    c2 = h[2];
) E) M/ _0 ^0 m7 l    d3 = h[3];
) u; y9 B) I$ P  g% X    e4 = h[4];
+ x. t) ?" |& ]& o8 c    f5 = h[5];
3 R3 u. b( S# P1 W    g6 = h[6];
5 \! u7 e- |3 Y; P9 W* a3 E# j4 X5 u    h7 = h[7];6 Q3 Z- g1 N3 `  U- O
  e5 m. g7 C1 c- t: F6 \
    for (i= 0; i<64; i++) {
- @' D9 e, [" B" Z        t1 = h7 + BSIG1(e4) + CHX(e4, f5, g6) + k[i] + w[i];* i& {* M. D) J1 J9 }. u% u8 e
        t2 = BSIG0(a0) + MAJ(a0, b1, c2);7 m4 m" x7 s7 Z7 l6 G
        h7 = g6;0 A3 f- q3 n: E' f0 N2 ~
        g6 = f5;, D( X( l8 _% W) m' r; O; O/ {
        f5 = e4;/ @& {1 ^1 f7 y2 l% T) U( r- G9 \
        e4 = d3 + t1;
8 e7 y; |0 F$ c/ V& ~. ~% m% Y        d3 = c2;+ c' [8 F9 L% C+ K  ~& ]% q3 m
        c2 = b1;
! O) _$ {/ `. o$ B) L1 R8 u2 @        b1 = a0;3 }' o- s- |3 |" c3 d  A
        a0 = t1 + t2;8 O2 M: Y! J- _! g
    }! H" m0 r' G2 G2 @% l! g$ f! ]( A3 `
1 K) Q  T2 \# x. i' e
    h[0] += a0;
5 m) p& u& c* e# u  M; B    h[1] += b1;( I( y) ]7 L$ P, j
    h[2] += c2;  Z" \7 ?4 S  r' L; Y5 b# n" {
    h[3] += d3;
& |' l8 s$ ~' E/ p7 v    h[4] += e4;
1 K2 X. t6 A$ A% o    h[5] += f5;
7 Y0 H1 b5 p' s$ `  j9 k    h[6] += g6;
" [# P: R% F. c# N, z$ ]    h[7] += h7;
+ R0 Z% ?  M$ E0 r, i) U& `1 y4 Z* c6 X$ O  _
    return 0;1 @7 H! Y# j2 u% y0 Y: b
}/ a( d9 G; x/ o
void tobe(uint8_t *lehash,uint8_t *out,uint8_t len){& a! F* s; M4 @2 P  H# X; S, ~
        int i =0,j=0;
. ^/ f0 Z: f7 K% W: B) x9 K0 H        for(i=0;i<len;i++)
/ n! H( R0 s: l( t# v* F                for(j=0;j<4;j++); @* z5 q" X& a
                        out[i*4+j] = lehash[(i+1)*4-j-1];
% D4 J7 N/ W3 R( k" N" A
) o8 ]7 A7 X+ I/ ?}
0 [5 M* M# X% u# ^) j  h1 f* @  v$ c
2 b( Y. I, p: L! nint sha256(const uint8_t *src, uint32_t len, uint8_t *hash){$ C7 J1 x9 j' q% ~' m2 k
        uint32_t h[8] = {0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19};- c& I4 w" o& K9 e+ A6 O
    uint32_t i;( M. {; \+ D; ]! R
    uint32_t bitlen = len * 8;
0 z; F" L9 t+ a    uint32_t n = len % 64 < 56 ? len / 64 + 1 : len / 64 + 2;/ E+ F) S( f* e
    uint32_t new_len = 64 * n;! |. R- k! |4 I0 D! K
    uint8_t  tmp[new_len];
5 c& J4 p! c& M          //bzero(tmp, new_len);/ g3 S3 L9 C2 X# x
                memset(tmp,0,new_len);! Q6 Y3 \* v2 U! u; l& p
    memcpy(tmp, src, len);
5 h  ?) Q* h4 {; O5 [" f  [% b) w    tmp[len] = 0x80;
; ]6 a8 C: V$ V0 ?; ?    tobe((uint8_t *)&bitlen,&tmp[new_len-4],1);/ Q! m! T  S* V* m7 j
# G& w. Y! N4 {" {
    for (i=0; i<n; i++)
. B( ]2 t1 Z% W8 H# q! a        dig(&tmp[i*64], h);' i4 e- O, H& W* {6 B) |( Q
           tobe((uint8_t *)h,hash,8);
# E6 P- D" ~5 w9 D; L/ h/ b    return 0;) x3 i+ z5 W% @' s
}! h& f# f, |: V( e0 ]
赞 收藏 1 评论0 发布时间:2019-5-6 07:04

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版