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