1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: smult_curve25519_ref.c,v 1.2 2013/11/02 22:02:14 markus Exp $ */ 2d059297112922cabb0c674840589be8db821fd9aAdam Langley/* 3d059297112922cabb0c674840589be8db821fd9aAdam Langleyversion 20081011 4d059297112922cabb0c674840589be8db821fd9aAdam LangleyMatthew Dempsky 5d059297112922cabb0c674840589be8db821fd9aAdam LangleyPublic domain. 6d059297112922cabb0c674840589be8db821fd9aAdam LangleyDerived from public domain code by D. J. Bernstein. 7d059297112922cabb0c674840589be8db821fd9aAdam Langley*/ 8d059297112922cabb0c674840589be8db821fd9aAdam Langley 9d059297112922cabb0c674840589be8db821fd9aAdam Langleyint crypto_scalarmult_curve25519(unsigned char *, const unsigned char *, const unsigned char *); 10d059297112922cabb0c674840589be8db821fd9aAdam Langley 11d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) 12d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 13d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int j; 14d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int u; 15d059297112922cabb0c674840589be8db821fd9aAdam Langley u = 0; 16d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 31;++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; } 17d059297112922cabb0c674840589be8db821fd9aAdam Langley u += a[31] + b[31]; out[31] = u; 18d059297112922cabb0c674840589be8db821fd9aAdam Langley} 19d059297112922cabb0c674840589be8db821fd9aAdam Langley 20d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void sub(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) 21d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 22d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int j; 23d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int u; 24d059297112922cabb0c674840589be8db821fd9aAdam Langley u = 218; 25d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 31;++j) { 26d059297112922cabb0c674840589be8db821fd9aAdam Langley u += a[j] + 65280 - b[j]; 27d059297112922cabb0c674840589be8db821fd9aAdam Langley out[j] = u & 255; 28d059297112922cabb0c674840589be8db821fd9aAdam Langley u >>= 8; 29d059297112922cabb0c674840589be8db821fd9aAdam Langley } 30d059297112922cabb0c674840589be8db821fd9aAdam Langley u += a[31] - b[31]; 31d059297112922cabb0c674840589be8db821fd9aAdam Langley out[31] = u; 32d059297112922cabb0c674840589be8db821fd9aAdam Langley} 33d059297112922cabb0c674840589be8db821fd9aAdam Langley 34d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void squeeze(unsigned int a[32]) 35d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 36d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int j; 37d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int u; 38d059297112922cabb0c674840589be8db821fd9aAdam Langley u = 0; 39d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } 40d059297112922cabb0c674840589be8db821fd9aAdam Langley u += a[31]; a[31] = u & 127; 41d059297112922cabb0c674840589be8db821fd9aAdam Langley u = 19 * (u >> 7); 42d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } 43d059297112922cabb0c674840589be8db821fd9aAdam Langley u += a[31]; a[31] = u; 44d059297112922cabb0c674840589be8db821fd9aAdam Langley} 45d059297112922cabb0c674840589be8db821fd9aAdam Langley 46d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic const unsigned int minusp[32] = { 47d059297112922cabb0c674840589be8db821fd9aAdam Langley 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 48d059297112922cabb0c674840589be8db821fd9aAdam Langley} ; 49d059297112922cabb0c674840589be8db821fd9aAdam Langley 50d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void freeze(unsigned int a[32]) 51d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 52d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int aorig[32]; 53d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int j; 54d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int negative; 55d059297112922cabb0c674840589be8db821fd9aAdam Langley 56d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 32;++j) aorig[j] = a[j]; 57d059297112922cabb0c674840589be8db821fd9aAdam Langley add(a,a,minusp); 58d059297112922cabb0c674840589be8db821fd9aAdam Langley negative = -((a[31] >> 7) & 1); 59d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 32;++j) a[j] ^= negative & (aorig[j] ^ a[j]); 60d059297112922cabb0c674840589be8db821fd9aAdam Langley} 61d059297112922cabb0c674840589be8db821fd9aAdam Langley 62d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void mult(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) 63d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 64d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int i; 65d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int j; 66d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int u; 67d059297112922cabb0c674840589be8db821fd9aAdam Langley 68d059297112922cabb0c674840589be8db821fd9aAdam Langley for (i = 0;i < 32;++i) { 69d059297112922cabb0c674840589be8db821fd9aAdam Langley u = 0; 70d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j <= i;++j) u += a[j] * b[i - j]; 71d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = i + 1;j < 32;++j) u += 38 * a[j] * b[i + 32 - j]; 72d059297112922cabb0c674840589be8db821fd9aAdam Langley out[i] = u; 73d059297112922cabb0c674840589be8db821fd9aAdam Langley } 74d059297112922cabb0c674840589be8db821fd9aAdam Langley squeeze(out); 75d059297112922cabb0c674840589be8db821fd9aAdam Langley} 76d059297112922cabb0c674840589be8db821fd9aAdam Langley 77d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void mult121665(unsigned int out[32],const unsigned int a[32]) 78d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 79d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int j; 80d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int u; 81d059297112922cabb0c674840589be8db821fd9aAdam Langley 82d059297112922cabb0c674840589be8db821fd9aAdam Langley u = 0; 83d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 31;++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; } 84d059297112922cabb0c674840589be8db821fd9aAdam Langley u += 121665 * a[31]; out[31] = u & 127; 85d059297112922cabb0c674840589be8db821fd9aAdam Langley u = 19 * (u >> 7); 86d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 31;++j) { u += out[j]; out[j] = u & 255; u >>= 8; } 87d059297112922cabb0c674840589be8db821fd9aAdam Langley u += out[j]; out[j] = u; 88d059297112922cabb0c674840589be8db821fd9aAdam Langley} 89d059297112922cabb0c674840589be8db821fd9aAdam Langley 90d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void square(unsigned int out[32],const unsigned int a[32]) 91d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 92d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int i; 93d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int j; 94d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int u; 95d059297112922cabb0c674840589be8db821fd9aAdam Langley 96d059297112922cabb0c674840589be8db821fd9aAdam Langley for (i = 0;i < 32;++i) { 97d059297112922cabb0c674840589be8db821fd9aAdam Langley u = 0; 98d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < i - j;++j) u += a[j] * a[i - j]; 99d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = i + 1;j < i + 32 - j;++j) u += 38 * a[j] * a[i + 32 - j]; 100d059297112922cabb0c674840589be8db821fd9aAdam Langley u *= 2; 101d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((i & 1) == 0) { 102d059297112922cabb0c674840589be8db821fd9aAdam Langley u += a[i / 2] * a[i / 2]; 103d059297112922cabb0c674840589be8db821fd9aAdam Langley u += 38 * a[i / 2 + 16] * a[i / 2 + 16]; 104d059297112922cabb0c674840589be8db821fd9aAdam Langley } 105d059297112922cabb0c674840589be8db821fd9aAdam Langley out[i] = u; 106d059297112922cabb0c674840589be8db821fd9aAdam Langley } 107d059297112922cabb0c674840589be8db821fd9aAdam Langley squeeze(out); 108d059297112922cabb0c674840589be8db821fd9aAdam Langley} 109d059297112922cabb0c674840589be8db821fd9aAdam Langley 110d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void select(unsigned int p[64],unsigned int q[64],const unsigned int r[64],const unsigned int s[64],unsigned int b) 111d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 112d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int j; 113d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int t; 114d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int bminus1; 115d059297112922cabb0c674840589be8db821fd9aAdam Langley 116d059297112922cabb0c674840589be8db821fd9aAdam Langley bminus1 = b - 1; 117d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 64;++j) { 118d059297112922cabb0c674840589be8db821fd9aAdam Langley t = bminus1 & (r[j] ^ s[j]); 119d059297112922cabb0c674840589be8db821fd9aAdam Langley p[j] = s[j] ^ t; 120d059297112922cabb0c674840589be8db821fd9aAdam Langley q[j] = r[j] ^ t; 121d059297112922cabb0c674840589be8db821fd9aAdam Langley } 122d059297112922cabb0c674840589be8db821fd9aAdam Langley} 123d059297112922cabb0c674840589be8db821fd9aAdam Langley 124d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void mainloop(unsigned int work[64],const unsigned char e[32]) 125d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 126d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int xzm1[64]; 127d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int xzm[64]; 128d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int xzmb[64]; 129d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int xzm1b[64]; 130d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int xznb[64]; 131d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int xzn1b[64]; 132d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int a0[64]; 133d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int a1[64]; 134d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int b0[64]; 135d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int b1[64]; 136d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int c1[64]; 137d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int r[32]; 138d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int s[32]; 139d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int t[32]; 140d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int u[32]; 141d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int j; 142d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int b; 143d059297112922cabb0c674840589be8db821fd9aAdam Langley int pos; 144d059297112922cabb0c674840589be8db821fd9aAdam Langley 145d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 32;++j) xzm1[j] = work[j]; 146d059297112922cabb0c674840589be8db821fd9aAdam Langley xzm1[32] = 1; 147d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 33;j < 64;++j) xzm1[j] = 0; 148d059297112922cabb0c674840589be8db821fd9aAdam Langley 149d059297112922cabb0c674840589be8db821fd9aAdam Langley xzm[0] = 1; 150d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 1;j < 64;++j) xzm[j] = 0; 151d059297112922cabb0c674840589be8db821fd9aAdam Langley 152d059297112922cabb0c674840589be8db821fd9aAdam Langley for (pos = 254;pos >= 0;--pos) { 153d059297112922cabb0c674840589be8db821fd9aAdam Langley b = e[pos / 8] >> (pos & 7); 154d059297112922cabb0c674840589be8db821fd9aAdam Langley b &= 1; 155d059297112922cabb0c674840589be8db821fd9aAdam Langley select(xzmb,xzm1b,xzm,xzm1,b); 156d059297112922cabb0c674840589be8db821fd9aAdam Langley add(a0,xzmb,xzmb + 32); 157d059297112922cabb0c674840589be8db821fd9aAdam Langley sub(a0 + 32,xzmb,xzmb + 32); 158d059297112922cabb0c674840589be8db821fd9aAdam Langley add(a1,xzm1b,xzm1b + 32); 159d059297112922cabb0c674840589be8db821fd9aAdam Langley sub(a1 + 32,xzm1b,xzm1b + 32); 160d059297112922cabb0c674840589be8db821fd9aAdam Langley square(b0,a0); 161d059297112922cabb0c674840589be8db821fd9aAdam Langley square(b0 + 32,a0 + 32); 162d059297112922cabb0c674840589be8db821fd9aAdam Langley mult(b1,a1,a0 + 32); 163d059297112922cabb0c674840589be8db821fd9aAdam Langley mult(b1 + 32,a1 + 32,a0); 164d059297112922cabb0c674840589be8db821fd9aAdam Langley add(c1,b1,b1 + 32); 165d059297112922cabb0c674840589be8db821fd9aAdam Langley sub(c1 + 32,b1,b1 + 32); 166d059297112922cabb0c674840589be8db821fd9aAdam Langley square(r,c1 + 32); 167d059297112922cabb0c674840589be8db821fd9aAdam Langley sub(s,b0,b0 + 32); 168d059297112922cabb0c674840589be8db821fd9aAdam Langley mult121665(t,s); 169d059297112922cabb0c674840589be8db821fd9aAdam Langley add(u,t,b0); 170d059297112922cabb0c674840589be8db821fd9aAdam Langley mult(xznb,b0,b0 + 32); 171d059297112922cabb0c674840589be8db821fd9aAdam Langley mult(xznb + 32,s,u); 172d059297112922cabb0c674840589be8db821fd9aAdam Langley square(xzn1b,c1); 173d059297112922cabb0c674840589be8db821fd9aAdam Langley mult(xzn1b + 32,r,work); 174d059297112922cabb0c674840589be8db821fd9aAdam Langley select(xzm,xzm1,xznb,xzn1b,b); 175d059297112922cabb0c674840589be8db821fd9aAdam Langley } 176d059297112922cabb0c674840589be8db821fd9aAdam Langley 177d059297112922cabb0c674840589be8db821fd9aAdam Langley for (j = 0;j < 64;++j) work[j] = xzm[j]; 178d059297112922cabb0c674840589be8db821fd9aAdam Langley} 179d059297112922cabb0c674840589be8db821fd9aAdam Langley 180d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void recip(unsigned int out[32],const unsigned int z[32]) 181d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 182d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int z2[32]; 183d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int z9[32]; 184d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int z11[32]; 185d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int z2_5_0[32]; 186d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int z2_10_0[32]; 187d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int z2_20_0[32]; 188d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int z2_50_0[32]; 189d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int z2_100_0[32]; 190d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int t0[32]; 191d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int t1[32]; 192d059297112922cabb0c674840589be8db821fd9aAdam Langley int i; 193d059297112922cabb0c674840589be8db821fd9aAdam Langley 194d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2 */ square(z2,z); 195d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 4 */ square(t1,z2); 196d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 8 */ square(t0,t1); 197d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 9 */ mult(z9,t0,z); 198d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 11 */ mult(z11,z9,z2); 199d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 22 */ square(t0,z11); 200d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^5 - 2^0 = 31 */ mult(z2_5_0,t0,z9); 201d059297112922cabb0c674840589be8db821fd9aAdam Langley 202d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^6 - 2^1 */ square(t0,z2_5_0); 203d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^7 - 2^2 */ square(t1,t0); 204d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^8 - 2^3 */ square(t0,t1); 205d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^9 - 2^4 */ square(t1,t0); 206d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^10 - 2^5 */ square(t0,t1); 207d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^10 - 2^0 */ mult(z2_10_0,t0,z2_5_0); 208d059297112922cabb0c674840589be8db821fd9aAdam Langley 209d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^11 - 2^1 */ square(t0,z2_10_0); 210d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^12 - 2^2 */ square(t1,t0); 211d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t0,t1); square(t1,t0); } 212d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^20 - 2^0 */ mult(z2_20_0,t1,z2_10_0); 213d059297112922cabb0c674840589be8db821fd9aAdam Langley 214d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^21 - 2^1 */ square(t0,z2_20_0); 215d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^22 - 2^2 */ square(t1,t0); 216d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { square(t0,t1); square(t1,t0); } 217d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^40 - 2^0 */ mult(t0,t1,z2_20_0); 218d059297112922cabb0c674840589be8db821fd9aAdam Langley 219d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^41 - 2^1 */ square(t1,t0); 220d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^42 - 2^2 */ square(t0,t1); 221d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t1,t0); square(t0,t1); } 222d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^50 - 2^0 */ mult(z2_50_0,t0,z2_10_0); 223d059297112922cabb0c674840589be8db821fd9aAdam Langley 224d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^51 - 2^1 */ square(t0,z2_50_0); 225d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^52 - 2^2 */ square(t1,t0); 226d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } 227d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^100 - 2^0 */ mult(z2_100_0,t1,z2_50_0); 228d059297112922cabb0c674840589be8db821fd9aAdam Langley 229d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^101 - 2^1 */ square(t1,z2_100_0); 230d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^102 - 2^2 */ square(t0,t1); 231d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { square(t1,t0); square(t0,t1); } 232d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^200 - 2^0 */ mult(t1,t0,z2_100_0); 233d059297112922cabb0c674840589be8db821fd9aAdam Langley 234d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^201 - 2^1 */ square(t0,t1); 235d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^202 - 2^2 */ square(t1,t0); 236d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } 237d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^250 - 2^0 */ mult(t0,t1,z2_50_0); 238d059297112922cabb0c674840589be8db821fd9aAdam Langley 239d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^251 - 2^1 */ square(t1,t0); 240d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^252 - 2^2 */ square(t0,t1); 241d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^253 - 2^3 */ square(t1,t0); 242d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^254 - 2^4 */ square(t0,t1); 243d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^255 - 2^5 */ square(t1,t0); 244d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 2^255 - 21 */ mult(out,t1,z11); 245d059297112922cabb0c674840589be8db821fd9aAdam Langley} 246d059297112922cabb0c674840589be8db821fd9aAdam Langley 247d059297112922cabb0c674840589be8db821fd9aAdam Langleyint crypto_scalarmult_curve25519(unsigned char *q, 248d059297112922cabb0c674840589be8db821fd9aAdam Langley const unsigned char *n, 249d059297112922cabb0c674840589be8db821fd9aAdam Langley const unsigned char *p) 250d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 251d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int work[96]; 252d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned char e[32]; 253d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int i; 254d059297112922cabb0c674840589be8db821fd9aAdam Langley for (i = 0;i < 32;++i) e[i] = n[i]; 255d059297112922cabb0c674840589be8db821fd9aAdam Langley e[0] &= 248; 256d059297112922cabb0c674840589be8db821fd9aAdam Langley e[31] &= 127; 257d059297112922cabb0c674840589be8db821fd9aAdam Langley e[31] |= 64; 258d059297112922cabb0c674840589be8db821fd9aAdam Langley for (i = 0;i < 32;++i) work[i] = p[i]; 259d059297112922cabb0c674840589be8db821fd9aAdam Langley mainloop(work,e); 260d059297112922cabb0c674840589be8db821fd9aAdam Langley recip(work + 32,work + 32); 261d059297112922cabb0c674840589be8db821fd9aAdam Langley mult(work + 64,work,work + 32); 262d059297112922cabb0c674840589be8db821fd9aAdam Langley freeze(work + 64); 263d059297112922cabb0c674840589be8db821fd9aAdam Langley for (i = 0;i < 32;++i) q[i] = work[64 + i]; 264d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 265d059297112922cabb0c674840589be8db821fd9aAdam Langley} 266