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