Home | History | Annotate | Download | only in asn1
      1 /* crypto/asn1/t_x509.c */
      2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      3  * All rights reserved.
      4  *
      5  * This package is an SSL implementation written
      6  * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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/buffer.h>
     62 #include <openssl/bn.h>
     63 #ifndef OPENSSL_NO_RSA
     64 #include <openssl/rsa.h>
     65 #endif
     66 #ifndef OPENSSL_NO_DSA
     67 #include <openssl/dsa.h>
     68 #endif
     69 #ifndef OPENSSL_NO_EC
     70 #include <openssl/ec.h>
     71 #endif
     72 #include <openssl/objects.h>
     73 #include <openssl/x509.h>
     74 #include <openssl/x509v3.h>
     75 
     76 #ifndef OPENSSL_NO_FP_API
     77 int X509_print_fp(FILE *fp, X509 *x)
     78 	{
     79 	return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
     80 	}
     81 
     82 int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, unsigned long cflag)
     83         {
     84         BIO *b;
     85         int ret;
     86 
     87         if ((b=BIO_new(BIO_s_file())) == NULL)
     88 		{
     89 		X509err(X509_F_X509_PRINT_EX_FP,ERR_R_BUF_LIB);
     90                 return(0);
     91 		}
     92         BIO_set_fp(b,fp,BIO_NOCLOSE);
     93         ret=X509_print_ex(b, x, nmflag, cflag);
     94         BIO_free(b);
     95         return(ret);
     96         }
     97 #endif
     98 
     99 int X509_print(BIO *bp, X509 *x)
    100 {
    101 	return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
    102 }
    103 
    104 int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
    105 	{
    106 	long l;
    107 	int ret=0,i;
    108 	char *m=NULL,mlch = ' ';
    109 	int nmindent = 0;
    110 	X509_CINF *ci;
    111 	ASN1_INTEGER *bs;
    112 	EVP_PKEY *pkey=NULL;
    113 	const char *neg;
    114 
    115 	if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
    116 			mlch = '\n';
    117 			nmindent = 12;
    118 	}
    119 
    120 	if(nmflags == X509_FLAG_COMPAT)
    121 		nmindent = 16;
    122 
    123 	ci=x->cert_info;
    124 	if(!(cflag & X509_FLAG_NO_HEADER))
    125 		{
    126 		if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err;
    127 		if (BIO_write(bp,"    Data:\n",10) <= 0) goto err;
    128 		}
    129 	if(!(cflag & X509_FLAG_NO_VERSION))
    130 		{
    131 		l=X509_get_version(x);
    132 		if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err;
    133 		}
    134 	if(!(cflag & X509_FLAG_NO_SERIAL))
    135 		{
    136 
    137 		if (BIO_write(bp,"        Serial Number:",22) <= 0) goto err;
    138 
    139 		bs=X509_get_serialNumber(x);
    140 		if (bs->length <= 4)
    141 			{
    142 			l=ASN1_INTEGER_get(bs);
    143 			if (l < 0)
    144 				{
    145 				l= -l;
    146 				neg="-";
    147 				}
    148 			else
    149 				neg="";
    150 			if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0)
    151 				goto err;
    152 			}
    153 		else
    154 			{
    155 			neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":"";
    156 			if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err;
    157 
    158 			for (i=0; i<bs->length; i++)
    159 				{
    160 				if (BIO_printf(bp,"%02x%c",bs->data[i],
    161 					((i+1 == bs->length)?'\n':':')) <= 0)
    162 					goto err;
    163 				}
    164 			}
    165 
    166 		}
    167 
    168 	if(!(cflag & X509_FLAG_NO_SIGNAME))
    169 		{
    170 		if (BIO_printf(bp,"%8sSignature Algorithm: ","") <= 0)
    171 			goto err;
    172 		if (i2a_ASN1_OBJECT(bp, ci->signature->algorithm) <= 0)
    173 			goto err;
    174 		if (BIO_puts(bp, "\n") <= 0)
    175 			goto err;
    176 		}
    177 
    178 	if(!(cflag & X509_FLAG_NO_ISSUER))
    179 		{
    180 		if (BIO_printf(bp,"        Issuer:%c",mlch) <= 0) goto err;
    181 		if (X509_NAME_print_ex(bp,X509_get_issuer_name(x),nmindent, nmflags) < 0) goto err;
    182 		if (BIO_write(bp,"\n",1) <= 0) goto err;
    183 		}
    184 	if(!(cflag & X509_FLAG_NO_VALIDITY))
    185 		{
    186 		if (BIO_write(bp,"        Validity\n",17) <= 0) goto err;
    187 		if (BIO_write(bp,"            Not Before: ",24) <= 0) goto err;
    188 		if (!ASN1_TIME_print(bp,X509_get_notBefore(x))) goto err;
    189 		if (BIO_write(bp,"\n            Not After : ",25) <= 0) goto err;
    190 		if (!ASN1_TIME_print(bp,X509_get_notAfter(x))) goto err;
    191 		if (BIO_write(bp,"\n",1) <= 0) goto err;
    192 		}
    193 	if(!(cflag & X509_FLAG_NO_SUBJECT))
    194 		{
    195 		if (BIO_printf(bp,"        Subject:%c",mlch) <= 0) goto err;
    196 		if (X509_NAME_print_ex(bp,X509_get_subject_name(x),nmindent, nmflags) < 0) goto err;
    197 		if (BIO_write(bp,"\n",1) <= 0) goto err;
    198 		}
    199 	if(!(cflag & X509_FLAG_NO_PUBKEY))
    200 		{
    201 		if (BIO_write(bp,"        Subject Public Key Info:\n",33) <= 0)
    202 			goto err;
    203 		if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0)
    204 			goto err;
    205 		if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
    206 			goto err;
    207 		if (BIO_puts(bp, "\n") <= 0)
    208 			goto err;
    209 
    210 		pkey=X509_get_pubkey(x);
    211 		if (pkey == NULL)
    212 			{
    213 			BIO_printf(bp,"%12sUnable to load Public Key\n","");
    214 			ERR_print_errors(bp);
    215 			}
    216 		else
    217 			{
    218 			EVP_PKEY_print_public(bp, pkey, 16, NULL);
    219 			EVP_PKEY_free(pkey);
    220 			}
    221 		}
    222 
    223 	if (!(cflag & X509_FLAG_NO_EXTENSIONS))
    224 		X509V3_extensions_print(bp, "X509v3 extensions",
    225 					ci->extensions, cflag, 8);
    226 
    227 	if(!(cflag & X509_FLAG_NO_SIGDUMP))
    228 		{
    229 		if(X509_signature_print(bp, x->sig_alg, x->signature) <= 0) goto err;
    230 		}
    231 	if(!(cflag & X509_FLAG_NO_AUX))
    232 		{
    233 		if (!X509_CERT_AUX_print(bp, x->aux, 0)) goto err;
    234 		}
    235 	ret=1;
    236 err:
    237 	if (m != NULL) OPENSSL_free(m);
    238 	return(ret);
    239 	}
    240 
    241 int X509_ocspid_print (BIO *bp, X509 *x)
    242 	{
    243 	unsigned char *der=NULL ;
    244 	unsigned char *dertmp;
    245 	int derlen;
    246 	int i;
    247 	unsigned char SHA1md[SHA_DIGEST_LENGTH];
    248 
    249 	/* display the hash of the subject as it would appear
    250 	   in OCSP requests */
    251 	if (BIO_printf(bp,"        Subject OCSP hash: ") <= 0)
    252 		goto err;
    253 	derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
    254 	if ((der = dertmp = (unsigned char *)OPENSSL_malloc (derlen)) == NULL)
    255 		goto err;
    256 	i2d_X509_NAME(x->cert_info->subject, &dertmp);
    257 
    258 	EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL);
    259 	for (i=0; i < SHA_DIGEST_LENGTH; i++)
    260 		{
    261 		if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0) goto err;
    262 		}
    263 	OPENSSL_free (der);
    264 	der=NULL;
    265 
    266 	/* display the hash of the public key as it would appear
    267 	   in OCSP requests */
    268 	if (BIO_printf(bp,"\n        Public key OCSP hash: ") <= 0)
    269 		goto err;
    270 
    271 	EVP_Digest(x->cert_info->key->public_key->data,
    272 		x->cert_info->key->public_key->length, SHA1md, NULL, EVP_sha1(), NULL);
    273 	for (i=0; i < SHA_DIGEST_LENGTH; i++)
    274 		{
    275 		if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0)
    276 			goto err;
    277 		}
    278 	BIO_printf(bp,"\n");
    279 
    280 	return (1);
    281 err:
    282 	if (der != NULL) OPENSSL_free(der);
    283 	return(0);
    284 	}
    285 
    286 int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
    287 {
    288 	unsigned char *s;
    289 	int i, n;
    290 	if (BIO_puts(bp,"    Signature Algorithm: ") <= 0) return 0;
    291 	if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) return 0;
    292 
    293 	n=sig->length;
    294 	s=sig->data;
    295 	for (i=0; i<n; i++)
    296 		{
    297 		if ((i%18) == 0)
    298 			if (BIO_write(bp,"\n        ",9) <= 0) return 0;
    299 			if (BIO_printf(bp,"%02x%s",s[i],
    300 				((i+1) == n)?"":":") <= 0) return 0;
    301 		}
    302 	if (BIO_write(bp,"\n",1) != 1) return 0;
    303 	return 1;
    304 }
    305 
    306 int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
    307 	{
    308 	int i,n;
    309 	char buf[80];
    310 	const char *p;
    311 
    312 	if (v == NULL) return(0);
    313 	n=0;
    314 	p=(const char *)v->data;
    315 	for (i=0; i<v->length; i++)
    316 		{
    317 		if ((p[i] > '~') || ((p[i] < ' ') &&
    318 			(p[i] != '\n') && (p[i] != '\r')))
    319 			buf[n]='.';
    320 		else
    321 			buf[n]=p[i];
    322 		n++;
    323 		if (n >= 80)
    324 			{
    325 			if (BIO_write(bp,buf,n) <= 0)
    326 				return(0);
    327 			n=0;
    328 			}
    329 		}
    330 	if (n > 0)
    331 		if (BIO_write(bp,buf,n) <= 0)
    332 			return(0);
    333 	return(1);
    334 	}
    335 
    336 int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
    337 {
    338 	if(tm->type == V_ASN1_UTCTIME) return ASN1_UTCTIME_print(bp, tm);
    339 	if(tm->type == V_ASN1_GENERALIZEDTIME)
    340 				return ASN1_GENERALIZEDTIME_print(bp, tm);
    341 	BIO_write(bp,"Bad time value",14);
    342 	return(0);
    343 }
    344 
    345 static const char *mon[12]=
    346     {
    347     "Jan","Feb","Mar","Apr","May","Jun",
    348     "Jul","Aug","Sep","Oct","Nov","Dec"
    349     };
    350 
    351 int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
    352 	{
    353 	char *v;
    354 	int gmt=0;
    355 	int i;
    356 	int y=0,M=0,d=0,h=0,m=0,s=0;
    357 	char *f = NULL;
    358 	int f_len = 0;
    359 
    360 	i=tm->length;
    361 	v=(char *)tm->data;
    362 
    363 	if (i < 12) goto err;
    364 	if (v[i-1] == 'Z') gmt=1;
    365 	for (i=0; i<12; i++)
    366 		if ((v[i] > '9') || (v[i] < '0')) goto err;
    367 	y= (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0');
    368 	M= (v[4]-'0')*10+(v[5]-'0');
    369 	if ((M > 12) || (M < 1)) goto err;
    370 	d= (v[6]-'0')*10+(v[7]-'0');
    371 	h= (v[8]-'0')*10+(v[9]-'0');
    372 	m=  (v[10]-'0')*10+(v[11]-'0');
    373 	if (tm->length >= 14 &&
    374 	    (v[12] >= '0') && (v[12] <= '9') &&
    375 	    (v[13] >= '0') && (v[13] <= '9'))
    376 		{
    377 		s=  (v[12]-'0')*10+(v[13]-'0');
    378 		/* Check for fractions of seconds. */
    379 		if (tm->length >= 15 && v[14] == '.')
    380 			{
    381 			int l = tm->length;
    382 			f = &v[14];	/* The decimal point. */
    383 			f_len = 1;
    384 			while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
    385 				++f_len;
    386 			}
    387 		}
    388 
    389 	if (BIO_printf(bp,"%s %2d %02d:%02d:%02d%.*s %d%s",
    390 		mon[M-1],d,h,m,s,f_len,f,y,(gmt)?" GMT":"") <= 0)
    391 		return(0);
    392 	else
    393 		return(1);
    394 err:
    395 	BIO_write(bp,"Bad time value",14);
    396 	return(0);
    397 	}
    398 
    399 int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
    400 	{
    401 	const char *v;
    402 	int gmt=0;
    403 	int i;
    404 	int y=0,M=0,d=0,h=0,m=0,s=0;
    405 
    406 	i=tm->length;
    407 	v=(const char *)tm->data;
    408 
    409 	if (i < 10) goto err;
    410 	if (v[i-1] == 'Z') gmt=1;
    411 	for (i=0; i<10; i++)
    412 		if ((v[i] > '9') || (v[i] < '0')) goto err;
    413 	y= (v[0]-'0')*10+(v[1]-'0');
    414 	if (y < 50) y+=100;
    415 	M= (v[2]-'0')*10+(v[3]-'0');
    416 	if ((M > 12) || (M < 1)) goto err;
    417 	d= (v[4]-'0')*10+(v[5]-'0');
    418 	h= (v[6]-'0')*10+(v[7]-'0');
    419 	m=  (v[8]-'0')*10+(v[9]-'0');
    420 	if (tm->length >=12 &&
    421 	    (v[10] >= '0') && (v[10] <= '9') &&
    422 	    (v[11] >= '0') && (v[11] <= '9'))
    423 		s=  (v[10]-'0')*10+(v[11]-'0');
    424 
    425 	if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s",
    426 		mon[M-1],d,h,m,s,y+1900,(gmt)?" GMT":"") <= 0)
    427 		return(0);
    428 	else
    429 		return(1);
    430 err:
    431 	BIO_write(bp,"Bad time value",14);
    432 	return(0);
    433 	}
    434 
    435 int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
    436 	{
    437 	char *s,*c,*b;
    438 	int ret=0,l,i;
    439 
    440 	l=80-2-obase;
    441 
    442 	b=X509_NAME_oneline(name,NULL,0);
    443 	if (!*b)
    444 		{
    445 		OPENSSL_free(b);
    446 		return 1;
    447 		}
    448 	s=b+1; /* skip the first slash */
    449 
    450 	c=s;
    451 	for (;;)
    452 		{
    453 #ifndef CHARSET_EBCDIC
    454 		if (	((*s == '/') &&
    455 				((s[1] >= 'A') && (s[1] <= 'Z') && (
    456 					(s[2] == '=') ||
    457 					((s[2] >= 'A') && (s[2] <= 'Z') &&
    458 					(s[3] == '='))
    459 				 ))) ||
    460 			(*s == '\0'))
    461 #else
    462 		if (	((*s == '/') &&
    463 				(isupper(s[1]) && (
    464 					(s[2] == '=') ||
    465 					(isupper(s[2]) &&
    466 					(s[3] == '='))
    467 				 ))) ||
    468 			(*s == '\0'))
    469 #endif
    470 			{
    471 			i=s-c;
    472 			if (BIO_write(bp,c,i) != i) goto err;
    473 			c=s+1;	/* skip following slash */
    474 			if (*s != '\0')
    475 				{
    476 				if (BIO_write(bp,", ",2) != 2) goto err;
    477 				}
    478 			l--;
    479 			}
    480 		if (*s == '\0') break;
    481 		s++;
    482 		l--;
    483 		}
    484 
    485 	ret=1;
    486 	if (0)
    487 		{
    488 err:
    489 		X509err(X509_F_X509_NAME_PRINT,ERR_R_BUF_LIB);
    490 		}
    491 	OPENSSL_free(b);
    492 	return(ret);
    493 	}
    494