c456b67b01c9833a262dd3915dfc5e7cd4ef2faa
[openssl.git] / crypto / asn1 / t_pkey.c
1 /* crypto/asn1/t_pkey.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include <openssl/objects.h>
62 #include <openssl/buffer.h>
63 #include <openssl/bn.h>
64 #ifndef OPENSSL_NO_RSA
65 #include <openssl/rsa.h>
66 #endif
67 #ifndef OPENSSL_NO_DH
68 #include <openssl/dh.h>
69 #endif
70 #ifndef OPENSSL_NO_DSA
71 #include <openssl/dsa.h>
72 #endif
73 #ifndef OPENSSL_NO_ECDSA
74 #include <openssl/ecdsa.h>
75 #endif
76
77 static int print(BIO *fp,const char *str,BIGNUM *num,
78                 unsigned char *buf,int off);
79 #ifndef OPENSSL_NO_RSA
80 #ifndef OPENSSL_NO_FP_API
81 int RSA_print_fp(FILE *fp, const RSA *x, int off)
82         {
83         BIO *b;
84         int ret;
85
86         if ((b=BIO_new(BIO_s_file())) == NULL)
87                 {
88                 RSAerr(RSA_F_RSA_PRINT_FP,ERR_R_BUF_LIB);
89                 return(0);
90                 }
91         BIO_set_fp(b,fp,BIO_NOCLOSE);
92         ret=RSA_print(b,x,off);
93         BIO_free(b);
94         return(ret);
95         }
96 #endif
97
98 int RSA_print(BIO *bp, const RSA *x, int off)
99         {
100         char str[128];
101         const char *s;
102         unsigned char *m=NULL;
103         int i,ret=0;
104
105         i=RSA_size(x);
106         m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10);
107         if (m == NULL)
108                 {
109                 RSAerr(RSA_F_RSA_PRINT,ERR_R_MALLOC_FAILURE);
110                 goto err;
111                 }
112
113         if (off)
114                 {
115                 if (off > 128) off=128;
116                 memset(str,' ',off);
117                 }
118         if (x->d != NULL)
119                 {
120                 if (off && (BIO_write(bp,str,off) <= 0)) goto err;
121                 if (BIO_printf(bp,"Private-Key: (%d bit)\n",BN_num_bits(x->n))
122                         <= 0) goto err;
123                 }
124
125         if (x->d == NULL)
126                 sprintf(str,"Modulus (%d bit):",BN_num_bits(x->n));
127         else
128                 strcpy(str,"modulus:");
129         if (!print(bp,str,x->n,m,off)) goto err;
130         s=(x->d == NULL)?"Exponent:":"publicExponent:";
131         if (!print(bp,s,x->e,m,off)) goto err;
132         if (!print(bp,"privateExponent:",x->d,m,off)) goto err;
133         if (!print(bp,"prime1:",x->p,m,off)) goto err;
134         if (!print(bp,"prime2:",x->q,m,off)) goto err;
135         if (!print(bp,"exponent1:",x->dmp1,m,off)) goto err;
136         if (!print(bp,"exponent2:",x->dmq1,m,off)) goto err;
137         if (!print(bp,"coefficient:",x->iqmp,m,off)) goto err;
138         ret=1;
139 err:
140         if (m != NULL) OPENSSL_free(m);
141         return(ret);
142         }
143 #endif /* OPENSSL_NO_RSA */
144
145 #ifndef OPENSSL_NO_DSA
146 #ifndef OPENSSL_NO_FP_API
147 int DSA_print_fp(FILE *fp, const DSA *x, int off)
148         {
149         BIO *b;
150         int ret;
151
152         if ((b=BIO_new(BIO_s_file())) == NULL)
153                 {
154                 DSAerr(DSA_F_DSA_PRINT_FP,ERR_R_BUF_LIB);
155                 return(0);
156                 }
157         BIO_set_fp(b,fp,BIO_NOCLOSE);
158         ret=DSA_print(b,x,off);
159         BIO_free(b);
160         return(ret);
161         }
162 #endif
163
164 int DSA_print(BIO *bp, const DSA *x, int off)
165         {
166         char str[128];
167         unsigned char *m=NULL;
168         int i,ret=0;
169         BIGNUM *bn=NULL;
170
171         if (x->p != NULL)
172                 bn=x->p;
173         else if (x->priv_key != NULL)
174                 bn=x->priv_key;
175         else if (x->pub_key != NULL)
176                 bn=x->pub_key;
177                 
178         /* larger than needed but what the hell :-) */
179         if (bn != NULL)
180                 i=BN_num_bytes(bn)*2;
181         else
182                 i=256;
183         m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10);
184         if (m == NULL)
185                 {
186                 DSAerr(DSA_F_DSA_PRINT,ERR_R_MALLOC_FAILURE);
187                 goto err;
188                 }
189
190         if (off)
191                 {
192                 if (off > 128) off=128;
193                 memset(str,' ',off);
194                 }
195         if (x->priv_key != NULL)
196                 {
197                 if (off && (BIO_write(bp,str,off) <= 0)) goto err;
198                 if (BIO_printf(bp,"Private-Key: (%d bit)\n",BN_num_bits(x->p))
199                         <= 0) goto err;
200                 }
201
202         if ((x->priv_key != NULL) && !print(bp,"priv:",x->priv_key,m,off))
203                 goto err;
204         if ((x->pub_key  != NULL) && !print(bp,"pub: ",x->pub_key,m,off))
205                 goto err;
206         if ((x->p != NULL) && !print(bp,"P:   ",x->p,m,off)) goto err;
207         if ((x->q != NULL) && !print(bp,"Q:   ",x->q,m,off)) goto err;
208         if ((x->g != NULL) && !print(bp,"G:   ",x->g,m,off)) goto err;
209         ret=1;
210 err:
211         if (m != NULL) OPENSSL_free(m);
212         return(ret);
213         }
214 #endif /* !OPENSSL_NO_DSA */
215
216 #ifndef OPENSSL_NO_EC
217 #ifndef OPENSSL_NO_FP_API
218 int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off)
219         {
220         BIO *b;
221         int ret;
222
223         if ((b=BIO_new(BIO_s_file())) == NULL)
224                 {
225                 ECerr(EC_F_ECPKPARAMETERS_PRINT_FP,ERR_R_BUF_LIB);
226                 return(0);
227                 }
228         BIO_set_fp(b, fp, BIO_NOCLOSE);
229         ret = ECPKParameters_print(b, x, off);
230         BIO_free(b);
231         return(ret);
232         }
233 #endif
234
235 int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
236         {
237         char str[128];
238         unsigned char *buffer=NULL;
239         size_t  buf_len=0, i;
240         int     ret=0, reason=ERR_R_BIO_LIB;
241         BN_CTX  *ctx=NULL;
242         EC_POINT *point=NULL;
243         BIGNUM  *p=NULL, *a=NULL, *b=NULL, *gen=NULL,
244                 *order=NULL, *cofactor=NULL, *seed=NULL;
245         
246         static const char *gen_compressed = "Generator (compressed):";
247         static const char *gen_uncompressed = "Generator (uncompressed):";
248         static const char *gen_hybrid = "Generator (hybrid):";
249  
250         if (!x)
251                 {
252                 reason = ERR_R_PASSED_NULL_PARAMETER;
253                 goto err;
254                 }
255
256         if (EC_GROUP_get_asn1_flag(x))
257                 {
258                 /* the curve parameter are given by an asn1 OID */
259                 int nid;
260
261                 if (off)
262                         {
263                         if (off > 128)
264                                 off=128;
265                         memset(str, ' ', off);
266                         if (BIO_write(bp, str, off) <= 0)
267                                 goto err;
268                         }
269
270                 nid = EC_GROUP_get_nid(x);
271                 if (nid == 0)
272                         goto err;
273
274                 if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0)
275                         goto err;
276                 if (BIO_printf(bp, "\n") <= 0)
277                         goto err;
278                 }
279         else
280                 {
281                 /* explicit parameters */
282                 /* TODO */
283                 point_conversion_form_t form;
284
285                 if ((p = BN_new()) == NULL || (a = BN_new()) == NULL ||
286                         (b = BN_new()) == NULL || (order = BN_new()) == NULL ||
287                         (cofactor = BN_new()) == NULL)
288                         {
289                         reason = ERR_R_MALLOC_FAILURE;
290                         goto err;
291                         }
292
293                 if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx))
294                         {
295                         reason = ERR_R_EC_LIB;
296                         goto err;
297                         }
298
299                 if ((point = EC_GROUP_get0_generator(x)) == NULL)
300                         {
301                         reason = ERR_R_EC_LIB;
302                         goto err;
303                         }
304                 if (!EC_GROUP_get_order(x, order, NULL) || 
305                         !EC_GROUP_get_cofactor(x, cofactor, NULL))
306                         {
307                         reason = ERR_R_EC_LIB;
308                         goto err;
309                         }
310                 
311                 form = EC_GROUP_get_point_conversion_form(x);
312
313                 if ((gen = EC_POINT_point2bn(x, point, 
314                                 form, NULL, ctx)) == NULL)
315                         {
316                         reason = ERR_R_EC_LIB;
317                         goto err;
318                         }
319
320                 buf_len = (size_t)BN_num_bytes(p);
321                 if (buf_len < (i = (size_t)BN_num_bytes(a)))
322                         buf_len = i;
323                 if (buf_len < (i = (size_t)BN_num_bytes(b)))
324                         buf_len = i;
325                 if (buf_len < (i = (size_t)BN_num_bytes(gen)))
326                         buf_len = i;
327                 if (buf_len < (i = (size_t)BN_num_bytes(order)))
328                         buf_len = i;
329                 if (buf_len < (i = (size_t)BN_num_bytes(cofactor))) 
330                         buf_len = i;
331
332                 if (EC_GROUP_get0_seed(x))
333                         {
334                         seed = BN_bin2bn(EC_GROUP_get0_seed(x),
335                                 EC_GROUP_get_seed_len(x), NULL);
336                         if (seed == NULL)
337                                 {
338                                 reason = ERR_R_BN_LIB;
339                                 goto err;
340                                 }
341                         if (buf_len < (i = (size_t)BN_num_bytes(seed))) 
342                                 buf_len = i;
343                         }
344
345                 buf_len += 10;
346                 if ((buffer = OPENSSL_malloc(buf_len)) == NULL)
347                         {
348                         reason = ERR_R_MALLOC_FAILURE;
349                         goto err;
350                         }
351                 if (off)
352                         {
353                         if (off > 128) off=128;
354                         memset(str,' ',off);
355                         }
356   
357                 if ((p != NULL) && !print(bp, "P:   ", p, buffer, off)) 
358                         goto err;
359                 if ((a != NULL) && !print(bp, "A:   ", a, buffer, off)) 
360                         goto err;
361                 if ((b != NULL) && !print(bp, "B:   ", b, buffer, off))
362                         goto err;
363                 if (form == POINT_CONVERSION_COMPRESSED)
364                         {
365                         if ((gen != NULL) && !print(bp, gen_compressed, gen,
366                                 buffer, off))
367                                 goto err;
368                         }
369                 else if (form == POINT_CONVERSION_UNCOMPRESSED)
370                         {
371                         if ((gen != NULL) && !print(bp, gen_uncompressed, gen,
372                                 buffer, off))
373                                 goto err;
374                         }
375                 else /* form == POINT_CONVERSION_HYBRID */
376                         {
377                         if ((gen != NULL) && !print(bp, gen_hybrid, gen,
378                                 buffer, off))
379                                 goto err;
380                         }
381                 if ((order != NULL) && !print(bp, "Order: ", order, 
382                         buffer, off)) goto err;
383                 if ((cofactor != NULL) && !print(bp, "Cofactor: ", cofactor, 
384                         buffer, off)) goto err;
385                 if ((seed != NULL) && !print(bp, "Seed:", seed, 
386                         buffer, off)) goto err;
387                 }
388         ret=1;
389 err:
390         if (!ret)
391                 ECerr(EC_F_ECPKPARAMETERS_PRINT, reason);
392         if (p) 
393                 BN_free(p);
394         if (a) 
395                 BN_free(a);
396         if (b)
397                 BN_free(b);
398         if (gen)
399                 BN_free(gen);
400         if (order)
401                 BN_free(order);
402         if (cofactor)
403                 BN_free(cofactor);
404         if (seed) 
405                 BN_free(seed);
406         if (ctx)
407                 BN_CTX_free(ctx);
408         if (buffer != NULL) 
409                 OPENSSL_free(buffer);
410         return(ret);    
411         }
412 #endif /* OPENSSL_NO_EC */
413
414
415 #ifndef OPENSSL_NO_ECDSA
416 #ifndef OPENSSL_NO_FP_API
417 int ECDSA_print_fp(FILE *fp, const ECDSA *x, int off)
418 {
419         BIO *b;
420         int ret;
421  
422         if ((b=BIO_new(BIO_s_file())) == NULL)
423         {
424                 ECDSAerr(ECDSA_F_ECDSA_PRINT_FP, ERR_R_BIO_LIB);
425                 return(0);
426         }
427         BIO_set_fp(b, fp, BIO_NOCLOSE);
428         ret = ECDSA_print(b, x, off);
429         BIO_free(b);
430         return(ret);
431 }
432 #endif
433
434 int ECDSA_print(BIO *bp, const ECDSA *x, int off)
435         {
436         char str[128];
437         unsigned char *buffer=NULL;
438         size_t  buf_len=0, i;
439         int     ret=0, reason=ERR_R_BIO_LIB;
440         BIGNUM  *pub_key=NULL;
441         BN_CTX  *ctx=NULL;
442  
443         if (!x || !x->group)
444                 {
445                 reason = ERR_R_PASSED_NULL_PARAMETER;
446                 goto err;
447                 }
448
449         if ((pub_key = EC_POINT_point2bn(x->group, x->pub_key,
450                 ECDSA_get_conversion_form(x), NULL, ctx)) == NULL)
451                 {
452                 reason = ERR_R_EC_LIB;
453                 goto err;
454                 }
455
456         buf_len = (size_t)BN_num_bytes(pub_key);
457         if (x->priv_key)
458                 {
459                 if ((i = (size_t)BN_num_bytes(x->priv_key)) > buf_len)
460                         buf_len = i;
461                 }
462
463         buf_len += 10;
464         if ((buffer = OPENSSL_malloc(buf_len)) == NULL)
465                 {
466                 reason = ERR_R_MALLOC_FAILURE;
467                 goto err;
468                 }
469         if (off)
470                 {
471                 if (off > 128) off=128;
472                 memset(str,' ',off);
473                 }
474         if (x->priv_key != NULL)
475                 {
476                 if (off && (BIO_write(bp, str, off) <= 0)) goto err;
477                 if (BIO_printf(bp, "Private-Key: (%d bit)\n", 
478                         BN_num_bits(x->priv_key)) <= 0) goto err;
479                 }
480   
481         if ((x->priv_key != NULL) && !print(bp, "priv:", x->priv_key, 
482                 buffer, off))
483                 goto err;
484         if ((pub_key != NULL) && !print(bp, "pub: ", pub_key,
485                 buffer, off))
486                 goto err;
487         if (!ECPKParameters_print(bp, x->group, off))
488                 goto err;
489         ret=1;
490 err:
491         if (!ret)
492                 ECDSAerr(ECDSA_F_ECDSA_PRINT, reason);
493         if (pub_key) 
494                 BN_free(pub_key);
495         if (ctx)
496                 BN_CTX_free(ctx);
497         if (buffer != NULL)
498                 OPENSSL_free(buffer);
499         return(ret);
500         }
501 #endif
502
503 static int print(BIO *bp, const char *number, BIGNUM *num, unsigned char *buf,
504              int off)
505         {
506         int n,i;
507         char str[128];
508         const char *neg;
509
510         if (num == NULL) return(1);
511         neg=(num->neg)?"-":"";
512         if (off)
513                 {
514                 if (off > 128) off=128;
515                 memset(str,' ',off);
516                 if (BIO_write(bp,str,off) <= 0) return(0);
517                 }
518
519         if (BN_num_bytes(num) <= BN_BYTES)
520                 {
521                 if (BIO_printf(bp,"%s %s%lu (%s0x%lx)\n",number,neg,
522                         (unsigned long)num->d[0],neg,(unsigned long)num->d[0])
523                         <= 0) return(0);
524                 }
525         else
526                 {
527                 buf[0]=0;
528                 if (BIO_printf(bp,"%s%s",number,
529                         (neg[0] == '-')?" (Negative)":"") <= 0)
530                         return(0);
531                 n=BN_bn2bin(num,&buf[1]);
532         
533                 if (buf[1] & 0x80)
534                         n++;
535                 else    buf++;
536
537                 for (i=0; i<n; i++)
538                         {
539                         if ((i%15) == 0)
540                                 {
541                                 str[0]='\n';
542                                 memset(&(str[1]),' ',off+4);
543                                 if (BIO_write(bp,str,off+1+4) <= 0) return(0);
544                                 }
545                         if (BIO_printf(bp,"%02x%s",buf[i],((i+1) == n)?"":":")
546                                 <= 0) return(0);
547                         }
548                 if (BIO_write(bp,"\n",1) <= 0) return(0);
549                 }
550         return(1);
551         }
552
553 #ifndef OPENSSL_NO_DH
554 #ifndef OPENSSL_NO_FP_API
555 int DHparams_print_fp(FILE *fp, const DH *x)
556         {
557         BIO *b;
558         int ret;
559
560         if ((b=BIO_new(BIO_s_file())) == NULL)
561                 {
562                 DHerr(DH_F_DHPARAMS_PRINT_FP,ERR_R_BUF_LIB);
563                 return(0);
564                 }
565         BIO_set_fp(b,fp,BIO_NOCLOSE);
566         ret=DHparams_print(b, x);
567         BIO_free(b);
568         return(ret);
569         }
570 #endif
571
572 int DHparams_print(BIO *bp, const DH *x)
573         {
574         unsigned char *m=NULL;
575         int reason=ERR_R_BUF_LIB,i,ret=0;
576
577         i=BN_num_bytes(x->p);
578         m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10);
579         if (m == NULL)
580                 {
581                 reason=ERR_R_MALLOC_FAILURE;
582                 goto err;
583                 }
584
585         if (BIO_printf(bp,"Diffie-Hellman-Parameters: (%d bit)\n",
586                 BN_num_bits(x->p)) <= 0)
587                 goto err;
588         if (!print(bp,"prime:",x->p,m,4)) goto err;
589         if (!print(bp,"generator:",x->g,m,4)) goto err;
590         if (x->length != 0)
591                 {
592                 if (BIO_printf(bp,"    recommended-private-length: %d bits\n",
593                         (int)x->length) <= 0) goto err;
594                 }
595         ret=1;
596         if (0)
597                 {
598 err:
599                 DHerr(DH_F_DHPARAMS_PRINT,reason);
600                 }
601         if (m != NULL) OPENSSL_free(m);
602         return(ret);
603         }
604 #endif
605
606 #ifndef OPENSSL_NO_DSA
607 #ifndef OPENSSL_NO_FP_API
608 int DSAparams_print_fp(FILE *fp, const DSA *x)
609         {
610         BIO *b;
611         int ret;
612
613         if ((b=BIO_new(BIO_s_file())) == NULL)
614                 {
615                 DSAerr(DSA_F_DSAPARAMS_PRINT_FP,ERR_R_BUF_LIB);
616                 return(0);
617                 }
618         BIO_set_fp(b,fp,BIO_NOCLOSE);
619         ret=DSAparams_print(b, x);
620         BIO_free(b);
621         return(ret);
622         }
623 #endif
624
625 int DSAparams_print(BIO *bp, const DSA *x)
626         {
627         unsigned char *m=NULL;
628         int reason=ERR_R_BUF_LIB,i,ret=0;
629
630         i=BN_num_bytes(x->p);
631         m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10);
632         if (m == NULL)
633                 {
634                 reason=ERR_R_MALLOC_FAILURE;
635                 goto err;
636                 }
637
638         if (BIO_printf(bp,"DSA-Parameters: (%d bit)\n",
639                 BN_num_bits(x->p)) <= 0)
640                 goto err;
641         if (!print(bp,"p:",x->p,m,4)) goto err;
642         if (!print(bp,"q:",x->q,m,4)) goto err;
643         if (!print(bp,"g:",x->g,m,4)) goto err;
644         ret=1;
645 err:
646         if (m != NULL) OPENSSL_free(m);
647         DSAerr(DSA_F_DSAPARAMS_PRINT,reason);
648         return(ret);
649         }
650
651 #endif /* !OPENSSL_NO_DSA */
652
653 #ifndef OPENSSL_NO_ECDSA
654 #ifndef OPENSSL_NO_FP_API
655 int ECDSAParameters_print_fp(FILE *fp, const ECDSA *x)
656         {
657         BIO *b;
658         int ret;
659  
660         if ((b=BIO_new(BIO_s_file())) == NULL)
661         {
662                 ECDSAerr(ECDSA_F_ECDSAPARAMETERS_PRINT_FP, ERR_R_BIO_LIB);
663                 return(0);
664         }
665         BIO_set_fp(b, fp, BIO_NOCLOSE);
666         ret = ECDSAParameters_print(b, x);
667         BIO_free(b);
668         return(ret);
669         }
670 #endif
671
672 int ECDSAParameters_print(BIO *bp, const ECDSA *x)
673         {
674         int     reason=ERR_R_EC_LIB, ret=0;
675         BIGNUM  *order=NULL;
676  
677         if (!x || !x->group)
678                 {
679                 reason = ERR_R_PASSED_NULL_PARAMETER;;
680                 goto err;
681                 }
682
683         if ((order = BN_new()) == NULL)
684                 {
685                 reason = ERR_R_MALLOC_FAILURE;
686                 goto err;
687                 }
688
689         if (!EC_GROUP_get_order(x->group, order, NULL))
690                 {
691                 reason = ERR_R_EC_LIB;
692                 goto err;
693                 }
694  
695         if (BIO_printf(bp, "ECDSA-Parameters: (%d bit)\n", 
696                 BN_num_bits(order)) <= 0)
697                 goto err;
698         if (!ECPKParameters_print(bp, x->group, 4))
699                 goto err;
700         ret=1;
701 err:
702         if (order)
703                 BN_free(order);
704         ECDSAerr(ECDSA_F_ECDSAPARAMETERS_PRINT, reason);
705         return(ret);
706         }
707   
708 #endif