Home | History | Annotate | Download | only in tls
      1 /*
      2  * Testing tool for ASN.1/X.509v3 routines
      3  * Copyright (c) 2006, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "includes.h"
     16 
     17 #include "common.h"
     18 #include "asn1.h"
     19 #include "x509v3.h"
     20 
     21 extern int wpa_debug_level;
     22 
     23 
     24 static const char * asn1_class_str(int class)
     25 {
     26 	switch (class) {
     27 	case ASN1_CLASS_UNIVERSAL:
     28 		return "Universal";
     29 	case ASN1_CLASS_APPLICATION:
     30 		return "Application";
     31 	case ASN1_CLASS_CONTEXT_SPECIFIC:
     32 		return "Context-specific";
     33 	case ASN1_CLASS_PRIVATE:
     34 		return "Private";
     35 	default:
     36 		return "?";
     37 	}
     38 }
     39 
     40 
     41 int asn1_parse(const u8 *buf, size_t len, int level)
     42 {
     43 	const u8 *pos, *prev, *end;
     44 	char prefix[10], str[100];
     45 	int _level;
     46 	struct asn1_hdr hdr;
     47 	struct asn1_oid oid;
     48 	u8 tmp;
     49 
     50 	_level = level;
     51 	if ((size_t) _level > sizeof(prefix) - 1)
     52 		_level = sizeof(prefix) - 1;
     53 	memset(prefix, ' ', _level);
     54 	prefix[_level] = '\0';
     55 
     56 	pos = buf;
     57 	end = buf + len;
     58 
     59 	while (pos < end) {
     60 		if (asn1_get_next(pos, end - pos, &hdr) < 0)
     61 			return -1;
     62 
     63 		prev = pos;
     64 		pos = hdr.payload;
     65 
     66 		wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) "
     67 			   "Tag %u Length %u",
     68 			   prefix, hdr.class, asn1_class_str(hdr.class),
     69 			   hdr.constructed,
     70 			   hdr.constructed ? "Constructed" : "Primitive",
     71 			   hdr.tag, hdr.length);
     72 
     73 		if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC &&
     74 		    hdr.constructed) {
     75 			if (asn1_parse(pos, hdr.length, level + 1) < 0)
     76 				return -1;
     77 			pos += hdr.length;
     78 		}
     79 
     80 		if (hdr.class != ASN1_CLASS_UNIVERSAL)
     81 			continue;
     82 
     83 		switch (hdr.tag) {
     84 		case ASN1_TAG_EOC:
     85 			if (hdr.length) {
     86 				wpa_printf(MSG_DEBUG, "ASN.1: Non-zero "
     87 					   "end-of-contents length (%u)",
     88 					   hdr.length);
     89 				return -1;
     90 			}
     91 			wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix);
     92 			break;
     93 		case ASN1_TAG_BOOLEAN:
     94 			if (hdr.length != 1) {
     95 				wpa_printf(MSG_DEBUG, "ASN.1: Unexpected "
     96 					   "Boolean length (%u)", hdr.length);
     97 				return -1;
     98 			}
     99 			tmp = *pos++;
    100 			wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s",
    101 				   prefix, tmp ? "TRUE" : "FALSE");
    102 			break;
    103 		case ASN1_TAG_INTEGER:
    104 			wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER",
    105 				    pos, hdr.length);
    106 			pos += hdr.length;
    107 			break;
    108 		case ASN1_TAG_BITSTRING:
    109 			wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString",
    110 				    pos, hdr.length);
    111 			pos += hdr.length;
    112 			break;
    113 		case ASN1_TAG_OCTETSTRING:
    114 			wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString",
    115 				    pos, hdr.length);
    116 			pos += hdr.length;
    117 			break;
    118 		case ASN1_TAG_NULL:
    119 			if (hdr.length) {
    120 				wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null "
    121 					   "length (%u)", hdr.length);
    122 				return -1;
    123 			}
    124 			wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix);
    125 			break;
    126 		case ASN1_TAG_OID:
    127 			if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) {
    128 				wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID");
    129 				return -1;
    130 			}
    131 			asn1_oid_to_str(&oid, str, sizeof(str));
    132 			wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str);
    133 			pos += hdr.length;
    134 			break;
    135 		case ANS1_TAG_RELATIVE_OID:
    136 			wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID",
    137 				    pos, hdr.length);
    138 			pos += hdr.length;
    139 			break;
    140 		case ASN1_TAG_SEQUENCE:
    141 			wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix);
    142 			if (asn1_parse(pos, hdr.length, level + 1) < 0)
    143 				return -1;
    144 			pos += hdr.length;
    145 			break;
    146 		case ASN1_TAG_SET:
    147 			wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix);
    148 			if (asn1_parse(pos, hdr.length, level + 1) < 0)
    149 				return -1;
    150 			pos += hdr.length;
    151 			break;
    152 		case ASN1_TAG_PRINTABLESTRING:
    153 			wpa_hexdump_ascii(MSG_MSGDUMP,
    154 					  "ASN.1: PrintableString",
    155 					  pos, hdr.length);
    156 			pos += hdr.length;
    157 			break;
    158 		case ASN1_TAG_IA5STRING:
    159 			wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String",
    160 					  pos, hdr.length);
    161 			pos += hdr.length;
    162 			break;
    163 		case ASN1_TAG_UTCTIME:
    164 			wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME",
    165 					  pos, hdr.length);
    166 			pos += hdr.length;
    167 			break;
    168 		case ASN1_TAG_VISIBLESTRING:
    169 			wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString",
    170 					  pos, hdr.length);
    171 			pos += hdr.length;
    172 			break;
    173 		default:
    174 			wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d",
    175 				   hdr.tag);
    176 			return -1;
    177 		}
    178 	}
    179 
    180 	return 0;
    181 }
    182 
    183 
    184 int main(int argc, char *argv[])
    185 {
    186 	FILE *f;
    187 	u8 buf[3000];
    188 	size_t len;
    189 	struct x509_certificate *cert;
    190 
    191 	wpa_debug_level = 0;
    192 
    193 	f = fopen(argv[1], "rb");
    194 	if (f == NULL)
    195 		return -1;
    196 	len = fread(buf, 1, sizeof(buf), f);
    197 	fclose(f);
    198 
    199 	if (asn1_parse(buf, len, 0) < 0)
    200 		printf("Failed to parse DER ASN.1\n");
    201 
    202 	printf("\n\n");
    203 
    204 	cert = x509_certificate_parse(buf, len);
    205 	if (cert == NULL)
    206 		printf("Failed to parse X.509 certificate\n");
    207 	x509_certificate_free(cert);
    208 
    209 	return 0;
    210 }
    211