Elliptic curves over GF(p), new BIGNUM functions, Montgomery re-implementation.
[openssl.git] / crypto / ec / ec.c
1 /*\r
2  *\r
3  *      ec.c\r
4  *\r
5  *      Elliptic Curve Arithmetic Functions\r
6  *\r
7  *      Copyright (C) Lenka Fibikova 2000\r
8  *\r
9  *\r
10  */\r
11 \r
12 \r
13 #include <stdio.h>\r
14 #include <stdlib.h>\r
15 #include <assert.h>\r
16 \r
17 #include "ec.h"\r
18 #include "bn_modfs.h"\r
19 \r
20 \r
21 \r
22 EC *EC_new()\r
23 {\r
24         EC *ret;\r
25 \r
26         ret=(EC *)malloc(sizeof(EC));\r
27         if (ret == NULL) return NULL;\r
28         ret->A = BN_new();\r
29         ret->B = BN_new();\r
30         ret->p = BN_new();\r
31         ret->h = BN_new();\r
32         ret->is_in_mont = 0;\r
33 \r
34         if (ret->A == NULL || ret->B == NULL || ret->p == NULL || ret->h == NULL)\r
35         {\r
36                 if (ret->A != NULL) BN_free(ret->A);\r
37                 if (ret->B != NULL) BN_free(ret->B);\r
38                 if (ret->p != NULL) BN_free(ret->p);\r
39                 if (ret->h != NULL) BN_free(ret->h);\r
40                 free(ret);\r
41                 return(NULL);\r
42         }\r
43         return(ret);\r
44 }\r
45 \r
46 \r
47 void EC_clear_free(EC *E)\r
48 {\r
49         if (E == NULL) return;\r
50 \r
51         if (E->A != NULL) BN_clear_free(E->A);\r
52         if (E->B != NULL) BN_clear_free(E->B);\r
53         if (E->p != NULL) BN_clear_free(E->p);\r
54         if (E->h != NULL) BN_clear_free(E->h);\r
55         E->is_in_mont = 0;\r
56         free(E);\r
57 }\r
58 \r
59 \r
60 #ifdef MONTGOMERY\r
61 int EC_to_montgomery(EC *E, BN_MONTGOMERY *mont, BN_CTX *ctx)\r
62 {\r
63         assert(E != NULL);\r
64         assert(E->A != NULL && E->B != NULL && E->p != NULL && E->h != NULL);\r
65 \r
66         assert(mont != NULL);\r
67         assert(mont->p != NULL);\r
68 \r
69         assert(ctx != NULL);\r
70 \r
71         if (E->is_in_mont) return 1;\r
72 \r
73         if (!BN_lshift(E->A, E->A, mont->R_num_bits)) return 0;\r
74         if (!BN_mod(E->A, E->A, mont->p, ctx)) return 0;\r
75 \r
76         if (!BN_lshift(E->B, E->B, mont->R_num_bits)) return 0;\r
77         if (!BN_mod(E->B, E->B, mont->p, ctx)) return 0;\r
78 \r
79         if (!BN_lshift(E->h, E->h, mont->R_num_bits)) return 0;\r
80         if (!BN_mod(E->h, E->h, mont->p, ctx)) return 0;\r
81 \r
82         E->is_in_mont = 1;\r
83         return 1;\r
84 \r
85 }\r
86 \r
87 \r
88 int EC_from_montgomery(EC *E, BN_MONTGOMERY *mont, BN_CTX *ctx)\r
89 {\r
90         assert(E != NULL);\r
91         assert(E->A != NULL && E->B != NULL && E->p != NULL && E->h != NULL);\r
92 \r
93         assert(mont != NULL);\r
94         assert(mont->p != NULL);\r
95 \r
96         assert(ctx != NULL);\r
97 \r
98         if (!E->is_in_mont) return 1;\r
99 \r
100         if (!BN_mont_red(E->A, mont, ctx)) return 0;\r
101         if (!BN_mont_red(E->B, mont, ctx)) return 0;\r
102         if (!BN_mont_red(E->h, mont, ctx)) return 0;\r
103 \r
104         E->is_in_mont = 0;\r
105         return 1;\r
106 }\r
107 #endif /* MONTGOMERY */\r
108 \r
109 int EC_set_half(EC *E)\r
110 /* h <- 1/2 mod p = (p + 1)/2 */\r
111 {\r
112         assert(E != NULL);\r
113         assert(E->p != NULL);\r
114         assert(E->h != NULL);\r
115         assert(!E->is_in_mont);\r
116 \r
117         if (BN_copy(E->h, E->p) == NULL) return 0; \r
118         if (!BN_add_word(E->h, 1)) return 0;\r
119         if (!BN_rshift1(E->h, E->h)) return 0; \r
120         return 1;\r
121 }\r