53f88c651738648853dbdbe376d783b6b004287f
[openssl.git] / crypto / ec / ectest.c
1 /* crypto/ec/ectest.c */
2 /* ====================================================================
3  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer. 
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    openssl-core@openssl.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This product includes cryptographic software written by Eric Young
51  * (eay@cryptsoft.com).  This product includes software written by Tim
52  * Hudson (tjh@cryptsoft.com).
53  *
54  */
55
56 #include <stdio.h>
57 #include <stdlib.h>
58
59
60 #ifdef OPENSSL_NO_EC
61 int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); return 0; }
62 #else
63
64
65 #include <openssl/ec.h>
66 #include <openssl/err.h>
67
68 #define ABORT do { \
69         fprintf(stderr, "%s:%d: ABORT\n", __FILE__, __LINE__); \
70         ERR_print_errors_fp(stderr); \
71         exit(1); \
72 } while (0)
73
74 int main(int argc, char *argv[])
75         {       
76         BN_CTX *ctx = NULL;
77         BIGNUM *p, *a, *b;
78         EC_GROUP *group;
79         EC_POINT *P, *Q, *R;
80         BIGNUM *x, *y, *z;
81         unsigned char buf[100];
82         size_t i, len;
83         
84         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
85         ERR_load_crypto_strings();
86
87 #if 0 /* optional */
88         ctx = BN_CTX_new();
89         if (!ctx) ABORT;
90 #endif
91
92         p = BN_new();
93         a = BN_new();
94         b = BN_new();
95         if (!p || !a || !b) ABORT;
96
97         if (!BN_hex2bn(&p, "17")) ABORT;
98         if (!BN_hex2bn(&a, "1")) ABORT;
99         if (!BN_hex2bn(&b, "1")) ABORT;
100         
101         group = EC_GROUP_new(EC_GFp_mont_method());
102         if (!group) ABORT;
103         if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
104         if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT;
105
106         fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 = x^3 + a*x + b  (mod 0x");
107         BN_print_fp(stdout, p);
108         fprintf(stdout, ")\n     a = 0x");
109         BN_print_fp(stdout, a);
110         fprintf(stdout, "\n     b = 0x");
111         BN_print_fp(stdout, b);
112         fprintf(stdout, "\n");
113
114         P = EC_POINT_new(group);
115         Q = EC_POINT_new(group);
116         R = EC_POINT_new(group);
117         if (!P || !Q || !R) ABORT;
118         
119         if (!EC_POINT_set_to_infinity(group, P)) ABORT;
120         if (!EC_POINT_is_at_infinity(group, P)) ABORT;
121
122         buf[0] = 0;
123         if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
124
125         if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
126         if (!EC_POINT_is_at_infinity(group, P)) ABORT;
127
128         x = BN_new();
129         y = BN_new();
130         z = BN_new();
131         if (!x || !y || !z) ABORT;
132
133         if (!BN_hex2bn(&x, "D")) ABORT;
134         if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT;
135         if (!EC_POINT_is_on_curve(group, Q, ctx))
136                 {
137                 if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT;
138                 fprintf(stderr, "Point is not on curve: x = 0x");
139                 BN_print_fp(stderr, x);
140                 fprintf(stderr, ", y = 0x");
141                 BN_print_fp(stderr, y);
142                 fprintf(stderr, "\n");
143                 ABORT;
144                 }
145
146         fprintf(stdout, "A cyclic subgroup:\n");
147         do
148                 {
149                 if (EC_POINT_is_at_infinity(group, P))
150                         fprintf(stdout, "     point at infinity\n");
151                 else
152                         {
153                         if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
154
155                         fprintf(stdout, "     x = 0x");
156                         BN_print_fp(stdout, x);
157                         fprintf(stdout, ", y = 0x");
158                         BN_print_fp(stdout, y);
159                         fprintf(stdout, "\n");
160                         }
161                 
162                 if (!EC_POINT_copy(R, P)) ABORT;
163                 if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
164
165 #if 0 /* optional */
166                 if (!EC_POINT_make_affine(group, P, ctx)) ABORT;
167 #endif
168                 }
169         while (!EC_POINT_is_at_infinity(group, P));
170
171         if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
172         if (!EC_POINT_is_at_infinity(group, P)) ABORT;
173
174         len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
175         if (len == 0) ABORT;
176         if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
177         if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
178         fprintf(stdout, "Generator as octect string, compressed form:\n     ");
179         for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
180         
181         len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
182         if (len == 0) ABORT;
183         if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
184         if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
185         fprintf(stdout, "\nGenerator as octect string, uncompressed form:\n     ");
186         for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
187         
188         len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
189         if (len == 0) ABORT;
190         if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
191         if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
192         fprintf(stdout, "\nGenerator as octect string, hybrid form:\n     ");
193         for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
194         
195         if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT;
196         fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n     X = 0x");
197         BN_print_fp(stdout, x);
198         fprintf(stdout, ", Y = 0x");
199         BN_print_fp(stdout, y);
200         fprintf(stdout, ", Z = 0x");
201         BN_print_fp(stdout, z);
202         fprintf(stdout, "\n");
203
204         if (!EC_POINT_invert(group, P, ctx)) ABORT;
205         if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
206
207         /* ... */
208
209         if (ctx)
210                 BN_CTX_free(ctx);
211         BN_free(p); BN_free(a); BN_free(b);
212         EC_GROUP_free(group);
213         EC_POINT_free(P);
214         EC_POINT_free(Q);
215         EC_POINT_free(R);
216         BN_free(x); BN_free(y); BN_free(z);
217
218         ERR_free_strings();
219         ERR_remove_state(0);
220         CRYPTO_mem_leaks_fp(stderr);
221         
222         return 0;
223         }
224 #endif