[BACK]Return to mod_ge25519.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / signify

Annotation of src/usr.bin/signify/mod_ge25519.c, Revision 1.2

1.2     ! deraadt     1: /* $OpenBSD: mod_ge25519.c,v 1.1 2014/01/08 05:00:01 tedu Exp $ */
1.1       tedu        2:
                      3: /*
                      4:  * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
                      5:  * Peter Schwabe, Bo-Yin Yang.
                      6:  * Copied from supercop-20130419/crypto_sign/ed25519/ref/ge25519.c
                      7:  */
                      8:
                      9: #include "fe25519.h"
                     10: #include "sc25519.h"
                     11: #include "ge25519.h"
                     12:
                     13: /*
                     14:  * Arithmetic on the twisted Edwards curve -x^2 + y^2 = 1 + dx^2y^2
                     15:  * with d = -(121665/121666) = 37095705934669439343138083508754565189542113879843219016388785533085940283555
                     16:  * Base point: (15112221349535400772501151409588531511454012693041857206046113283949847762202,46316835694926478169428394003475163141307993866256225615783033603165251855960);
                     17:  */
                     18:
                     19: /* d */
                     20: static const fe25519 ge25519_ecd = {{0xA3, 0x78, 0x59, 0x13, 0xCA, 0x4D, 0xEB, 0x75, 0xAB, 0xD8, 0x41, 0x41, 0x4D, 0x0A, 0x70, 0x00,
                     21:                       0x98, 0xE8, 0x79, 0x77, 0x79, 0x40, 0xC7, 0x8C, 0x73, 0xFE, 0x6F, 0x2B, 0xEE, 0x6C, 0x03, 0x52}};
                     22: /* 2*d */
                     23: static const fe25519 ge25519_ec2d = {{0x59, 0xF1, 0xB2, 0x26, 0x94, 0x9B, 0xD6, 0xEB, 0x56, 0xB1, 0x83, 0x82, 0x9A, 0x14, 0xE0, 0x00,
                     24:                        0x30, 0xD1, 0xF3, 0xEE, 0xF2, 0x80, 0x8E, 0x19, 0xE7, 0xFC, 0xDF, 0x56, 0xDC, 0xD9, 0x06, 0x24}};
                     25: /* sqrt(-1) */
                     26: static const fe25519 ge25519_sqrtm1 = {{0xB0, 0xA0, 0x0E, 0x4A, 0x27, 0x1B, 0xEE, 0xC4, 0x78, 0xE4, 0x2F, 0xAD, 0x06, 0x18, 0x43, 0x2F,
                     27:                          0xA7, 0xD7, 0xFB, 0x3D, 0x99, 0x00, 0x4D, 0x2B, 0x0B, 0xDF, 0xC1, 0x4F, 0x80, 0x24, 0x83, 0x2B}};
                     28:
                     29: #define ge25519_p3 ge25519
                     30:
                     31: typedef struct
                     32: {
                     33:   fe25519 x;
                     34:   fe25519 z;
                     35:   fe25519 y;
                     36:   fe25519 t;
                     37: } ge25519_p1p1;
                     38:
                     39: typedef struct
                     40: {
                     41:   fe25519 x;
                     42:   fe25519 y;
                     43:   fe25519 z;
                     44: } ge25519_p2;
                     45:
                     46: typedef struct
                     47: {
                     48:   fe25519 x;
                     49:   fe25519 y;
                     50: } ge25519_aff;
                     51:
                     52:
                     53: /* Packed coordinates of the base point */
                     54: const ge25519 ge25519_base = {{{0x1A, 0xD5, 0x25, 0x8F, 0x60, 0x2D, 0x56, 0xC9, 0xB2, 0xA7, 0x25, 0x95, 0x60, 0xC7, 0x2C, 0x69,
                     55:                                 0x5C, 0xDC, 0xD6, 0xFD, 0x31, 0xE2, 0xA4, 0xC0, 0xFE, 0x53, 0x6E, 0xCD, 0xD3, 0x36, 0x69, 0x21}},
                     56:                               {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
                     57:                                 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}},
                     58:                               {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                     59:                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
                     60:                               {{0xA3, 0xDD, 0xB7, 0xA5, 0xB3, 0x8A, 0xDE, 0x6D, 0xF5, 0x52, 0x51, 0x77, 0x80, 0x9F, 0xF0, 0x20,
                     61:                                 0x7D, 0xE3, 0xAB, 0x64, 0x8E, 0x4E, 0xEA, 0x66, 0x65, 0x76, 0x8B, 0xD7, 0x0F, 0x5F, 0x87, 0x67}}};
                     62:
                     63: #ifndef VERIFYONLY
                     64: /* Multiples of the base point in affine representation */
                     65: static const ge25519_aff ge25519_base_multiples_affine[425] = {
                     66: #include "ge25519_base.data"
                     67: };
                     68: #endif
                     69:
                     70: static void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p)
                     71: {
                     72:   fe25519_mul(&r->x, &p->x, &p->t);
                     73:   fe25519_mul(&r->y, &p->y, &p->z);
                     74:   fe25519_mul(&r->z, &p->z, &p->t);
                     75: }
                     76:
                     77: static void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p)
                     78: {
                     79:   p1p1_to_p2((ge25519_p2 *)r, p);
                     80:   fe25519_mul(&r->t, &p->x, &p->y);
                     81: }
                     82:
1.2     ! deraadt    83: #ifndef VERIFYONLY
1.1       tedu       84: static void ge25519_mixadd2(ge25519_p3 *r, const ge25519_aff *q)
                     85: {
                     86:   fe25519 a,b,t1,t2,c,d,e,f,g,h,qt;
                     87:   fe25519_mul(&qt, &q->x, &q->y);
                     88:   fe25519_sub(&a, &r->y, &r->x); /* A = (Y1-X1)*(Y2-X2) */
                     89:   fe25519_add(&b, &r->y, &r->x); /* B = (Y1+X1)*(Y2+X2) */
                     90:   fe25519_sub(&t1, &q->y, &q->x);
                     91:   fe25519_add(&t2, &q->y, &q->x);
                     92:   fe25519_mul(&a, &a, &t1);
                     93:   fe25519_mul(&b, &b, &t2);
                     94:   fe25519_sub(&e, &b, &a); /* E = B-A */
                     95:   fe25519_add(&h, &b, &a); /* H = B+A */
                     96:   fe25519_mul(&c, &r->t, &qt); /* C = T1*k*T2 */
                     97:   fe25519_mul(&c, &c, &ge25519_ec2d);
                     98:   fe25519_add(&d, &r->z, &r->z); /* D = Z1*2 */
                     99:   fe25519_sub(&f, &d, &c); /* F = D-C */
                    100:   fe25519_add(&g, &d, &c); /* G = D+C */
                    101:   fe25519_mul(&r->x, &e, &f);
                    102:   fe25519_mul(&r->y, &h, &g);
                    103:   fe25519_mul(&r->z, &g, &f);
                    104:   fe25519_mul(&r->t, &e, &h);
                    105: }
1.2     ! deraadt   106: #endif
1.1       tedu      107:
                    108: static void add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q)
                    109: {
                    110:   fe25519 a, b, c, d, t;
                    111:
                    112:   fe25519_sub(&a, &p->y, &p->x); /* A = (Y1-X1)*(Y2-X2) */
                    113:   fe25519_sub(&t, &q->y, &q->x);
                    114:   fe25519_mul(&a, &a, &t);
                    115:   fe25519_add(&b, &p->x, &p->y); /* B = (Y1+X1)*(Y2+X2) */
                    116:   fe25519_add(&t, &q->x, &q->y);
                    117:   fe25519_mul(&b, &b, &t);
                    118:   fe25519_mul(&c, &p->t, &q->t); /* C = T1*k*T2 */
                    119:   fe25519_mul(&c, &c, &ge25519_ec2d);
                    120:   fe25519_mul(&d, &p->z, &q->z); /* D = Z1*2*Z2 */
                    121:   fe25519_add(&d, &d, &d);
                    122:   fe25519_sub(&r->x, &b, &a); /* E = B-A */
                    123:   fe25519_sub(&r->t, &d, &c); /* F = D-C */
                    124:   fe25519_add(&r->z, &d, &c); /* G = D+C */
                    125:   fe25519_add(&r->y, &b, &a); /* H = B+A */
                    126: }
                    127:
                    128: /* See http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd */
                    129: static void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p)
                    130: {
                    131:   fe25519 a,b,c,d;
                    132:   fe25519_square(&a, &p->x);
                    133:   fe25519_square(&b, &p->y);
                    134:   fe25519_square(&c, &p->z);
                    135:   fe25519_add(&c, &c, &c);
                    136:   fe25519_neg(&d, &a);
                    137:
                    138:   fe25519_add(&r->x, &p->x, &p->y);
                    139:   fe25519_square(&r->x, &r->x);
                    140:   fe25519_sub(&r->x, &r->x, &a);
                    141:   fe25519_sub(&r->x, &r->x, &b);
                    142:   fe25519_add(&r->z, &d, &b);
                    143:   fe25519_sub(&r->t, &r->z, &c);
                    144:   fe25519_sub(&r->y, &d, &b);
                    145: }
                    146:
1.2     ! deraadt   147: #ifndef VERIFYONLY
1.1       tedu      148: /* Constant-time version of: if(b) r = p */
                    149: static void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b)
                    150: {
                    151:   fe25519_cmov(&r->x, &p->x, b);
                    152:   fe25519_cmov(&r->y, &p->y, b);
                    153: }
                    154:
                    155: static unsigned char equal(signed char b,signed char c)
                    156: {
                    157:   unsigned char ub = b;
                    158:   unsigned char uc = c;
                    159:   unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
                    160:   crypto_uint32 y = x; /* 0: yes; 1..255: no */
                    161:   y -= 1; /* 4294967295: yes; 0..254: no */
                    162:   y >>= 31; /* 1: yes; 0: no */
                    163:   return y;
                    164: }
                    165:
                    166: static unsigned char negative(signed char b)
                    167: {
                    168:   unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
                    169:   x >>= 63; /* 1: yes; 0: no */
                    170:   return x;
                    171: }
                    172:
                    173: static void choose_t(ge25519_aff *t, unsigned long long pos, signed char b)
                    174: {
                    175:   /* constant time */
                    176:   fe25519 v;
                    177:   *t = ge25519_base_multiples_affine[5*pos+0];
                    178:   cmov_aff(t, &ge25519_base_multiples_affine[5*pos+1],equal(b,1) | equal(b,-1));
                    179:   cmov_aff(t, &ge25519_base_multiples_affine[5*pos+2],equal(b,2) | equal(b,-2));
                    180:   cmov_aff(t, &ge25519_base_multiples_affine[5*pos+3],equal(b,3) | equal(b,-3));
                    181:   cmov_aff(t, &ge25519_base_multiples_affine[5*pos+4],equal(b,-4));
                    182:   fe25519_neg(&v, &t->x);
                    183:   fe25519_cmov(&t->x, &v, negative(b));
                    184: }
                    185: #endif
                    186:
                    187: static void setneutral(ge25519 *r)
                    188: {
                    189:   fe25519_setzero(&r->x);
                    190:   fe25519_setone(&r->y);
                    191:   fe25519_setone(&r->z);
                    192:   fe25519_setzero(&r->t);
                    193: }
                    194:
                    195: /* ********************************************************************
                    196:  *                    EXPORTED FUNCTIONS
                    197:  ******************************************************************** */
                    198:
                    199: /* return 0 on success, -1 otherwise */
                    200: int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32])
                    201: {
                    202:   unsigned char par;
                    203:   fe25519 t, chk, num, den, den2, den4, den6;
                    204:   fe25519_setone(&r->z);
                    205:   par = p[31] >> 7;
                    206:   fe25519_unpack(&r->y, p);
                    207:   fe25519_square(&num, &r->y); /* x = y^2 */
                    208:   fe25519_mul(&den, &num, &ge25519_ecd); /* den = dy^2 */
                    209:   fe25519_sub(&num, &num, &r->z); /* x = y^2-1 */
                    210:   fe25519_add(&den, &r->z, &den); /* den = dy^2+1 */
                    211:
                    212:   /* Computation of sqrt(num/den) */
                    213:   /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */
                    214:   fe25519_square(&den2, &den);
                    215:   fe25519_square(&den4, &den2);
                    216:   fe25519_mul(&den6, &den4, &den2);
                    217:   fe25519_mul(&t, &den6, &num);
                    218:   fe25519_mul(&t, &t, &den);
                    219:
                    220:   fe25519_pow2523(&t, &t);
                    221:   /* 2. computation of r->x = t * num * den^3 */
                    222:   fe25519_mul(&t, &t, &num);
                    223:   fe25519_mul(&t, &t, &den);
                    224:   fe25519_mul(&t, &t, &den);
                    225:   fe25519_mul(&r->x, &t, &den);
                    226:
                    227:   /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not: */
                    228:   fe25519_square(&chk, &r->x);
                    229:   fe25519_mul(&chk, &chk, &den);
                    230:   if (!fe25519_iseq_vartime(&chk, &num))
                    231:     fe25519_mul(&r->x, &r->x, &ge25519_sqrtm1);
                    232:
                    233:   /* 4. Now we have one of the two square roots, except if input was not a square */
                    234:   fe25519_square(&chk, &r->x);
                    235:   fe25519_mul(&chk, &chk, &den);
                    236:   if (!fe25519_iseq_vartime(&chk, &num))
                    237:     return -1;
                    238:
                    239:   /* 5. Choose the desired square root according to parity: */
                    240:   if(fe25519_getparity(&r->x) != (1-par))
                    241:     fe25519_neg(&r->x, &r->x);
                    242:
                    243:   fe25519_mul(&r->t, &r->x, &r->y);
                    244:   return 0;
                    245: }
                    246:
                    247: void ge25519_pack(unsigned char r[32], const ge25519_p3 *p)
                    248: {
                    249:   fe25519 tx, ty, zi;
                    250:   fe25519_invert(&zi, &p->z);
                    251:   fe25519_mul(&tx, &p->x, &zi);
                    252:   fe25519_mul(&ty, &p->y, &zi);
                    253:   fe25519_pack(r, &ty);
                    254:   r[31] ^= fe25519_getparity(&tx) << 7;
                    255: }
                    256:
                    257: int ge25519_isneutral_vartime(const ge25519_p3 *p)
                    258: {
                    259:   int ret = 1;
                    260:   if(!fe25519_iszero(&p->x)) ret = 0;
                    261:   if(!fe25519_iseq_vartime(&p->y, &p->z)) ret = 0;
                    262:   return ret;
                    263: }
                    264:
                    265: /* computes [s1]p1 + [s2]p2 */
                    266: void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2)
                    267: {
                    268:   ge25519_p1p1 tp1p1;
                    269:   ge25519_p3 pre[16];
                    270:   unsigned char b[127];
                    271:   int i;
                    272:
                    273:   /* precomputation                                                        s2 s1 */
                    274:   setneutral(pre);                                                      /* 00 00 */
                    275:   pre[1] = *p1;                                                         /* 00 01 */
                    276:   dbl_p1p1(&tp1p1,(ge25519_p2 *)p1);      p1p1_to_p3( &pre[2], &tp1p1); /* 00 10 */
                    277:   add_p1p1(&tp1p1,&pre[1], &pre[2]);      p1p1_to_p3( &pre[3], &tp1p1); /* 00 11 */
                    278:   pre[4] = *p2;                                                         /* 01 00 */
                    279:   add_p1p1(&tp1p1,&pre[1], &pre[4]);      p1p1_to_p3( &pre[5], &tp1p1); /* 01 01 */
                    280:   add_p1p1(&tp1p1,&pre[2], &pre[4]);      p1p1_to_p3( &pre[6], &tp1p1); /* 01 10 */
                    281:   add_p1p1(&tp1p1,&pre[3], &pre[4]);      p1p1_to_p3( &pre[7], &tp1p1); /* 01 11 */
                    282:   dbl_p1p1(&tp1p1,(ge25519_p2 *)p2);      p1p1_to_p3( &pre[8], &tp1p1); /* 10 00 */
                    283:   add_p1p1(&tp1p1,&pre[1], &pre[8]);      p1p1_to_p3( &pre[9], &tp1p1); /* 10 01 */
                    284:   dbl_p1p1(&tp1p1,(ge25519_p2 *)&pre[5]); p1p1_to_p3(&pre[10], &tp1p1); /* 10 10 */
                    285:   add_p1p1(&tp1p1,&pre[3], &pre[8]);      p1p1_to_p3(&pre[11], &tp1p1); /* 10 11 */
                    286:   add_p1p1(&tp1p1,&pre[4], &pre[8]);      p1p1_to_p3(&pre[12], &tp1p1); /* 11 00 */
                    287:   add_p1p1(&tp1p1,&pre[1],&pre[12]);      p1p1_to_p3(&pre[13], &tp1p1); /* 11 01 */
                    288:   add_p1p1(&tp1p1,&pre[2],&pre[12]);      p1p1_to_p3(&pre[14], &tp1p1); /* 11 10 */
                    289:   add_p1p1(&tp1p1,&pre[3],&pre[12]);      p1p1_to_p3(&pre[15], &tp1p1); /* 11 11 */
                    290:
                    291:   sc25519_2interleave2(b,s1,s2);
                    292:
                    293:   /* scalar multiplication */
                    294:   *r = pre[b[126]];
                    295:   for(i=125;i>=0;i--)
                    296:   {
                    297:     dbl_p1p1(&tp1p1, (ge25519_p2 *)r);
                    298:     p1p1_to_p2((ge25519_p2 *) r, &tp1p1);
                    299:     dbl_p1p1(&tp1p1, (ge25519_p2 *)r);
                    300:     if(b[i]!=0)
                    301:     {
                    302:       p1p1_to_p3(r, &tp1p1);
                    303:       add_p1p1(&tp1p1, r, &pre[b[i]]);
                    304:     }
                    305:     if(i != 0) p1p1_to_p2((ge25519_p2 *)r, &tp1p1);
                    306:     else p1p1_to_p3(r, &tp1p1);
                    307:   }
                    308: }
                    309:
                    310: #ifndef VERIFYONLY
                    311: void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s)
                    312: {
                    313:   signed char b[85];
                    314:   int i;
                    315:   ge25519_aff t;
                    316:   sc25519_window3(b,s);
                    317:
                    318:   choose_t((ge25519_aff *)r, 0, b[0]);
                    319:   fe25519_setone(&r->z);
                    320:   fe25519_mul(&r->t, &r->x, &r->y);
                    321:   for(i=1;i<85;i++)
                    322:   {
                    323:     choose_t(&t, (unsigned long long) i, b[i]);
                    324:     ge25519_mixadd2(r, &t);
                    325:   }
                    326: }
                    327: #endif