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

Annotation of src/usr.bin/ssh/fe25519.c, Revision 1.2

1.2     ! djm         1: /* $OpenBSD$ */
1.1       markus      2:
                      3: /* Public Domain, from supercop-20130419/crypto_sign/ed25519/ref/fe25519.c */
                      4:
                      5: #define WINDOWSIZE 1 /* Should be 1,2, or 4 */
                      6: #define WINDOWMASK ((1<<WINDOWSIZE)-1)
                      7:
                      8: #include "fe25519.h"
                      9:
                     10: static crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
                     11: {
                     12:   crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */
                     13:   x -= 1; /* 4294967295: yes; 0..65534: no */
                     14:   x >>= 31; /* 1: yes; 0: no */
                     15:   return x;
                     16: }
                     17:
                     18: static crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
                     19: {
                     20:   unsigned int x = a;
                     21:   x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */
                     22:   x >>= 31; /* 0: yes; 1: no */
                     23:   x ^= 1; /* 1: yes; 0: no */
                     24:   return x;
                     25: }
                     26:
                     27: static crypto_uint32 times19(crypto_uint32 a)
                     28: {
                     29:   return (a << 4) + (a << 1) + a;
                     30: }
                     31:
                     32: static crypto_uint32 times38(crypto_uint32 a)
                     33: {
                     34:   return (a << 5) + (a << 2) + (a << 1);
                     35: }
                     36:
                     37: static void reduce_add_sub(fe25519 *r)
                     38: {
                     39:   crypto_uint32 t;
                     40:   int i,rep;
                     41:
                     42:   for(rep=0;rep<4;rep++)
                     43:   {
                     44:     t = r->v[31] >> 7;
                     45:     r->v[31] &= 127;
                     46:     t = times19(t);
                     47:     r->v[0] += t;
                     48:     for(i=0;i<31;i++)
                     49:     {
                     50:       t = r->v[i] >> 8;
                     51:       r->v[i+1] += t;
                     52:       r->v[i] &= 255;
                     53:     }
                     54:   }
                     55: }
                     56:
                     57: static void reduce_mul(fe25519 *r)
                     58: {
                     59:   crypto_uint32 t;
                     60:   int i,rep;
                     61:
                     62:   for(rep=0;rep<2;rep++)
                     63:   {
                     64:     t = r->v[31] >> 7;
                     65:     r->v[31] &= 127;
                     66:     t = times19(t);
                     67:     r->v[0] += t;
                     68:     for(i=0;i<31;i++)
                     69:     {
                     70:       t = r->v[i] >> 8;
                     71:       r->v[i+1] += t;
                     72:       r->v[i] &= 255;
                     73:     }
                     74:   }
                     75: }
                     76:
                     77: /* reduction modulo 2^255-19 */
                     78: void fe25519_freeze(fe25519 *r)
                     79: {
                     80:   int i;
                     81:   crypto_uint32 m = equal(r->v[31],127);
                     82:   for(i=30;i>0;i--)
                     83:     m &= equal(r->v[i],255);
                     84:   m &= ge(r->v[0],237);
                     85:
                     86:   m = -m;
                     87:
                     88:   r->v[31] -= m&127;
                     89:   for(i=30;i>0;i--)
                     90:     r->v[i] -= m&255;
                     91:   r->v[0] -= m&237;
                     92: }
                     93:
                     94: void fe25519_unpack(fe25519 *r, const unsigned char x[32])
                     95: {
                     96:   int i;
                     97:   for(i=0;i<32;i++) r->v[i] = x[i];
                     98:   r->v[31] &= 127;
                     99: }
                    100:
                    101: /* Assumes input x being reduced below 2^255 */
                    102: void fe25519_pack(unsigned char r[32], const fe25519 *x)
                    103: {
                    104:   int i;
                    105:   fe25519 y = *x;
                    106:   fe25519_freeze(&y);
                    107:   for(i=0;i<32;i++)
                    108:     r[i] = y.v[i];
                    109: }
                    110:
                    111: int fe25519_iszero(const fe25519 *x)
                    112: {
                    113:   int i;
                    114:   int r;
                    115:   fe25519 t = *x;
                    116:   fe25519_freeze(&t);
                    117:   r = equal(t.v[0],0);
                    118:   for(i=1;i<32;i++)
                    119:     r &= equal(t.v[i],0);
                    120:   return r;
                    121: }
                    122:
                    123: int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y)
                    124: {
                    125:   int i;
                    126:   fe25519 t1 = *x;
                    127:   fe25519 t2 = *y;
                    128:   fe25519_freeze(&t1);
                    129:   fe25519_freeze(&t2);
                    130:   for(i=0;i<32;i++)
                    131:     if(t1.v[i] != t2.v[i]) return 0;
                    132:   return 1;
                    133: }
                    134:
                    135: void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b)
                    136: {
                    137:   int i;
                    138:   crypto_uint32 mask = b;
                    139:   mask = -mask;
                    140:   for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]);
                    141: }
                    142:
                    143: unsigned char fe25519_getparity(const fe25519 *x)
                    144: {
                    145:   fe25519 t = *x;
                    146:   fe25519_freeze(&t);
                    147:   return t.v[0] & 1;
                    148: }
                    149:
                    150: void fe25519_setone(fe25519 *r)
                    151: {
                    152:   int i;
                    153:   r->v[0] = 1;
                    154:   for(i=1;i<32;i++) r->v[i]=0;
                    155: }
                    156:
                    157: void fe25519_setzero(fe25519 *r)
                    158: {
                    159:   int i;
                    160:   for(i=0;i<32;i++) r->v[i]=0;
                    161: }
                    162:
                    163: void fe25519_neg(fe25519 *r, const fe25519 *x)
                    164: {
                    165:   fe25519 t;
                    166:   int i;
                    167:   for(i=0;i<32;i++) t.v[i]=x->v[i];
                    168:   fe25519_setzero(r);
                    169:   fe25519_sub(r, r, &t);
                    170: }
                    171:
                    172: void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y)
                    173: {
                    174:   int i;
                    175:   for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i];
                    176:   reduce_add_sub(r);
                    177: }
                    178:
                    179: void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y)
                    180: {
                    181:   int i;
                    182:   crypto_uint32 t[32];
                    183:   t[0] = x->v[0] + 0x1da;
                    184:   t[31] = x->v[31] + 0xfe;
                    185:   for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe;
                    186:   for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i];
                    187:   reduce_add_sub(r);
                    188: }
                    189:
                    190: void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y)
                    191: {
                    192:   int i,j;
                    193:   crypto_uint32 t[63];
                    194:   for(i=0;i<63;i++)t[i] = 0;
                    195:
                    196:   for(i=0;i<32;i++)
                    197:     for(j=0;j<32;j++)
                    198:       t[i+j] += x->v[i] * y->v[j];
                    199:
                    200:   for(i=32;i<63;i++)
                    201:     r->v[i-32] = t[i-32] + times38(t[i]);
                    202:   r->v[31] = t[31]; /* result now in r[0]...r[31] */
                    203:
                    204:   reduce_mul(r);
                    205: }
                    206:
                    207: void fe25519_square(fe25519 *r, const fe25519 *x)
                    208: {
                    209:   fe25519_mul(r, x, x);
                    210: }
                    211:
                    212: void fe25519_invert(fe25519 *r, const fe25519 *x)
                    213: {
                    214:        fe25519 z2;
                    215:        fe25519 z9;
                    216:        fe25519 z11;
                    217:        fe25519 z2_5_0;
                    218:        fe25519 z2_10_0;
                    219:        fe25519 z2_20_0;
                    220:        fe25519 z2_50_0;
                    221:        fe25519 z2_100_0;
                    222:        fe25519 t0;
                    223:        fe25519 t1;
                    224:        int i;
                    225:
                    226:        /* 2 */ fe25519_square(&z2,x);
                    227:        /* 4 */ fe25519_square(&t1,&z2);
                    228:        /* 8 */ fe25519_square(&t0,&t1);
                    229:        /* 9 */ fe25519_mul(&z9,&t0,x);
                    230:        /* 11 */ fe25519_mul(&z11,&z9,&z2);
                    231:        /* 22 */ fe25519_square(&t0,&z11);
                    232:        /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t0,&z9);
                    233:
                    234:        /* 2^6 - 2^1 */ fe25519_square(&t0,&z2_5_0);
                    235:        /* 2^7 - 2^2 */ fe25519_square(&t1,&t0);
                    236:        /* 2^8 - 2^3 */ fe25519_square(&t0,&t1);
                    237:        /* 2^9 - 2^4 */ fe25519_square(&t1,&t0);
                    238:        /* 2^10 - 2^5 */ fe25519_square(&t0,&t1);
                    239:        /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t0,&z2_5_0);
                    240:
                    241:        /* 2^11 - 2^1 */ fe25519_square(&t0,&z2_10_0);
                    242:        /* 2^12 - 2^2 */ fe25519_square(&t1,&t0);
                    243:        /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
                    244:        /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t1,&z2_10_0);
                    245:
                    246:        /* 2^21 - 2^1 */ fe25519_square(&t0,&z2_20_0);
                    247:        /* 2^22 - 2^2 */ fe25519_square(&t1,&t0);
                    248:        /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
                    249:        /* 2^40 - 2^0 */ fe25519_mul(&t0,&t1,&z2_20_0);
                    250:
                    251:        /* 2^41 - 2^1 */ fe25519_square(&t1,&t0);
                    252:        /* 2^42 - 2^2 */ fe25519_square(&t0,&t1);
                    253:        /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
                    254:        /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0);
                    255:
                    256:        /* 2^51 - 2^1 */ fe25519_square(&t0,&z2_50_0);
                    257:        /* 2^52 - 2^2 */ fe25519_square(&t1,&t0);
                    258:        /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
                    259:        /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t1,&z2_50_0);
                    260:
                    261:        /* 2^101 - 2^1 */ fe25519_square(&t1,&z2_100_0);
                    262:        /* 2^102 - 2^2 */ fe25519_square(&t0,&t1);
                    263:        /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
                    264:        /* 2^200 - 2^0 */ fe25519_mul(&t1,&t0,&z2_100_0);
                    265:
                    266:        /* 2^201 - 2^1 */ fe25519_square(&t0,&t1);
                    267:        /* 2^202 - 2^2 */ fe25519_square(&t1,&t0);
                    268:        /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
                    269:        /* 2^250 - 2^0 */ fe25519_mul(&t0,&t1,&z2_50_0);
                    270:
                    271:        /* 2^251 - 2^1 */ fe25519_square(&t1,&t0);
                    272:        /* 2^252 - 2^2 */ fe25519_square(&t0,&t1);
                    273:        /* 2^253 - 2^3 */ fe25519_square(&t1,&t0);
                    274:        /* 2^254 - 2^4 */ fe25519_square(&t0,&t1);
                    275:        /* 2^255 - 2^5 */ fe25519_square(&t1,&t0);
                    276:        /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11);
                    277: }
                    278:
                    279: void fe25519_pow2523(fe25519 *r, const fe25519 *x)
                    280: {
                    281:        fe25519 z2;
                    282:        fe25519 z9;
                    283:        fe25519 z11;
                    284:        fe25519 z2_5_0;
                    285:        fe25519 z2_10_0;
                    286:        fe25519 z2_20_0;
                    287:        fe25519 z2_50_0;
                    288:        fe25519 z2_100_0;
                    289:        fe25519 t;
                    290:        int i;
                    291:
                    292:        /* 2 */ fe25519_square(&z2,x);
                    293:        /* 4 */ fe25519_square(&t,&z2);
                    294:        /* 8 */ fe25519_square(&t,&t);
                    295:        /* 9 */ fe25519_mul(&z9,&t,x);
                    296:        /* 11 */ fe25519_mul(&z11,&z9,&z2);
                    297:        /* 22 */ fe25519_square(&t,&z11);
                    298:        /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9);
                    299:
                    300:        /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0);
                    301:        /* 2^10 - 2^5 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); }
                    302:        /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0);
                    303:
                    304:        /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0);
                    305:        /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
                    306:        /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0);
                    307:
                    308:        /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0);
                    309:        /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); }
                    310:        /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0);
                    311:
                    312:        /* 2^41 - 2^1 */ fe25519_square(&t,&t);
                    313:        /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
                    314:        /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0);
                    315:
                    316:        /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0);
                    317:        /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
                    318:        /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0);
                    319:
                    320:        /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0);
                    321:        /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); }
                    322:        /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0);
                    323:
                    324:        /* 2^201 - 2^1 */ fe25519_square(&t,&t);
                    325:        /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
                    326:        /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0);
                    327:
                    328:        /* 2^251 - 2^1 */ fe25519_square(&t,&t);
                    329:        /* 2^252 - 2^2 */ fe25519_square(&t,&t);
                    330:        /* 2^252 - 3 */ fe25519_mul(r,&t,x);
                    331: }