1 /* 2 Ignores top bit of h. 3 */ 4 5 void 6 fe25519_frombytes(fe25519 h, const unsigned char *s) 7 { 8 const uint64_t mask = 0x7ffffffffffffULL; 9 uint64_t h0, h1, h2, h3, h4; 10 11 h0 = (LOAD64_LE(s ) ) & mask; 12 h1 = (LOAD64_LE(s + 6) >> 3) & mask; 13 h2 = (LOAD64_LE(s + 12) >> 6) & mask; 14 h3 = (LOAD64_LE(s + 19) >> 1) & mask; 15 h4 = (LOAD64_LE(s + 24) >> 12) & mask; 16 17 h[0] = h0; 18 h[1] = h1; 19 h[2] = h2; 20 h[3] = h3; 21 h[4] = h4; 22 } 23 24 static void 25 fe25519_reduce(fe25519 h, const fe25519 f) 26 { 27 const uint64_t mask = 0x7ffffffffffffULL; 28 uint128_t t[5]; 29 30 t[0] = f[0]; 31 t[1] = f[1]; 32 t[2] = f[2]; 33 t[3] = f[3]; 34 t[4] = f[4]; 35 36 t[1] += t[0] >> 51; 37 t[0] &= mask; 38 t[2] += t[1] >> 51; 39 t[1] &= mask; 40 t[3] += t[2] >> 51; 41 t[2] &= mask; 42 t[4] += t[3] >> 51; 43 t[3] &= mask; 44 t[0] += 19 * (t[4] >> 51); 45 t[4] &= mask; 46 47 t[1] += t[0] >> 51; 48 t[0] &= mask; 49 t[2] += t[1] >> 51; 50 t[1] &= mask; 51 t[3] += t[2] >> 51; 52 t[2] &= mask; 53 t[4] += t[3] >> 51; 54 t[3] &= mask; 55 t[0] += 19 * (t[4] >> 51); 56 t[4] &= mask; 57 58 /* now t is between 0 and 2^255-1, properly carried. */ 59 /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ 60 61 t[0] += 19ULL; 62 63 t[1] += t[0] >> 51; 64 t[0] &= mask; 65 t[2] += t[1] >> 51; 66 t[1] &= mask; 67 t[3] += t[2] >> 51; 68 t[2] &= mask; 69 t[4] += t[3] >> 51; 70 t[3] &= mask; 71 t[0] += 19ULL * (t[4] >> 51); 72 t[4] &= mask; 73 74 /* now between 19 and 2^255-1 in both cases, and offset by 19. */ 75 76 t[0] += 0x8000000000000 - 19ULL; 77 t[1] += 0x8000000000000 - 1ULL; 78 t[2] += 0x8000000000000 - 1ULL; 79 t[3] += 0x8000000000000 - 1ULL; 80 t[4] += 0x8000000000000 - 1ULL; 81 82 /* now between 2^255 and 2^256-20, and offset by 2^255. */ 83 84 t[1] += t[0] >> 51; 85 t[0] &= mask; 86 t[2] += t[1] >> 51; 87 t[1] &= mask; 88 t[3] += t[2] >> 51; 89 t[2] &= mask; 90 t[4] += t[3] >> 51; 91 t[3] &= mask; 92 t[4] &= mask; 93 94 h[0] = t[0]; 95 h[1] = t[1]; 96 h[2] = t[2]; 97 h[3] = t[3]; 98 h[4] = t[4]; 99 } 100 101 void 102 fe25519_tobytes(unsigned char *s, const fe25519 h) 103 { 104 fe25519 t; 105 uint64_t t0, t1, t2, t3; 106 107 fe25519_reduce(t, h); 108 t0 = t[0] | (t[1] << 51); 109 t1 = (t[1] >> 13) | (t[2] << 38); 110 t2 = (t[2] >> 26) | (t[3] << 25); 111 t3 = (t[3] >> 39) | (t[4] << 12); 112 STORE64_LE(s + 0, t0); 113 STORE64_LE(s + 8, t1); 114 STORE64_LE(s + 16, t2); 115 STORE64_LE(s + 24, t3); 116 } 117