├── bin └── log ├── .gitignore ├── inc ├── rng.h ├── csidh_util.h ├── edwards_curve.h ├── fp512 │ ├── addc.h │ ├── simba_withdummy_2.h │ ├── simba_dummyfree.h │ └── simba_withdummy_1.h └── fp.h ├── sample-keys ├── 1-2.ss ├── 2-1.ss ├── 3-2.ss ├── 4-3.ss ├── 1.montgomery.le.pk ├── 2.montgomery.le.pk ├── 3.montgomery.le.pk ├── 4.montgomery.le.pk ├── 1.montgomery.le.sk ├── 2.montgomery.le.sk ├── 3.montgomery.le.sk ├── 4.montgomery.le.sk └── README ├── lib ├── rng.c ├── isogenies.c ├── action_simba_withdummy_1.c ├── action_simba_dummyfree.c ├── fp512.S ├── point_arith.c └── action_simba_withdummy_2.c ├── main ├── action_timing.c ├── action_cost.c ├── csidh.c └── csidh_util.c ├── README.md ├── Makefile └── LICENSE /bin/log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/csidh 2 | bin/action_cost 3 | bin/action_timing 4 | -------------------------------------------------------------------------------- /inc/rng.h: -------------------------------------------------------------------------------- 1 | #ifndef RNG_H 2 | #define RNG_H 3 | 4 | #include 5 | 6 | void randombytes(void *x, size_t l); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /sample-keys/1-2.ss: -------------------------------------------------------------------------------- 1 | 36837B4B74157F8FA58631650CFEF8189312A6BD02F09C9E7F584C4E12BD628FA32CA7C9695EE16E51BDFB3B735CFD07DBA8134AD5096BE3B375F18263768A3E 2 | -------------------------------------------------------------------------------- /sample-keys/2-1.ss: -------------------------------------------------------------------------------- 1 | 36837B4B74157F8FA58631650CFEF8189312A6BD02F09C9E7F584C4E12BD628FA32CA7C9695EE16E51BDFB3B735CFD07DBA8134AD5096BE3B375F18263768A3E 2 | -------------------------------------------------------------------------------- /sample-keys/3-2.ss: -------------------------------------------------------------------------------- 1 | 2A35A80C05758E929F0B10FDFF0CF4AA5684724037D77B99026EB4C42CC82A2CC81DC0C0F3AB3571AA7031809BB0392651DD6824C3348B7FCF2171B1699C8E05 2 | -------------------------------------------------------------------------------- /sample-keys/4-3.ss: -------------------------------------------------------------------------------- 1 | 5320D95205573B399FAF9D9D5F53CC2710B2008EBA518732ED2CC934BC9D08DCF755E8CB889056CCC7B256C6ABB588457138417B4A832A23B38C9C80D8F9970C 2 | -------------------------------------------------------------------------------- /sample-keys/1.montgomery.le.pk: -------------------------------------------------------------------------------- 1 | a74552f05013afa94a943f0c0340bdc9919fdee3c3be5e238f94e672229278b87c52621bb5bd1ffbb56b277be5bd5c2d1b9559709bb340b3e3eab085d10a7047 2 | -------------------------------------------------------------------------------- /sample-keys/2.montgomery.le.pk: -------------------------------------------------------------------------------- 1 | 5a911b9242736f1b968756daabf15d1e86893278f3dfd4ad5fc48ecab2f1ceaa1e450d7734367cda401d031137b31d1fe37eab70725f85b1407a9b1b2e718d2d 2 | -------------------------------------------------------------------------------- /sample-keys/3.montgomery.le.pk: -------------------------------------------------------------------------------- 1 | 534bd00ddc29277b208d61edee35df768b6c35324a8b65d734af2e3571e97c8bee11dbf2135cc88a373a63565af25d3ede152fdf4fd80800640cef10824d7164 2 | -------------------------------------------------------------------------------- /sample-keys/4.montgomery.le.pk: -------------------------------------------------------------------------------- 1 | 98db03c962fa0bf3df4261b91afaa267811518b440360acfd092d80c5f79a219d254bacbc0b6b061a11890f932e867ab7045b60207cf828161bb647245991442 2 | -------------------------------------------------------------------------------- /sample-keys/1.montgomery.le.sk: -------------------------------------------------------------------------------- 1 | 03030f020a0e0b070b030a020b0e0f070c100c0c08010c030e160206060203070a020b0b120a17130e0b061602031b071b061b1613021a171a12130f061b06131202170f030b0f060b07 2 | -------------------------------------------------------------------------------- /sample-keys/2.montgomery.le.sk: -------------------------------------------------------------------------------- 1 | 0b02030602020603020b07020b0f0f0210080d110508040e0f0302130b0b130f070a0f1706130b03160a121b021b120e0607031a1b121a0e0b1a030a0a170e06120f0b0e0f07030f0306 2 | -------------------------------------------------------------------------------- /sample-keys/3.montgomery.le.sk: -------------------------------------------------------------------------------- 1 | 0f0f0a0a0b0a0a0f0b020f020f0f070a0c0809080105101707031307160b0b06160b131603070a120b060b03071a161b130b02060e071607170b0f13070a060f0a170b1b1b060e070b0e 2 | -------------------------------------------------------------------------------- /sample-keys/4.montgomery.le.sk: -------------------------------------------------------------------------------- 1 | 0b0a060e06070f020f0e0e0702060a0f110c0d10110d011702160e170b030f0a0b0f130f0b06060b12020b07160713070e1b0a0a061b031212171617030a020e120a0b0b170203060e0f 2 | -------------------------------------------------------------------------------- /sample-keys/README: -------------------------------------------------------------------------------- 1 | These keys are CSIDH test vector keys. The public keys and the shared secret 2 | output are little endian and in the Montgomery form. The secret key format is 3 | not portable between implementations. 4 | -------------------------------------------------------------------------------- /lib/rng.c: -------------------------------------------------------------------------------- 1 | 2 | #include "rng.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void randombytes(void *x, size_t l) 9 | { 10 | static int fd = -1; 11 | ssize_t n; 12 | if (fd < 0 && 0 > (fd = open("/dev/urandom", O_RDONLY))) 13 | exit(1); 14 | for (size_t i = 0; i < l; i += n) 15 | if (0 >= (n = read(fd, (char *) x + i, l - i))) 16 | exit(2); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /inc/csidh_util.h: -------------------------------------------------------------------------------- 1 | #ifndef CSIDH_UTIL_H 2 | #define CSIDH_UTIL_H 3 | 4 | #include "fp.h" 5 | #include "edwards_curve.h" 6 | 7 | extern const fp R_mod_p; 8 | 9 | #define VERSION 0.1 10 | 11 | void pprint_pk(void *x); 12 | 13 | void pprint_sk(void *y); 14 | 15 | void pprint_ss(uint64_t *x); 16 | 17 | void save_file(char *file, void *buf, size_t len); 18 | 19 | void error_exit(char *str); 20 | 21 | int read_file(const char *file, uint8_t *buf, size_t len); 22 | 23 | int read_stdin(uint8_t *buf, int len); 24 | #endif 25 | -------------------------------------------------------------------------------- /inc/edwards_curve.h: -------------------------------------------------------------------------------- 1 | #ifndef _EC_H_ 2 | #define _EC_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "fp.h" 9 | 10 | // projective Edwards y-coordinates (to be used with the patching) 11 | typedef uint64_t proj[2][NUMBER_OF_WORDS] __attribute__((aligned(64))); 12 | // A curve will be defined as type proj where the first and second entries will be the constants a and (a -d). 13 | 14 | uint64_t FP_ADD_COMPUTED, // Variable used for counting the number of field additions. 15 | FP_SQR_COMPUTED, // Variable used for counting the number of field squarings. 16 | FP_MUL_COMPUTED; // Variable used for counting the number of field multiplications. 17 | 18 | // Framework to be used: the files required must be in the folder: ./inc/fp$(BITLENGTH_OF_P)/ 19 | #include "addc.h" // Addition chains, Public curve, public points T_{+} and T_{-}, and the list of prime factors l_i's 20 | 21 | #if defined WITHDUMMY_1 22 | #include "simba_withdummy_1.h" // csidh with dummy operations and using only one torsion point T_{+} 23 | #elif defined WITHDUMMY_2 24 | #include "simba_withdummy_2.h" // csidh with dummy operations and using two torsion point T_{+} and T_{-} 25 | #elif defined DUMMYFREE 26 | #include "simba_dummyfree.h" // dummy-free csidh using two torsion points T_{+} and T_{-} 27 | #endif 28 | 29 | // Functions related with the point arithmetic 30 | int isinfinity(const proj P); // To determine if a projective y-coordinate point is the infinity 31 | void point_copy(proj Q, const proj P); // To make a copy of a point 32 | uint8_t areEqual(const proj P, const proj Q); // To check if two points are equal 33 | 34 | void yDBL(proj Q, const proj P, const proj A); 35 | void yADD(proj R, const proj P, const proj Q, const proj PQ); 36 | void yMUL(proj Q, const proj P, const proj A, uint8_t const i); 37 | 38 | void elligator(proj T_plus, proj T_minus, const proj A); 39 | 40 | void cofactor_multiples(proj P[], const proj A, int8_t lower, int8_t upper); 41 | uint8_t validate(const proj A); 42 | 43 | // Functions related with isogenies 44 | void yISOG(proj Pk[], proj C, const proj P, const proj A, const uint8_t i); 45 | void yEVAL(proj R, const proj Q, const proj Pk[], const uint8_t i); 46 | 47 | // functions related with the action 48 | void action_evaluation(proj C, const uint8_t key[], const proj A); 49 | void random_key(uint8_t key[]); 50 | void printf_key(uint8_t key[], char *c); 51 | 52 | #endif /* Arithmetic and isogenies on Edwards curve */ 53 | -------------------------------------------------------------------------------- /main/action_timing.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "fp.h" 5 | #include "edwards_curve.h" 6 | 7 | // Measuring the perfomance 8 | static uint64_t get_cycles() 9 | { 10 | uint32_t lo, hi; 11 | asm volatile("rdtsc":"=a"(lo),"=d"(hi)); 12 | return ((uint64_t)hi<<32) | lo; 13 | }; 14 | 15 | static uint8_t csidh(proj out, const uint8_t sk[], const proj in) 16 | { 17 | FP_ADD_COMPUTED = 0; 18 | FP_SQR_COMPUTED = 0; 19 | FP_MUL_COMPUTED = 0; 20 | 21 | if (!validate(in)) { 22 | return 0; 23 | }; 24 | action_evaluation(out, sk, in); 25 | return 1; 26 | }; 27 | 28 | unsigned long its = 1024; 29 | 30 | int main() 31 | { 32 | unsigned int i; 33 | 34 | double cc_min = 0xFFFFFFFFFFFFFFFF, cc_max = 0; 35 | double cc_mean = 0, cc_variance = 0; 36 | 37 | double cc_sample[its], cc_0, cc_1; 38 | 39 | // --- 40 | uint8_t key[N]; 41 | proj random_E; 42 | 43 | point_copy(random_E, E); 44 | 45 | for(i = 0; i < its; ++i) 46 | { 47 | 48 | if (its >= 100 && i % (its / 100) == 0) { 49 | printf("Doing %lu iterations of action with validation key:\t", its); 50 | printf("%2lu%%", 100 * i / its); 51 | fflush(stdout); 52 | printf("\r\x1b[K"); 53 | } 54 | 55 | random_key(key); 56 | cc_0 = get_cycles(); 57 | assert(csidh(random_E, key, random_E)); 58 | cc_1 = get_cycles(); 59 | 60 | cc_sample[i] = (double)(cc_1 - cc_0) / (1000000.0) ; 61 | // --- 62 | 63 | 64 | /**************************************/ 65 | if(cc_min > cc_sample[i]) 66 | cc_min = cc_sample[i]; 67 | 68 | /**************************************/ 69 | if(cc_max < cc_sample[i]) 70 | cc_max = cc_sample[i]; 71 | 72 | /**************************************/ 73 | cc_mean += (double)cc_sample[i]; 74 | }; 75 | 76 | 77 | cc_mean = cc_mean / ((double)its * 1.0); 78 | 79 | for (i = 0; i < its; ++i) 80 | { 81 | cc_variance += (cc_sample[i] - cc_mean)*(cc_sample[i] - cc_mean); 82 | }; 83 | 84 | cc_variance = cc_variance / ((double)its - 1.0); 85 | 86 | printf("\x1b[01;33mIterations: %lu\x1b[0m\n\n", its); 87 | 88 | printf("\x1b[33mAverage number of clock cycles: \x1b[32m %f \x1b[0m\n", cc_mean); 89 | printf("\x1b[33mStandar deviation of the number of clock cycles: \x1b[32m %f \x1b[0m\n", sqrt(cc_variance)); 90 | printf("\x1b[33mMinimum of the number clock cycles: \x1b[32m %f \x1b[0m\n", cc_min); 91 | printf("\x1b[33mMaximum of the number of clock cycles: \x1b[32m %f \x1b[0m\n", cc_max); 92 | printf("\n"); 93 | 94 | return 0; 95 | }; 96 | -------------------------------------------------------------------------------- /inc/fp512/addc.h: -------------------------------------------------------------------------------- 1 | #ifndef _ADDC_H_ 2 | #define _ADDC_H_ 3 | 4 | // The public Edward's curve with coefficients a and b. E is isomorphic to E' / F_p : y^2 = x^3 + x 5 | // a and (a - d) in Montgomery domain represetantion 6 | static proj E = { 7 | { 0x767762E5FD1E1599, 0x33C5743A49A0B6F6, 0x68FC0C0364C77443, 0xB9AA1E24F83F56DB, 0x3914101F20520EFB, 0x7B1ED6D95B1542B4, 0x114A8BE928C8828A, 0x3793732BBB24F40}, // a 8 | { 0xECEEC5CBFA3C2B32, 0x678AE87493416DEC, 0xD1F81806C98EE886, 0x73543C49F07EADB6, 0x7228203E40A41DF7, 0xF63DADB2B62A8568, 0x229517D251910514, 0x6F26E6577649E80} // a - d 9 | }; 10 | 11 | // Shortest differential addition chains for each l_i 12 | static uint64_t ADDITION_CHAIN[] = { 13 | 0x231, 0x324, 0x10, 0x2D8, 0x140, 0x50, 0x14, 0x108, 14 | 0x101, 0x144, 0x148, 0x122, 0x141, 0x51, 0x12A, 0x109, 15 | 0x118, 0x1A2, 0x181, 0x0, 0x134, 0x194, 0x185, 0x191, 16 | 0x1, 0x198, 0x82, 0x88, 0x81, 0x8A, 0xC0, 0xA1, 17 | 0xD0, 0xC2, 0x98, 0xD4, 0xC5, 0x2B, 0x40, 0xE8, 18 | 0xE1, 0x4A, 0x60, 0xC, 0x68, 0x49, 0x0, 0x6C, 19 | 0x4, 0x14, 0x24, 0x9, 0x2C, 0x32, 0x36, 0x1, 20 | 0x11, 0x18, 0x3, 0x8, 0xA, 0xD, 0x4, 0x5, 21 | 0x0, 0x1, 0x1, 0x0, 0x0, 0x612, 0x268, 0x312, 22 | 0xD1, 0x352 23 | }; 24 | 25 | // Length of the shortest differential addition chain for each l_i 26 | static uint8_t ADDITION_CHAIN_LENGTH[] = { 27 | 11, 11, 10, 11, 10, 10, 10, 10, 28 | 10, 10, 10, 10, 10, 10, 10, 10, 29 | 10, 10, 10, 9, 10, 10, 10, 10, 30 | 9, 10, 9, 9, 9, 9, 9, 9, 31 | 9, 9, 9, 9, 9, 9, 8, 9, 32 | 9, 8, 8, 8, 8, 8, 7, 8, 33 | 7, 7, 7, 7, 7, 7, 7, 6, 34 | 6, 6, 6, 5, 5, 5, 4, 4, 35 | 3, 3, 2, 1, 0, 12, 11, 11, 36 | 11, 11 37 | }; 38 | 39 | // L 40 | static uint32_t L[] = { 41 | 349, 347, 337, 331, 317, 313, 311, 307, 42 | 293, 283, 281, 277, 271, 269, 263, 257, 43 | 251, 241, 239, 233, 229, 227, 223, 211, 44 | 199, 197, 193, 191, 181, 179, 173, 167, 45 | 163, 157, 151, 149, 139, 137, 131, 127, 46 | 113, 109, 107, 103, 101, 97, 89, 83, 47 | 79, 73, 71, 67, 61, 59, 53, 47, 48 | 43, 41, 37, 31, 29, 23, 19, 17, 49 | 13, 11, 7, 5, 3, 587, 373, 367, 50 | 359, 353 51 | }; 52 | 53 | static uint16_t BITS_OF_L[] = { 54 | 9, 9, 9, 9, 9, 9, 9, 9, 55 | 9, 9, 9, 9, 9, 9, 9, 9, 56 | 8, 8, 8, 8, 8, 8, 8, 8, 57 | 8, 8, 8, 8, 8, 8, 8, 8, 58 | 8, 8, 8, 8, 8, 8, 8, 7, 59 | 7, 7, 7, 7, 7, 7, 7, 7, 60 | 7, 7, 7, 7, 6, 6, 6, 6, 61 | 6, 6, 6, 5, 5, 5, 5, 5, 62 | 4, 4, 3, 3, 2, 10, 9, 9, 63 | 9, 9 64 | }; 65 | 66 | #define BITS_OF_4SQRT_OF_P 258 67 | #define LARGE_L 587 68 | // The l_i's are only required for isogeny constructions 69 | #endif /* Addition chains */ 70 | -------------------------------------------------------------------------------- /inc/fp512/simba_withdummy_2.h: -------------------------------------------------------------------------------- 1 | #ifndef _SIMBA_PARAMETERS_H_ 2 | #define _SIMBA_PARAMETERS_H_ 3 | 4 | // SIMBA-(NUMBER_OF_BATCHES)-MY 5 | #define NUMBER_OF_BATCHES 3 6 | #define MY 8 7 | 8 | // (each entry corresponds to the number of degree-(l_i) to be required in the action: this the one given in Onuki et al. work) 9 | static int8_t B[] = { 10 | 2, 3, 3, 3, 3, 3, 3, 3, 11 | 3, 3, 3, 4, 4, 4, 4, 4, 12 | 4, 4, 4, 4, 4, 4, 4, 4, 13 | 4, 4, 5, 5, 5, 5, 5, 5, 14 | 5, 6, 6, 6, 6, 6, 7, 7, 15 | 7, 7, 7, 7, 7, 7, 7, 7, 16 | 7, 7, 8, 9, 9, 9, 10, 10, 17 | 10, 10, 9, 8, 8, 8, 7, 7, 18 | 7, 7, 7, 6, 5, 1, 2, 2, 19 | 2, 2 20 | }; 21 | 22 | // (NUMBER_OF_BATCHES) different subsets (i.e., batches) 23 | static uint8_t BATCH_0[] = { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72 }; 24 | static uint8_t BATCH_1[] = { 1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73 }; 25 | static uint8_t BATCH_2[] = { 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71 }; 26 | 27 | static uint8_t SIZE_OF_EACH_BATCH[NUMBER_OF_BATCHES] = {25, 25, 24}; 28 | static uint8_t *BATCHES[NUMBER_OF_BATCHES] = { BATCH_0, BATCH_1, BATCH_2 }; 29 | 30 | static uint8_t LAST_ISOGENY[NUMBER_OF_BATCHES] = { 72, 73, 71 }; 31 | static uint16_t NUMBER_OF_ISOGENIES = 404; 32 | 33 | // The complement of each batch 34 | static uint8_t SIZE_OF_EACH_COMPLEMENT_BATCH[NUMBER_OF_BATCHES] = { 49, 49, 50 }; 35 | static uint8_t COMPLEMENT_OF_EACH_BATCH[NUMBER_OF_BATCHES][N] = { 36 | { 1, 2, 37 | 4, 5, 38 | 7, 8, 39 | 10, 11, 40 | 13, 14, 41 | 16, 17, 42 | 19, 20, 43 | 22, 23, 44 | 25, 26, 45 | 28, 29, 46 | 31, 32, 47 | 34, 35, 48 | 37, 38, 49 | 40, 41, 50 | 43, 44, 51 | 46, 47, 52 | 49, 50, 53 | 52, 53, 54 | 55, 56, 55 | 58, 59, 56 | 61, 62, 57 | 64, 65, 58 | 67, 68, 59 | 70, 71, 60 | 73, 61 | 74, 74, 62 | 74, 74, 63 | 74, 74, 64 | 74, 74, 65 | 74, 74, 66 | 74, 74, 67 | 74, 74, 68 | 74, 74, 69 | 74, 74, 70 | 74, 74, 71 | 74, 74, 72 | 74, 74, 73 | 74 74 | }, 75 | { 0, 2, 76 | 3, 5, 77 | 6, 8, 78 | 9, 11, 79 | 12, 14, 80 | 15, 17, 81 | 18, 20, 82 | 21, 23, 83 | 24, 26, 84 | 27, 29, 85 | 30, 32, 86 | 33, 35, 87 | 36, 38, 88 | 39, 41, 89 | 42, 44, 90 | 45, 47, 91 | 48, 50, 92 | 51, 53, 93 | 54, 56, 94 | 57, 59, 95 | 60, 62, 96 | 63, 65, 97 | 66, 68, 98 | 69, 71, 99 | 72, 100 | 74, 74, 101 | 74, 74, 102 | 74, 74, 103 | 74, 74, 104 | 74, 74, 105 | 74, 74, 106 | 74, 74, 107 | 74, 74, 108 | 74, 74, 109 | 74, 74, 110 | 74, 74, 111 | 74, 74, 112 | 74 113 | }, 114 | { 0, 1, 115 | 3, 4, 116 | 6, 7, 117 | 9, 10, 118 | 12, 13, 119 | 15, 16, 120 | 18, 19, 121 | 21, 22, 122 | 24, 25, 123 | 27, 28, 124 | 30, 31, 125 | 33, 34, 126 | 36, 37, 127 | 39, 40, 128 | 42, 43, 129 | 45, 46, 130 | 48, 49, 131 | 51, 52, 132 | 54, 55, 133 | 57, 58, 134 | 60, 61, 135 | 63, 64, 136 | 66, 67, 137 | 69, 70, 138 | 72, 73, 139 | 74, 74, 140 | 74, 74, 141 | 74, 74, 142 | 74, 74, 143 | 74, 74, 144 | 74, 74, 145 | 74, 74, 146 | 74, 74, 147 | 74, 74, 148 | 74, 74, 149 | 74, 74, 150 | 74, 74 151 | } 152 | }; 153 | #endif 154 | -------------------------------------------------------------------------------- /inc/fp512/simba_dummyfree.h: -------------------------------------------------------------------------------- 1 | #ifndef _SIMBA_PARAMETERS_H_ 2 | #define _SIMBA_PARAMETERS_H_ 3 | 4 | // SIMBA-(NUMBER_OF_BATCHES)-MY 5 | #define NUMBER_OF_BATCHES 5 6 | #define MY 11 7 | 8 | // (each entry corresponds to the number of degree-(l_i) to be required in the action: this the one given in MCR work) 9 | static int8_t B[] = { 10 | 7, 7, 7, 7, 7, 7, 7, 7, 11 | 7, 7, 7, 7, 7, 7, 7, 7, 12 | 8, 8, 8, 8, 8, 8, 8, 11, 13 | 11, 11, 11, 11, 11, 11, 11, 11, 14 | 11, 11, 11, 11, 11, 11, 11, 11, 15 | 11, 13, 13, 13, 13, 13, 13, 13, 16 | 13, 13, 13, 13, 13, 13, 13, 13, 17 | 13, 13, 13, 13, 13, 13, 13, 13, 18 | 13, 13, 13, 13, 13, 5, 7, 7, 19 | 7, 7 20 | }; 21 | 22 | // (NUMBER_OF_BATCHES) different subsets (i.e., batches) 23 | static uint8_t BATCH_0[] = { 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70 }; 24 | static uint8_t BATCH_1[] = { 1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71 }; 25 | static uint8_t BATCH_2[] = { 2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72 }; 26 | static uint8_t BATCH_3[] = { 3, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53, 58, 63, 68, 73 }; 27 | static uint8_t BATCH_4[] = { 4, 9, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64, 69 }; 28 | 29 | static uint8_t SIZE_OF_EACH_BATCH[NUMBER_OF_BATCHES] = {15, 15, 15, 15, 14}; 30 | static uint8_t *BATCHES[NUMBER_OF_BATCHES] = { BATCH_0, BATCH_1, BATCH_2, BATCH_3, BATCH_4 }; 31 | 32 | static uint8_t LAST_ISOGENY[NUMBER_OF_BATCHES] = { 70, 71, 72, 73, 69 }; 33 | static uint16_t NUMBER_OF_ISOGENIES = 763; 34 | 35 | // The complement of each batch 36 | static uint8_t SIZE_OF_EACH_COMPLEMENT_BATCH[NUMBER_OF_BATCHES] = {59, 59, 59, 59, 60}; 37 | static uint8_t COMPLEMENT_OF_EACH_BATCH[NUMBER_OF_BATCHES][N] = { 38 | { 1, 2, 3, 4, 39 | 6, 7, 8, 9, 40 | 11, 12, 13, 14, 41 | 16, 17, 18, 19, 42 | 21, 22, 23, 24, 43 | 26, 27, 28, 29, 44 | 31, 32, 33, 34, 45 | 36, 37, 38, 39, 46 | 41, 42, 43, 44, 47 | 46, 47, 48, 49, 48 | 51, 52, 53, 54, 49 | 56, 57, 58, 59, 50 | 61, 62, 63, 64, 51 | 66, 67, 68, 69, 52 | 71, 72, 73, 53 | 74, 74, 74, 74, 54 | 74, 74, 74, 74, 55 | 74, 74, 74, 74, 56 | 74, 74, 74 57 | }, 58 | { 0, 2, 3, 4, 59 | 5, 7, 8, 9, 60 | 10, 12, 13, 14, 61 | 15, 17, 18, 19, 62 | 20, 22, 23, 24, 63 | 25, 27, 28, 29, 64 | 30, 32, 33, 34, 65 | 35, 37, 38, 39, 66 | 40, 42, 43, 44, 67 | 45, 47, 48, 49, 68 | 50, 52, 53, 54, 69 | 55, 57, 58, 59, 70 | 60, 62, 63, 64, 71 | 65, 67, 68, 69, 72 | 70, 72, 73, 73 | 74, 74, 74, 74, 74 | 74, 74, 74, 74, 75 | 74, 74, 74, 74, 76 | 74, 74, 74 77 | }, 78 | { 0, 1, 3, 4, 79 | 5, 6, 8, 9, 80 | 10, 11, 13, 14, 81 | 15, 16, 18, 19, 82 | 20, 21, 23, 24, 83 | 25, 26, 28, 29, 84 | 30, 31, 33, 34, 85 | 35, 36, 38, 39, 86 | 40, 41, 43, 44, 87 | 45, 46, 48, 49, 88 | 50, 51, 53, 54, 89 | 55, 56, 58, 59, 90 | 60, 61, 63, 64, 91 | 65, 66, 68, 69, 92 | 70, 71, 73, 93 | 74, 74, 74, 74, 94 | 74, 74, 74, 74, 95 | 74, 74, 74, 74, 96 | 74, 74, 74 97 | }, 98 | { 0, 1, 2, 4, 99 | 5, 6, 7, 9, 100 | 10, 11, 12, 14, 101 | 15, 16, 17, 19, 102 | 20, 21, 22, 24, 103 | 25, 26, 27, 29, 104 | 30, 31, 32, 34, 105 | 35, 36, 37, 39, 106 | 40, 41, 42, 44, 107 | 45, 46, 47, 49, 108 | 50, 51, 52, 54, 109 | 55, 56, 57, 59, 110 | 60, 61, 62, 64, 111 | 65, 66, 67, 69, 112 | 70, 71, 72, 113 | 74, 74, 74, 74, 114 | 74, 74, 74, 74, 115 | 74, 74, 74, 74, 116 | 74, 74, 74 117 | }, 118 | { 0, 1, 2, 3, 119 | 5, 6, 7, 8, 120 | 10, 11, 12, 13, 121 | 15, 16, 17, 18, 122 | 20, 21, 22, 23, 123 | 25, 26, 27, 28, 124 | 30, 31, 32, 33, 125 | 35, 36, 37, 38, 126 | 40, 41, 42, 43, 127 | 45, 46, 47, 48, 128 | 50, 51, 52, 53, 129 | 55, 56, 57, 58, 130 | 60, 61, 62, 63, 131 | 65, 66, 67, 68, 132 | 70, 71, 72, 73, 133 | 74, 74, 74, 74, 134 | 74, 74, 74, 74, 135 | 74, 74, 74, 74, 136 | 74, 74 } 137 | }; 138 | #endif 139 | -------------------------------------------------------------------------------- /inc/fp512/simba_withdummy_1.h: -------------------------------------------------------------------------------- 1 | #ifndef _SIMBA_PARAMETERS_H_ 2 | #define _SIMBA_PARAMETERS_H_ 3 | 4 | // SIMBA-(NUMBER_OF_BATCHES)-MY 5 | #define NUMBER_OF_BATCHES 5 6 | #define MY 11 7 | 8 | // (each entry corresponds to the number of degree-(l_i) to be required in the action: this the one given in MCR work) 9 | static int8_t B[] = { 10 | 7, 7, 7, 7, 7, 7, 7, 7, 11 | 7, 7, 7, 7, 7, 7, 7, 7, 12 | 8, 8, 8, 8, 8, 8, 8, 11, 13 | 11, 11, 11, 11, 11, 11, 11, 11, 14 | 11, 11, 11, 11, 11, 11, 11, 11, 15 | 11, 13, 13, 13, 13, 13, 13, 13, 16 | 13, 13, 13, 13, 13, 13, 13, 13, 17 | 13, 13, 13, 13, 13, 13, 13, 13, 18 | 13, 13, 13, 13, 13, 5, 7, 7, 19 | 7, 7 20 | }; 21 | 22 | // (NUMBER_OF_BATCHES) different subsets (i.e., batches) 23 | static uint8_t BATCH_0[] = { 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70 }; 24 | static uint8_t BATCH_1[] = { 1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71 }; 25 | static uint8_t BATCH_2[] = { 2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72 }; 26 | static uint8_t BATCH_3[] = { 3, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53, 58, 63, 68, 73 }; 27 | static uint8_t BATCH_4[] = { 4, 9, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64, 69 }; 28 | 29 | static uint8_t SIZE_OF_EACH_BATCH[NUMBER_OF_BATCHES] = {15, 15, 15, 15, 14}; 30 | static uint8_t *BATCHES[NUMBER_OF_BATCHES] = { BATCH_0, BATCH_1, BATCH_2, BATCH_3, BATCH_4 }; 31 | 32 | static uint8_t LAST_ISOGENY[NUMBER_OF_BATCHES] = { 70, 71, 72, 73, 69 }; 33 | static uint16_t NUMBER_OF_ISOGENIES = 763; 34 | 35 | // The complement of each batch 36 | static uint8_t SIZE_OF_EACH_COMPLEMENT_BATCH[NUMBER_OF_BATCHES] = {59, 59, 59, 59, 60}; 37 | static uint8_t COMPLEMENT_OF_EACH_BATCH[NUMBER_OF_BATCHES][N] = { 38 | { 1, 2, 3, 4, 39 | 6, 7, 8, 9, 40 | 11, 12, 13, 14, 41 | 16, 17, 18, 19, 42 | 21, 22, 23, 24, 43 | 26, 27, 28, 29, 44 | 31, 32, 33, 34, 45 | 36, 37, 38, 39, 46 | 41, 42, 43, 44, 47 | 46, 47, 48, 49, 48 | 51, 52, 53, 54, 49 | 56, 57, 58, 59, 50 | 61, 62, 63, 64, 51 | 66, 67, 68, 69, 52 | 71, 72, 73, 53 | 74, 74, 74, 74, 54 | 74, 74, 74, 74, 55 | 74, 74, 74, 74, 56 | 74, 74, 74 57 | }, 58 | { 0, 2, 3, 4, 59 | 5, 7, 8, 9, 60 | 10, 12, 13, 14, 61 | 15, 17, 18, 19, 62 | 20, 22, 23, 24, 63 | 25, 27, 28, 29, 64 | 30, 32, 33, 34, 65 | 35, 37, 38, 39, 66 | 40, 42, 43, 44, 67 | 45, 47, 48, 49, 68 | 50, 52, 53, 54, 69 | 55, 57, 58, 59, 70 | 60, 62, 63, 64, 71 | 65, 67, 68, 69, 72 | 70, 72, 73, 73 | 74, 74, 74, 74, 74 | 74, 74, 74, 74, 75 | 74, 74, 74, 74, 76 | 74, 74, 74 77 | }, 78 | { 0, 1, 3, 4, 79 | 5, 6, 8, 9, 80 | 10, 11, 13, 14, 81 | 15, 16, 18, 19, 82 | 20, 21, 23, 24, 83 | 25, 26, 28, 29, 84 | 30, 31, 33, 34, 85 | 35, 36, 38, 39, 86 | 40, 41, 43, 44, 87 | 45, 46, 48, 49, 88 | 50, 51, 53, 54, 89 | 55, 56, 58, 59, 90 | 60, 61, 63, 64, 91 | 65, 66, 68, 69, 92 | 70, 71, 73, 93 | 74, 74, 74, 74, 94 | 74, 74, 74, 74, 95 | 74, 74, 74, 74, 96 | 74, 74, 74 97 | }, 98 | { 0, 1, 2, 4, 99 | 5, 6, 7, 9, 100 | 10, 11, 12, 14, 101 | 15, 16, 17, 19, 102 | 20, 21, 22, 24, 103 | 25, 26, 27, 29, 104 | 30, 31, 32, 34, 105 | 35, 36, 37, 39, 106 | 40, 41, 42, 44, 107 | 45, 46, 47, 49, 108 | 50, 51, 52, 54, 109 | 55, 56, 57, 59, 110 | 60, 61, 62, 64, 111 | 65, 66, 67, 69, 112 | 70, 71, 72, 113 | 74, 74, 74, 74, 114 | 74, 74, 74, 74, 115 | 74, 74, 74, 74, 116 | 74, 74, 74 117 | }, 118 | { 0, 1, 2, 3, 119 | 5, 6, 7, 8, 120 | 10, 11, 12, 13, 121 | 15, 16, 17, 18, 122 | 20, 21, 22, 23, 123 | 25, 26, 27, 28, 124 | 30, 31, 32, 33, 125 | 35, 36, 37, 38, 126 | 40, 41, 42, 43, 127 | 45, 46, 47, 48, 128 | 50, 51, 52, 53, 129 | 55, 56, 57, 58, 130 | 60, 61, 62, 63, 131 | 65, 66, 67, 68, 132 | 70, 71, 72, 73, 133 | 74, 74, 74, 74, 134 | 74, 74, 74, 74, 135 | 74, 74, 74, 74, 136 | 74, 74 } 137 | }; 138 | #endif 139 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stronger and Faster Side-Channel Protections for CSIDH 2 | 3 | This is joined work with: 4 | 5 | * Daniel Cervantes-Vázquez, 6 | * Mathilde Chenu de La Morinerie, 7 | * Jesús-Javier Chi-Domínguez, 8 | * Luca De Feo, 9 | * Francisco Rodríguez-Henríquez, and 10 | * Benjamin Smith. 11 | 12 | This work uses the fact that the action used in the CSIDH protocol 13 | can be computed with 14 | 1. shortest differential addition chains, 15 | 2. only Edwards curves (no hybrid between Montgomery and Edwards), 16 | 3. A projective elligator with u randomly chosen from {2, (p-1)/2}, and 17 | 4. the only two ``if statements'' used are for asking if a ``public'' 18 | point is the infinity point. 19 | The implemented methods are Simba with one and two torsion points, 20 | which require dummy operations. 21 | In addition, a dummy-free CSIDH approach was implemented where each 22 | secret exponent e_i corresponding to l_i is randomly chosen from 23 | 1. the set of all odd integer number in {-b_i, ..., b_i} if b_i is odd, or 24 | 2. the set of all even integer number in {-b_i, ..., b_i} if b_i is even. 25 | Here, b_i is the number of degree-(l_i) isogenies to be computed. 26 | 27 | [Notes] 28 | [1] 29 | The Simba method implemented is based on the work of Michael Meyer, 30 | Fabio Campos, Steffen Reith: 31 | "On Lions and Elligators: An efficient constant-time implementation of CSIDH". 32 | IACR Cryptology ePrint Archive 2018: 1198 (2018). 33 | [2] 34 | This implementation re-use the field arithmetic implemented in the 35 | original CSIDH paper by Wouter Castryck, Tanja Lange, Chloe Martindale, 36 | Lorenz Panny, Joost Renes: 37 | "CSIDH: An Efficient Post-Quantum Commutative Group Action". 38 | ASIACRYPT (3) 2018: 395-427. 39 | (its eprint version can be download at https://eprint.iacr.org/2018/383) 40 | 41 | # ------------------------------------------------------------------------ 42 | This C code implementation was perfomed by: 43 | 44 | * Daniel Cervantes-Vázquez , 45 | * Jesús-Javier Chi-Domínguez , and 46 | * Francisco Rodríguez-Henríquez . 47 | 48 | # ------------------------------------------------------------------------ 49 | # C code 50 | To compile the files you can do the following: 51 | 52 | First, you can use any version of gcc compiler (just set the variable CC as 53 | an input of the Makefile [variable CC is optional, gcc is set by default]). 54 | 55 | # Testing a CSIDH protocol (key exchange protocol) 56 | [Compilation] 57 | 58 | (Using dummy operations and one torsion point) 59 | make csidh BITLENGTH_OF_P=512 TYPE=WITHDUMMY_1 60 | (Using dummy operations and two torsion points) 61 | make csidh BITLENGTH_OF_P=512 TYPE=WITHDUMMY_2 62 | (Dummy-free approach and using two torsion points) 63 | make csidh BITLENGTH_OF_P=512 TYPE=DUMMYFREE 64 | 65 | 66 | [Execution] 67 | 68 | ./bin/csidh 69 | 70 | 71 | # Running-time: number of field operations 72 | [Compilation] 73 | 74 | (Using dummy operations and one torsion point) 75 | make action_cost BITLENGTH_OF_P=512 TYPE=WITHDUMMY_1 76 | (Using dummy operations and two torsion points) 77 | make action_cost BITLENGTH_OF_P=512 TYPE=WITHDUMMY_2 78 | (Dummy-free approach and using two torsion points) 79 | make action_cost BITLENGTH_OF_P=512 TYPE=DUMMYFREE 80 | 81 | [Execution] 82 | 83 | ./bin/action_cost 84 | 85 | # Running-time: number of clock cycles 86 | [Compilation] 87 | 88 | (Using dummy operations and one torsion point) 89 | make action_timing BITLENGTH_OF_P=512 TYPE=WITHDUMMY_1 90 | (Using dummy operations and two torsion points) 91 | make action_timing BITLENGTH_OF_P=512 TYPE=WITHDUMMY_2 92 | (Dummy-free approach and using two torsion points) 93 | make action_timing BITLENGTH_OF_P=512 TYPE=DUMMYFREE 94 | 95 | [Execution] 96 | 97 | ./bin/action_timing 98 | 99 | # Clean 100 | 101 | make clean 102 | -------------------------------------------------------------------------------- /main/action_cost.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "fp.h" 5 | #include "edwards_curve.h" 6 | 7 | // Measuring the perfomance 8 | static uint64_t get_cycles() 9 | { 10 | uint32_t lo, hi; 11 | asm volatile("rdtsc":"=a"(lo),"=d"(hi)); 12 | return ((uint64_t)hi<<32) | lo; 13 | }; 14 | 15 | static uint8_t csidh(proj out, const uint8_t sk[], const proj in) 16 | { 17 | FP_ADD_COMPUTED = 0; 18 | FP_SQR_COMPUTED = 0; 19 | FP_MUL_COMPUTED = 0; 20 | 21 | if (!validate(in)) { 22 | return 0; 23 | }; 24 | action_evaluation(out, sk, in); 25 | return 1; 26 | }; 27 | 28 | unsigned long its = 1024; 29 | 30 | int main() 31 | { 32 | unsigned int i; 33 | 34 | uint64_t add_min = 0xFFFFFFFFFFFFFFFF, add_max = 0, 35 | sqr_min = 0xFFFFFFFFFFFFFFFF, sqr_max = 0, 36 | mul_min = 0xFFFFFFFFFFFFFFFF, mul_max = 0; 37 | 38 | float add_mean = 0, add_variance = 0, 39 | sqr_mean = 0, sqr_variance = 0, 40 | mul_mean = 0, mul_variance = 0; 41 | 42 | uint64_t add_sample[its], 43 | sqr_sample[its], 44 | mul_sample[its]; 45 | 46 | // --- 47 | uint8_t key[N]; 48 | proj random_E; 49 | point_copy(random_E, E); 50 | 51 | for(i = 0; i < its; ++i) 52 | { 53 | 54 | if (its >= 100 && i % (its / 100) == 0) { 55 | printf("Doing %lu iterations of action with validation key:\t", its); 56 | printf("%2lu%%", 100 * i / its); 57 | fflush(stdout); 58 | printf("\r\x1b[K"); 59 | } 60 | 61 | random_key(key); 62 | assert(csidh(random_E, key, random_E)); 63 | 64 | // --- 65 | add_sample[i] = FP_ADD_COMPUTED; 66 | sqr_sample[i] = FP_SQR_COMPUTED; 67 | mul_sample[i] = FP_MUL_COMPUTED; 68 | 69 | /**************************************/ 70 | if(add_min > add_sample[i]) 71 | add_min = add_sample[i]; 72 | if(sqr_min > sqr_sample[i]) 73 | sqr_min = sqr_sample[i]; 74 | if(mul_min > mul_sample[i]) 75 | mul_min = mul_sample[i]; 76 | 77 | /**************************************/ 78 | if(add_max < add_sample[i]) 79 | add_max = add_sample[i]; 80 | if(sqr_max < sqr_sample[i]) 81 | sqr_max = sqr_sample[i]; 82 | if(mul_max < mul_sample[i]) 83 | mul_max = mul_sample[i]; 84 | 85 | /**************************************/ 86 | add_mean += (float)add_sample[i]; 87 | sqr_mean += (float)sqr_sample[i]; 88 | mul_mean += (float)mul_sample[i]; 89 | }; 90 | 91 | 92 | add_mean = add_mean / ((float)its * 1.0); 93 | sqr_mean = sqr_mean / ((float)its * 1.0); 94 | mul_mean = mul_mean / ((float)its * 1.0); 95 | 96 | for (i = 0; i < its; ++i) 97 | { 98 | add_variance += (add_sample[i] - add_mean)*(add_sample[i] - add_mean); 99 | sqr_variance += (sqr_sample[i] - sqr_mean)*(sqr_sample[i] - sqr_mean); 100 | mul_variance += (mul_sample[i] - mul_mean)*(mul_sample[i] - mul_mean); 101 | }; 102 | 103 | add_variance = add_variance / ((float)its - 1.0); 104 | sqr_variance = sqr_variance / ((float)its - 1.0); 105 | mul_variance = mul_variance / ((float)its - 1.0); 106 | 107 | printf("\x1b[01;33mIterations: %lu\x1b[0m\n\n", its); 108 | 109 | printf("\x1b[33mAverage costs:\x1b[0m\n"); 110 | printf("\t %f additions,\n", add_mean); 111 | printf("\t\x1b[32m %f squarings,\x1b[0m\n", sqr_mean); 112 | printf("\t\x1b[31m %f multiplications.\x1b[0m\n", mul_mean); 113 | 114 | printf("\n"); 115 | 116 | printf("\x1b[33mStandard deviation of the costs:\x1b[0m\n"); 117 | printf("\t %f additions,\n", sqrt(add_variance)); 118 | printf("\t\x1b[32m %f squarings,\x1b[0m\n", sqrt(sqr_variance)); 119 | printf("\t\x1b[31m %f multiplications.\x1b[0m\n", sqrt(mul_variance)); 120 | 121 | printf("\n"); 122 | 123 | printf("\x1b[33mMinimum costs:\x1b[0m\n"); 124 | printf("\t %lu additions,\n", add_min); 125 | printf("\t\x1b[32m %lu squarings,\x1b[0m\n", sqr_min); 126 | printf("\t\x1b[31m %lu multiplications.\x1b[0m\n", mul_min); 127 | 128 | printf("\n"); 129 | 130 | printf("\x1b[33mMaximum costs:\x1b[0m\n"); 131 | printf("\t %lu additions,\n", add_max); 132 | printf("\t\x1b[32m %lu squarings,\x1b[0m\n", sqr_max); 133 | printf("\t\x1b[31m %lu multiplications.\x1b[0m\n", mul_max); 134 | 135 | return 0; 136 | }; 137 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # INCLUDE FOLDER 2 | BITLENGTH_OF_P?=512 3 | BITS?=$(BITLENGTH_OF_P) 4 | TYPE?=DUMMYFREE 5 | INC_DIR+= -I./inc -I./inc/fp$(BITLENGTH_OF_P)/ 6 | # GLOBAL FLAGS 7 | CFLAGS_ALWAYS?=-fcommon 8 | # COMPILER 9 | CC?=gcc-10 10 | 11 | # REQUIRED FOR TESTS 12 | FILES_REQUIRED_IN_CSIDH=./lib/rng.c \ 13 | ./lib/fp$(BITLENGTH_OF_P).S \ 14 | ./lib/point_arith.c ./lib/isogenies.c \ 15 | ./lib/action_simba_$(shell echo $(TYPE) | tr A-Z a-z).c \ 16 | ./main/csidh.c 17 | 18 | OUTPUT_CSIDH=./bin/csidh 19 | CFLAGS_CSIDH=-O3 -funroll-loops -fomit-frame-pointer -m64 -mbmi2 -DFP_$(BITLENGTH_OF_P) -D$(TYPE) 20 | 21 | FILES_REQUIRED_IN_CSIDH_UTIL=./lib/rng.c \ 22 | ./lib/fp$(BITLENGTH_OF_P).S \ 23 | ./lib/point_arith.c ./lib/isogenies.c \ 24 | ./lib/action_simba_$(shell echo $(TYPE) | tr A-Z a-z).c \ 25 | ./main/csidh_util.c 26 | OUTPUT_CSIDH_UTIL=./bin/csidh-p$(BITS)-util 27 | CFLAGS_CSIDH_UTIL=-O3 -funroll-loops -fomit-frame-pointer -m64 -mbmi2 -DFP_$(BITLENGTH_OF_P) -D$(TYPE) -DBITS=$(BITS) 28 | 29 | # REQUIRED FOR COSTS 30 | FILES_REQUIRED_IN_ACTION=./lib/rng.c \ 31 | ./lib/fp$(BITLENGTH_OF_P).S \ 32 | ./lib/point_arith.c ./lib/isogenies.c \ 33 | ./lib/action_simba_$(shell echo $(TYPE) | tr A-Z a-z).c \ 34 | ./main/action_cost.c 35 | 36 | OUTPUT_ACTION=./bin/action_cost 37 | CFLAGS_ACTION=-O3 -funroll-loops -fomit-frame-pointer -m64 -mbmi2 -DFP_$(BITLENGTH_OF_P) -D$(TYPE) -lm 38 | 39 | # REQUIRED FOR CLOCK CYCLES 40 | FILES_REQUIRED_IN_ACTION_CC=./lib/rng.c \ 41 | ./lib/fp$(BITLENGTH_OF_P).S \ 42 | ./lib/point_arith.c ./lib/isogenies.c \ 43 | ./lib/action_simba_$(shell echo $(TYPE) | tr A-Z a-z).c \ 44 | ./main/action_timing.c 45 | 46 | OUTPUT_ACTION_CC=./bin/action_timing 47 | CFLAGS_ACTION_CC=-O3 -funroll-loops -fomit-frame-pointer -m64 -mbmi2 -DFP_$(BITLENGTH_OF_P) -D$(TYPE) -lm 48 | 49 | help: 50 | @echo "\nusage: make csidh BITLENGTH_OF_P=[512] TYPE=[WITHDUMMY_1/WITHDUMMY_2/DUMMYFREE]" 51 | @echo "usage: make csidh_util BITLENGTH_OF_P=[512] TYPE=[WITHDUMMY_1/WITHDUMMY_2/DUMMYFREE]" 52 | @echo "usage: make util_test" 53 | @echo "usage: make regenerate_test_vectors" 54 | @echo "usage: make action_cost BITLENGTH_OF_P=[512] TYPE=[WITHDUMMY_1/WITHDUMMY_2/DUMMYFREE]" 55 | @echo "usage: make action_timing BITLENGTH_OF_P=[512] TYPE=[WITHDUMMY_1/WITHDUMMY_2/DUMMYFREE]" 56 | @echo "usage: make clean\n" 57 | @echo "In addition, you can use an specific compiler by setting the variable CC with the " 58 | @echo "compiler name.\n\t\tCC=[any version of gcc compiler]" 59 | 60 | util: csidh_util 61 | csidh_util: 62 | $(CC) $(INC_DIR) $(FILES_REQUIRED_IN_CSIDH_UTIL) -o $(OUTPUT_CSIDH_UTIL) $(CFLAGS_CSIDH_UTIL) $(CFLAGS_ALWAYS) 63 | 64 | regenerate_test_vectors: 65 | ./bin/csidh-p512-util -g -p sample-keys/1.montgomery.le.pk -s sample-keys/1.montgomery.le.sk 66 | ./bin/csidh-p512-util -g -p sample-keys/2.montgomery.le.pk -s sample-keys/2.montgomery.le.sk 67 | ./bin/csidh-p512-util -g -p sample-keys/3.montgomery.le.pk -s sample-keys/3.montgomery.le.sk 68 | ./bin/csidh-p512-util -g -p sample-keys/4.montgomery.le.pk -s sample-keys/4.montgomery.le.sk 69 | ./bin/csidh-p512-util -d -p sample-keys/2.montgomery.le.pk -s sample-keys/1.montgomery.le.sk > sample-keys/1-2.ss 70 | ./bin/csidh-p512-util -d -p sample-keys/1.montgomery.le.pk -s sample-keys/2.montgomery.le.sk > sample-keys/2-1.ss 71 | ./bin/csidh-p512-util -d -p sample-keys/2.montgomery.le.pk -s sample-keys/3.montgomery.le.sk > sample-keys/3-2.ss 72 | ./bin/csidh-p512-util -d -p sample-keys/3.montgomery.le.pk -s sample-keys/4.montgomery.le.sk > sample-keys/4-3.ss 73 | 74 | util_test: util 75 | echo "BEGIN util-test" 76 | ./bin/csidh-p512-util -d -p sample-keys/2.montgomery.le.pk -s sample-keys/1.montgomery.le.sk > sample-keys/1-2.ss.test_result 77 | diff sample-keys/1-2.ss.test_result sample-keys/1-2.ss 78 | ./bin/csidh-p512-util -d -p sample-keys/1.montgomery.le.pk -s sample-keys/2.montgomery.le.sk > sample-keys/2-1.ss.test_result 79 | diff sample-keys/2-1.ss.test_result sample-keys/2-1.ss 80 | ./bin/csidh-p512-util -d -p sample-keys/2.montgomery.le.pk -s sample-keys/3.montgomery.le.sk > sample-keys/3-2.ss.test_result 81 | diff sample-keys/3-2.ss.test_result sample-keys/3-2.ss 82 | ./bin/csidh-p512-util -d -p sample-keys/3.montgomery.le.pk -s sample-keys/4.montgomery.le.sk > sample-keys/4-3.ss.test_result 83 | diff sample-keys/4-3.ss.test_result sample-keys/4-3.ss 84 | rm sample-keys/*.test_result 85 | echo "END util-test" 86 | 87 | csidh: 88 | $(CC) $(INC_DIR) $(FILES_REQUIRED_IN_CSIDH) -o $(OUTPUT_CSIDH) $(CFLAGS_CSIDH) $(CFLAGS_ALWAYS) 89 | 90 | action_cost: 91 | $(CC) $(INC_DIR) $(FILES_REQUIRED_IN_ACTION) -o $(OUTPUT_ACTION) $(CFLAGS_ACTION) $(CFLAGS_ALWAYS) 92 | 93 | action_timing: 94 | $(CC) $(INC_DIR) $(FILES_REQUIRED_IN_ACTION_CC) -o $(OUTPUT_ACTION_CC) $(CFLAGS_ACTION_CC) $(CFLAGS_ALWAYS) 95 | 96 | clean: 97 | rm -f ./bin/* sample-keys/*.test_result 98 | 99 | -------------------------------------------------------------------------------- /lib/isogenies.c: -------------------------------------------------------------------------------- 1 | #include "edwards_curve.h" 2 | 3 | /* ----------------------------------------------------------------------------- * 4 | yISOG() 5 | Inputs: the projective Edwards y-coordinate of y(P)=YP/ZP, the Edwards curve 6 | constant A[0]:=a and A[1]:=(a - d), and integer number 0 <= i < N; 7 | Output: degree-l isogenous Edwards curve constants C[0]:=a and C[1]:=(a - d) 8 | determined by y(P), and the y-coordinate projective of y(P), y([2]P), 9 | ... y([(l-1)/2]P) 10 | * ----------------------------------------------------------------------------- */ 11 | void yISOG(proj Pk[], proj C, const proj P, const proj A, const uint8_t i) 12 | { 13 | uint8_t mask; 14 | int64_t bits_l; 15 | uint64_t j, 16 | l = L[i], // l_i 17 | s = l >> 1; // s <- (l_i - 1) / 2 18 | 19 | bits_l = 0; 20 | while (l > 0) 21 | { 22 | l >>= 1; 23 | bits_l += 1; 24 | }; // number of bits of l 25 | l = L[i]; 26 | // --- 27 | fp By[2], Bz[2], tmp_0, tmp_1, tmp_d; 28 | 29 | copy(tmp_0, A[0], NUMBER_OF_WORDS); // a 30 | fp_sub(tmp_d, A[0], A[1]); // d 31 | copy(tmp_1, tmp_d, NUMBER_OF_WORDS); 32 | 33 | copy(By[0], P[0], NUMBER_OF_WORDS); copy(By[1], P[0], NUMBER_OF_WORDS); 34 | copy(Bz[0], P[1], NUMBER_OF_WORDS); copy(Bz[1], P[1], NUMBER_OF_WORDS); 35 | 36 | point_copy(Pk[0], P); // P 37 | yDBL(Pk[1], P, A); // [2]P 38 | 39 | for(j = 2; j < s; j++) 40 | { 41 | fp_mul(By[0], By[0], Pk[j - 1][0]); 42 | fp_mul(Bz[0], Bz[0], Pk[j - 1][1]); 43 | yADD(Pk[j], Pk[j - 1], P, Pk[j - 2]); // [j + 1]P 44 | 45 | FP_MUL_COMPUTED += 2; 46 | }; 47 | 48 | mask = isequal(l, 3) ^ 1; // If l = 3 then we keep with the current values of By[0] and Bz[0]. This ask is done in constant-time 49 | fp_mul(By[1], By[0], Pk[s - 1][0]); // This an extra cost for a degree-3 construction 50 | fp_mul(Bz[1], Bz[0], Pk[s - 1][1]); // This an extra cost for a degree-3 construction 51 | fp_cswap(By[0], By[1], mask); // constant-time swap: dummy or not dummy, that is the question. 52 | fp_cswap(Bz[0], Bz[1], mask); // constant-time swap: dummy or not dummy, that is the question. 53 | 54 | // left-to-right method for computing a^l and d^l 55 | bits_l -= 1; 56 | for(j = 1; j <= bits_l; j++) 57 | { 58 | fp_sqr(tmp_0, tmp_0); 59 | fp_sqr(tmp_1, tmp_1); 60 | //if( ( (0x1 << (bits_l - j) ) & l ) != 0x0) 61 | if( ( (l >> (bits_l - j)) & 1 ) != 0) 62 | { 63 | fp_mul(tmp_0, tmp_0, A[0]); 64 | fp_mul(tmp_1, tmp_1, tmp_d); 65 | 66 | FP_MUL_COMPUTED += 2; 67 | }; 68 | 69 | FP_SQR_COMPUTED += 2; 70 | }; 71 | 72 | for(j = 0; j < 3; j++) 73 | { 74 | fp_sqr(By[0], By[0]); 75 | fp_sqr(Bz[0], Bz[0]); 76 | 77 | FP_SQR_COMPUTED += 2; 78 | }; 79 | 80 | fp_mul(C[0], tmp_0, Bz[0]); 81 | fp_mul(C[1], tmp_1, By[0]); 82 | fp_sub(C[1], C[0], C[1]); 83 | 84 | FP_ADD_COMPUTED += 2; 85 | FP_MUL_COMPUTED += 4; 86 | };// Cost ~ (3l + log(l) - 7)M + (l + 2log(l) + 3)S + (3l - 1)a 87 | 88 | /* ----------------------------------------------------------------------------- * 89 | yEVAL() 90 | Inputs: the projective Edwards y-coordinate of y(Q)=YQ/ZQ, the y-coordinate 91 | projective of y(P), y([2]P), ..., y([(l-1)/2]P), and integer number 92 | 0 <= i < N; 93 | Output: the image of y(Q) under a degree-L[i] isogeny with kernel generated 94 | by y(P). 95 | * ----------------------------------------------------------------------------- */ 96 | void yEVAL(proj R, const proj Q, const proj Pk[], const uint8_t i) 97 | { 98 | int j; 99 | fp tmp_0, tmp_1, s_0, s_1; 100 | 101 | proj tmp_Q; 102 | point_copy(tmp_Q, Q); // This is for allowing Q <- image of Q 103 | 104 | // Evaluating Q 105 | fp_mul(s_0, tmp_Q[0], Pk[0][1]); 106 | fp_mul(s_1, tmp_Q[1], Pk[0][0]); 107 | // Mapping R into the isomorphic Montgomery curve 108 | fp_add(R[0], s_0, s_1); 109 | fp_sub(R[1], s_0, s_1); 110 | 111 | uint64_t s = (L[i] >> 1); 112 | for(j = 1; j < s; j++) 113 | { 114 | // Evaluating Q 115 | fp_mul(s_0, tmp_Q[0], Pk[j][1]); 116 | fp_mul(s_1, tmp_Q[1], Pk[j][0]); 117 | fp_add(tmp_0, s_0, s_1); 118 | fp_sub(tmp_1, s_0, s_1); 119 | fp_mul(R[0], R[0], tmp_0); 120 | fp_mul(R[1], R[1], tmp_1); 121 | 122 | FP_ADD_COMPUTED += 2; 123 | FP_MUL_COMPUTED += 4; 124 | }; 125 | 126 | fp_sqr(R[0], R[0]); 127 | fp_sqr(R[1], R[1]); 128 | // Mapping Q into the isomorphic Montgomery curve 129 | fp_add(tmp_0, tmp_Q[1], tmp_Q[0]); 130 | fp_sub(tmp_1, tmp_Q[1], tmp_Q[0]); 131 | fp_mul(tmp_0, R[0], tmp_0); 132 | fp_mul(tmp_1, R[1], tmp_1); 133 | // Mapping R into the Edwards curve 134 | fp_sub(R[0], tmp_0, tmp_1); 135 | fp_add(R[1], tmp_0, tmp_1); 136 | 137 | FP_ADD_COMPUTED += 6; 138 | FP_SQR_COMPUTED += 2; 139 | FP_MUL_COMPUTED += 4; 140 | };// Cost : 2(l - 1)M + 2S + (3 + l)a 141 | 142 | -------------------------------------------------------------------------------- /inc/fp.h: -------------------------------------------------------------------------------- 1 | #ifndef _Fp_H_ 2 | #define _Fp_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define __STDC_FORMAT_MACROS 10 | #include 11 | 12 | #include "rng.h" 13 | 14 | #if defined FP_512 15 | #define N 74 // Number of l_i's such that l_i | [(p+1)/4] 16 | #define LOG2_OF_N_PLUS_ONE 8 17 | #define NUMBER_OF_WORDS 8 // Number of 64-bit words 18 | 19 | // If a new field arithmetic will be used, just add it but taking in count that it is required: 20 | // fp_add(output, input_x, input_y), 21 | // fp_sub(output, input_x, input_y), 22 | // fp_mul(output, input_x, input_y), 23 | // fp_sqr(output, input_x), 24 | // fp_inv(input), 25 | // fp_issquare(input), and 26 | // fp_random(input); 27 | // This above functions must be implemented allowing that the output variable can be one of the inputs. 28 | 29 | #endif 30 | 31 | typedef uint64_t fp[NUMBER_OF_WORDS] __attribute__((aligned(64))); // 512-bits integer number in Montgomery domain (To be used with the patching) 32 | 33 | extern const fp p; 34 | extern const fp R_mod_p; 35 | extern const fp R_squared_mod_p; // required for mapping a random fp element 2 <= u <= (p-1)/2 into the Montgomery domain 36 | extern const fp p_minus_1_halves; // (p-1)/2 used for find a random fp element 2 <= u <= (p-1)/2 37 | 38 | // All operations are perfomed in the Montgomery domain 39 | void fp_cswap(fp x, fp y, uint8_t c); 40 | 41 | void fp_add(fp c, const fp a, const fp b); 42 | void fp_sub(fp c, const fp a, const fp b); 43 | void fp_mul(fp c, const fp a, const fp b); 44 | void fp_sqr(fp b, const fp a); 45 | 46 | void fp_inv(fp x); 47 | uint8_t fp_issquare(fp const x); 48 | void fp_random(fp x); // This function should be modified in order to have a better random function: e.g., shake256. 49 | 50 | #define set_zero(x, NUM)\ 51 | memset(x, 0, sizeof(uint64_t) * NUM); 52 | 53 | #define set_one(x, NUM) {\ 54 | int i;\ 55 | x[0] = 1; \ 56 | for (i=1; i < NUM; i++)\ 57 | x[i] = 0;\ 58 | } 59 | 60 | #define copy(x, y, NUM)\ 61 | memcpy(x, y, sizeof(uint64_t)*NUM); 62 | 63 | /* ------------------------------------------------------------- * 64 | compare() 65 | inputs: two integer numbers x and y, and the number of 64-bits 66 | words of x and y. 67 | outputs: 68 | +1 if x > y, 69 | -1 if x < y, or 70 | 0 if x = y. 71 | * ------------------------------------------------------------- */ 72 | static inline int compare(uint64_t *x, uint64_t *y, int NUM) 73 | { 74 | int i; 75 | for (i=NUM-1; i >= 0; i--) 76 | { 77 | if (x[i] != y[i]) 78 | return x[i] > y[i] ? 1 : -1; 79 | } 80 | return 0; 81 | } 82 | 83 | /* ------------------------------------------------------------- * 84 | iszero() 85 | inputs: two integer numbers x and y, and the number of 64-bits 86 | words of x and y. 87 | outputs: 88 | 1 if x = 0, 89 | 0 otherwise 90 | * ------------------------------------------------------------- */ 91 | static inline int iszero(uint64_t *x, int NUM) 92 | { 93 | int i; 94 | uint64_t c = 0; 95 | for (i=NUM-1; i >= 0; i--) 96 | c |= x[i]; 97 | return (c == 0); 98 | } 99 | 100 | /* ------------------------------------------------------------- * 101 | fp_print() 102 | inputs: an integer number x, the number of 64-bits words of x, 103 | an integer in {1,0}, and a string. 104 | Note: This function prints the integer x 105 | * ------------------------------------------------------------- */ 106 | static void fp_print(uint64_t *x, int NUM, int TYPE, char *c) 107 | { 108 | int i; 109 | printf("%s := 0x", c); 110 | for(i=NUM-1; i > -1; i--){ 111 | if(TYPE == 1) 112 | printf("%.16" PRIX64 " ", x[i]); 113 | else 114 | printf("%.16" PRIX64 "", x[i]); 115 | } 116 | printf(";\n"); 117 | } 118 | 119 | /* decision bit b has to be either 0 or 1 */ 120 | static void cmov(int8_t *r, const int8_t a, uint32_t b) 121 | { 122 | uint32_t t; 123 | b = -b; /* Now b is either 0 or 0xffffffff */ 124 | t = (*r ^ a) & b; 125 | *r ^= t; 126 | } 127 | 128 | /* check if a and b are equal in constant time */ 129 | static uint32_t isequal(uint32_t a, uint32_t b) 130 | { 131 | //size_t i; 132 | uint32_t r = 0; 133 | unsigned char *ta = (unsigned char *)&a; 134 | unsigned char *tb = (unsigned char *)&b; 135 | r = (ta[0] ^ tb[0]) | (ta[1] ^ tb[1]) | (ta[2] ^ tb[2]) | (ta[3] ^ tb[3]); 136 | r = (-r); 137 | r = r >> 31; 138 | return (uint32_t)(1-r); 139 | } 140 | 141 | /* get priv[pos] in constant time */ 142 | static uint32_t lookup(size_t pos, int8_t const priv[]) 143 | { 144 | int b; 145 | int8_t r = priv[0]; 146 | for(size_t i = 1; i < N; i++) 147 | { 148 | b = isequal(i, pos); 149 | cmov(&r, priv[i], b); 150 | } 151 | return r; 152 | } 153 | 154 | // constant-time comparison: -1 if x < y, 0 otherwise. 155 | static int32_t issmaller(int32_t x, int32_t y) 156 | { 157 | int32_t xy = x ^ y; 158 | int32_t c = x - y; 159 | c ^= xy & (c ^ x); 160 | return (c >> 31); 161 | } 162 | #endif /* Fp */ 163 | -------------------------------------------------------------------------------- /main/csidh.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fp.h" 4 | #include "edwards_curve.h" 5 | 6 | // Measuring the perfomance 7 | static uint64_t get_cycles() 8 | { 9 | uint32_t lo, hi; 10 | asm volatile("rdtsc":"=a"(lo),"=d"(hi)); 11 | return ((uint64_t)hi<<32) | lo; 12 | }; 13 | 14 | static uint8_t csidh(proj out, const uint8_t sk[], const proj in) 15 | { 16 | FP_ADD_COMPUTED = 0; 17 | FP_SQR_COMPUTED = 0; 18 | FP_MUL_COMPUTED = 0; 19 | 20 | if (!validate(in)) { 21 | return 0; 22 | }; 23 | 24 | action_evaluation(out, sk, in); 25 | return 1; 26 | }; 27 | 28 | int main() 29 | { 30 | uint64_t c0, c1; 31 | 32 | fp u; 33 | uint8_t sk_alice[N], // secret key of Alice 34 | sk_bob[N]; // secret key of Bob 35 | 36 | 37 | // --- 38 | proj random_E, tmp_E; 39 | uint8_t key[N]; 40 | random_key(key); 41 | csidh(random_E, key, E); 42 | 43 | // --- 44 | printf("NOTE: all the arithmetic is in Montgomery domain. "); 45 | printf("In addition, the ordering of the prime factors l_i's is:\n"); 46 | printf("L := {\t %3d", L[0]); 47 | 48 | for(int i = 1; i < N; i++) 49 | { 50 | printf(", %3d", L[i]); 51 | if( (i % 18) == 17 ) 52 | printf("\n\t"); 53 | }; 54 | printf("};\n"); 55 | 56 | printf("Moreover, the secret exponents belong to { -B_i, ..., 0, ..., B_i } where\n"); 57 | printf("B := {\t %3d", B[0]); 58 | for(int i = 1; i < N; i++) 59 | { 60 | printf(", %3d", B[i]); 61 | if( (i % 18) == 17 ) 62 | printf("\n\t"); 63 | }; 64 | printf("};\n"); 65 | printf("The dummy-free case implies that the secret exponents satisfy (e_i mod 2) = (b_i mod 2).\n"); 66 | 67 | printf("-----------------------------------------------------------------------------------------------------\n"); 68 | printf("First step: Alice and Bob random generate a secret key, and both compute and send their public curves\n\n"); 69 | // Alice: random key generation 70 | random_key(sk_alice); 71 | printf_key(sk_alice, "sk_alice"); 72 | 73 | proj E_alice; 74 | c0 = get_cycles(); 75 | assert(csidh(E_alice, sk_alice, E)); 76 | c1 = get_cycles(); 77 | fp_print(E_alice[0], NUMBER_OF_WORDS, 0, "E_alice_a "); 78 | fp_print(E_alice[1], NUMBER_OF_WORDS, 0, "E_alice_ad"); 79 | printf("clock cycles: %3.03lf\n", ( 1.0 * (c1 - c0)) / (1000000.0)); 80 | printf("Number of field operations computed: (%lu)M + (%lu)S + (%lu)a\n\n", FP_MUL_COMPUTED, FP_SQR_COMPUTED, FP_ADD_COMPUTED); 81 | 82 | // Bob: random key generation 83 | random_key(sk_bob); 84 | printf_key(sk_bob, "sk_bob"); 85 | 86 | proj E_bob; 87 | c0 = get_cycles(); 88 | assert(csidh(E_bob, sk_bob, E)); 89 | c1 = get_cycles(); 90 | fp_print(E_bob[0], NUMBER_OF_WORDS, 0, "E_bob_a "); 91 | fp_print(E_bob[1], NUMBER_OF_WORDS, 0, "E_bob_ad"); 92 | printf("clock cycles: %3.03lf\n", ( 1.0 * (c1 - c0)) / (1000000.0)); 93 | printf("Number of field operations computed: (%lu)M + (%lu)S + (%lu)a\n", FP_MUL_COMPUTED, FP_SQR_COMPUTED, FP_ADD_COMPUTED); 94 | 95 | 96 | printf("\n"); 97 | printf("------------------------------------------------------------------------------------------------------------\n"); 98 | printf("Second step: Alice a Bob compute the shared secret by using the public curves of Bob and Alice, respectively\n"); 99 | // Alice: shared secret 100 | proj ss_alice; 101 | c0 = get_cycles(); 102 | assert(csidh(ss_alice, sk_alice, E_bob)); 103 | c1 = get_cycles(); 104 | fp_print(ss_alice[0], NUMBER_OF_WORDS, 0, "ss_alice_a "); 105 | fp_print(ss_alice[1], NUMBER_OF_WORDS, 0, "ss_alice_ad"); 106 | printf("clock cycles: %3.03lf\n", ( 1.0 * (c1 - c0)) / (1000000.0)); 107 | printf("Number of field operations computed: (%lu)M + (%lu)S + (%lu)a\n", FP_MUL_COMPUTED, FP_SQR_COMPUTED, FP_ADD_COMPUTED); 108 | 109 | printf("\n"); 110 | // Bob: shared secret 111 | proj ss_bob; 112 | c0 = get_cycles(); 113 | assert(csidh(ss_bob, sk_bob, E_alice)); 114 | c1 = get_cycles(); 115 | fp_print(ss_bob[0], NUMBER_OF_WORDS, 0, "ss_bob_a "); 116 | fp_print(ss_bob[1], NUMBER_OF_WORDS, 0, "ss_bob_ad"); 117 | printf("clock cycles: %3.03lf\n", ( 1.0 * (c1 - c0)) / (1000000.0)); 118 | printf("Number of field operations computed: (%lu)M + (%lu)S + (%lu)a\n", FP_MUL_COMPUTED, FP_SQR_COMPUTED, FP_ADD_COMPUTED); 119 | 120 | printf("\n"); 121 | printf("------------------------------------------------------------------------------------------------------------\n"); 122 | printf("At the end of the protocol, Alice and Bob have different but isomorphic Edwards curves. In other words, the\n"); 123 | printf("Montgomery curve isomorphic to each one is the same. Thus, (ss_alice_a / ss_alice_ad) = (ss_bob_a / ss_bob_ad).\n"); 124 | 125 | fp ss_a, ss_b; 126 | fp_inv(ss_alice[1]); 127 | fp_mul(ss_a, ss_alice[0], ss_alice[1]); 128 | 129 | fp_inv(ss_bob[1]); 130 | fp_mul(ss_b, ss_bob[0], ss_bob[1]); 131 | fp_print(ss_a, NUMBER_OF_WORDS, 0, "ss_a"); 132 | fp_print(ss_b, NUMBER_OF_WORDS, 0, "ss_b"); 133 | 134 | if( compare(ss_a, ss_b, NUMBER_OF_WORDS) != 0 ) 135 | { 136 | printf("\x1b[31m _ ___ __ _ _ __ __ __ _ __ _____ __ _ _ __ _ \x1b[0m\n"); 137 | printf("\x1b[31m|\\|/ \\ | |_ / \\| ||_|| (_ |_ / |_)|_ / | (_ |_||_||_)|_ | \\ \x1b[0m\n"); 138 | printf("\x1b[31m| |\\_/ | |__\\_X|_|| ||__ __)|__\\__| \\|__\\__ | __)| || || \\|__|_/ \x1b[0m\n"); 139 | } 140 | else 141 | { 142 | printf("\x1b[32m __ _ _ __ __ __ _ __ _____ __ _ _ __ _ \x1b[0m\n"); 143 | printf("\x1b[32m|_ / \\| ||_|| (_ |_ / |_)|_ / | (_ |_||_||_)|_ | \\ \x1b[0m\n"); 144 | printf("\x1b[32m|__\\_X|_|| ||__ __)|__\\__| \\|__\\__ | __)| || || \\|__|_/ \x1b[0m\n"); 145 | } 146 | printf("\n"); 147 | 148 | return 0; 149 | }; 150 | -------------------------------------------------------------------------------- /main/csidh_util.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "csidh_util.h" 10 | 11 | void normalize_public_key(proj public_key, fp *out) { 12 | /* Compress the public key from x,y (256 bits) to x/y,NULL (128 bits) */ 13 | // public_key has entries x,y or public_key[0] and public_key[1] 14 | fp n_public_key; 15 | fp_inv(public_key[1]); // fp_inv becomes x,1/y or public_key[0] = x and public_key[1] = 1/y 16 | fp_mul(n_public_key, public_key[0], public_key[1]); // normalized_public_key is x*1/y or x/y aka public_key[0]/public_key[1] 17 | /* Convert to Montgomery form */ 18 | fp_mul(n_public_key, n_public_key, E[1]); // x/y * 4 19 | fp_sub(n_public_key, n_public_key, E[0]); // x/y - 2 20 | memcpy(out, n_public_key, sizeof(fp)); 21 | } 22 | 23 | // slightly modified csidh from main/csidh.c 24 | static uint8_t csidh(proj out, const uint8_t sk[], const proj in) 25 | { 26 | if (!validate(in)) { 27 | return 0; 28 | }; 29 | 30 | action_evaluation(out, sk, in); 31 | return 1; 32 | }; 33 | 34 | void pprint_ss(uint64_t *x) 35 | { 36 | /* for p512 we print 8 64bit little endian values as hex. */ 37 | int ceiling = 7; 38 | int i; 39 | for(i=ceiling; i >= 0; --i){ 40 | printf("%.16" PRIX64 "", x[i]); 41 | } 42 | printf("\n"); 43 | } 44 | 45 | void pprint_pk(void *x) { 46 | for (size_t i = 0; i < (sizeof(proj)/2); ++i) { 47 | printf("%02hhx", ((uint8_t *)x)[i]); 48 | } 49 | printf("\n"); 50 | }; 51 | 52 | void pprint_sk(void *x) { 53 | for (size_t i = 0; i < sizeof(uint8_t[N]); ++i) { 54 | printf("%02hhx", ((uint8_t *)x)[i]); 55 | } 56 | printf("\n"); 57 | }; 58 | 59 | void save_file(char *file, void *buf, size_t len) { 60 | FILE *fhandle; 61 | if (file != NULL) { 62 | fhandle = fopen(file, "w"); 63 | if (fhandle == NULL) { 64 | fprintf(stderr, "Unable to open %s\n", file); 65 | exit(1); 66 | } 67 | for (size_t i = 0; i < len; ++i) 68 | fprintf(fhandle, "%02hhx", ((uint8_t *)buf)[i]); 69 | fprintf(fhandle, "\n"); 70 | fclose(fhandle); 71 | } 72 | } 73 | 74 | void error_exit(char *str) { 75 | fprintf(stderr, "%s\n", str); 76 | exit(1); 77 | } 78 | 79 | int read_file(const char *file, uint8_t *buf, size_t len) { 80 | size_t c = 0; 81 | FILE *fhandle; 82 | fhandle = fopen(file, "r"); 83 | if (fhandle == NULL) { 84 | fprintf(stderr, "Unable to open %s\n", file); 85 | exit(3); 86 | } 87 | for (size_t i = 0; i < len; ++i) { 88 | c += fscanf(fhandle, "%02hhx", &buf[i]); 89 | } 90 | fclose(fhandle); 91 | return c; 92 | } 93 | 94 | int read_stdin(uint8_t *buf, int len) { 95 | size_t c = 0; 96 | for (size_t i = 0; i < len; ++i) { 97 | c += fscanf(stdin, "%02hhx", &buf[i]); 98 | } 99 | return c; 100 | } 101 | 102 | int main(int argc, char **argv) { 103 | uint8_t private_key[N]; 104 | proj expanded_public_key; 105 | proj public_key; 106 | proj shared_secret_key; 107 | 108 | explicit_bzero(&private_key, sizeof(private_key)); 109 | explicit_bzero(&public_key, sizeof(proj)); 110 | explicit_bzero(&expanded_public_key, sizeof(proj)); 111 | explicit_bzero(&shared_secret_key, sizeof(proj)); 112 | 113 | int csidh_validate = 0; 114 | int option = 0; 115 | size_t verbose = 0; 116 | size_t generation_mode = 0; 117 | size_t derivation_mode = 0; 118 | size_t error = 0; 119 | char *priv_key_file = NULL; 120 | char *pub_key_file = NULL; 121 | 122 | while ((option = getopt(argc, argv, "hvVgdp:s:")) != -1) { 123 | switch (option) { 124 | case 'V': 125 | fprintf(stderr, "csidh-p%i-util version: %f\n", BITS, VERSION); 126 | return 0; 127 | case 'h': 128 | fprintf(stderr, "csidh-p%i-util version: %f\n", BITS, VERSION); 129 | fprintf(stderr, " -V: print version\n"); 130 | fprintf(stderr, " -verbose: increase verbosity\n"); 131 | fprintf(stderr, " -g: key generation mode\n"); 132 | fprintf(stderr, " -d: key derivation mode\n"); 133 | fprintf(stderr, " -p: public key file name\n"); 134 | fprintf(stderr, " -s: private key file name\n"); 135 | return 0; 136 | case 'v': 137 | verbose += 1; 138 | break; 139 | case 'g': 140 | generation_mode = 1; 141 | if (derivation_mode) { 142 | error += 1; 143 | }; 144 | break; 145 | case 'd': 146 | derivation_mode = 1; 147 | if (generation_mode) { 148 | error = 1; 149 | }; 150 | break; 151 | case 'p': 152 | pub_key_file = optarg; 153 | if (verbose) { 154 | fprintf(stderr, "pub_key_file=%s\n", pub_key_file); 155 | }; 156 | break; 157 | case 's': 158 | priv_key_file = optarg; 159 | if (verbose) { 160 | fprintf(stderr, "priv_key_file=%s\n", priv_key_file); 161 | }; 162 | break; 163 | default: 164 | exit(1); 165 | } 166 | } 167 | 168 | if (error) { 169 | error_exit("Mutually exclusive options chosen"); 170 | } 171 | 172 | if (generation_mode) { 173 | if (verbose) { 174 | fprintf(stderr, "Key generation mode\n"); 175 | } 176 | random_key(private_key); 177 | csidh_validate = csidh(public_key, private_key, E); 178 | if (!csidh_validate) { 179 | error_exit("csidh_validate: failed"); 180 | } 181 | if (priv_key_file == NULL){ 182 | pprint_sk(private_key); 183 | } else { 184 | if (verbose) { pprint_sk(private_key); } 185 | save_file(priv_key_file, &private_key, sizeof(uint8_t [N])); 186 | } 187 | 188 | /* Normalize (aka compress) the public key in size from 256 bits to 128 bits. */ 189 | fp normalized_public_key; 190 | explicit_bzero(&normalized_public_key, sizeof(fp)); 191 | normalize_public_key(public_key, &normalized_public_key); 192 | if (pub_key_file == NULL){ 193 | pprint_pk(normalized_public_key); 194 | } else { 195 | if (verbose) { pprint_pk(normalized_public_key);} 196 | save_file(pub_key_file, normalized_public_key, (sizeof(proj)/2)); 197 | } 198 | return 0; 199 | } 200 | 201 | if (derivation_mode) { 202 | if (verbose) { 203 | fprintf(stderr, "DH mode\n"); 204 | } 205 | 206 | if (sizeof(private_key) != 207 | ((priv_key_file != NULL) 208 | ? read_file(priv_key_file, (uint8_t *)&private_key, 209 | sizeof(private_key)) 210 | : read_stdin((uint8_t *)&private_key, sizeof(private_key)))) { 211 | error_exit("Unable to read correct number of bytes for private key"); 212 | } 213 | 214 | if ((sizeof(public_key)/2) != 215 | ((pub_key_file != NULL) 216 | ? read_file(pub_key_file, (uint8_t *)public_key, 217 | (sizeof(proj)/2)) 218 | : read_stdin((uint8_t *)public_key, (sizeof(proj)/2)))) { 219 | error_exit("Unable to read correct number of bytes for public key"); 220 | } 221 | 222 | /* Expand the normalized key and convert from Montgomery to Edwards form. */ 223 | /* 224 | * If one wanted to use Edwards rather than Montgomery, the three lines 225 | * below could be replaced with the following two lines: 226 | * 227 | * memcpy(expanded_public_key[1], R_mod_p, (sizeof(expanded_public_key[1]))); 228 | * memcpy(expanded_public_key[0], public_key, (sizeof(expanded_public_key[0]))); 229 | * 230 | * */ 231 | memcpy(expanded_public_key[1], E[1], (sizeof(expanded_public_key[1]))); // E[1] ==2 232 | memcpy(expanded_public_key[0], public_key, (sizeof(expanded_public_key[0]))); // Original value from user in Montgomery form 233 | fp_add(expanded_public_key[0], expanded_public_key[0], E[0]); // E[0] == 4 234 | 235 | /* Operate on the expanded public key. */ 236 | csidh_validate = csidh(shared_secret_key, private_key, expanded_public_key); 237 | if (!csidh_validate) { 238 | error_exit("csidh_validate: failed"); 239 | } 240 | 241 | /* Normalize our shared secret. */ 242 | fp shared_secret; 243 | fp_inv(shared_secret_key[1]); 244 | fp_mul(shared_secret, shared_secret_key[0], shared_secret_key[1]); 245 | /* Convert from Edwards to Montgomery. */ 246 | fp_mul(shared_secret, shared_secret, E[1]); // x/y * 4 247 | fp_sub(shared_secret, shared_secret, E[0]); // x/y - 2 248 | 249 | if (verbose) { 250 | pprint_sk(private_key); 251 | pprint_pk(expanded_public_key); 252 | } 253 | /* Output shared secret in Little Endian to match the other known CSIDH 254 | * implementations. */ 255 | pprint_ss(shared_secret); 256 | return 0; 257 | } 258 | 259 | return 1; 260 | } 261 | -------------------------------------------------------------------------------- /lib/action_simba_withdummy_1.c: -------------------------------------------------------------------------------- 1 | #include "edwards_curve.h" 2 | 3 | void random_key(uint8_t key[]) 4 | { 5 | uint8_t i, tmp; 6 | for(i = 0; i < N; i++) 7 | { 8 | // Random number from |[0, B]| 9 | randombytes(&tmp, 1); 10 | while ( issmaller((int32_t)B[i], (int32_t)tmp) == -1 ) // constant-time comparison 11 | randombytes(&tmp, 1); 12 | key[i] = tmp; 13 | 14 | }; 15 | }; 16 | 17 | void printf_key(uint8_t key[], char *c) 18 | { 19 | int i; 20 | printf("%s := ", c); 21 | printf("{\t %2d", key[0]); 22 | 23 | for(i = 1; i < N; i++) 24 | { 25 | printf(", %2d", key[i]); 26 | if( (i % 18) == 17 ) 27 | printf("\n\t\t"); 28 | }; 29 | 30 | printf("};\n"); 31 | 32 | }; 33 | 34 | /* ----------------------------------------------------------------------------------------------- * 35 | action_evaluation() 36 | inputs: a the secret key, the Edwards curve constants A[0]:=a, and A[1]:=(a - d); 37 | output: the isogenous Edwards curve constants C[0]:=a' and C[1]:=(a' - d') determined by the action 38 | evaluated at the secret key and public curve A 39 | 40 | NOTE: As far as we've understood how simba works; this next code implements simba approach. 41 | The action computed by the next code uses only one torsion point T_{+}, which its affine 42 | y-coordinate (in the isomorphic Montgomery curve) belongs to Fp. 43 | * ----------------------------------------------------------------------------------------------- */ 44 | void action_evaluation(proj C, const uint8_t key[], const proj A) 45 | { 46 | // -------------------------------------------------------------------------------------------------------- 47 | // SIMBA parameters 48 | // Batches 49 | uint8_t batches[NUMBER_OF_BATCHES][SIZE_OF_EACH_BATCH[0]]; 50 | uint8_t size_of_each_batch[NUMBER_OF_BATCHES]; 51 | 52 | for(uint8_t i = 0; i < NUMBER_OF_BATCHES; i++) 53 | memcpy(batches[i], BATCHES[i], sizeof(uint8_t) * SIZE_OF_EACH_BATCH[i]); 54 | 55 | memcpy(size_of_each_batch, SIZE_OF_EACH_BATCH, sizeof(uint8_t) * NUMBER_OF_BATCHES); 56 | // Complement of each batch 57 | uint8_t complement_of_each_batch[NUMBER_OF_BATCHES][N]; 58 | uint8_t size_of_each_complement_batch[NUMBER_OF_BATCHES]; 59 | 60 | memcpy(complement_of_each_batch, COMPLEMENT_OF_EACH_BATCH, sizeof(uint8_t) * NUMBER_OF_BATCHES * N); 61 | memcpy(size_of_each_complement_batch, SIZE_OF_EACH_COMPLEMENT_BATCH, sizeof(uint8_t) * NUMBER_OF_BATCHES); 62 | // -------------------------------------------------------------------------------------------------------- 63 | 64 | // -------------------------------------------------------------------------------------------------------- 65 | // Copy of public and private data (the private key is modified each iteration) 66 | uint8_t tmp_e[N]; 67 | memcpy(tmp_e, key, sizeof(uint8_t) * N); // exponents 68 | 69 | proj current_A[2], current_Tp[2]; 70 | point_copy(current_A[0], A); // initial Edwards curve constants a and (a -d) 71 | // -------------------------------------------------------------------------------------------------------- 72 | 73 | // -------------------------------------------------------------------------------------------------------- 74 | // Vairables required for running SIMBA 75 | int8_t ec = 0, mask; 76 | uint16_t count = 0; 77 | proj G[2], K[(LARGE_L >> 1) + 1], Z; // Current kernel 78 | uint8_t finished[N]; // flag that determines if the maximum number of isogeny constructions has been reached 79 | memset(finished, 0, sizeof(uint8_t) * N); 80 | 81 | int8_t counter[N]; // This variable determines how many isogeny construcctions has been perfomed 82 | memset(counter, 0, sizeof(int8_t) * N); 83 | memcpy(counter, B, sizeof(int8_t) * N); // At the beginning, we must perfomed b_i isogeny constructions for each l_i 84 | uint64_t isog_counter = 0; // Total number of isogeny construction perfomed 85 | 86 | uint8_t last_isogeny[NUMBER_OF_BATCHES]; 87 | //index for skipping point evaluations (the last one of each batch) 88 | memcpy(last_isogeny, LAST_ISOGENY, sizeof(uint8_t) * NUMBER_OF_BATCHES); 89 | uint32_t bc; 90 | // -------------------------------------------------------------------------------------------------------- 91 | 92 | // -------------------------------------------------------------------------------------------------------- 93 | // Main loop 94 | uint8_t m = 0, i, j; 95 | uint64_t number_of_batches = NUMBER_OF_BATCHES; 96 | uint32_t si; 97 | 98 | while (isog_counter < NUMBER_OF_ISOGENIES) 99 | { 100 | m = (m + 1) % number_of_batches; 101 | 102 | if(count == MY*number_of_batches) { //merge the batches after my rounds 103 | m = 0; 104 | size_of_each_complement_batch[m] = 0; 105 | size_of_each_batch[m] = 0; 106 | number_of_batches = 1; 107 | 108 | for(i = 0; i < N; i++) { 109 | if( counter[i] == 0 ) 110 | { 111 | // l_i's reached 112 | complement_of_each_batch[m][size_of_each_complement_batch[m]] = i; 113 | size_of_each_complement_batch[m] += 1; 114 | } 115 | else 116 | { 117 | last_isogeny[0] = i; 118 | // l_i's not reached 119 | batches[m][size_of_each_batch[m]] = i; 120 | size_of_each_batch[m] += 1; 121 | }; 122 | } 123 | } 124 | 125 | // Before constructing isogenies, we must to search for suitable point 126 | elligator(current_Tp[0], current_Tp[1], current_A[0]); 127 | 128 | // Next, it is required to multiply the point by 4 and each l_i that doesn't belong to the current batch 129 | yDBL(current_Tp[0], current_Tp[0], current_A[0]); // mult. by [2] 130 | yDBL(current_Tp[0], current_Tp[0], current_A[0]); // mult. by [2] 131 | // Now, it is required to multiply by the complement of the batch 132 | for(i = 0; i < size_of_each_complement_batch[m]; i++) 133 | yMUL(current_Tp[0], current_Tp[0], current_A[0], complement_of_each_batch[m][i]); 134 | 135 | for(i = 0; i < size_of_each_batch[m]; i++) 136 | { 137 | if( finished[batches[m][i]] == 1 ) 138 | { 139 | //depends only on randomness 140 | continue; 141 | } 142 | else 143 | { 144 | // Now, a degree-(l_{batches[m][i]}) will be constructed 145 | point_copy(G[0], current_Tp[0]); 146 | for (j = (i + 1); j < size_of_each_batch[m]; j++) 147 | { 148 | if( finished[batches[m][j]] == 0 ) 149 | { 150 | //depends only on randomness 151 | yMUL(G[0], G[0], current_A[0], batches[m][j]); 152 | }; 153 | }; 154 | 155 | if ( isinfinity(G[0]) != 1 ) 156 | { 157 | point_copy(G[1], current_Tp[0]); 158 | 159 | ec = lookup(batches[m][i], tmp_e); // To get current e_i in constant-time 160 | bc = isequal(ec, 0) & 1; // Bit that determines if a dummy operation will be perfomed 161 | 162 | fp_cswap(G[0][0], G[1][0], bc); // constant-time swap: dummy or not dummy, that is the question. 163 | fp_cswap(G[0][1], G[1][1], bc); // constant-time swap: dummy or not dummy, that is the question. 164 | 165 | yISOG(K, current_A[1], G[0], current_A[0], batches[m][i]); 166 | 167 | if ( isequal(batches[m][i], last_isogeny[m]) == 0) // constant-time ask: just for avoiding the last isogeny evaluation 168 | { 169 | mask = isequal(L[batches[m][i]], 3); // Just for catching the case l = 3. This ask is done in constant-time 170 | si = (L[batches[m][i]] >> 1); // (l - 1) / 2 171 | 172 | yEVAL(current_Tp[1], current_Tp[0], K, batches[m][i]); 173 | 174 | yADD(Z, K[(si + mask) - 1], G[0], K[(si + mask) - 2]); // [(l + 1)/2]G[0] 175 | fp_cswap(Z[0], K[si][0], mask ^ 1); // constant-time swap: catching degree-3 isogeny case 176 | fp_cswap(Z[1], K[si][1], mask ^ 1); // constant-time swap: catching degree-3 isogeny case 177 | yADD(current_Tp[0], K[si], K[si - 1], G[0]); // [l]G[0] 178 | 179 | fp_cswap(current_Tp[0][0], current_Tp[1][0], bc ^ 1); // constant-time swap: dummy or not dummy, that is the question. 180 | fp_cswap(current_Tp[0][1], current_Tp[1][1], bc ^ 1); // constant-time swap: dummy or not dummy, that is the question. 181 | }; 182 | 183 | fp_cswap(current_A[0][0], current_A[1][0], bc ^ 1); // constant-time swap: dummy or not dummy, that is the question. 184 | fp_cswap(current_A[0][1], current_A[1][1], bc ^ 1); // constant-time swap: dummy or not dummy, that is the question. 185 | 186 | tmp_e[batches[m][i]] = ec - (bc ^ 1); 187 | counter[batches[m][i]] -= 1; 188 | isog_counter += 1; 189 | } 190 | 191 | if( counter[batches[m][i]] == 0 ) 192 | { 193 | //depends only on randomness 194 | finished[batches[m][i]] = 1; 195 | complement_of_each_batch[m][size_of_each_complement_batch[m]] = batches[m][i]; 196 | size_of_each_complement_batch[m] += 1; 197 | }; 198 | }; 199 | }; 200 | count += 1; 201 | }; 202 | 203 | // -------------------------------------------------------------------------------------------------------- 204 | point_copy(C, current_A[0]); 205 | }; 206 | -------------------------------------------------------------------------------- /lib/action_simba_dummyfree.c: -------------------------------------------------------------------------------- 1 | #include "edwards_curve.h" 2 | 3 | void random_key(uint8_t key[]) 4 | { 5 | uint8_t i, tmp, r; 6 | int8_t exp, sgn; 7 | for(i = 0; i < N; i++) 8 | { 9 | 10 | r = B[i] & 0x1; // B_i mod 2 11 | 12 | // exp is randomly selected from |[ 0, B ]| 13 | randombytes(&tmp, 1); 14 | while ( issmaller((int32_t)B[i], (int32_t)tmp) == -1 ) // constant-time comparison 15 | randombytes(&tmp, 1); 16 | 17 | exp = (int8_t)tmp; 18 | 19 | // Mapping integers from |[ 0, B |] into 20 | // |[ -B/2, B/2]| if B is even, or 21 | // |[ -(B+1)/2, (B-1)/2 ]| if B is odd. 22 | exp = ( (exp << 1) - (B[i] + r) ) >> 1; 23 | 24 | // Mapping into the set |[-B, B]|. 25 | exp = (exp << 1) + r; 26 | sgn = exp >> 7; // sign of exp 27 | 28 | // Next, to write key[i] = e || ((1 + sgn)/2) 29 | cmov(&exp, -exp, sgn == -1); 30 | key[i] = (exp << 1) ^ (1 & (1 + sgn)); 31 | }; 32 | }; 33 | 34 | void printf_key(uint8_t key[], char *c) 35 | { 36 | int i; 37 | printf("%s := ", c); 38 | printf("{\t %3d", (int)( (2*(key[0] & 0x1) - 1) * (key[0] >> 1) )); 39 | 40 | for(i = 1; i < N; i++) 41 | { 42 | printf(", %3d", (int)( (2*(key[i] & 0x1) - 1) * (key[i] >> 1) ) ); 43 | if( (i % 18) == 17 ) 44 | printf("\n\t\t"); 45 | }; 46 | 47 | printf("};\n"); 48 | 49 | }; 50 | 51 | /* ----------------------------------------------------------------------------------------------- * 52 | action_evaluation() 53 | inputs: a the secret key, the Edwards curve constants A[0]:=a, and A[1]:=(a - d); 54 | output: the isogenous Edwards curve constants C[0]:=a' and C[1]:=(a' - d') determined by the action 55 | evaluated at the secret key and public curve A 56 | 57 | NOTE: As far as we've understood how simba works; this next code implements simba approach. 58 | The action computed by the next code uses only one torsion point T_{+}, which its affine 59 | y-coordinate (in the isomorphic Montgomery curve) belongs to Fp. 60 | * ----------------------------------------------------------------------------------------------- */ 61 | void action_evaluation(proj C, const uint8_t key[], const proj A) 62 | { 63 | // -------------------------------------------------------------------------------------------------------- 64 | // SIMBA parameters 65 | // Batches 66 | uint8_t batches[NUMBER_OF_BATCHES][SIZE_OF_EACH_BATCH[0]]; 67 | uint8_t size_of_each_batch[NUMBER_OF_BATCHES]; 68 | 69 | for(uint8_t i = 0; i < NUMBER_OF_BATCHES; i++) 70 | memcpy(batches[i], BATCHES[i], sizeof(uint8_t) * SIZE_OF_EACH_BATCH[i]); 71 | 72 | memcpy(size_of_each_batch, SIZE_OF_EACH_BATCH, sizeof(uint8_t) * NUMBER_OF_BATCHES); 73 | // Complement of each batch 74 | uint8_t complement_of_each_batch[NUMBER_OF_BATCHES][N]; 75 | uint8_t size_of_each_complement_batch[NUMBER_OF_BATCHES]; 76 | 77 | memcpy(complement_of_each_batch, COMPLEMENT_OF_EACH_BATCH, sizeof(uint8_t) * NUMBER_OF_BATCHES * N); 78 | memcpy(size_of_each_complement_batch, SIZE_OF_EACH_COMPLEMENT_BATCH, sizeof(uint8_t) * NUMBER_OF_BATCHES); 79 | // -------------------------------------------------------------------------------------------------------- 80 | 81 | // -------------------------------------------------------------------------------------------------------- 82 | // Copy of public and private data (the private key is modified each iteration) 83 | uint8_t tmp_e[N]; 84 | memcpy(tmp_e, key, sizeof(uint8_t) * N); // exponents 85 | 86 | proj current_A, current_T[2]; 87 | point_copy(current_A, A); // initial Edwards curve constants a and (a -d) 88 | // -------------------------------------------------------------------------------------------------------- 89 | 90 | // -------------------------------------------------------------------------------------------------------- 91 | // Vairables required for running SIMBA 92 | int8_t ec = 0; 93 | uint16_t count = 0; 94 | proj G[2], K[(LARGE_L >> 1) + 1]; // Current kernel 95 | uint8_t finished[N]; // flag that determines if the maximum number of isogeny constructions has been reached 96 | memset(finished, 0, sizeof(uint8_t) * N); 97 | 98 | int8_t counter[N]; // This variable determines how many isogeny construcctions has been perfomed 99 | memset(counter, 0, sizeof(int8_t) * N); 100 | memcpy(counter, B, sizeof(int8_t) * N); // At the beginning, we must perfomed b_i isogeny constructions for each l_i 101 | uint64_t isog_counter = 0; // Total number of isogeny construction perfomed 102 | 103 | uint8_t last_isogeny[NUMBER_OF_BATCHES]; 104 | //index for skipping point evaluations (the last one of each batch) 105 | memcpy(last_isogeny, LAST_ISOGENY, sizeof(uint8_t) * NUMBER_OF_BATCHES); 106 | uint32_t bc; 107 | // -------------------------------------------------------------------------------------------------------- 108 | 109 | // -------------------------------------------------------------------------------------------------------- 110 | // Main loop 111 | uint8_t m = 0, i, j; 112 | uint64_t number_of_batches = NUMBER_OF_BATCHES; 113 | uint32_t si; 114 | 115 | while (isog_counter < NUMBER_OF_ISOGENIES) 116 | { 117 | m = (m + 1) % number_of_batches; 118 | 119 | if(count == MY*number_of_batches) { //merge the batches after my rounds 120 | m = 0; 121 | size_of_each_complement_batch[m] = 0; 122 | size_of_each_batch[m] = 0; 123 | number_of_batches = 1; 124 | 125 | for(i = 0; i < N; i++) { 126 | if( counter[i] == 0 ) 127 | { 128 | // l_i's reached 129 | complement_of_each_batch[m][size_of_each_complement_batch[m]] = i; 130 | size_of_each_complement_batch[m] += 1; 131 | } 132 | else 133 | { 134 | last_isogeny[0] = i; 135 | // l_i's not reached 136 | batches[m][size_of_each_batch[m]] = i; 137 | size_of_each_batch[m] += 1; 138 | }; 139 | } 140 | } 141 | 142 | // Before constructing isogenies, we must to search for suitable point 143 | elligator(current_T[1], current_T[0], current_A); 144 | 145 | // Next, it is required to multiply the point by 4 and each l_i that doesn't belong to the current batch 146 | // T_{-} 147 | yDBL(current_T[0], current_T[0], current_A); // mult. by [2] 148 | yDBL(current_T[0], current_T[0], current_A); // mult. by [2] 149 | // T_{+} 150 | yDBL(current_T[1], current_T[1], current_A); // mult. by [2] 151 | yDBL(current_T[1], current_T[1], current_A); // mult. by [2] 152 | // Now, it is required to multiply by the complement of the batch 153 | for(i = 0; i < size_of_each_complement_batch[m]; i++) 154 | { 155 | yMUL(current_T[0], current_T[0], current_A, complement_of_each_batch[m][i]); 156 | yMUL(current_T[1], current_T[1], current_A, complement_of_each_batch[m][i]); 157 | }; 158 | 159 | for(i = 0; i < size_of_each_batch[m]; i++) 160 | { 161 | if( finished[batches[m][i]] == 1 ) 162 | { 163 | //depends only on randomness 164 | continue; 165 | } 166 | else 167 | { 168 | // Now, a degree-(l_{batches[m][i]}) will be constructed 169 | point_copy(G[0], current_T[0]); 170 | point_copy(G[1], current_T[1]); 171 | 172 | ec = lookup(batches[m][i], tmp_e); // To get current e_i in constant-time 173 | fp_cswap(G[0][0], G[1][0], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 174 | fp_cswap(G[0][1], G[1][1], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 175 | 176 | fp_cswap(current_T[0][0], current_T[1][0], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 177 | fp_cswap(current_T[0][1], current_T[1][1], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 178 | 179 | for (j = (i + 1); j < size_of_each_batch[m]; j++) 180 | { 181 | if( finished[batches[m][j]] == 0 ) 182 | { 183 | //depends only on randomness 184 | yMUL(G[0], G[0], current_A, batches[m][j]); 185 | }; 186 | }; 187 | 188 | if ( (isinfinity(G[0]) != 1) && (isinfinity(G[1]) != 1) ) // Depending on randomness 189 | { 190 | bc = isequal(ec >> 1, 0) & 1; // Bit that determine the current isogeny. This ask is done in constant-time 191 | 192 | yISOG(K, current_A, G[0], current_A, batches[m][i]); 193 | 194 | if ( isequal(batches[m][i], last_isogeny[m]) == 0) // constant-time ask: just for avoiding the last isogeny evaluation 195 | { 196 | yEVAL(current_T[0], current_T[0], K, batches[m][i]); // evaluation of T[0] 197 | yEVAL(current_T[1], current_T[1], K, batches[m][i]); // evaluation of T[1] 198 | 199 | yMUL(current_T[1], current_T[1], current_A, batches[m][i]); // [l]T[1] 200 | }; 201 | 202 | tmp_e[batches[m][i]] = ((((ec >> 1) - (bc ^ 1)) ^ bc) << 1) ^ ((ec & 0x1) ^ bc); 203 | counter[batches[m][i]] -= 1; 204 | isog_counter += 1; 205 | } 206 | else 207 | { 208 | // We must perform at most two scalar multiplications by l. 209 | yMUL(current_T[1], current_T[1], current_A, batches[m][i]); 210 | }; 211 | 212 | fp_cswap(current_T[0][0], current_T[1][0], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 213 | fp_cswap(current_T[0][1], current_T[1][1], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 214 | 215 | if( counter[batches[m][i]] == 0 ) 216 | { 217 | //depends only on randomness 218 | finished[batches[m][i]] = 1; 219 | complement_of_each_batch[m][size_of_each_complement_batch[m]] = batches[m][i]; 220 | size_of_each_complement_batch[m] += 1; 221 | }; 222 | }; 223 | }; 224 | count += 1; 225 | }; 226 | 227 | // -------------------------------------------------------------------------------------------------------- 228 | point_copy(C, current_A); 229 | }; 230 | -------------------------------------------------------------------------------- /lib/fp512.S: -------------------------------------------------------------------------------- 1 | 2 | .intel_syntax noprefix 3 | 4 | .section .rodata 5 | 6 | .set pbits, 511 7 | .global p 8 | p: 9 | .quad 0x1b81b90533c6c87b, 0xc2721bf457aca835, 0x516730cc1f0b4f25, 0xa7aac6c567f35507 10 | .quad 0x5afbfcc69322c9cd, 0xb42d083aedc88c42, 0xfc8ab0d15e3e4c4a, 0x65b48e8f740f89bf 11 | 12 | 13 | .global R_mod_p 14 | R_mod_p: /* 2^512 mod p */ 15 | .quad 0xc8fc8df598726f0a, 0x7b1bc81750a6af95, 0x5d319e67c1e961b4, 0xb0aa7275301955f1 16 | .quad 0x4a080672d9ba6c64, 0x97a5ef8a246ee77b, 0x06ea9e5d4383676a, 0x3496e2e117e0ec80 17 | 18 | 19 | /* (2^512)^2 mod p */ 20 | .global R_squared_mod_p 21 | R_squared_mod_p: 22 | .quad 0x36905b572ffc1724, 0x67086f4525f1f27d, 0x4faf3fbfd22370ca, 0x192ea214bcc584b1 23 | .quad 0x5dae03ee2f5de3d0, 0x1e9248731776b371, 0xad5f166e20e4f52d, 0x4ed759aea6f3917e 24 | 25 | /* -p^-1 mod 2^64 */ 26 | .inv_min_p_mod_r: 27 | .quad 0x66c1301f632e294d 28 | 29 | 30 | .section .text 31 | 32 | /* Integer addition */ 33 | .u512_add: 34 | mov rax, [rsi + 0] 35 | add rax, [rdx + 0] 36 | mov [rdi + 0], rax 37 | .set k, 1 38 | .rept 7 39 | mov rax, [rsi + 8*k] 40 | adc rax, [rdx + 8*k] 41 | mov [rdi + 8*k], rax 42 | .set k, k+1 43 | .endr 44 | setc al 45 | movzx rax, al 46 | ret 47 | 48 | /* Integer substraction */ 49 | .u512_sub: 50 | mov rax, [rsi + 0] 51 | sub rax, [rdx + 0] 52 | mov [rdi + 0], rax 53 | .set k, 1 54 | .rept 7 55 | mov rax, [rsi + 8*k] 56 | sbb rax, [rdx + 8*k] 57 | mov [rdi + 8*k], rax 58 | .set k, k+1 59 | .endr 60 | setc al 61 | movzx rax, al 62 | ret 63 | 64 | .global fp_copy 65 | fp_copy: 66 | cld 67 | mov rcx, 8 68 | rep movsq 69 | ret 70 | 71 | .global fp_cswap 72 | fp_cswap: 73 | movzx rax, dl 74 | neg rax 75 | .set k, 0 76 | .rept 8 77 | mov rcx, [rdi + 8*k] 78 | mov rdx, [rsi + 8*k] 79 | 80 | mov r8, rcx 81 | xor r8, rdx 82 | and r8, rax 83 | 84 | xor rcx, r8 85 | xor rdx, r8 86 | 87 | mov [rdi + 8*k], rcx 88 | mov [rsi + 8*k], rdx 89 | 90 | .set k, k+1 91 | .endr 92 | ret 93 | 94 | .reduce_once: 95 | push rbp 96 | mov rbp, rdi 97 | 98 | mov rdi, [rbp + 0] 99 | sub rdi, [rip + p + 0] 100 | mov rsi, [rbp + 8] 101 | sbb rsi, [rip + p + 8] 102 | mov rdx, [rbp + 16] 103 | sbb rdx, [rip + p + 16] 104 | mov rcx, [rbp + 24] 105 | sbb rcx, [rip + p + 24] 106 | mov r8, [rbp + 32] 107 | sbb r8, [rip + p + 32] 108 | mov r9, [rbp + 40] 109 | sbb r9, [rip + p + 40] 110 | mov r10, [rbp + 48] 111 | sbb r10, [rip + p + 48] 112 | mov r11, [rbp + 56] 113 | sbb r11, [rip + p + 56] 114 | 115 | setnc al 116 | movzx rax, al 117 | neg rax 118 | 119 | .macro cswap2, r, m 120 | xor \r, \m 121 | and \r, rax 122 | xor \m, \r 123 | .endm 124 | 125 | cswap2 rdi, [rbp + 0] 126 | cswap2 rsi, [rbp + 8] 127 | cswap2 rdx, [rbp + 16] 128 | cswap2 rcx, [rbp + 24] 129 | cswap2 r8, [rbp + 32] 130 | cswap2 r9, [rbp + 40] 131 | cswap2 r10, [rbp + 48] 132 | cswap2 r11, [rbp + 56] 133 | 134 | pop rbp 135 | ret 136 | 137 | .global fp_add 138 | fp_add: 139 | push rdi 140 | call .u512_add 141 | pop rdi 142 | jmp .reduce_once 143 | 144 | .global fp_sub 145 | fp_sub: 146 | push rdi 147 | call .u512_sub 148 | pop rdi 149 | xor rsi, rsi 150 | xor rdx, rdx 151 | xor rcx, rcx 152 | xor r8, r8 153 | xor r9, r9 154 | xor r10, r10 155 | xor r11, r11 156 | test rax, rax 157 | cmovnz rax, [rip + p + 0] 158 | cmovnz rsi, [rip + p + 8] 159 | cmovnz rdx, [rip + p + 16] 160 | cmovnz rcx, [rip + p + 24] 161 | cmovnz r8, [rip + p + 32] 162 | cmovnz r9, [rip + p + 40] 163 | cmovnz r10, [rip + p + 48] 164 | cmovnz r11, [rip + p + 56] 165 | add [rdi + 0], rax 166 | adc [rdi + 8], rsi 167 | adc [rdi + 16], rdx 168 | adc [rdi + 24], rcx 169 | adc [rdi + 32], r8 170 | adc [rdi + 40], r9 171 | adc [rdi + 48], r10 172 | adc [rdi + 56], r11 173 | ret 174 | 175 | /* Montgomery arithmetic */ 176 | 177 | .global fp_mul 178 | fp_mul: 179 | push rbp 180 | push rbx 181 | push r12 182 | push r13 183 | push r14 184 | push r15 185 | 186 | push rdi 187 | 188 | mov rdi, rsi 189 | mov rsi, rdx 190 | 191 | xor r8, r8 192 | xor r9, r9 193 | xor r10, r10 194 | xor r11, r11 195 | xor r12, r12 196 | xor r13, r13 197 | xor r14, r14 198 | xor r15, r15 199 | xor rbp, rbp 200 | 201 | /* flags are already cleared */ 202 | 203 | .macro MULSTEP, k, r0, r1, r2, r3, r4, r5, r6, r7, r8 204 | 205 | mov rdx, [rsi + 0] 206 | mulx rcx, rdx, [rdi + 8*\k] 207 | add rdx, \r0 208 | mulx rcx, rdx, [rip + .inv_min_p_mod_r] 209 | 210 | xor rax, rax /* clear flags */ 211 | 212 | mulx rbx, rax, [rip + p + 0] 213 | adox \r0, rax 214 | 215 | mulx rcx, rax, [rip + p + 8] 216 | adcx \r1, rbx 217 | adox \r1, rax 218 | 219 | mulx rbx, rax, [rip + p + 16] 220 | adcx \r2, rcx 221 | adox \r2, rax 222 | 223 | mulx rcx, rax, [rip + p + 24] 224 | adcx \r3, rbx 225 | adox \r3, rax 226 | 227 | mulx rbx, rax, [rip + p + 32] 228 | adcx \r4, rcx 229 | adox \r4, rax 230 | 231 | mulx rcx, rax, [rip + p + 40] 232 | adcx \r5, rbx 233 | adox \r5, rax 234 | 235 | mulx rbx, rax, [rip + p + 48] 236 | adcx \r6, rcx 237 | adox \r6, rax 238 | 239 | mulx rcx, rax, [rip + p + 56] 240 | adcx \r7, rbx 241 | adox \r7, rax 242 | 243 | mov rax, 0 244 | adcx \r8, rcx 245 | adox \r8, rax 246 | 247 | 248 | mov rdx, [rdi + 8*\k] 249 | 250 | xor rax, rax /* clear flags */ 251 | 252 | mulx rbx, rax, [rsi + 0] 253 | adox \r0, rax 254 | 255 | mulx rcx, rax, [rsi + 8] 256 | adcx \r1, rbx 257 | adox \r1, rax 258 | 259 | mulx rbx, rax, [rsi + 16] 260 | adcx \r2, rcx 261 | adox \r2, rax 262 | 263 | mulx rcx, rax, [rsi + 24] 264 | adcx \r3, rbx 265 | adox \r3, rax 266 | 267 | mulx rbx, rax, [rsi + 32] 268 | adcx \r4, rcx 269 | adox \r4, rax 270 | 271 | mulx rcx, rax, [rsi + 40] 272 | adcx \r5, rbx 273 | adox \r5, rax 274 | 275 | mulx rbx, rax, [rsi + 48] 276 | adcx \r6, rcx 277 | adox \r6, rax 278 | 279 | mulx rcx, rax, [rsi + 56] 280 | adcx \r7, rbx 281 | adox \r7, rax 282 | 283 | mov rax, 0 284 | adcx \r8, rcx 285 | adox \r8, rax 286 | 287 | .endm 288 | 289 | MULSTEP 0, r8, r9, r10, r11, r12, r13, r14, r15, rbp 290 | MULSTEP 1, r9, r10, r11, r12, r13, r14, r15, rbp, r8 291 | MULSTEP 2, r10, r11, r12, r13, r14, r15, rbp, r8, r9 292 | MULSTEP 3, r11, r12, r13, r14, r15, rbp, r8, r9, r10 293 | MULSTEP 4, r12, r13, r14, r15, rbp, r8, r9, r10, r11 294 | MULSTEP 5, r13, r14, r15, rbp, r8, r9, r10, r11, r12 295 | MULSTEP 6, r14, r15, rbp, r8, r9, r10, r11, r12, r13 296 | MULSTEP 7, r15, rbp, r8, r9, r10, r11, r12, r13, r14 297 | 298 | pop rdi 299 | 300 | mov [rdi + 0], rbp 301 | mov [rdi + 8], r8 302 | mov [rdi + 16], r9 303 | mov [rdi + 24], r10 304 | mov [rdi + 32], r11 305 | mov [rdi + 40], r12 306 | mov [rdi + 48], r13 307 | mov [rdi + 56], r14 308 | 309 | pop r15 310 | pop r14 311 | pop r13 312 | pop r12 313 | pop rbx 314 | pop rbp 315 | jmp .reduce_once 316 | 317 | .fp_mul2: 318 | mov rdx, rdi 319 | jmp fp_mul 320 | 321 | .global fp_sqr 322 | fp_sqr: 323 | /* TODO implement optimized Montgomery squaring */ 324 | mov rdx, rsi 325 | jmp fp_mul 326 | 327 | .fp_sq1: 328 | mov rsi, rdi 329 | jmp fp_sqr 330 | 331 | /* (obviously) not constant time in the exponent! */ 332 | .fp_pow: 333 | push rbx 334 | mov rbx, rsi 335 | push r12 336 | push r13 337 | push rdi 338 | sub rsp, 64 339 | 340 | mov rsi, rdi 341 | mov rdi, rsp 342 | call fp_copy 343 | 344 | mov rdi, [rsp + 64] 345 | lea rsi, [rip + R_mod_p] 346 | call fp_copy 347 | 348 | .macro POWSTEP, k 349 | mov r13, [rbx + 8*\k] 350 | xor r12, r12 351 | 352 | 0: 353 | test r13, 1 354 | jz 1f 355 | 356 | mov rdi, [rsp + 64] 357 | mov rsi, rsp 358 | call .fp_mul2 359 | 360 | 1: 361 | mov rdi, rsp 362 | call .fp_sq1 363 | 364 | shr r13 365 | 366 | inc r12 367 | test r12, 64 368 | jz 0b 369 | .endm 370 | 371 | POWSTEP 0 372 | POWSTEP 1 373 | POWSTEP 2 374 | POWSTEP 3 375 | POWSTEP 4 376 | POWSTEP 5 377 | POWSTEP 6 378 | POWSTEP 7 379 | 380 | add rsp, 64+8 381 | pop r13 382 | pop r12 383 | pop rbx 384 | ret 385 | 386 | .section .rodata 387 | .p_minus_2: 388 | .quad 0x1b81b90533c6c879, 0xc2721bf457aca835, 0x516730cc1f0b4f25, 0xa7aac6c567f35507 389 | .quad 0x5afbfcc69322c9cd, 0xb42d083aedc88c42, 0xfc8ab0d15e3e4c4a, 0x65b48e8f740f89bf 390 | 391 | .section .text 392 | 393 | /* TODO use a better addition chain? */ 394 | .global fp_inv 395 | fp_inv: 396 | lea rsi, [rip + .p_minus_2] 397 | jmp .fp_pow 398 | 399 | .section .rodata 400 | .global p_minus_1_halves 401 | p_minus_1_halves: 402 | .quad 0x8dc0dc8299e3643d, 0xe1390dfa2bd6541a, 0xa8b398660f85a792, 0xd3d56362b3f9aa83 403 | .quad 0x2d7dfe63499164e6, 0x5a16841d76e44621, 0xfe455868af1f2625, 0x32da4747ba07c4df 404 | 405 | .section .text 406 | 407 | /* TODO use a better addition chain? */ 408 | .global fp_issquare 409 | fp_issquare: 410 | push rdi 411 | lea rsi, [rip + p_minus_1_halves] 412 | call .fp_pow 413 | pop rdi 414 | 415 | xor rax, rax 416 | .set k, 0 417 | .rept 8 418 | mov rsi, [rdi + 8*k] 419 | xor rsi, [rip + R_mod_p + 8*k] 420 | or rax, rsi 421 | .set k, k+1 422 | .endr 423 | test rax, rax 424 | setz al 425 | movzx rax, al 426 | ret 427 | 428 | 429 | /* not constant time (but this shouldn't leak anything of importance) */ 430 | .global fp_random 431 | fp_random: 432 | 433 | push rdi 434 | mov rsi, 64 435 | call randombytes 436 | pop rdi 437 | mov rax, 1 438 | shl rax, (pbits % 64) 439 | dec rax 440 | and [rdi + 56], rax 441 | 442 | .set k, 7 443 | .rept 8 444 | mov rax, [rip + p + 8*k] 445 | cmp [rdi + 8*k], rax 446 | jge fp_random 447 | jl 0f 448 | .set k, k-1 449 | .endr 450 | 0: 451 | ret 452 | 453 | -------------------------------------------------------------------------------- /lib/point_arith.c: -------------------------------------------------------------------------------- 1 | #include "edwards_curve.h" 2 | 3 | /* ------------------------------------------------------------- * 4 | isinfinity() 5 | inputs: the projective Edwards y-coordinates of y(P)=YP/ZP; 6 | output: 7 | 1 if YP == ZP, or 8 | 0 if YP != ZP 9 | * ------------------------------------------------------------- */ 10 | int isinfinity(const proj P) 11 | { 12 | fp tmp; 13 | fp_sub(tmp, P[0], P[1]); // A substraction in order to ask in constant-time: this can be improvement 14 | return iszero(tmp, NUMBER_OF_WORDS); // constant-time comparison 15 | }; 16 | 17 | /* ------------------------------------------------------------- * 18 | areEqual() 19 | inputs: the projective Edwards y-coordinates of y(P)=YP/ZP and 20 | y(Q)=YQ/ZQ; 21 | output: 22 | 1 if YP*ZQ == ZP*YQ, or 23 | 0 if YP*ZQ != ZP*YQ 24 | * ------------------------------------------------------------- */ 25 | uint8_t areEqual(const proj P, const proj Q) 26 | { 27 | fp YPZQ, ZPYQ; 28 | fp_mul(YPZQ, P[0], Q[1]); 29 | fp_mul(ZPYQ, P[1], Q[0]); 30 | return (0 == compare(YPZQ, ZPYQ, NUMBER_OF_WORDS)); 31 | }; 32 | /* ------------------------------------------------------------- * 33 | point_copy() 34 | inputs: a projective Edwards y-coordinates of y(P)=YP/ZP; 35 | output: a copy of the projective Edwards's y-coordinate of y(P) 36 | * ------------------------------------------------------------- */ 37 | void point_copy(proj Q, const proj P) 38 | { 39 | copy(Q[0], P[0], NUMBER_OF_WORDS); 40 | copy(Q[1], P[1], NUMBER_OF_WORDS); 41 | }; 42 | 43 | /* ---------------------------------------------------------------------- * 44 | This is NOT the stereotypical Edwards y-only doubling, since it make 45 | use of the constant ad := a-d 46 | 47 | yDBL() 48 | inputs: the projective Edwards y-coordinates of y(P)=YP/ZP, and the 49 | Edwards curve constant A[0]:=a, and A[1]:=(a - d); 50 | output: the projective Edwards x-coordinates y([2]P)=Y2P/Z2P 51 | * ---------------------------------------------------------------------- */ 52 | void yDBL(proj Q, const proj P, const proj A) 53 | { 54 | fp tmp_0, tmp_1; 55 | // Firstly, yDBL is performed like a xDBL but on the isomorphic Montgomery curve 56 | fp_sqr(tmp_0, P[0]); 57 | fp_sqr(tmp_1, P[1]); 58 | 59 | fp_mul(Q[1], A[1], tmp_0); 60 | fp_mul(Q[0], Q[1], tmp_1); 61 | fp_sub(tmp_1, tmp_1, tmp_0); 62 | fp_mul(tmp_0, A[0], tmp_1); 63 | fp_add(Q[1], Q[1], tmp_0); 64 | fp_mul(tmp_0, Q[1], tmp_1); 65 | 66 | // Lastly, the result is mapping into the Edward's curve 67 | fp_add(Q[1], Q[0], tmp_0); 68 | fp_sub(Q[0], Q[0], tmp_0); 69 | 70 | FP_ADD_COMPUTED += 4; 71 | FP_SQR_COMPUTED += 2; 72 | FP_MUL_COMPUTED += 4; 73 | };// Cost : 4M + 2S + 4a 74 | 75 | /* ---------------------------------------------------------------------- * 76 | yADD() 77 | inputs: the projective Edwards y-coordinates of y(P)=YP/ZP, y(Q)=YQ/ZQ, 78 | and y(P-Q)=YPQ/ZPQ; 79 | output: the projective Edwards y-coordinates of y(P+Q) 80 | * ---------------------------------------------------------------------- */ 81 | void yADD(proj R, const proj P, const proj Q, const proj PQ) 82 | { 83 | fp tmp_0, tmp_1, xD, zD; 84 | // Firstly, the difference is mapping into the isomorphic Montgomery curve 85 | fp_add(xD, PQ[1], PQ[0]); 86 | fp_sub(zD, PQ[1], PQ[0]); 87 | 88 | // Secondly, yADDL is performed like a xADD (similarly to our yDBL) 89 | fp_mul(tmp_0, P[1], Q[0]); 90 | fp_mul(tmp_1, P[0], Q[1]); 91 | 92 | fp_sub(R[1], tmp_0, tmp_1); 93 | fp_add(R[0], tmp_0, tmp_1); 94 | 95 | fp_sqr(R[1], R[1]); 96 | fp_sqr(R[0], R[0]); 97 | 98 | fp_mul(tmp_0, R[0], zD); 99 | fp_mul(tmp_1, R[1], xD); 100 | 101 | // Lastly, the result is mapping into the Edward's curve 102 | fp_sub(R[0], tmp_0, tmp_1); 103 | fp_add(R[1], tmp_0, tmp_1); 104 | 105 | FP_ADD_COMPUTED += 6; 106 | FP_SQR_COMPUTED += 2; 107 | FP_MUL_COMPUTED += 4; 108 | };// Cost : 4M + 2S + 6a 109 | 110 | /* ---------------------------------------------------------------------- * 111 | yMUL() 112 | inputs: the projective Edwards y-coordinates of y(P)=YP/ZP, the Edwards 113 | curve constant A[0]:=a, and A[1]:=(a - d), and an positive 114 | integer integer number 0 <= i <= (N - 1); 115 | output: the projective Edwards y-coordinates y([l_i]P) 116 | * ---------------------------------------------------------------------- */ 117 | void yMUL(proj Q, const proj P, const proj A, uint8_t const i) 118 | { 119 | proj R[3], T; 120 | 121 | // Initial 3-tuple of points 122 | point_copy(R[0], P); // P 123 | yDBL(R[1], P, A); // [2]P 124 | yADD(R[2], R[1], R[0], P); // [3]P 125 | 126 | // main loop 127 | uint8_t j; 128 | uint32_t tmp = ADDITION_CHAIN[i]; 129 | for(j = 0; j < ADDITION_CHAIN_LENGTH[i]; j++) 130 | { 131 | if (isinfinity(R[tmp & 0x1]) == 1) 132 | yDBL(T, R[2], A); 133 | else 134 | yADD(T, R[2], R[(tmp & 0x1) ^ 0x1], R[tmp & 0x1]); 135 | // updating 136 | point_copy(R[0], R[(tmp & 0x1) ^ 0x1]); 137 | point_copy(R[1], R[2]); 138 | point_copy(R[2], T); 139 | 140 | tmp >>= 1; 141 | }; 142 | point_copy(Q, R[2]); // At last, R[2] is equal to [l_{i}]P 143 | };// Cost ~ 1.5*Ceil[log_2(l)]*(4M + 2S) 144 | 145 | /* ------------------------------------------------------------------------------- * 146 | elligator() 147 | Inputs: the Edwards curve constant A[0]:=a, and A[1]:=(a - d), and an integer 148 | number i in {0, ..., 15}; 149 | output: the projective Edwards y-coordinates of y(T_{+}) = YT_{+}/ZT_{+} and 150 | y(T_{-}) = YT_{-}/ZT_{-} such that the y-coordinate of the image of the 151 | affine points of T_{+} and T_{-} in the Montgomery curve belong to F_p 152 | and F_{p^2}\F_p, respectively. 153 | * ------------------------------------------------------------------------------- */ 154 | void elligator(proj T_plus, proj T_minus, const proj A) 155 | { 156 | set_zero(T_plus[0], NUMBER_OF_WORDS); // Initial value is zero 157 | set_zero(T_minus[0], NUMBER_OF_WORDS); // Initial value is zero 158 | 159 | // u is randomly selecting from {2, ..., (p-1)/2} 160 | fp u; 161 | fp_random(u); 162 | while ( compare(u, (uint64_t *)p_minus_1_halves, NUMBER_OF_WORDS) > 0) 163 | fp_random(u); 164 | 165 | fp_mul(u, u, R_squared_mod_p); // mapping u into the Montgomery domain 166 | 167 | // --- 168 | fp tmp, u2_plus_1, Cu2_minus_1, tmp_0, tmp_1, alpha, beta; 169 | set_zero(alpha, NUMBER_OF_WORDS); // 0 170 | fp_add(beta, alpha, u); // u 171 | 172 | fp_sqr(T_plus[1], u); // u^2 173 | fp_add(u2_plus_1, T_plus[1], R_mod_p); // u^2 + 1 174 | fp_sub(tmp, T_plus[1], R_mod_p); // u^2 - 1 175 | fp_mul(Cu2_minus_1, A[1], tmp); // C' * (u^2 - 1) 176 | 177 | // The goal is to evaluate in the projective Montgomery curve isomorphic to A 178 | fp_sub(T_minus[1], A[0], A[1]); // A' := 2 * (a + d) and C' := (a - d) are 179 | fp_add(T_minus[1], T_minus[1], A[0]); // projective constants of the isomorphic 180 | fp_add(T_minus[1], T_minus[1], T_minus[1]); // Montgomery curve 181 | 182 | fp_mul(tmp_0, T_minus[1], Cu2_minus_1); // A' * C' * (u^2 - 1) 183 | 184 | fp_sqr(tmp_1, T_minus[1]); // (A')^2 185 | fp_mul(tmp_1, tmp_1, T_plus[1]); // (A' * u)^2 186 | fp_sqr(tmp, Cu2_minus_1); // [C' * (u^2 - 1)]^2 187 | fp_add(tmp_1, tmp_1, tmp); // (A' * u)^2 + [C' * (u^2 - 1)]^2 188 | 189 | fp_mul(tmp, tmp_0, tmp_1); // {A' * C' * (u^2 - 1)} * {(A' * u)^2 + [C' * (u^2 - 1)]^2} =? { [C' * (u^2 - 1)]^2 * w}^2 190 | 191 | // 192 | fp_cswap(alpha, beta ,iszero(tmp, NUMBER_OF_WORDS)); // alpha = 0 if A' = 0; alpha = u otherwise 193 | fp_mul(u2_plus_1, alpha, u2_plus_1); // u2_plus_1 = 0 if A' != 0; u2_plus_1 = u^3 + u 194 | fp_mul(alpha, alpha, Cu2_minus_1); // alpha * C' * (u^2 - 1) 195 | 196 | // the projective y-coordinate of T_{+} or T_{-} 197 | fp_add(T_plus[0], T_plus[0], T_minus[1]); // [C' * (u^2 - 1) * v] = A' 198 | // the projective y-coordinate of T_{-} or T_{+} 199 | fp_sub(T_minus[0], T_minus[0], T_minus[1]); // -[C' * (u^2 - 1) * v] = -A' 200 | fp_mul(T_minus[0], T_minus[0], T_plus[1]); // -[ (C' * v) + A'] * (u^2) = -A' * (u^2) 201 | 202 | fp_add(T_plus[0], T_plus[0], alpha); // A' + alpha*C'*(u^2-1) 203 | fp_sub(T_minus[0], T_minus[0], alpha); // -A' * (u^2) - alpha*C'*(u^2-1) 204 | 205 | fp_add(tmp, tmp, u2_plus_1); // Now, if A'=0 then tmp = u^3 + u 206 | // Only one legendre symbol computation is required 207 | uint8_t legendre_symbol = fp_issquare(tmp) & 0x1; 208 | fp_cswap(T_plus[0], T_minus[0], legendre_symbol ^ 1); // constant-time swap for determining T_{+} or T_{-}. 209 | 210 | // Finally, we mapping the points into the Edward's curves 211 | // T_{+} 212 | fp_add(T_plus[1], T_plus[0], Cu2_minus_1); 213 | fp_sub(T_plus[0], T_plus[0], Cu2_minus_1); 214 | // T_{-} 215 | fp_add(T_minus[1], T_minus[0], Cu2_minus_1); 216 | fp_sub(T_minus[0], T_minus[0], Cu2_minus_1); 217 | 218 | FP_ADD_COMPUTED += 16; 219 | FP_SQR_COMPUTED += 3; 220 | FP_MUL_COMPUTED += 8; 221 | 222 | FP_MUL_COMPUTED += 1; // This multiplication is for mapping the input u<-{2, ..., (p-1)/2} into the Montgomery domain 223 | };// Cost : 1(legendre s.) + 8M + 3S + 16a 224 | 225 | /* compute [(p+1)/l] P for all l in our list of primes. */ 226 | /* divide and conquer is much faster than doing it naively, 227 | * but uses more memory. */ 228 | void cofactor_multiples(proj P[], const proj A, int8_t lower, int8_t upper) 229 | { 230 | assert(lower < upper); 231 | 232 | if ( (upper - lower) == 1) 233 | return; 234 | 235 | int8_t mid = lower + (upper - lower + 1) / 2; 236 | 237 | point_copy(P[mid], P[lower]); 238 | for (int8_t i = lower; i < mid; ++i) 239 | yMUL(P[mid], P[mid], A, i); 240 | 241 | for (int8_t i = mid; i < upper; ++i) 242 | yMUL(P[lower], P[lower], A, i); 243 | 244 | cofactor_multiples(P, A, lower, mid); 245 | cofactor_multiples(P, A, mid, upper); 246 | }; 247 | 248 | /* never accepts invalid keys. */ 249 | uint8_t validate(const proj A) 250 | { 251 | do { 252 | 253 | proj P[N]; 254 | 255 | fp_random(P[0][0]); 256 | while ( compare(P[0][0], (uint64_t *)p, NUMBER_OF_WORDS) > 0) 257 | fp_random(P[0][0]); 258 | 259 | set_zero(P[0][1], NUMBER_OF_WORDS); 260 | fp_add(P[0][1], P[0][1], R_mod_p); // Z is set to 1 (in montgomery domain) 261 | 262 | yDBL(P[0], P[0], A); // mult. by [2] 263 | yDBL(P[0], P[0], A); // mult. by [2] 264 | 265 | cofactor_multiples(P, A, 0, N); 266 | 267 | uint16_t bits_of_the_order = 0; 268 | for (uint8_t i = N - 1; i < N; --i) { 269 | 270 | /* we only gain information if [(p+1)/l] P is non-zero */ 271 | if (isinfinity(P[i]) != 1) 272 | { 273 | yMUL(P[i], P[i], A, i); 274 | 275 | if (isinfinity(P[i]) != 1) 276 | { 277 | /* P does not have order dividing p+1. */ 278 | return 0; 279 | } 280 | 281 | bits_of_the_order += BITS_OF_L[i]; // in this case order ~ 2^bits_of_the_order > 4*p^(1/2) ~ 2^BITS_OF_SQRT_OF_P 282 | 283 | if (bits_of_the_order > BITS_OF_4SQRT_OF_P) 284 | { 285 | /* returns borrow */ 286 | /* order > 4 sqrt(p), hence definitely supersingular */ 287 | return 1; 288 | } 289 | } 290 | } 291 | 292 | /* P didn't have big enough order to prove supersingularity. */ 293 | } while (1); 294 | }; 295 | 296 | -------------------------------------------------------------------------------- /lib/action_simba_withdummy_2.c: -------------------------------------------------------------------------------- 1 | #include "edwards_curve.h" 2 | 3 | void random_key(uint8_t key[]) 4 | { 5 | uint8_t i, tmp; 6 | int8_t exp, sgn; 7 | for(i = 0; i < N; i++) 8 | { 9 | // exp is randomly selected from |[ 0, 2B ]| 10 | randombytes(&tmp, 1); 11 | while ( issmaller((int32_t)B[i] << 1, (int32_t)tmp) == -1 ) // constant-time comparison 12 | randombytes(&tmp, 1); 13 | 14 | exp = (int8_t)tmp; 15 | // Mapping integers from |[ 0, 2B |] into |[ -B, B ]| 16 | exp = exp - (int8_t)B[i]; 17 | sgn = exp >> 7; // sign of exp 18 | 19 | // Next, to write key[i] = e || ((1 + sgn)/2) 20 | cmov(&exp, -exp, sgn == -1); 21 | key[i] = (exp << 1) ^ (1 & (1 + sgn)); 22 | }; 23 | }; 24 | 25 | void printf_key(uint8_t key[], char *c) 26 | { 27 | int i; 28 | printf("%s := ", c); 29 | printf("{\t %3d", (int)( (2*(key[0] & 0x1) - 1) * (key[0] >> 1) )); 30 | 31 | for(i = 1; i < N; i++) 32 | { 33 | printf(", %3d", (int)( (2*(key[i] & 0x1) - 1) * (key[i] >> 1) ) ); 34 | if( (i % 18) == 17 ) 35 | printf("\n\t\t"); 36 | }; 37 | 38 | printf("};\n"); 39 | 40 | }; 41 | 42 | /* ----------------------------------------------------------------------------------------------- * 43 | action_evaluation() 44 | inputs: a the secret key, the Edwards curve constants A[0]:=a, and A[1]:=(a - d); 45 | output: the isogenous Edwards curve constants C[0]:=a' and C[1]:=(a' - d') determined by the action 46 | evaluated at the secret key and public curve A 47 | 48 | NOTE: As far as we've understood how simba works; this next code implements simba approach. The 49 | action computed by the next code uses two torsion points T_{+} and T_{-}, which their affine 50 | y-coordinates (in the isomorphic Montgomery curve) belongs to Fp and Fp2\Fp, respectively. 51 | * ----------------------------------------------------------------------------------------------- */ 52 | void action_evaluation(proj C, const uint8_t key[], const proj A) 53 | { 54 | // -------------------------------------------------------------------------------------------------------- 55 | // SIMBA parameters 56 | // Batches 57 | uint8_t batches[NUMBER_OF_BATCHES][SIZE_OF_EACH_BATCH[0]]; 58 | uint8_t size_of_each_batch[NUMBER_OF_BATCHES]; 59 | 60 | for(uint8_t i = 0; i < NUMBER_OF_BATCHES; i++) 61 | memcpy(batches[i], BATCHES[i], sizeof(uint8_t) * SIZE_OF_EACH_BATCH[i]); 62 | 63 | memcpy(size_of_each_batch, SIZE_OF_EACH_BATCH, sizeof(uint8_t) * NUMBER_OF_BATCHES); 64 | // Complement of each batch 65 | uint8_t complement_of_each_batch[NUMBER_OF_BATCHES][N]; 66 | uint8_t size_of_each_complement_batch[NUMBER_OF_BATCHES]; 67 | 68 | memcpy(complement_of_each_batch, COMPLEMENT_OF_EACH_BATCH, sizeof(uint8_t) * NUMBER_OF_BATCHES * N); 69 | memcpy(size_of_each_complement_batch, SIZE_OF_EACH_COMPLEMENT_BATCH, sizeof(uint8_t) * NUMBER_OF_BATCHES); 70 | // -------------------------------------------------------------------------------------------------------- 71 | 72 | // -------------------------------------------------------------------------------------------------------- 73 | // Copy of public and private data (the private key is modified each iteration) 74 | uint8_t tmp_e[N]; 75 | memcpy(tmp_e, key, sizeof(uint8_t) * N); // exponents 76 | 77 | proj current_A[2], current_T[4]; 78 | point_copy(current_A[0], A); // initial Edwards curve constants a and (a -d) 79 | // -------------------------------------------------------------------------------------------------------- 80 | 81 | // -------------------------------------------------------------------------------------------------------- 82 | // Vairables required for running SIMBA 83 | int8_t ec = 0, mask; 84 | uint16_t count = 0; 85 | proj G[4], K[(LARGE_L >> 1) + 1], Z; // Current kernel 86 | uint8_t finished[N]; // flag that determines if the maximum number of isogeny constructions has been reached 87 | memset(finished, 0, sizeof(uint8_t) * N); 88 | 89 | int8_t counter[N]; // This variable determines how many isogeny construcctions has been perfomed 90 | memset(counter, 0, sizeof(int8_t) * N); 91 | memcpy(counter, B, sizeof(int8_t) * N); // At the beginning, we must perfomed b_i isogeny constructions for each l_i 92 | uint64_t isog_counter = 0; // Total number of isogeny construction perfomed 93 | 94 | uint8_t last_isogeny[NUMBER_OF_BATCHES]; 95 | //index for skipping point evaluations (the last one of each batch) 96 | memcpy(last_isogeny, LAST_ISOGENY, sizeof(uint8_t) * NUMBER_OF_BATCHES); 97 | uint32_t bc; 98 | // -------------------------------------------------------------------------------------------------------- 99 | 100 | // -------------------------------------------------------------------------------------------------------- 101 | // Main loop 102 | uint8_t m = 0, i, j; 103 | uint64_t number_of_batches = NUMBER_OF_BATCHES; 104 | uint32_t si; 105 | 106 | while (isog_counter < NUMBER_OF_ISOGENIES) 107 | { 108 | m = (m + 1) % number_of_batches; 109 | 110 | if(count == MY*number_of_batches) { //merge the batches after my rounds 111 | m = 0; 112 | size_of_each_complement_batch[m] = 0; 113 | size_of_each_batch[m] = 0; 114 | number_of_batches = 1; 115 | 116 | for(i = 0; i < N; i++) { 117 | if( counter[i] == 0 ) 118 | { 119 | // l_i reached 120 | complement_of_each_batch[m][size_of_each_complement_batch[m]] = i; 121 | size_of_each_complement_batch[m] += 1; 122 | } 123 | else 124 | { 125 | last_isogeny[0] = i; 126 | // l_i not reached 127 | batches[m][size_of_each_batch[m]] = i; 128 | size_of_each_batch[m] += 1; 129 | }; 130 | } 131 | } 132 | 133 | // Before constructing isogenies, we must to search for suitable points 134 | elligator(current_T[1], current_T[0], current_A[0]); 135 | 136 | // Next, it is required to multiply the point by 4 and each l_i that doesn't belong to the current batch 137 | // T_{-} 138 | yDBL(current_T[0], current_T[0], current_A[0]); // mult. by [2] 139 | yDBL(current_T[0], current_T[0], current_A[0]); // mult. by [2] 140 | // T_{+} 141 | yDBL(current_T[1], current_T[1], current_A[0]); // mult. by [2] 142 | yDBL(current_T[1], current_T[1], current_A[0]); // mult. by [2] 143 | // Now, it is required to multiply by the complement of the batch 144 | for(i = 0; i < size_of_each_complement_batch[m]; i++) 145 | { 146 | yMUL(current_T[0], current_T[0], current_A[0], complement_of_each_batch[m][i]); // Corresponding with T_{-} 147 | yMUL(current_T[1], current_T[1], current_A[0], complement_of_each_batch[m][i]); // Corresponding with T_{+} 148 | }; 149 | 150 | for(i = 0; i < size_of_each_batch[m]; i++) 151 | { 152 | if( finished[batches[m][i]] == 1 ) 153 | { 154 | //depends only on randomness 155 | continue; 156 | } 157 | else 158 | { 159 | // Now, a degree-(l_{batches[m][i]}) will be constructed. Let l = l_{batches[m][i]}. 160 | point_copy(G[0], current_T[0]); // order-l point determined by T_{-} 161 | point_copy(G[1], current_T[1]); // order-l point determined by T_{+} 162 | point_copy(G[2], current_T[0]); // T_{-} 163 | point_copy(G[3], current_T[1]); // T_{+} 164 | 165 | ec = lookup(batches[m][i], tmp_e); // To get current e_i in constant-time 166 | fp_cswap(G[0][0], G[1][0], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 167 | fp_cswap(G[0][1], G[1][1], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 168 | fp_cswap(G[2][0], G[3][0], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 169 | fp_cswap(G[2][1], G[3][1], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 170 | 171 | fp_cswap(current_T[0][0], current_T[1][0], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 172 | fp_cswap(current_T[0][1], current_T[1][1], (ec & 1)); // constant-time swap: T_{+} or T_{-}, that is the question. 173 | 174 | for (j = (i + 1); j < size_of_each_batch[m]; j++) 175 | { 176 | if( finished[batches[m][j]] == 0 ) 177 | { 178 | //depends only on randomness 179 | yMUL(G[0], G[0], current_A[0], batches[m][j]); // Corresponding with T_{-} 180 | }; 181 | }; 182 | 183 | if (isinfinity(G[0]) != 1) // Depending on randomness 184 | { 185 | bc = isequal(ec >> 1, 0) & 1; // Bit that determines if a dummy operation will be perfomed 186 | 187 | fp_cswap(G[0][0], G[2][0], bc); // constant-time swap: dummy or not dummy, that is the question. 188 | fp_cswap(G[0][1], G[2][1], bc); // constant-time swap: dummy or not dummy, that is the question. 189 | 190 | yISOG(K, current_A[1], G[0], current_A[0], batches[m][i]); 191 | 192 | if ( isequal(batches[m][i], last_isogeny[m]) == 0) // constant-time ask: just for avoiding the last isogeny evaluation 193 | { 194 | mask = isequal(L[batches[m][i]], 3); // Just for catching the case l = 3. This ask is done in constant-time 195 | si = (L[batches[m][i]] >> 1); // (l - 1) / 2 196 | 197 | yMUL(current_T[1], current_T[1], current_A[0], batches[m][i]); // [l]T[1] 198 | 199 | yEVAL(current_T[2], current_T[0], K, batches[m][i]); // evaluation of T[0] 200 | yEVAL(current_T[3], current_T[1], K, batches[m][i]); // evaluation of T[0] 201 | 202 | yADD(Z, K[(si + mask) - 1], G[0], K[(si + mask) - 2]); // [(l + 1)/2]G[0] 203 | fp_cswap(Z[0], K[si][0], mask ^ 1); // constant-time swap: catching degree-3 isogeny case 204 | fp_cswap(Z[1], K[si][1], mask ^ 1); // constant-time swap: catching degree-3 isogeny case 205 | yADD(current_T[0], K[si], K[si - 1], G[0]); // [l]T[0] 206 | 207 | fp_cswap(current_T[0][0], current_T[2][0], bc ^ 1); // constant-time swap: dummy or not dummy, that is the question. 208 | fp_cswap(current_T[0][1], current_T[2][1], bc ^ 1); // constant-time swap: dummy or not dummy, that is the question. 209 | fp_cswap(current_T[1][0], current_T[3][0], bc ^ 1); // constant-time swap: dummy or not dummy, that is the question. 210 | fp_cswap(current_T[1][1], current_T[3][1], bc ^ 1); // constant-time swap: dummy or not dummy, that is the question. 211 | 212 | }; 213 | 214 | fp_cswap(current_A[0][0], current_A[1][0], bc ^ 1); // constant-time swap: dummy or not dummy, that is the question. 215 | fp_cswap(current_A[0][1], current_A[1][1], bc ^ 1); // constant-time swap: dummy or not dummy, that is the question. 216 | 217 | tmp_e[batches[m][i]] = (((ec >> 1) - (bc ^ 1)) << 1) ^ (ec & 0x1); 218 | counter[batches[m][i]] -= 1; 219 | isog_counter += 1; 220 | } 221 | else 222 | { 223 | // We must perform two scalar multiplications by l. 224 | yMUL(current_T[1], current_T[1], current_A[0], batches[m][i]); 225 | }; 226 | 227 | fp_cswap(current_T[0][0], current_T[1][0], (ec & 1)); // constant-time swap: dummy or not dummy, that is the question. 228 | fp_cswap(current_T[0][1], current_T[1][1], (ec & 1)); // constant-time swap: dummy or not dummy, that is the question. 229 | 230 | if( counter[batches[m][i]] == 0 ) 231 | { 232 | //depends only on randomness 233 | 234 | finished[batches[m][i]] = 1; 235 | complement_of_each_batch[m][size_of_each_complement_batch[m]] = batches[m][i]; 236 | size_of_each_complement_batch[m] += 1; 237 | }; 238 | }; 239 | }; 240 | count += 1; 241 | }; 242 | 243 | 244 | // -------------------------------------------------------------------------------------------------------- 245 | point_copy(C, current_A[0]); 246 | }; 247 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------