1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.] */
56 
57 #include <openssl/asn1.h>
58 #include <openssl/bio.h>
59 #include <openssl/digest.h>
60 #include <openssl/err.h>
61 #include <openssl/evp.h>
62 #include <openssl/mem.h>
63 #include <openssl/obj.h>
64 #include <openssl/x509.h>
65 #include <openssl/x509v3.h>
66 
67 #include "../evp/internal.h"
68 
69 #ifndef OPENSSL_NO_FP_API
X509_print_ex_fp(FILE * fp,X509 * x,unsigned long nmflag,unsigned long cflag)70 int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, unsigned long cflag)
71         {
72         BIO *b;
73         int ret;
74 
75         if ((b=BIO_new(BIO_s_file())) == NULL)
76 		{
77 		OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
78                 return(0);
79 		}
80         BIO_set_fp(b,fp,BIO_NOCLOSE);
81         ret=X509_print_ex(b, x, nmflag, cflag);
82         BIO_free(b);
83         return(ret);
84         }
85 
X509_print_fp(FILE * fp,X509 * x)86 int X509_print_fp(FILE *fp, X509 *x)
87 	{
88 	return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
89 	}
90 #endif
91 
X509_print(BIO * bp,X509 * x)92 int X509_print(BIO *bp, X509 *x)
93 {
94 	return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
95 }
96 
X509_print_ex(BIO * bp,X509 * x,unsigned long nmflags,unsigned long cflag)97 int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
98 	{
99 	long l;
100 	int ret=0,i;
101 	char *m=NULL,mlch = ' ';
102 	int nmindent = 0;
103 	X509_CINF *ci;
104 	ASN1_INTEGER *bs;
105 	EVP_PKEY *pkey=NULL;
106 	const char *neg;
107 
108 	if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
109 			mlch = '\n';
110 			nmindent = 12;
111 	}
112 
113 	if(nmflags == X509_FLAG_COMPAT)
114 		nmindent = 16;
115 
116 	ci=x->cert_info;
117 	if(!(cflag & X509_FLAG_NO_HEADER))
118 		{
119 		if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err;
120 		if (BIO_write(bp,"    Data:\n",10) <= 0) goto err;
121 		}
122 	if(!(cflag & X509_FLAG_NO_VERSION))
123 		{
124 		l=X509_get_version(x);
125 		if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err;
126 		}
127 	if(!(cflag & X509_FLAG_NO_SERIAL))
128 		{
129 
130 		if (BIO_write(bp,"        Serial Number:",22) <= 0) goto err;
131 
132 		bs=X509_get_serialNumber(x);
133 		if (bs->length <= (int)sizeof(long))
134 			{
135 			l=ASN1_INTEGER_get(bs);
136 			if (bs->type == V_ASN1_NEG_INTEGER)
137 				{
138 				l= -l;
139 				neg="-";
140 				}
141 			else
142 				neg="";
143 			if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0)
144 				goto err;
145 			}
146 		else
147 			{
148 			neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":"";
149 			if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err;
150 
151 			for (i=0; i<bs->length; i++)
152 				{
153 				if (BIO_printf(bp,"%02x%c",bs->data[i],
154 					((i+1 == bs->length)?'\n':':')) <= 0)
155 					goto err;
156 				}
157 			}
158 
159 		}
160 
161 	if(!(cflag & X509_FLAG_NO_SIGNAME))
162 		{
163 		if (X509_signature_print(bp, ci->signature, NULL) <= 0)
164 			goto err;
165 		}
166 
167 	if(!(cflag & X509_FLAG_NO_ISSUER))
168 		{
169 		if (BIO_printf(bp,"        Issuer:%c",mlch) <= 0) goto err;
170 		if (X509_NAME_print_ex(bp,X509_get_issuer_name(x),nmindent, nmflags) < 0) goto err;
171 		if (BIO_write(bp,"\n",1) <= 0) goto err;
172 		}
173 	if(!(cflag & X509_FLAG_NO_VALIDITY))
174 		{
175 		if (BIO_write(bp,"        Validity\n",17) <= 0) goto err;
176 		if (BIO_write(bp,"            Not Before: ",24) <= 0) goto err;
177 		if (!ASN1_TIME_print(bp,X509_get_notBefore(x))) goto err;
178 		if (BIO_write(bp,"\n            Not After : ",25) <= 0) goto err;
179 		if (!ASN1_TIME_print(bp,X509_get_notAfter(x))) goto err;
180 		if (BIO_write(bp,"\n",1) <= 0) goto err;
181 		}
182 	if(!(cflag & X509_FLAG_NO_SUBJECT))
183 		{
184 		if (BIO_printf(bp,"        Subject:%c",mlch) <= 0) goto err;
185 		if (X509_NAME_print_ex(bp,X509_get_subject_name(x),nmindent, nmflags) < 0) goto err;
186 		if (BIO_write(bp,"\n",1) <= 0) goto err;
187 		}
188 	if(!(cflag & X509_FLAG_NO_PUBKEY))
189 		{
190 		if (BIO_write(bp,"        Subject Public Key Info:\n",33) <= 0)
191 			goto err;
192 		if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0)
193 			goto err;
194 		if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
195 			goto err;
196 		if (BIO_puts(bp, "\n") <= 0)
197 			goto err;
198 
199 		pkey=X509_get_pubkey(x);
200 		if (pkey == NULL)
201 			{
202 			BIO_printf(bp,"%12sUnable to load Public Key\n","");
203 			BIO_print_errors(bp);
204 			}
205 		else
206 			{
207 			EVP_PKEY_print_public(bp, pkey, 16, NULL);
208 			EVP_PKEY_free(pkey);
209 			}
210 		}
211 
212 	if(!(cflag & X509_FLAG_NO_IDS))
213 		{
214 		if (ci->issuerUID)
215 			{
216 			if (BIO_printf(bp,"%8sIssuer Unique ID: ","") <= 0)
217 				goto err;
218 			if (!X509_signature_dump(bp, ci->issuerUID, 12))
219 				goto err;
220 			}
221 		if (ci->subjectUID)
222 			{
223 			if (BIO_printf(bp,"%8sSubject Unique ID: ","") <= 0)
224 				goto err;
225 			if (!X509_signature_dump(bp, ci->subjectUID, 12))
226 				goto err;
227 			}
228 		}
229 
230 	if (!(cflag & X509_FLAG_NO_EXTENSIONS))
231 		X509V3_extensions_print(bp, "X509v3 extensions",
232 					ci->extensions, cflag, 8);
233 
234 	if(!(cflag & X509_FLAG_NO_SIGDUMP))
235 		{
236 		if(X509_signature_print(bp, x->sig_alg, x->signature) <= 0) goto err;
237 		}
238 	if(!(cflag & X509_FLAG_NO_AUX))
239 		{
240 		if (!X509_CERT_AUX_print(bp, x->aux, 0)) goto err;
241 		}
242 	ret=1;
243 err:
244 	if (m != NULL) OPENSSL_free(m);
245 	return(ret);
246 	}
247 
X509_ocspid_print(BIO * bp,X509 * x)248 int X509_ocspid_print (BIO *bp, X509 *x)
249 	{
250 	unsigned char *der=NULL ;
251 	unsigned char *dertmp;
252 	int derlen;
253 	int i;
254 	unsigned char SHA1md[SHA_DIGEST_LENGTH];
255 
256 	/* display the hash of the subject as it would appear
257 	   in OCSP requests */
258 	if (BIO_printf(bp,"        Subject OCSP hash: ") <= 0)
259 		goto err;
260 	derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
261 	if ((der = dertmp = (unsigned char *)OPENSSL_malloc (derlen)) == NULL)
262 		goto err;
263 	i2d_X509_NAME(x->cert_info->subject, &dertmp);
264 
265 	if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
266 		goto err;
267 	for (i=0; i < SHA_DIGEST_LENGTH; i++)
268 		{
269 		if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0) goto err;
270 		}
271 	OPENSSL_free (der);
272 	der=NULL;
273 
274 	/* display the hash of the public key as it would appear
275 	   in OCSP requests */
276 	if (BIO_printf(bp,"\n        Public key OCSP hash: ") <= 0)
277 		goto err;
278 
279 	if (!EVP_Digest(x->cert_info->key->public_key->data,
280 			x->cert_info->key->public_key->length,
281 			SHA1md, NULL, EVP_sha1(), NULL))
282 		goto err;
283 	for (i=0; i < SHA_DIGEST_LENGTH; i++)
284 		{
285 		if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0)
286 			goto err;
287 		}
288 	BIO_printf(bp,"\n");
289 
290 	return (1);
291 err:
292 	if (der != NULL) OPENSSL_free(der);
293 	return(0);
294 	}
295 
X509_signature_print(BIO * bp,X509_ALGOR * sigalg,ASN1_STRING * sig)296 int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
297 {
298 	int sig_nid;
299 	if (BIO_puts(bp,"    Signature Algorithm: ") <= 0) return 0;
300 	if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) return 0;
301 
302 	sig_nid = OBJ_obj2nid(sigalg->algorithm);
303 	if (sig_nid != NID_undef)
304 		{
305 		int pkey_nid, dig_nid;
306 		const EVP_PKEY_ASN1_METHOD *ameth;
307 		if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid))
308 			{
309 			ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
310 			if (ameth && ameth->sig_print)
311 				return ameth->sig_print(bp, sigalg, sig, 9, 0);
312 			}
313 		}
314 	if (sig)
315 		return X509_signature_dump(bp, sig, 9);
316 	else if (BIO_puts(bp, "\n") <= 0)
317 		return 0;
318 	return 1;
319 }
320 
ASN1_STRING_print(BIO * bp,const ASN1_STRING * v)321 int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
322 	{
323 	int i,n;
324 	char buf[80];
325 	const char *p;
326 
327 	if (v == NULL) return(0);
328 	n=0;
329 	p=(const char *)v->data;
330 	for (i=0; i<v->length; i++)
331 		{
332 		if ((p[i] > '~') || ((p[i] < ' ') &&
333 			(p[i] != '\n') && (p[i] != '\r')))
334 			buf[n]='.';
335 		else
336 			buf[n]=p[i];
337 		n++;
338 		if (n >= 80)
339 			{
340 			if (BIO_write(bp,buf,n) <= 0)
341 				return(0);
342 			n=0;
343 			}
344 		}
345 	if (n > 0)
346 		if (BIO_write(bp,buf,n) <= 0)
347 			return(0);
348 	return(1);
349 	}
350 
ASN1_TIME_print(BIO * bp,const ASN1_TIME * tm)351 int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
352 {
353 	if(tm->type == V_ASN1_UTCTIME) return ASN1_UTCTIME_print(bp, tm);
354 	if(tm->type == V_ASN1_GENERALIZEDTIME)
355 				return ASN1_GENERALIZEDTIME_print(bp, tm);
356 	BIO_write(bp,"Bad time value",14);
357 	return(0);
358 }
359 
360 static const char *const mon[12]=
361     {
362     "Jan","Feb","Mar","Apr","May","Jun",
363     "Jul","Aug","Sep","Oct","Nov","Dec"
364     };
365 
ASN1_GENERALIZEDTIME_print(BIO * bp,const ASN1_GENERALIZEDTIME * tm)366 int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
367 	{
368 	char *v;
369 	int gmt=0;
370 	int i;
371 	int y=0,M=0,d=0,h=0,m=0,s=0;
372 	char *f = NULL;
373 	int f_len = 0;
374 
375 	i=tm->length;
376 	v=(char *)tm->data;
377 
378 	if (i < 12) goto err;
379 	if (v[i-1] == 'Z') gmt=1;
380 	for (i=0; i<12; i++)
381 		if ((v[i] > '9') || (v[i] < '0')) goto err;
382 	y= (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0');
383 	M= (v[4]-'0')*10+(v[5]-'0');
384 	if ((M > 12) || (M < 1)) goto err;
385 	d= (v[6]-'0')*10+(v[7]-'0');
386 	h= (v[8]-'0')*10+(v[9]-'0');
387 	m=  (v[10]-'0')*10+(v[11]-'0');
388 	if (tm->length >= 14 &&
389 	    (v[12] >= '0') && (v[12] <= '9') &&
390 	    (v[13] >= '0') && (v[13] <= '9'))
391 		{
392 		s=  (v[12]-'0')*10+(v[13]-'0');
393 		/* Check for fractions of seconds. */
394 		if (tm->length >= 15 && v[14] == '.')
395 			{
396 			int l = tm->length;
397 			f = &v[14];	/* The decimal point. */
398 			f_len = 1;
399 			while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
400 				++f_len;
401 			}
402 		}
403 
404 	if (BIO_printf(bp,"%s %2d %02d:%02d:%02d%.*s %d%s",
405 		mon[M-1],d,h,m,s,f_len,f,y,(gmt)?" GMT":"") <= 0)
406 		return(0);
407 	else
408 		return(1);
409 err:
410 	BIO_write(bp,"Bad time value",14);
411 	return(0);
412 	}
413 
ASN1_UTCTIME_print(BIO * bp,const ASN1_UTCTIME * tm)414 int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
415 	{
416 	const char *v;
417 	int gmt=0;
418 	int i;
419 	int y=0,M=0,d=0,h=0,m=0,s=0;
420 
421 	i=tm->length;
422 	v=(const char *)tm->data;
423 
424 	if (i < 10) goto err;
425 	if (v[i-1] == 'Z') gmt=1;
426 	for (i=0; i<10; i++)
427 		if ((v[i] > '9') || (v[i] < '0')) goto err;
428 	y= (v[0]-'0')*10+(v[1]-'0');
429 	if (y < 50) y+=100;
430 	M= (v[2]-'0')*10+(v[3]-'0');
431 	if ((M > 12) || (M < 1)) goto err;
432 	d= (v[4]-'0')*10+(v[5]-'0');
433 	h= (v[6]-'0')*10+(v[7]-'0');
434 	m=  (v[8]-'0')*10+(v[9]-'0');
435 	if (tm->length >=12 &&
436 	    (v[10] >= '0') && (v[10] <= '9') &&
437 	    (v[11] >= '0') && (v[11] <= '9'))
438 		s=  (v[10]-'0')*10+(v[11]-'0');
439 
440 	if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s",
441 		mon[M-1],d,h,m,s,y+1900,(gmt)?" GMT":"") <= 0)
442 		return(0);
443 	else
444 		return(1);
445 err:
446 	BIO_write(bp,"Bad time value",14);
447 	return(0);
448 	}
449 
X509_NAME_print(BIO * bp,X509_NAME * name,int obase)450 int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
451 	{
452 	char *s,*c,*b;
453 	int ret=0,l,i;
454 
455 	l=80-2-obase;
456 
457 	b=X509_NAME_oneline(name,NULL,0);
458 	if (!b)
459 		return 0;
460 	if (!*b)
461 		{
462 		OPENSSL_free(b);
463 		return 1;
464 		}
465 	s=b+1; /* skip the first slash */
466 
467 	c=s;
468 	for (;;)
469 		{
470 		if (	((*s == '/') &&
471 				((s[1] >= 'A') && (s[1] <= 'Z') && (
472 					(s[2] == '=') ||
473 					((s[2] >= 'A') && (s[2] <= 'Z') &&
474 					(s[3] == '='))
475 				 ))) ||
476 			(*s == '\0'))
477 			{
478 			i=s-c;
479 			if (BIO_write(bp,c,i) != i) goto err;
480 			c=s+1;	/* skip following slash */
481 			if (*s != '\0')
482 				{
483 				if (BIO_write(bp,", ",2) != 2) goto err;
484 				}
485 			l--;
486 			}
487 		if (*s == '\0') break;
488 		s++;
489 		l--;
490 		}
491 
492 	ret=1;
493 	if (0)
494 		{
495 err:
496 		OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
497 		}
498 	OPENSSL_free(b);
499 	return(ret);
500 	}
501