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