00001
00016 #include "includes.h"
00017
00018 #include "common.h"
00019 #include "asn1.h"
00020 #include "x509v3.h"
00021
00022 extern int wpa_debug_level;
00023
00024
00025 static const char * asn1_class_str(int class)
00026 {
00027 switch (class) {
00028 case ASN1_CLASS_UNIVERSAL:
00029 return "Universal";
00030 case ASN1_CLASS_APPLICATION:
00031 return "Application";
00032 case ASN1_CLASS_CONTEXT_SPECIFIC:
00033 return "Context-specific";
00034 case ASN1_CLASS_PRIVATE:
00035 return "Private";
00036 default:
00037 return "?";
00038 }
00039 }
00040
00041
00042 int asn1_parse(const u8 *buf, size_t len, int level)
00043 {
00044 const u8 *pos, *prev, *end;
00045 char prefix[10], str[100];
00046 int _level;
00047 struct asn1_hdr hdr;
00048 struct asn1_oid oid;
00049 u8 tmp;
00050
00051 _level = level;
00052 if ((size_t) _level > sizeof(prefix) - 1)
00053 _level = sizeof(prefix) - 1;
00054 memset(prefix, ' ', _level);
00055 prefix[_level] = '\0';
00056
00057 pos = buf;
00058 end = buf + len;
00059
00060 while (pos < end) {
00061 if (asn1_get_next(pos, end - pos, &hdr) < 0)
00062 return -1;
00063
00064 prev = pos;
00065 pos = hdr.payload;
00066
00067 wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) "
00068 "Tag %u Length %u",
00069 prefix, hdr.class, asn1_class_str(hdr.class),
00070 hdr.constructed,
00071 hdr.constructed ? "Constructed" : "Primitive",
00072 hdr.tag, hdr.length);
00073
00074 if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC &&
00075 hdr.constructed) {
00076 if (asn1_parse(pos, hdr.length, level + 1) < 0)
00077 return -1;
00078 pos += hdr.length;
00079 }
00080
00081 if (hdr.class != ASN1_CLASS_UNIVERSAL)
00082 continue;
00083
00084 switch (hdr.tag) {
00085 case ASN1_TAG_EOC:
00086 if (hdr.length) {
00087 wpa_printf(MSG_DEBUG, "ASN.1: Non-zero "
00088 "end-of-contents length (%u)",
00089 hdr.length);
00090 return -1;
00091 }
00092 wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix);
00093 break;
00094 case ASN1_TAG_BOOLEAN:
00095 if (hdr.length != 1) {
00096 wpa_printf(MSG_DEBUG, "ASN.1: Unexpected "
00097 "Boolean length (%u)", hdr.length);
00098 return -1;
00099 }
00100 tmp = *pos++;
00101 wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s",
00102 prefix, tmp ? "TRUE" : "FALSE");
00103 break;
00104 case ASN1_TAG_INTEGER:
00105 wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER",
00106 pos, hdr.length);
00107 pos += hdr.length;
00108 break;
00109 case ASN1_TAG_BITSTRING:
00110 wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString",
00111 pos, hdr.length);
00112 pos += hdr.length;
00113 break;
00114 case ASN1_TAG_OCTETSTRING:
00115 wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString",
00116 pos, hdr.length);
00117 pos += hdr.length;
00118 break;
00119 case ASN1_TAG_NULL:
00120 if (hdr.length) {
00121 wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null "
00122 "length (%u)", hdr.length);
00123 return -1;
00124 }
00125 wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix);
00126 break;
00127 case ASN1_TAG_OID:
00128 if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) {
00129 wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID");
00130 return -1;
00131 }
00132 asn1_oid_to_str(&oid, str, sizeof(str));
00133 wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str);
00134 pos += hdr.length;
00135 break;
00136 case ANS1_TAG_RELATIVE_OID:
00137 wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID",
00138 pos, hdr.length);
00139 pos += hdr.length;
00140 break;
00141 case ASN1_TAG_SEQUENCE:
00142 wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix);
00143 if (asn1_parse(pos, hdr.length, level + 1) < 0)
00144 return -1;
00145 pos += hdr.length;
00146 break;
00147 case ASN1_TAG_SET:
00148 wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix);
00149 if (asn1_parse(pos, hdr.length, level + 1) < 0)
00150 return -1;
00151 pos += hdr.length;
00152 break;
00153 case ASN1_TAG_PRINTABLESTRING:
00154 wpa_hexdump_ascii(MSG_MSGDUMP,
00155 "ASN.1: PrintableString",
00156 pos, hdr.length);
00157 pos += hdr.length;
00158 break;
00159 case ASN1_TAG_IA5STRING:
00160 wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String",
00161 pos, hdr.length);
00162 pos += hdr.length;
00163 break;
00164 case ASN1_TAG_UTCTIME:
00165 wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME",
00166 pos, hdr.length);
00167 pos += hdr.length;
00168 break;
00169 case ASN1_TAG_VISIBLESTRING:
00170 wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString",
00171 pos, hdr.length);
00172 pos += hdr.length;
00173 break;
00174 default:
00175 wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d",
00176 hdr.tag);
00177 return -1;
00178 }
00179 }
00180
00181 return 0;
00182 }
00183
00184
00185 int main(int argc, char *argv[])
00186 {
00187 FILE *f;
00188 u8 buf[3000];
00189 size_t len;
00190 struct x509_certificate *cert;
00191
00192 wpa_debug_level = 0;
00193
00194 f = fopen(argv[1], "rb");
00195 if (f == NULL)
00196 return -1;
00197 len = fread(buf, 1, sizeof(buf), f);
00198 fclose(f);
00199
00200 if (asn1_parse(buf, len, 0) < 0)
00201 printf("Failed to parse DER ASN.1\n");
00202
00203 printf("\n\n");
00204
00205 cert = x509_certificate_parse(buf, len);
00206 if (cert == NULL)
00207 printf("Failed to parse X.509 certificate\n");
00208 x509_certificate_free(cert);
00209
00210 return 0;
00211 }
00212