ecdhtest.c revision 331638
1/* crypto/ecdh/ecdhtest.c */
2/* ====================================================================
3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4 *
5 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7 * to the OpenSSL project.
8 *
9 * The ECC Code is licensed pursuant to the OpenSSL open source
10 * license provided below.
11 *
12 * The ECDH software is originally written by Douglas Stebila of
13 * Sun Microsystems Laboratories.
14 *
15 */
16/* ====================================================================
17 * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 *
23 * 1. Redistributions of source code must retain the above copyright
24 *    notice, this list of conditions and the following disclaimer.
25 *
26 * 2. Redistributions in binary form must reproduce the above copyright
27 *    notice, this list of conditions and the following disclaimer in
28 *    the documentation and/or other materials provided with the
29 *    distribution.
30 *
31 * 3. All advertising materials mentioning features or use of this
32 *    software must display the following acknowledgment:
33 *    "This product includes software developed by the OpenSSL Project
34 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35 *
36 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37 *    endorse or promote products derived from this software without
38 *    prior written permission. For written permission, please contact
39 *    openssl-core@openssl.org.
40 *
41 * 5. Products derived from this software may not be called "OpenSSL"
42 *    nor may "OpenSSL" appear in their names without prior written
43 *    permission of the OpenSSL Project.
44 *
45 * 6. Redistributions of any form whatsoever must retain the following
46 *    acknowledgment:
47 *    "This product includes software developed by the OpenSSL Project
48 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
54 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61 * OF THE POSSIBILITY OF SUCH DAMAGE.
62 * ====================================================================
63 *
64 * This product includes cryptographic software written by Eric Young
65 * (eay@cryptsoft.com).  This product includes software written by Tim
66 * Hudson (tjh@cryptsoft.com).
67 *
68 */
69
70#include <stdio.h>
71#include <stdlib.h>
72#include <string.h>
73
74#include "../e_os.h"
75
76#include <openssl/opensslconf.h> /* for OPENSSL_NO_ECDH */
77#include <openssl/crypto.h>
78#include <openssl/bio.h>
79#include <openssl/bn.h>
80#include <openssl/objects.h>
81#include <openssl/rand.h>
82#include <openssl/sha.h>
83#include <openssl/err.h>
84
85#ifdef OPENSSL_NO_ECDH
86int main(int argc, char *argv[])
87{
88    printf("No ECDH support\n");
89    return (0);
90}
91#else
92# include <openssl/ec.h>
93# include <openssl/ecdh.h>
94
95# ifdef OPENSSL_SYS_WIN16
96#  define MS_CALLBACK     _far _loadds
97# else
98#  define MS_CALLBACK
99# endif
100
101# if 0
102static void MS_CALLBACK cb(int p, int n, void *arg);
103# endif
104
105static const char rnd_seed[] =
106    "string to make the random number generator think it has entropy";
107
108static const int KDF1_SHA1_len = 20;
109static void *KDF1_SHA1(const void *in, size_t inlen, void *out,
110                       size_t *outlen)
111{
112# ifndef OPENSSL_NO_SHA
113    if (*outlen < SHA_DIGEST_LENGTH)
114        return NULL;
115    else
116        *outlen = SHA_DIGEST_LENGTH;
117    return SHA1(in, inlen, out);
118# else
119    return NULL;
120# endif
121}
122
123static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out)
124{
125    EC_KEY *a = NULL;
126    EC_KEY *b = NULL;
127    BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL;
128    char buf[12];
129    unsigned char *abuf = NULL, *bbuf = NULL;
130    int i, alen, blen, aout, bout, ret = 0;
131    const EC_GROUP *group;
132
133    a = EC_KEY_new_by_curve_name(nid);
134    b = EC_KEY_new_by_curve_name(nid);
135    if (a == NULL || b == NULL)
136        goto err;
137
138    group = EC_KEY_get0_group(a);
139
140    if ((x_a = BN_new()) == NULL)
141        goto err;
142    if ((y_a = BN_new()) == NULL)
143        goto err;
144    if ((x_b = BN_new()) == NULL)
145        goto err;
146    if ((y_b = BN_new()) == NULL)
147        goto err;
148
149    BIO_puts(out, "Testing key generation with ");
150    BIO_puts(out, text);
151# ifdef NOISY
152    BIO_puts(out, "\n");
153# else
154    (void)BIO_flush(out);
155# endif
156
157    if (!EC_KEY_generate_key(a))
158        goto err;
159
160    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
161        NID_X9_62_prime_field) {
162        if (!EC_POINT_get_affine_coordinates_GFp
163            (group, EC_KEY_get0_public_key(a), x_a, y_a, ctx))
164            goto err;
165    }
166# ifndef OPENSSL_NO_EC2M
167    else {
168        if (!EC_POINT_get_affine_coordinates_GF2m(group,
169                                                  EC_KEY_get0_public_key(a),
170                                                  x_a, y_a, ctx))
171            goto err;
172    }
173# endif
174# ifdef NOISY
175    BIO_puts(out, "  pri 1=");
176    BN_print(out, a->priv_key);
177    BIO_puts(out, "\n  pub 1=");
178    BN_print(out, x_a);
179    BIO_puts(out, ",");
180    BN_print(out, y_a);
181    BIO_puts(out, "\n");
182# else
183    BIO_printf(out, " .");
184    (void)BIO_flush(out);
185# endif
186
187    if (!EC_KEY_generate_key(b))
188        goto err;
189
190    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
191        NID_X9_62_prime_field) {
192        if (!EC_POINT_get_affine_coordinates_GFp
193            (group, EC_KEY_get0_public_key(b), x_b, y_b, ctx))
194            goto err;
195    }
196# ifndef OPENSSL_NO_EC2M
197    else {
198        if (!EC_POINT_get_affine_coordinates_GF2m(group,
199                                                  EC_KEY_get0_public_key(b),
200                                                  x_b, y_b, ctx))
201            goto err;
202    }
203# endif
204
205# ifdef NOISY
206    BIO_puts(out, "  pri 2=");
207    BN_print(out, b->priv_key);
208    BIO_puts(out, "\n  pub 2=");
209    BN_print(out, x_b);
210    BIO_puts(out, ",");
211    BN_print(out, y_b);
212    BIO_puts(out, "\n");
213# else
214    BIO_printf(out, ".");
215    (void)BIO_flush(out);
216# endif
217
218    alen = KDF1_SHA1_len;
219    abuf = (unsigned char *)OPENSSL_malloc(alen);
220    aout =
221        ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1);
222
223# ifdef NOISY
224    BIO_puts(out, "  key1 =");
225    for (i = 0; i < aout; i++) {
226        sprintf(buf, "%02X", abuf[i]);
227        BIO_puts(out, buf);
228    }
229    BIO_puts(out, "\n");
230# else
231    BIO_printf(out, ".");
232    (void)BIO_flush(out);
233# endif
234
235    blen = KDF1_SHA1_len;
236    bbuf = (unsigned char *)OPENSSL_malloc(blen);
237    bout =
238        ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1);
239
240# ifdef NOISY
241    BIO_puts(out, "  key2 =");
242    for (i = 0; i < bout; i++) {
243        sprintf(buf, "%02X", bbuf[i]);
244        BIO_puts(out, buf);
245    }
246    BIO_puts(out, "\n");
247# else
248    BIO_printf(out, ".");
249    (void)BIO_flush(out);
250# endif
251
252    if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
253# ifndef NOISY
254        BIO_printf(out, " failed\n\n");
255        BIO_printf(out, "key a:\n");
256        BIO_printf(out, "private key: ");
257        BN_print(out, EC_KEY_get0_private_key(a));
258        BIO_printf(out, "\n");
259        BIO_printf(out, "public key (x,y): ");
260        BN_print(out, x_a);
261        BIO_printf(out, ",");
262        BN_print(out, y_a);
263        BIO_printf(out, "\nkey b:\n");
264        BIO_printf(out, "private key: ");
265        BN_print(out, EC_KEY_get0_private_key(b));
266        BIO_printf(out, "\n");
267        BIO_printf(out, "public key (x,y): ");
268        BN_print(out, x_b);
269        BIO_printf(out, ",");
270        BN_print(out, y_b);
271        BIO_printf(out, "\n");
272        BIO_printf(out, "generated key a: ");
273        for (i = 0; i < bout; i++) {
274            sprintf(buf, "%02X", bbuf[i]);
275            BIO_puts(out, buf);
276        }
277        BIO_printf(out, "\n");
278        BIO_printf(out, "generated key b: ");
279        for (i = 0; i < aout; i++) {
280            sprintf(buf, "%02X", abuf[i]);
281            BIO_puts(out, buf);
282        }
283        BIO_printf(out, "\n");
284# endif
285        fprintf(stderr, "Error in ECDH routines\n");
286        ret = 0;
287    } else {
288# ifndef NOISY
289        BIO_printf(out, " ok\n");
290# endif
291        ret = 1;
292    }
293 err:
294    ERR_print_errors_fp(stderr);
295
296    if (abuf != NULL)
297        OPENSSL_free(abuf);
298    if (bbuf != NULL)
299        OPENSSL_free(bbuf);
300    if (x_a)
301        BN_free(x_a);
302    if (y_a)
303        BN_free(y_a);
304    if (x_b)
305        BN_free(x_b);
306    if (y_b)
307        BN_free(y_b);
308    if (b)
309        EC_KEY_free(b);
310    if (a)
311        EC_KEY_free(a);
312    return (ret);
313}
314
315/* Keys and shared secrets from RFC 7027 */
316
317static const unsigned char bp256_da[] = {
318    0x81, 0xDB, 0x1E, 0xE1, 0x00, 0x15, 0x0F, 0xF2, 0xEA, 0x33, 0x8D, 0x70,
319    0x82, 0x71, 0xBE, 0x38, 0x30, 0x0C, 0xB5, 0x42, 0x41, 0xD7, 0x99, 0x50,
320    0xF7, 0x7B, 0x06, 0x30, 0x39, 0x80, 0x4F, 0x1D
321};
322
323static const unsigned char bp256_db[] = {
324    0x55, 0xE4, 0x0B, 0xC4, 0x1E, 0x37, 0xE3, 0xE2, 0xAD, 0x25, 0xC3, 0xC6,
325    0x65, 0x45, 0x11, 0xFF, 0xA8, 0x47, 0x4A, 0x91, 0xA0, 0x03, 0x20, 0x87,
326    0x59, 0x38, 0x52, 0xD3, 0xE7, 0xD7, 0x6B, 0xD3
327};
328
329static const unsigned char bp256_Z[] = {
330    0x89, 0xAF, 0xC3, 0x9D, 0x41, 0xD3, 0xB3, 0x27, 0x81, 0x4B, 0x80, 0x94,
331    0x0B, 0x04, 0x25, 0x90, 0xF9, 0x65, 0x56, 0xEC, 0x91, 0xE6, 0xAE, 0x79,
332    0x39, 0xBC, 0xE3, 0x1F, 0x3A, 0x18, 0xBF, 0x2B
333};
334
335static const unsigned char bp384_da[] = {
336    0x1E, 0x20, 0xF5, 0xE0, 0x48, 0xA5, 0x88, 0x6F, 0x1F, 0x15, 0x7C, 0x74,
337    0xE9, 0x1B, 0xDE, 0x2B, 0x98, 0xC8, 0xB5, 0x2D, 0x58, 0xE5, 0x00, 0x3D,
338    0x57, 0x05, 0x3F, 0xC4, 0xB0, 0xBD, 0x65, 0xD6, 0xF1, 0x5E, 0xB5, 0xD1,
339    0xEE, 0x16, 0x10, 0xDF, 0x87, 0x07, 0x95, 0x14, 0x36, 0x27, 0xD0, 0x42
340};
341
342static const unsigned char bp384_db[] = {
343    0x03, 0x26, 0x40, 0xBC, 0x60, 0x03, 0xC5, 0x92, 0x60, 0xF7, 0x25, 0x0C,
344    0x3D, 0xB5, 0x8C, 0xE6, 0x47, 0xF9, 0x8E, 0x12, 0x60, 0xAC, 0xCE, 0x4A,
345    0xCD, 0xA3, 0xDD, 0x86, 0x9F, 0x74, 0xE0, 0x1F, 0x8B, 0xA5, 0xE0, 0x32,
346    0x43, 0x09, 0xDB, 0x6A, 0x98, 0x31, 0x49, 0x7A, 0xBA, 0xC9, 0x66, 0x70
347};
348
349static const unsigned char bp384_Z[] = {
350    0x0B, 0xD9, 0xD3, 0xA7, 0xEA, 0x0B, 0x3D, 0x51, 0x9D, 0x09, 0xD8, 0xE4,
351    0x8D, 0x07, 0x85, 0xFB, 0x74, 0x4A, 0x6B, 0x35, 0x5E, 0x63, 0x04, 0xBC,
352    0x51, 0xC2, 0x29, 0xFB, 0xBC, 0xE2, 0x39, 0xBB, 0xAD, 0xF6, 0x40, 0x37,
353    0x15, 0xC3, 0x5D, 0x4F, 0xB2, 0xA5, 0x44, 0x4F, 0x57, 0x5D, 0x4F, 0x42
354};
355
356static const unsigned char bp512_da[] = {
357    0x16, 0x30, 0x2F, 0xF0, 0xDB, 0xBB, 0x5A, 0x8D, 0x73, 0x3D, 0xAB, 0x71,
358    0x41, 0xC1, 0xB4, 0x5A, 0xCB, 0xC8, 0x71, 0x59, 0x39, 0x67, 0x7F, 0x6A,
359    0x56, 0x85, 0x0A, 0x38, 0xBD, 0x87, 0xBD, 0x59, 0xB0, 0x9E, 0x80, 0x27,
360    0x96, 0x09, 0xFF, 0x33, 0x3E, 0xB9, 0xD4, 0xC0, 0x61, 0x23, 0x1F, 0xB2,
361    0x6F, 0x92, 0xEE, 0xB0, 0x49, 0x82, 0xA5, 0xF1, 0xD1, 0x76, 0x4C, 0xAD,
362    0x57, 0x66, 0x54, 0x22
363};
364
365static const unsigned char bp512_db[] = {
366    0x23, 0x0E, 0x18, 0xE1, 0xBC, 0xC8, 0x8A, 0x36, 0x2F, 0xA5, 0x4E, 0x4E,
367    0xA3, 0x90, 0x20, 0x09, 0x29, 0x2F, 0x7F, 0x80, 0x33, 0x62, 0x4F, 0xD4,
368    0x71, 0xB5, 0xD8, 0xAC, 0xE4, 0x9D, 0x12, 0xCF, 0xAB, 0xBC, 0x19, 0x96,
369    0x3D, 0xAB, 0x8E, 0x2F, 0x1E, 0xBA, 0x00, 0xBF, 0xFB, 0x29, 0xE4, 0xD7,
370    0x2D, 0x13, 0xF2, 0x22, 0x45, 0x62, 0xF4, 0x05, 0xCB, 0x80, 0x50, 0x36,
371    0x66, 0xB2, 0x54, 0x29
372};
373
374static const unsigned char bp512_Z[] = {
375    0xA7, 0x92, 0x70, 0x98, 0x65, 0x5F, 0x1F, 0x99, 0x76, 0xFA, 0x50, 0xA9,
376    0xD5, 0x66, 0x86, 0x5D, 0xC5, 0x30, 0x33, 0x18, 0x46, 0x38, 0x1C, 0x87,
377    0x25, 0x6B, 0xAF, 0x32, 0x26, 0x24, 0x4B, 0x76, 0xD3, 0x64, 0x03, 0xC0,
378    0x24, 0xD7, 0xBB, 0xF0, 0xAA, 0x08, 0x03, 0xEA, 0xFF, 0x40, 0x5D, 0x3D,
379    0x24, 0xF1, 0x1A, 0x9B, 0x5C, 0x0B, 0xEF, 0x67, 0x9F, 0xE1, 0x45, 0x4B,
380    0x21, 0xC4, 0xCD, 0x1F
381};
382
383/* Given private value and NID, create EC_KEY structure */
384
385static EC_KEY *mk_eckey(int nid, const unsigned char *p, size_t plen)
386{
387    int ok = 0;
388    EC_KEY *k = NULL;
389    BIGNUM *priv = NULL;
390    EC_POINT *pub = NULL;
391    const EC_GROUP *grp;
392    k = EC_KEY_new_by_curve_name(nid);
393    if (!k)
394        goto err;
395    priv = BN_bin2bn(p, plen, NULL);
396    if (!priv)
397        goto err;
398    if (!EC_KEY_set_private_key(k, priv))
399        goto err;
400    grp = EC_KEY_get0_group(k);
401    pub = EC_POINT_new(grp);
402    if (!pub)
403        goto err;
404    if (!EC_POINT_mul(grp, pub, priv, NULL, NULL, NULL))
405        goto err;
406    if (!EC_KEY_set_public_key(k, pub))
407        goto err;
408    ok = 1;
409 err:
410    if (priv)
411        BN_clear_free(priv);
412    if (pub)
413        EC_POINT_free(pub);
414    if (ok)
415        return k;
416    else if (k)
417        EC_KEY_free(k);
418    return NULL;
419}
420
421/*
422 * Known answer test: compute shared secret and check it matches expected
423 * value.
424 */
425
426static int ecdh_kat(BIO *out, const char *cname, int nid,
427                    const unsigned char *k1, size_t k1_len,
428                    const unsigned char *k2, size_t k2_len,
429                    const unsigned char *Z, size_t Zlen)
430{
431    int rv = 0;
432    EC_KEY *key1 = NULL, *key2 = NULL;
433    unsigned char *Ztmp = NULL;
434    size_t Ztmplen;
435    BIO_puts(out, "Testing ECDH shared secret with ");
436    BIO_puts(out, cname);
437    key1 = mk_eckey(nid, k1, k1_len);
438    key2 = mk_eckey(nid, k2, k2_len);
439    if (!key1 || !key2)
440        goto err;
441    Ztmplen = (EC_GROUP_get_degree(EC_KEY_get0_group(key1)) + 7) / 8;
442    if (Ztmplen != Zlen)
443        goto err;
444    Ztmp = OPENSSL_malloc(Ztmplen);
445    if (!ECDH_compute_key(Ztmp, Ztmplen,
446                          EC_KEY_get0_public_key(key2), key1, 0))
447        goto err;
448    if (memcmp(Ztmp, Z, Zlen))
449        goto err;
450    memset(Ztmp, 0, Zlen);
451    if (!ECDH_compute_key(Ztmp, Ztmplen,
452                          EC_KEY_get0_public_key(key1), key2, 0))
453        goto err;
454    if (memcmp(Ztmp, Z, Zlen))
455        goto err;
456    rv = 1;
457 err:
458    if (key1)
459        EC_KEY_free(key1);
460    if (key2)
461        EC_KEY_free(key2);
462    if (Ztmp)
463        OPENSSL_free(Ztmp);
464    if (rv)
465        BIO_puts(out, " ok\n");
466    else {
467        fprintf(stderr, "Error in ECDH routines\n");
468        ERR_print_errors_fp(stderr);
469    }
470    return rv;
471}
472
473# define test_ecdh_kat(bio, curve, bits) \
474        ecdh_kat(bio, curve, NID_brainpoolP##bits##r1, \
475                bp##bits##_da, sizeof(bp##bits##_da), \
476                bp##bits##_db, sizeof(bp##bits##_db), \
477                bp##bits##_Z, sizeof(bp##bits##_Z))
478
479int main(int argc, char *argv[])
480{
481    BN_CTX *ctx = NULL;
482    int ret = 1;
483    BIO *out;
484
485    CRYPTO_malloc_debug_init();
486    CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
487    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
488
489# ifdef OPENSSL_SYS_WIN32
490    CRYPTO_malloc_init();
491# endif
492
493    RAND_seed(rnd_seed, sizeof(rnd_seed));
494
495    out = BIO_new(BIO_s_file());
496    if (out == NULL)
497        EXIT(1);
498    BIO_set_fp(out, stdout, BIO_NOCLOSE);
499
500    if ((ctx = BN_CTX_new()) == NULL)
501        goto err;
502
503    /* NIST PRIME CURVES TESTS */
504    if (!test_ecdh_curve
505        (NID_X9_62_prime192v1, "NIST Prime-Curve P-192", ctx, out))
506        goto err;
507    if (!test_ecdh_curve(NID_secp224r1, "NIST Prime-Curve P-224", ctx, out))
508        goto err;
509    if (!test_ecdh_curve
510        (NID_X9_62_prime256v1, "NIST Prime-Curve P-256", ctx, out))
511        goto err;
512    if (!test_ecdh_curve(NID_secp384r1, "NIST Prime-Curve P-384", ctx, out))
513        goto err;
514    if (!test_ecdh_curve(NID_secp521r1, "NIST Prime-Curve P-521", ctx, out))
515        goto err;
516# ifndef OPENSSL_NO_EC2M
517    /* NIST BINARY CURVES TESTS */
518    if (!test_ecdh_curve(NID_sect163k1, "NIST Binary-Curve K-163", ctx, out))
519        goto err;
520    if (!test_ecdh_curve(NID_sect163r2, "NIST Binary-Curve B-163", ctx, out))
521        goto err;
522    if (!test_ecdh_curve(NID_sect233k1, "NIST Binary-Curve K-233", ctx, out))
523        goto err;
524    if (!test_ecdh_curve(NID_sect233r1, "NIST Binary-Curve B-233", ctx, out))
525        goto err;
526    if (!test_ecdh_curve(NID_sect283k1, "NIST Binary-Curve K-283", ctx, out))
527        goto err;
528    if (!test_ecdh_curve(NID_sect283r1, "NIST Binary-Curve B-283", ctx, out))
529        goto err;
530    if (!test_ecdh_curve(NID_sect409k1, "NIST Binary-Curve K-409", ctx, out))
531        goto err;
532    if (!test_ecdh_curve(NID_sect409r1, "NIST Binary-Curve B-409", ctx, out))
533        goto err;
534    if (!test_ecdh_curve(NID_sect571k1, "NIST Binary-Curve K-571", ctx, out))
535        goto err;
536    if (!test_ecdh_curve(NID_sect571r1, "NIST Binary-Curve B-571", ctx, out))
537        goto err;
538# endif
539    if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP256r1", 256))
540        goto err;
541    if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP384r1", 384))
542        goto err;
543    if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP512r1", 512))
544        goto err;
545
546    ret = 0;
547
548 err:
549    ERR_print_errors_fp(stderr);
550    if (ctx)
551        BN_CTX_free(ctx);
552    BIO_free(out);
553    CRYPTO_cleanup_all_ex_data();
554    ERR_remove_thread_state(NULL);
555    CRYPTO_mem_leaks_fp(stderr);
556    EXIT(ret);
557    return (ret);
558}
559
560# if 0
561static void MS_CALLBACK cb(int p, int n, void *arg)
562{
563    char c = '*';
564
565    if (p == 0)
566        c = '.';
567    if (p == 1)
568        c = '+';
569    if (p == 2)
570        c = '*';
571    if (p == 3)
572        c = '\n';
573    BIO_write((BIO *)arg, &c, 1);
574    (void)BIO_flush((BIO *)arg);
575#  ifdef LINT
576    p = n;
577#  endif
578}
579# endif
580#endif
581