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 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Binary polynomial ECC support in OpenSSL originally developed by
61 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62 */
63
64#include <stdio.h>
65#include "cryptlib.h"
66#include <openssl/objects.h>
67#include <openssl/buffer.h>
68#include <openssl/bn.h>
69#ifndef OPENSSL_NO_RSA
70#include <openssl/rsa.h>
71#endif
72#ifndef OPENSSL_NO_DH
73#include <openssl/dh.h>
74#endif
75#ifndef OPENSSL_NO_DSA
76#include <openssl/dsa.h>
77#endif
78#ifndef OPENSSL_NO_EC
79#include <openssl/ec.h>
80#endif
81
82static int print(BIO *fp,const char *str, const BIGNUM *num,
83		unsigned char *buf,int off);
84#ifndef OPENSSL_NO_EC
85static int print_bin(BIO *fp, const char *str, const unsigned char *num,
86		size_t len, int off);
87#endif
88#ifndef OPENSSL_NO_RSA
89#ifndef OPENSSL_NO_FP_API
90int RSA_print_fp(FILE *fp, const RSA *x, int off)
91	{
92	BIO *b;
93	int ret;
94
95	if ((b=BIO_new(BIO_s_file())) == NULL)
96		{
97		RSAerr(RSA_F_RSA_PRINT_FP,ERR_R_BUF_LIB);
98		return(0);
99		}
100	BIO_set_fp(b,fp,BIO_NOCLOSE);
101	ret=RSA_print(b,x,off);
102	BIO_free(b);
103	return(ret);
104	}
105#endif
106
107int RSA_print(BIO *bp, const RSA *x, int off)
108	{
109	char str[128];
110	const char *s;
111	unsigned char *m=NULL;
112	int ret=0, mod_len = 0;
113	size_t buf_len=0, i;
114
115	if (x->n)
116		buf_len = (size_t)BN_num_bytes(x->n);
117	if (x->e)
118		if (buf_len < (i = (size_t)BN_num_bytes(x->e)))
119			buf_len = i;
120	if (x->d)
121		if (buf_len < (i = (size_t)BN_num_bytes(x->d)))
122			buf_len = i;
123	if (x->p)
124		if (buf_len < (i = (size_t)BN_num_bytes(x->p)))
125			buf_len = i;
126	if (x->q)
127		if (buf_len < (i = (size_t)BN_num_bytes(x->q)))
128			buf_len = i;
129	if (x->dmp1)
130		if (buf_len < (i = (size_t)BN_num_bytes(x->dmp1)))
131			buf_len = i;
132	if (x->dmq1)
133		if (buf_len < (i = (size_t)BN_num_bytes(x->dmq1)))
134			buf_len = i;
135	if (x->iqmp)
136		if (buf_len < (i = (size_t)BN_num_bytes(x->iqmp)))
137			buf_len = i;
138
139	m=(unsigned char *)OPENSSL_malloc(buf_len+10);
140	if (m == NULL)
141		{
142		RSAerr(RSA_F_RSA_PRINT,ERR_R_MALLOC_FAILURE);
143		goto err;
144		}
145
146	if (x->n != NULL)
147		mod_len = BN_num_bits(x->n);
148
149	if (x->d != NULL)
150		{
151		if(!BIO_indent(bp,off,128))
152		   goto err;
153		if (BIO_printf(bp,"Private-Key: (%d bit)\n", mod_len)
154			<= 0) goto err;
155		}
156
157	if (x->d == NULL)
158		BIO_snprintf(str,sizeof str,"Modulus (%d bit):", mod_len);
159	else
160		BUF_strlcpy(str,"modulus:",sizeof str);
161	if (!print(bp,str,x->n,m,off)) goto err;
162	s=(x->d == NULL)?"Exponent:":"publicExponent:";
163	if ((x->e != NULL) && !print(bp,s,x->e,m,off))
164		goto err;
165	if ((x->d != NULL) && !print(bp,"privateExponent:",x->d,m,off))
166		goto err;
167	if ((x->p != NULL) && !print(bp,"prime1:",x->p,m,off))
168		goto err;
169	if ((x->q != NULL) && !print(bp,"prime2:",x->q,m,off))
170		goto err;
171	if ((x->dmp1 != NULL) && !print(bp,"exponent1:",x->dmp1,m,off))
172		goto err;
173	if ((x->dmq1 != NULL) && !print(bp,"exponent2:",x->dmq1,m,off))
174		goto err;
175	if ((x->iqmp != NULL) && !print(bp,"coefficient:",x->iqmp,m,off))
176		goto err;
177	ret=1;
178err:
179	if (m != NULL) OPENSSL_free(m);
180	return(ret);
181	}
182#endif /* OPENSSL_NO_RSA */
183
184#ifndef OPENSSL_NO_DSA
185#ifndef OPENSSL_NO_FP_API
186int DSA_print_fp(FILE *fp, const DSA *x, int off)
187	{
188	BIO *b;
189	int ret;
190
191	if ((b=BIO_new(BIO_s_file())) == NULL)
192		{
193		DSAerr(DSA_F_DSA_PRINT_FP,ERR_R_BUF_LIB);
194		return(0);
195		}
196	BIO_set_fp(b,fp,BIO_NOCLOSE);
197	ret=DSA_print(b,x,off);
198	BIO_free(b);
199	return(ret);
200	}
201#endif
202
203int DSA_print(BIO *bp, const DSA *x, int off)
204	{
205	unsigned char *m=NULL;
206	int ret=0;
207	size_t buf_len=0,i;
208
209	if (x->p)
210		buf_len = (size_t)BN_num_bytes(x->p);
211	if (x->q)
212		if (buf_len < (i = (size_t)BN_num_bytes(x->q)))
213			buf_len = i;
214	if (x->g)
215		if (buf_len < (i = (size_t)BN_num_bytes(x->g)))
216			buf_len = i;
217	if (x->priv_key)
218		if (buf_len < (i = (size_t)BN_num_bytes(x->priv_key)))
219			buf_len = i;
220	if (x->pub_key)
221		if (buf_len < (i = (size_t)BN_num_bytes(x->pub_key)))
222			buf_len = i;
223
224	m=(unsigned char *)OPENSSL_malloc(buf_len+10);
225	if (m == NULL)
226		{
227		DSAerr(DSA_F_DSA_PRINT,ERR_R_MALLOC_FAILURE);
228		goto err;
229		}
230
231	if (x->priv_key != NULL)
232		{
233		if(!BIO_indent(bp,off,128))
234		   goto err;
235		if (BIO_printf(bp,"Private-Key: (%d bit)\n",BN_num_bits(x->p))
236			<= 0) goto err;
237		}
238
239	if ((x->priv_key != NULL) && !print(bp,"priv:",x->priv_key,m,off))
240		goto err;
241	if ((x->pub_key  != NULL) && !print(bp,"pub: ",x->pub_key,m,off))
242		goto err;
243	if ((x->p != NULL) && !print(bp,"P:   ",x->p,m,off)) goto err;
244	if ((x->q != NULL) && !print(bp,"Q:   ",x->q,m,off)) goto err;
245	if ((x->g != NULL) && !print(bp,"G:   ",x->g,m,off)) goto err;
246	ret=1;
247err:
248	if (m != NULL) OPENSSL_free(m);
249	return(ret);
250	}
251#endif /* !OPENSSL_NO_DSA */
252
253#ifndef OPENSSL_NO_EC
254#ifndef OPENSSL_NO_FP_API
255int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off)
256	{
257	BIO *b;
258	int ret;
259
260	if ((b=BIO_new(BIO_s_file())) == NULL)
261		{
262		ECerr(EC_F_ECPKPARAMETERS_PRINT_FP,ERR_R_BUF_LIB);
263		return(0);
264		}
265	BIO_set_fp(b, fp, BIO_NOCLOSE);
266	ret = ECPKParameters_print(b, x, off);
267	BIO_free(b);
268	return(ret);
269	}
270
271int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off)
272	{
273	BIO *b;
274	int ret;
275
276	if ((b=BIO_new(BIO_s_file())) == NULL)
277		{
278		ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB);
279		return(0);
280		}
281	BIO_set_fp(b, fp, BIO_NOCLOSE);
282	ret = EC_KEY_print(b, x, off);
283	BIO_free(b);
284	return(ret);
285	}
286#endif
287
288int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
289	{
290	unsigned char *buffer=NULL;
291	size_t	buf_len=0, i;
292	int     ret=0, reason=ERR_R_BIO_LIB;
293	BN_CTX  *ctx=NULL;
294	const EC_POINT *point=NULL;
295	BIGNUM	*p=NULL, *a=NULL, *b=NULL, *gen=NULL,
296		*order=NULL, *cofactor=NULL;
297	const unsigned char *seed;
298	size_t	seed_len=0;
299
300	static const char *gen_compressed = "Generator (compressed):";
301	static const char *gen_uncompressed = "Generator (uncompressed):";
302	static const char *gen_hybrid = "Generator (hybrid):";
303
304	if (!x)
305		{
306		reason = ERR_R_PASSED_NULL_PARAMETER;
307		goto err;
308		}
309
310	if (EC_GROUP_get_asn1_flag(x))
311		{
312		/* the curve parameter are given by an asn1 OID */
313		int nid;
314
315		if (!BIO_indent(bp, off, 128))
316			goto err;
317
318		nid = EC_GROUP_get_curve_name(x);
319		if (nid == 0)
320			goto err;
321
322		if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0)
323			goto err;
324		if (BIO_printf(bp, "\n") <= 0)
325			goto err;
326		}
327	else
328		{
329		/* explicit parameters */
330		int is_char_two = 0;
331		point_conversion_form_t form;
332		int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x));
333
334		if (tmp_nid == NID_X9_62_characteristic_two_field)
335			is_char_two = 1;
336
337		if ((p = BN_new()) == NULL || (a = BN_new()) == NULL ||
338			(b = BN_new()) == NULL || (order = BN_new()) == NULL ||
339			(cofactor = BN_new()) == NULL)
340			{
341			reason = ERR_R_MALLOC_FAILURE;
342			goto err;
343			}
344
345		if (is_char_two)
346			{
347			if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx))
348				{
349				reason = ERR_R_EC_LIB;
350				goto err;
351				}
352			}
353		else /* prime field */
354			{
355			if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx))
356				{
357				reason = ERR_R_EC_LIB;
358				goto err;
359				}
360			}
361
362		if ((point = EC_GROUP_get0_generator(x)) == NULL)
363			{
364			reason = ERR_R_EC_LIB;
365			goto err;
366			}
367		if (!EC_GROUP_get_order(x, order, NULL) ||
368            		!EC_GROUP_get_cofactor(x, cofactor, NULL))
369			{
370			reason = ERR_R_EC_LIB;
371			goto err;
372			}
373
374		form = EC_GROUP_get_point_conversion_form(x);
375
376		if ((gen = EC_POINT_point2bn(x, point,
377				form, NULL, ctx)) == NULL)
378			{
379			reason = ERR_R_EC_LIB;
380			goto err;
381			}
382
383		buf_len = (size_t)BN_num_bytes(p);
384		if (buf_len < (i = (size_t)BN_num_bytes(a)))
385			buf_len = i;
386		if (buf_len < (i = (size_t)BN_num_bytes(b)))
387			buf_len = i;
388		if (buf_len < (i = (size_t)BN_num_bytes(gen)))
389			buf_len = i;
390		if (buf_len < (i = (size_t)BN_num_bytes(order)))
391			buf_len = i;
392		if (buf_len < (i = (size_t)BN_num_bytes(cofactor)))
393			buf_len = i;
394
395		if ((seed = EC_GROUP_get0_seed(x)) != NULL)
396			seed_len = EC_GROUP_get_seed_len(x);
397
398		buf_len += 10;
399		if ((buffer = OPENSSL_malloc(buf_len)) == NULL)
400			{
401			reason = ERR_R_MALLOC_FAILURE;
402			goto err;
403			}
404
405		if (!BIO_indent(bp, off, 128))
406			goto err;
407
408		/* print the 'short name' of the field type */
409		if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid))
410			<= 0)
411			goto err;
412
413		if (is_char_two)
414			{
415			/* print the 'short name' of the base type OID */
416			int basis_type = EC_GROUP_get_basis_type(x);
417			if (basis_type == 0)
418				goto err;
419
420			if (!BIO_indent(bp, off, 128))
421				goto err;
422
423			if (BIO_printf(bp, "Basis Type: %s\n",
424				OBJ_nid2sn(basis_type)) <= 0)
425				goto err;
426
427			/* print the polynomial */
428			if ((p != NULL) && !print(bp, "Polynomial:", p, buffer,
429				off))
430				goto err;
431			}
432		else
433			{
434			if ((p != NULL) && !print(bp, "Prime:", p, buffer,off))
435				goto err;
436			}
437		if ((a != NULL) && !print(bp, "A:   ", a, buffer, off))
438			goto err;
439		if ((b != NULL) && !print(bp, "B:   ", b, buffer, off))
440			goto err;
441		if (form == POINT_CONVERSION_COMPRESSED)
442			{
443			if ((gen != NULL) && !print(bp, gen_compressed, gen,
444				buffer, off))
445				goto err;
446			}
447		else if (form == POINT_CONVERSION_UNCOMPRESSED)
448			{
449			if ((gen != NULL) && !print(bp, gen_uncompressed, gen,
450				buffer, off))
451				goto err;
452			}
453		else /* form == POINT_CONVERSION_HYBRID */
454			{
455			if ((gen != NULL) && !print(bp, gen_hybrid, gen,
456				buffer, off))
457				goto err;
458			}
459		if ((order != NULL) && !print(bp, "Order: ", order,
460			buffer, off)) goto err;
461		if ((cofactor != NULL) && !print(bp, "Cofactor: ", cofactor,
462			buffer, off)) goto err;
463		if (seed && !print_bin(bp, "Seed:", seed, seed_len, off))
464			goto err;
465		}
466	ret=1;
467err:
468	if (!ret)
469 		ECerr(EC_F_ECPKPARAMETERS_PRINT, reason);
470	if (p)
471		BN_free(p);
472	if (a)
473		BN_free(a);
474	if (b)
475		BN_free(b);
476	if (gen)
477		BN_free(gen);
478	if (order)
479		BN_free(order);
480	if (cofactor)
481		BN_free(cofactor);
482	if (ctx)
483		BN_CTX_free(ctx);
484	if (buffer != NULL)
485		OPENSSL_free(buffer);
486	return(ret);
487	}
488
489int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
490	{
491	unsigned char *buffer=NULL;
492	size_t	buf_len=0, i;
493	int     ret=0, reason=ERR_R_BIO_LIB;
494	BIGNUM  *pub_key=NULL, *order=NULL;
495	BN_CTX  *ctx=NULL;
496	const EC_GROUP *group;
497	const EC_POINT *public_key;
498	const BIGNUM *priv_key;
499
500	if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL)
501		{
502		reason = ERR_R_PASSED_NULL_PARAMETER;
503		goto err;
504		}
505
506	public_key = EC_KEY_get0_public_key(x);
507	if ((pub_key = EC_POINT_point2bn(group, public_key,
508		EC_KEY_get_conv_form(x), NULL, ctx)) == NULL)
509		{
510		reason = ERR_R_EC_LIB;
511		goto err;
512		}
513
514	buf_len = (size_t)BN_num_bytes(pub_key);
515	priv_key = EC_KEY_get0_private_key(x);
516	if (priv_key != NULL)
517		{
518		if ((i = (size_t)BN_num_bytes(priv_key)) > buf_len)
519			buf_len = i;
520		}
521
522	buf_len += 10;
523	if ((buffer = OPENSSL_malloc(buf_len)) == NULL)
524		{
525		reason = ERR_R_MALLOC_FAILURE;
526		goto err;
527		}
528
529	if (priv_key != NULL)
530		{
531		if (!BIO_indent(bp, off, 128))
532			goto err;
533		if ((order = BN_new()) == NULL)
534			goto err;
535		if (!EC_GROUP_get_order(group, order, NULL))
536			goto err;
537		if (BIO_printf(bp, "Private-Key: (%d bit)\n",
538			BN_num_bits(order)) <= 0) goto err;
539		}
540
541	if ((priv_key != NULL) && !print(bp, "priv:", priv_key,
542		buffer, off))
543		goto err;
544	if ((pub_key != NULL) && !print(bp, "pub: ", pub_key,
545		buffer, off))
546		goto err;
547	if (!ECPKParameters_print(bp, group, off))
548		goto err;
549	ret=1;
550err:
551	if (!ret)
552 		ECerr(EC_F_EC_KEY_PRINT, reason);
553	if (pub_key)
554		BN_free(pub_key);
555	if (order)
556		BN_free(order);
557	if (ctx)
558		BN_CTX_free(ctx);
559	if (buffer != NULL)
560		OPENSSL_free(buffer);
561	return(ret);
562	}
563#endif /* OPENSSL_NO_EC */
564
565static int print(BIO *bp, const char *number, const BIGNUM *num, unsigned char *buf,
566	     int off)
567	{
568	int n,i;
569	const char *neg;
570
571	if (num == NULL) return(1);
572	neg = (BN_is_negative(num))?"-":"";
573	if(!BIO_indent(bp,off,128))
574		return 0;
575	if (BN_is_zero(num))
576		{
577		if (BIO_printf(bp, "%s 0\n", number) <= 0)
578			return 0;
579		return 1;
580		}
581
582	if (BN_num_bytes(num) <= BN_BYTES)
583		{
584		if (BIO_printf(bp,"%s %s%lu (%s0x%lx)\n",number,neg,
585			(unsigned long)num->d[0],neg,(unsigned long)num->d[0])
586			<= 0) return(0);
587		}
588	else
589		{
590		buf[0]=0;
591		if (BIO_printf(bp,"%s%s",number,
592			(neg[0] == '-')?" (Negative)":"") <= 0)
593			return(0);
594		n=BN_bn2bin(num,&buf[1]);
595
596		if (buf[1] & 0x80)
597			n++;
598		else	buf++;
599
600		for (i=0; i<n; i++)
601			{
602			if ((i%15) == 0)
603				{
604				if(BIO_puts(bp,"\n") <= 0
605				   || !BIO_indent(bp,off+4,128))
606				    return 0;
607				}
608			if (BIO_printf(bp,"%02x%s",buf[i],((i+1) == n)?"":":")
609				<= 0) return(0);
610			}
611		if (BIO_write(bp,"\n",1) <= 0) return(0);
612		}
613	return(1);
614	}
615
616#ifndef OPENSSL_NO_EC
617static int print_bin(BIO *fp, const char *name, const unsigned char *buf,
618		size_t len, int off)
619	{
620	size_t i;
621	char str[128];
622
623	if (buf == NULL)
624		return 1;
625	if (off)
626		{
627		if (off > 128)
628			off=128;
629		memset(str,' ',off);
630		if (BIO_write(fp, str, off) <= 0)
631			return 0;
632		}
633
634	if (BIO_printf(fp,"%s", name) <= 0)
635		return 0;
636
637	for (i=0; i<len; i++)
638		{
639		if ((i%15) == 0)
640			{
641			str[0]='\n';
642			memset(&(str[1]),' ',off+4);
643			if (BIO_write(fp, str, off+1+4) <= 0)
644				return 0;
645			}
646		if (BIO_printf(fp,"%02x%s",buf[i],((i+1) == len)?"":":") <= 0)
647			return 0;
648		}
649	if (BIO_write(fp,"\n",1) <= 0)
650		return 0;
651
652	return 1;
653	}
654#endif
655
656#ifndef OPENSSL_NO_DH
657#ifndef OPENSSL_NO_FP_API
658int DHparams_print_fp(FILE *fp, const DH *x)
659	{
660	BIO *b;
661	int ret;
662
663	if ((b=BIO_new(BIO_s_file())) == NULL)
664		{
665		DHerr(DH_F_DHPARAMS_PRINT_FP,ERR_R_BUF_LIB);
666		return(0);
667		}
668	BIO_set_fp(b,fp,BIO_NOCLOSE);
669	ret=DHparams_print(b, x);
670	BIO_free(b);
671	return(ret);
672	}
673#endif
674
675int DHparams_print(BIO *bp, const DH *x)
676	{
677	unsigned char *m=NULL;
678	int reason=ERR_R_BUF_LIB,ret=0;
679	size_t buf_len=0, i;
680
681	if (x->p)
682		buf_len = (size_t)BN_num_bytes(x->p);
683	else
684		{
685		reason = ERR_R_PASSED_NULL_PARAMETER;
686		goto err;
687		}
688	if (x->g)
689		if (buf_len < (i = (size_t)BN_num_bytes(x->g)))
690			buf_len = i;
691	m=(unsigned char *)OPENSSL_malloc(buf_len+10);
692	if (m == NULL)
693		{
694		reason=ERR_R_MALLOC_FAILURE;
695		goto err;
696		}
697
698	if (BIO_printf(bp,"Diffie-Hellman-Parameters: (%d bit)\n",
699		BN_num_bits(x->p)) <= 0)
700		goto err;
701	if (!print(bp,"prime:",x->p,m,4)) goto err;
702	if (!print(bp,"generator:",x->g,m,4)) goto err;
703	if (x->length != 0)
704		{
705		if (BIO_printf(bp,"    recommended-private-length: %d bits\n",
706			(int)x->length) <= 0) goto err;
707		}
708	ret=1;
709	if (0)
710		{
711err:
712		DHerr(DH_F_DHPARAMS_PRINT,reason);
713		}
714	if (m != NULL) OPENSSL_free(m);
715	return(ret);
716	}
717#endif
718
719#ifndef OPENSSL_NO_DSA
720#ifndef OPENSSL_NO_FP_API
721int DSAparams_print_fp(FILE *fp, const DSA *x)
722	{
723	BIO *b;
724	int ret;
725
726	if ((b=BIO_new(BIO_s_file())) == NULL)
727		{
728		DSAerr(DSA_F_DSAPARAMS_PRINT_FP,ERR_R_BUF_LIB);
729		return(0);
730		}
731	BIO_set_fp(b,fp,BIO_NOCLOSE);
732	ret=DSAparams_print(b, x);
733	BIO_free(b);
734	return(ret);
735	}
736#endif
737
738int DSAparams_print(BIO *bp, const DSA *x)
739	{
740	unsigned char *m=NULL;
741	int ret=0;
742	size_t buf_len=0,i;
743
744	if (x->p)
745		buf_len = (size_t)BN_num_bytes(x->p);
746	else
747		{
748		DSAerr(DSA_F_DSAPARAMS_PRINT,DSA_R_MISSING_PARAMETERS);
749		goto err;
750		}
751	if (x->q)
752		if (buf_len < (i = (size_t)BN_num_bytes(x->q)))
753			buf_len = i;
754	if (x->g)
755		if (buf_len < (i = (size_t)BN_num_bytes(x->g)))
756			buf_len = i;
757	m=(unsigned char *)OPENSSL_malloc(buf_len+10);
758	if (m == NULL)
759		{
760		DSAerr(DSA_F_DSAPARAMS_PRINT,ERR_R_MALLOC_FAILURE);
761		goto err;
762		}
763
764	if (BIO_printf(bp,"DSA-Parameters: (%d bit)\n",
765		BN_num_bits(x->p)) <= 0)
766		goto err;
767	if (!print(bp,"p:",x->p,m,4)) goto err;
768	if ((x->q != NULL) && !print(bp,"q:",x->q,m,4)) goto err;
769	if ((x->g != NULL) && !print(bp,"g:",x->g,m,4)) goto err;
770	ret=1;
771err:
772	if (m != NULL) OPENSSL_free(m);
773	return(ret);
774	}
775
776#endif /* !OPENSSL_NO_DSA */
777
778#ifndef OPENSSL_NO_EC
779#ifndef OPENSSL_NO_FP_API
780int ECParameters_print_fp(FILE *fp, const EC_KEY *x)
781	{
782	BIO *b;
783	int ret;
784
785	if ((b=BIO_new(BIO_s_file())) == NULL)
786		{
787		ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB);
788		return(0);
789		}
790	BIO_set_fp(b, fp, BIO_NOCLOSE);
791	ret = ECParameters_print(b, x);
792	BIO_free(b);
793	return(ret);
794	}
795#endif
796
797int ECParameters_print(BIO *bp, const EC_KEY *x)
798	{
799	int     reason=ERR_R_EC_LIB, ret=0;
800	BIGNUM	*order=NULL;
801	const EC_GROUP *group;
802
803	if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL)
804		{
805		reason = ERR_R_PASSED_NULL_PARAMETER;;
806		goto err;
807		}
808
809	if ((order = BN_new()) == NULL)
810		{
811		reason = ERR_R_MALLOC_FAILURE;
812		goto err;
813		}
814
815	if (!EC_GROUP_get_order(group, order, NULL))
816		{
817		reason = ERR_R_EC_LIB;
818		goto err;
819		}
820
821	if (BIO_printf(bp, "ECDSA-Parameters: (%d bit)\n",
822		BN_num_bits(order)) <= 0)
823		goto err;
824	if (!ECPKParameters_print(bp, group, 4))
825		goto err;
826	ret=1;
827err:
828	if (order)
829		BN_free(order);
830	ECerr(EC_F_ECPARAMETERS_PRINT, reason);
831	return(ret);
832	}
833
834#endif
835