ecdhtest.c revision 296341
1154484Sjhb/* crypto/ecdh/ecdhtest.c */
2154484Sjhb/* ====================================================================
3154484Sjhb * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4154484Sjhb *
5154484Sjhb * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6154484Sjhb * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7154484Sjhb * to the OpenSSL project.
8154484Sjhb *
9154484Sjhb * The ECC Code is licensed pursuant to the OpenSSL open source
10154484Sjhb * license provided below.
11154484Sjhb *
12154484Sjhb * The ECDH software is originally written by Douglas Stebila of
13154484Sjhb * Sun Microsystems Laboratories.
14154484Sjhb *
15154484Sjhb */
16154484Sjhb/* ====================================================================
17154484Sjhb * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
18154484Sjhb *
19154484Sjhb * Redistribution and use in source and binary forms, with or without
20154484Sjhb * modification, are permitted provided that the following conditions
21154484Sjhb * are met:
22154484Sjhb *
23154484Sjhb * 1. Redistributions of source code must retain the above copyright
24154484Sjhb *    notice, this list of conditions and the following disclaimer.
25154484Sjhb *
26154484Sjhb * 2. Redistributions in binary form must reproduce the above copyright
27154484Sjhb *    notice, this list of conditions and the following disclaimer in
28154484Sjhb *    the documentation and/or other materials provided with the
29154484Sjhb *    distribution.
30154484Sjhb *
31154484Sjhb * 3. All advertising materials mentioning features or use of this
32154484Sjhb *    software must display the following acknowledgment:
33154484Sjhb *    "This product includes software developed by the OpenSSL Project
34154484Sjhb *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35154485Sjhb *
36164159Skmacy * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37154485Sjhb *    endorse or promote products derived from this software without
38154484Sjhb *    prior written permission. For written permission, please contact
39154484Sjhb *    openssl-core@openssl.org.
40174629Sjeff *
41154484Sjhb * 5. Products derived from this software may not be called "OpenSSL"
42154484Sjhb *    nor may "OpenSSL" appear in their names without prior written
43174629Sjeff *    permission of the OpenSSL Project.
44174629Sjeff *
45189845Sjeff * 6. Redistributions of any form whatsoever must retain the following
46174629Sjeff *    acknowledgment:
47174629Sjeff *    "This product includes software developed by the OpenSSL Project
48164159Skmacy *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49189845Sjeff *
50174629Sjeff * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51164159Skmacy * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52154484Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53154484Sjhb * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
54154484Sjhb * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55154484Sjhb * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56154484Sjhb * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57174629Sjeff * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58174629Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59154484Sjhb * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60154484Sjhb * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61154484Sjhb * OF THE POSSIBILITY OF SUCH DAMAGE.
62154484Sjhb * ====================================================================
63154484Sjhb *
64154484Sjhb * This product includes cryptographic software written by Eric Young
65173444Sups * (eay@cryptsoft.com).  This product includes software written by Tim
66256001Sjhb * Hudson (tjh@cryptsoft.com).
67154941Sjhb *
68164246Skmacy */
69154484Sjhb
70154484Sjhb#include <stdio.h>
71154484Sjhb#include <stdlib.h>
72154484Sjhb#include <string.h>
73154484Sjhb
74154484Sjhb#include "../e_os.h"
75154484Sjhb
76154484Sjhb#include <openssl/opensslconf.h> /* for OPENSSL_NO_ECDH */
77154484Sjhb#include <openssl/crypto.h>
78154484Sjhb#include <openssl/bio.h>
79154484Sjhb#include <openssl/bn.h>
80154484Sjhb#include <openssl/objects.h>
81154484Sjhb#include <openssl/rand.h>
82154484Sjhb#include <openssl/sha.h>
83154484Sjhb#include <openssl/err.h>
84154484Sjhb
85154484Sjhb#ifdef OPENSSL_NO_ECDH
86154484Sjhbint main(int argc, char *argv[])
87154484Sjhb{
88154484Sjhb    printf("No ECDH support\n");
89154484Sjhb    return (0);
90154484Sjhb}
91154484Sjhb#else
92154484Sjhb# include <openssl/ec.h>
93179025Sattilio# include <openssl/ecdh.h>
94154484Sjhb
95154484Sjhb# ifdef OPENSSL_SYS_WIN16
96154484Sjhb#  define MS_CALLBACK     _far _loadds
97154484Sjhb# else
98154484Sjhb#  define MS_CALLBACK
99154484Sjhb# endif
100154484Sjhb
101154484Sjhb# if 0
102154484Sjhbstatic void MS_CALLBACK cb(int p, int n, void *arg);
103154484Sjhb# endif
104154484Sjhb
105154484Sjhbstatic const char rnd_seed[] =
106154484Sjhb    "string to make the random number generator think it has entropy";
107154484Sjhb
108154484Sjhbstatic const int KDF1_SHA1_len = 20;
109154484Sjhbstatic void *KDF1_SHA1(const void *in, size_t inlen, void *out,
110154484Sjhb                       size_t *outlen)
111154484Sjhb{
112154484Sjhb# ifndef OPENSSL_NO_SHA
113154484Sjhb    if (*outlen < SHA_DIGEST_LENGTH)
114154484Sjhb        return NULL;
115154484Sjhb    else
116154484Sjhb        *outlen = SHA_DIGEST_LENGTH;
117154484Sjhb    return SHA1(in, inlen, out);
118154484Sjhb# else
119154484Sjhb    return NULL;
120154484Sjhb# endif
121154484Sjhb}
122154484Sjhb
123154484Sjhbstatic int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out)
124154484Sjhb{
125164159Skmacy    EC_KEY *a = NULL;
126164159Skmacy    EC_KEY *b = NULL;
127174629Sjeff    BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL;
128174629Sjeff    char buf[12];
129174629Sjeff    unsigned char *abuf = NULL, *bbuf = NULL;
130174629Sjeff    int i, alen, blen, aout, bout, ret = 0;
131174629Sjeff    const EC_GROUP *group;
132174629Sjeff
133174629Sjeff    a = EC_KEY_new_by_curve_name(nid);
134174629Sjeff    b = EC_KEY_new_by_curve_name(nid);
135174629Sjeff    if (a == NULL || b == NULL)
136174629Sjeff        goto err;
137174629Sjeff
138174629Sjeff    group = EC_KEY_get0_group(a);
139209390Sed
140209390Sed    if ((x_a = BN_new()) == NULL)
141174629Sjeff        goto err;
142174629Sjeff    if ((y_a = BN_new()) == NULL)
143174629Sjeff        goto err;
144174629Sjeff    if ((x_b = BN_new()) == NULL)
145174629Sjeff        goto err;
146174629Sjeff    if ((y_b = BN_new()) == NULL)
147174629Sjeff        goto err;
148174629Sjeff
149175010Sjeff    BIO_puts(out, "Testing key generation with ");
150174629Sjeff    BIO_puts(out, text);
151174629Sjeff# ifdef NOISY
152174629Sjeff    BIO_puts(out, "\n");
153174629Sjeff# else
154180852Skmacy    (void)BIO_flush(out);
155174629Sjeff# endif
156174629Sjeff
157174629Sjeff    if (!EC_KEY_generate_key(a))
158174629Sjeff        goto err;
159174629Sjeff
160174629Sjeff    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
161174629Sjeff        NID_X9_62_prime_field) {
162174629Sjeff        if (!EC_POINT_get_affine_coordinates_GFp
163174629Sjeff            (group, EC_KEY_get0_public_key(a), x_a, y_a, ctx))
164174629Sjeff            goto err;
165174629Sjeff    }
166174629Sjeff# ifndef OPENSSL_NO_EC2M
167174629Sjeff    else {
168174629Sjeff        if (!EC_POINT_get_affine_coordinates_GF2m(group,
169174629Sjeff                                                  EC_KEY_get0_public_key(a),
170215034Sbrucec                                                  x_a, y_a, ctx))
171174629Sjeff            goto err;
172174629Sjeff    }
173174629Sjeff# endif
174174629Sjeff# ifdef NOISY
175174629Sjeff    BIO_puts(out, "  pri 1=");
176174629Sjeff    BN_print(out, a->priv_key);
177174629Sjeff    BIO_puts(out, "\n  pub 1=");
178174629Sjeff    BN_print(out, x_a);
179174629Sjeff    BIO_puts(out, ",");
180174629Sjeff    BN_print(out, y_a);
181174629Sjeff    BIO_puts(out, "\n");
182174629Sjeff# else
183174629Sjeff    BIO_printf(out, " .");
184174629Sjeff    (void)BIO_flush(out);
185174629Sjeff# endif
186174629Sjeff
187174629Sjeff    if (!EC_KEY_generate_key(b))
188189845Sjeff        goto err;
189189845Sjeff
190174629Sjeff    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
191212750Smdf        NID_X9_62_prime_field) {
192174629Sjeff        if (!EC_POINT_get_affine_coordinates_GFp
193174629Sjeff            (group, EC_KEY_get0_public_key(b), x_b, y_b, ctx))
194174629Sjeff            goto err;
195174629Sjeff    }
196174629Sjeff# ifndef OPENSSL_NO_EC2M
197174629Sjeff    else {
198209390Sed        if (!EC_POINT_get_affine_coordinates_GF2m(group,
199174629Sjeff                                                  EC_KEY_get0_public_key(b),
200164159Skmacy                                                  x_b, y_b, ctx))
201174629Sjeff            goto err;
202209390Sed    }
203164159Skmacy# endif
204174629Sjeff
205174629Sjeff# ifdef NOISY
206209390Sed    BIO_puts(out, "  pri 2=");
207174629Sjeff    BN_print(out, b->priv_key);
208174629Sjeff    BIO_puts(out, "\n  pub 2=");
209174629Sjeff    BN_print(out, x_b);
210174629Sjeff    BIO_puts(out, ",");
211174629Sjeff    BN_print(out, y_b);
212174629Sjeff    BIO_puts(out, "\n");
213174629Sjeff# else
214174629Sjeff    BIO_printf(out, ".");
215174629Sjeff    (void)BIO_flush(out);
216174629Sjeff# endif
217174629Sjeff
218174629Sjeff    alen = KDF1_SHA1_len;
219174629Sjeff    abuf = (unsigned char *)OPENSSL_malloc(alen);
220174629Sjeff    aout =
221174629Sjeff        ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1);
222174629Sjeff
223174629Sjeff# ifdef NOISY
224174629Sjeff    BIO_puts(out, "  key1 =");
225174629Sjeff    for (i = 0; i < aout; i++) {
226174629Sjeff        sprintf(buf, "%02X", abuf[i]);
227174629Sjeff        BIO_puts(out, buf);
228174629Sjeff    }
229174629Sjeff    BIO_puts(out, "\n");
230174629Sjeff# else
231174629Sjeff    BIO_printf(out, ".");
232174629Sjeff    (void)BIO_flush(out);
233174629Sjeff# endif
234174629Sjeff
235174629Sjeff    blen = KDF1_SHA1_len;
236174629Sjeff    bbuf = (unsigned char *)OPENSSL_malloc(blen);
237174629Sjeff    bout =
238174629Sjeff        ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1);
239174629Sjeff
240174629Sjeff# ifdef NOISY
241189845Sjeff    BIO_puts(out, "  key2 =");
242189845Sjeff    for (i = 0; i < bout; i++) {
243189845Sjeff        sprintf(buf, "%02X", bbuf[i]);
244189845Sjeff        BIO_puts(out, buf);
245189845Sjeff    }
246189845Sjeff    BIO_puts(out, "\n");
247174629Sjeff# else
248189845Sjeff    BIO_printf(out, ".");
249189845Sjeff    (void)BIO_flush(out);
250189845Sjeff# endif
251189845Sjeff
252189845Sjeff    if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
253189845Sjeff# ifndef NOISY
254189845Sjeff        BIO_printf(out, " failed\n\n");
255209059Sjhb        BIO_printf(out, "key a:\n");
256189845Sjeff        BIO_printf(out, "private key: ");
257189845Sjeff        BN_print(out, EC_KEY_get0_private_key(a));
258189845Sjeff        BIO_printf(out, "\n");
259189845Sjeff        BIO_printf(out, "public key (x,y): ");
260189845Sjeff        BN_print(out, x_a);
261189845Sjeff        BIO_printf(out, ",");
262189845Sjeff        BN_print(out, y_a);
263189845Sjeff        BIO_printf(out, "\nkey b:\n");
264189845Sjeff        BIO_printf(out, "private key: ");
265189845Sjeff        BN_print(out, EC_KEY_get0_private_key(b));
266189845Sjeff        BIO_printf(out, "\n");
267189845Sjeff        BIO_printf(out, "public key (x,y): ");
268189845Sjeff        BN_print(out, x_b);
269189845Sjeff        BIO_printf(out, ",");
270189845Sjeff        BN_print(out, y_b);
271189845Sjeff        BIO_printf(out, "\n");
272189845Sjeff        BIO_printf(out, "generated key a: ");
273189845Sjeff        for (i = 0; i < bout; i++) {
274189845Sjeff            sprintf(buf, "%02X", bbuf[i]);
275174629Sjeff            BIO_puts(out, buf);
276174629Sjeff        }
277174629Sjeff        BIO_printf(out, "\n");
278174629Sjeff        BIO_printf(out, "generated key b: ");
279174629Sjeff        for (i = 0; i < aout; i++) {
280189845Sjeff            sprintf(buf, "%02X", abuf[i]);
281189845Sjeff            BIO_puts(out, buf);
282189845Sjeff        }
283189845Sjeff        BIO_printf(out, "\n");
284189845Sjeff# endif
285189845Sjeff        fprintf(stderr, "Error in ECDH routines\n");
286189845Sjeff        ret = 0;
287189845Sjeff    } else {
288174629Sjeff# ifndef NOISY
289174629Sjeff        BIO_printf(out, " ok\n");
290189845Sjeff# endif
291189845Sjeff        ret = 1;
292189845Sjeff    }
293189845Sjeff err:
294189845Sjeff    ERR_print_errors_fp(stderr);
295189845Sjeff
296174629Sjeff    if (abuf != NULL)
297174629Sjeff        OPENSSL_free(abuf);
298174629Sjeff    if (bbuf != NULL)
299174629Sjeff        OPENSSL_free(bbuf);
300174629Sjeff    if (x_a)
301174629Sjeff        BN_free(x_a);
302189845Sjeff    if (y_a)
303189845Sjeff        BN_free(y_a);
304189845Sjeff    if (x_b)
305174629Sjeff        BN_free(x_b);
306174629Sjeff    if (y_b)
307174629Sjeff        BN_free(y_b);
308174629Sjeff    if (b)
309189845Sjeff        EC_KEY_free(b);
310174629Sjeff    if (a)
311174629Sjeff        EC_KEY_free(a);
312174629Sjeff    return (ret);
313174629Sjeff}
314174629Sjeff
315174629Sjeffint main(int argc, char *argv[])
316174629Sjeff{
317174629Sjeff    BN_CTX *ctx = NULL;
318174629Sjeff    int ret = 1;
319174629Sjeff    BIO *out;
320180852Skmacy
321180852Skmacy    CRYPTO_malloc_debug_init();
322174629Sjeff    CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
323174629Sjeff    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
324174629Sjeff
325174629Sjeff# ifdef OPENSSL_SYS_WIN32
326174629Sjeff    CRYPTO_malloc_init();
327174629Sjeff# endif
328175010Sjeff
329174629Sjeff    RAND_seed(rnd_seed, sizeof rnd_seed);
330174629Sjeff
331174629Sjeff    out = BIO_new(BIO_s_file());
332174629Sjeff    if (out == NULL)
333174629Sjeff        EXIT(1);
334174629Sjeff    BIO_set_fp(out, stdout, BIO_NOCLOSE);
335174629Sjeff
336174629Sjeff    if ((ctx = BN_CTX_new()) == NULL)
337174629Sjeff        goto err;
338174629Sjeff
339174629Sjeff    /* NIST PRIME CURVES TESTS */
340174629Sjeff    if (!test_ecdh_curve
341175010Sjeff        (NID_X9_62_prime192v1, "NIST Prime-Curve P-192", ctx, out))
342174629Sjeff        goto err;
343174629Sjeff    if (!test_ecdh_curve(NID_secp224r1, "NIST Prime-Curve P-224", ctx, out))
344174629Sjeff        goto err;
345174629Sjeff    if (!test_ecdh_curve
346174629Sjeff        (NID_X9_62_prime256v1, "NIST Prime-Curve P-256", ctx, out))
347174629Sjeff        goto err;
348174629Sjeff    if (!test_ecdh_curve(NID_secp384r1, "NIST Prime-Curve P-384", ctx, out))
349174629Sjeff        goto err;
350174629Sjeff    if (!test_ecdh_curve(NID_secp521r1, "NIST Prime-Curve P-521", ctx, out))
351174629Sjeff        goto err;
352175010Sjeff# ifndef OPENSSL_NO_EC2M
353174629Sjeff    /* NIST BINARY CURVES TESTS */
354174629Sjeff    if (!test_ecdh_curve(NID_sect163k1, "NIST Binary-Curve K-163", ctx, out))
355174629Sjeff        goto err;
356174629Sjeff    if (!test_ecdh_curve(NID_sect163r2, "NIST Binary-Curve B-163", ctx, out))
357180852Skmacy        goto err;
358180852Skmacy    if (!test_ecdh_curve(NID_sect233k1, "NIST Binary-Curve K-233", ctx, out))
359174629Sjeff        goto err;
360174629Sjeff    if (!test_ecdh_curve(NID_sect233r1, "NIST Binary-Curve B-233", ctx, out))
361174629Sjeff        goto err;
362174629Sjeff    if (!test_ecdh_curve(NID_sect283k1, "NIST Binary-Curve K-283", ctx, out))
363174629Sjeff        goto err;
364174629Sjeff    if (!test_ecdh_curve(NID_sect283r1, "NIST Binary-Curve B-283", ctx, out))
365167012Skmacy        goto err;
366174629Sjeff    if (!test_ecdh_curve(NID_sect409k1, "NIST Binary-Curve K-409", ctx, out))
367174629Sjeff        goto err;
368174629Sjeff    if (!test_ecdh_curve(NID_sect409r1, "NIST Binary-Curve B-409", ctx, out))
369174629Sjeff        goto err;
370174629Sjeff    if (!test_ecdh_curve(NID_sect571k1, "NIST Binary-Curve K-571", ctx, out))
371174629Sjeff        goto err;
372174629Sjeff    if (!test_ecdh_curve(NID_sect571r1, "NIST Binary-Curve B-571", ctx, out))
373174629Sjeff        goto err;
374174629Sjeff# endif
375174629Sjeff
376174629Sjeff    ret = 0;
377174629Sjeff
378174629Sjeff err:
379174629Sjeff    ERR_print_errors_fp(stderr);
380174629Sjeff    if (ctx)
381174629Sjeff        BN_CTX_free(ctx);
382174629Sjeff    BIO_free(out);
383174629Sjeff    CRYPTO_cleanup_all_ex_data();
384174629Sjeff    ERR_remove_thread_state(NULL);
385174629Sjeff    CRYPTO_mem_leaks_fp(stderr);
386174629Sjeff    EXIT(ret);
387174629Sjeff    return (ret);
388174629Sjeff}
389174629Sjeff
390174629Sjeff# if 0
391174629Sjeffstatic void MS_CALLBACK cb(int p, int n, void *arg)
392175010Sjeff{
393174629Sjeff    char c = '*';
394217916Smdf
395217916Smdf    if (p == 0)
396217916Smdf        c = '.';
397212750Smdf    if (p == 1)
398180852Skmacy        c = '+';
399180852Skmacy    if (p == 2)
400175010Sjeff        c = '*';
401175010Sjeff    if (p == 3)
402189845Sjeff        c = '\n';
403174629Sjeff    BIO_write((BIO *)arg, &c, 1);
404174629Sjeff    (void)BIO_flush((BIO *)arg);
405174629Sjeff#  ifdef LINT
406174629Sjeff    p = n;
407174629Sjeff#  endif
408174629Sjeff}
409174629Sjeff# endif
410175010Sjeff#endif
411174629Sjeff