]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/tls/x509v3.c
Remove src/crypto from default include path
[thirdparty/hostap.git] / src / tls / x509v3.c
CommitLineData
6fc6879b
JM
1/*
2 * X.509v3 certificate parsing and processing (RFC 3280 profile)
3 * Copyright (c) 2006-2007, Jouni Malinen <j@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
19#ifdef CONFIG_INTERNAL_X509
20
03da66bd 21#include "crypto/crypto.h"
6fc6879b 22#include "asn1.h"
6fc6879b
JM
23#include "x509v3.h"
24
25
26static void x509_free_name(struct x509_name *name)
27{
28 os_free(name->cn);
29 os_free(name->c);
30 os_free(name->l);
31 os_free(name->st);
32 os_free(name->o);
33 os_free(name->ou);
34 os_free(name->email);
35 name->cn = name->c = name->l = name->st = name->o = name->ou = NULL;
36 name->email = NULL;
efe22727
JM
37
38 os_free(name->alt_email);
39 os_free(name->dns);
40 os_free(name->uri);
41 os_free(name->ip);
42 name->alt_email = name->dns = name->uri = NULL;
43 name->ip = NULL;
44 name->ip_len = 0;
45 os_memset(&name->rid, 0, sizeof(name->rid));
6fc6879b
JM
46}
47
48
49/**
50 * x509_certificate_free - Free an X.509 certificate
51 * @cert: Certificate to be freed
52 */
53void x509_certificate_free(struct x509_certificate *cert)
54{
55 if (cert == NULL)
56 return;
57 if (cert->next) {
58 wpa_printf(MSG_DEBUG, "X509: x509_certificate_free: cer=%p "
59 "was still on a list (next=%p)\n",
60 cert, cert->next);
61 }
62 x509_free_name(&cert->issuer);
63 x509_free_name(&cert->subject);
64 os_free(cert->public_key);
65 os_free(cert->sign_value);
66 os_free(cert);
67}
68
69
70/**
71 * x509_certificate_free - Free an X.509 certificate chain
72 * @cert: Pointer to the first certificate in the chain
73 */
74void x509_certificate_chain_free(struct x509_certificate *cert)
75{
76 struct x509_certificate *next;
77
78 while (cert) {
79 next = cert->next;
80 cert->next = NULL;
81 x509_certificate_free(cert);
82 cert = next;
83 }
84}
85
86
87static int x509_whitespace(char c)
88{
89 return c == ' ' || c == '\t';
90}
91
92
93static void x509_str_strip_whitespace(char *a)
94{
95 char *ipos, *opos;
96 int remove_whitespace = 1;
97
98 ipos = opos = a;
99
100 while (*ipos) {
101 if (remove_whitespace && x509_whitespace(*ipos))
102 ipos++;
103 else {
104 remove_whitespace = x509_whitespace(*ipos);
105 *opos++ = *ipos++;
106 }
107 }
108
109 *opos-- = '\0';
110 if (opos > a && x509_whitespace(*opos))
111 *opos = '\0';
112}
113
114
115static int x509_str_compare(const char *a, const char *b)
116{
117 char *aa, *bb;
118 int ret;
119
120 if (!a && b)
121 return -1;
122 if (a && !b)
123 return 1;
124 if (!a && !b)
125 return 0;
126
127 aa = os_strdup(a);
128 bb = os_strdup(b);
129
130 if (aa == NULL || bb == NULL) {
131 os_free(aa);
132 os_free(bb);
133 return os_strcasecmp(a, b);
134 }
135
136 x509_str_strip_whitespace(aa);
137 x509_str_strip_whitespace(bb);
138
139 ret = os_strcasecmp(aa, bb);
140
141 os_free(aa);
142 os_free(bb);
143
144 return ret;
145}
146
147
148/**
149 * x509_name_compare - Compare X.509 certificate names
150 * @a: Certificate name
151 * @b: Certificate name
152 * Returns: <0, 0, or >0 based on whether a is less than, equal to, or
153 * greater than b
154 */
155int x509_name_compare(struct x509_name *a, struct x509_name *b)
156{
157 int res;
158
159 if (!a && b)
160 return -1;
161 if (a && !b)
162 return 1;
163 if (!a && !b)
164 return 0;
165
166 res = x509_str_compare(a->cn, b->cn);
167 if (res)
168 return res;
169 res = x509_str_compare(a->c, b->c);
170 if (res)
171 return res;
172 res = x509_str_compare(a->l, b->l);
173 if (res)
174 return res;
175 res = x509_str_compare(a->st, b->st);
176 if (res)
177 return res;
178 res = x509_str_compare(a->o, b->o);
179 if (res)
180 return res;
181 res = x509_str_compare(a->ou, b->ou);
182 if (res)
183 return res;
184 res = x509_str_compare(a->email, b->email);
185 if (res)
186 return res;
187
188 return 0;
189}
190
191
192static int x509_parse_algorithm_identifier(
193 const u8 *buf, size_t len,
194 struct x509_algorithm_identifier *id, const u8 **next)
195{
196 struct asn1_hdr hdr;
197 const u8 *pos, *end;
198
199 /*
200 * AlgorithmIdentifier ::= SEQUENCE {
201 * algorithm OBJECT IDENTIFIER,
202 * parameters ANY DEFINED BY algorithm OPTIONAL
203 * }
204 */
205
206 if (asn1_get_next(buf, len, &hdr) < 0 ||
207 hdr.class != ASN1_CLASS_UNIVERSAL ||
208 hdr.tag != ASN1_TAG_SEQUENCE) {
209 wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
210 "(AlgorithmIdentifier) - found class %d tag 0x%x",
211 hdr.class, hdr.tag);
212 return -1;
213 }
214 pos = hdr.payload;
215 end = pos + hdr.length;
216
217 if (end > buf + len)
218 return -1;
219
220 *next = end;
221
222 if (asn1_get_oid(pos, end - pos, &id->oid, &pos))
223 return -1;
224
225 /* TODO: optional parameters */
226
227 return 0;
228}
229
230
231static int x509_parse_public_key(const u8 *buf, size_t len,
232 struct x509_certificate *cert,
233 const u8 **next)
234{
235 struct asn1_hdr hdr;
236 const u8 *pos, *end;
237
238 /*
239 * SubjectPublicKeyInfo ::= SEQUENCE {
240 * algorithm AlgorithmIdentifier,
241 * subjectPublicKey BIT STRING
242 * }
243 */
244
245 pos = buf;
246 end = buf + len;
247
248 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
249 hdr.class != ASN1_CLASS_UNIVERSAL ||
250 hdr.tag != ASN1_TAG_SEQUENCE) {
251 wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
252 "(SubjectPublicKeyInfo) - found class %d tag 0x%x",
253 hdr.class, hdr.tag);
254 return -1;
255 }
256 pos = hdr.payload;
257
258 if (pos + hdr.length > end)
259 return -1;
260 end = pos + hdr.length;
261 *next = end;
262
263 if (x509_parse_algorithm_identifier(pos, end - pos,
264 &cert->public_key_alg, &pos))
265 return -1;
266
267 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
268 hdr.class != ASN1_CLASS_UNIVERSAL ||
269 hdr.tag != ASN1_TAG_BITSTRING) {
270 wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING "
271 "(subjectPublicKey) - found class %d tag 0x%x",
272 hdr.class, hdr.tag);
273 return -1;
274 }
275 if (hdr.length < 1)
276 return -1;
277 pos = hdr.payload;
278 if (*pos) {
279 wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits",
280 *pos);
281 /*
282 * TODO: should this be rejected? X.509 certificates are
283 * unlikely to use such a construction. Now we would end up
284 * including the extra bits in the buffer which may also be
285 * ok.
286 */
287 }
288 os_free(cert->public_key);
289 cert->public_key = os_malloc(hdr.length - 1);
290 if (cert->public_key == NULL) {
291 wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for "
292 "public key");
293 return -1;
294 }
295 os_memcpy(cert->public_key, pos + 1, hdr.length - 1);
296 cert->public_key_len = hdr.length - 1;
297 wpa_hexdump(MSG_MSGDUMP, "X509: subjectPublicKey",
298 cert->public_key, cert->public_key_len);
299
300 return 0;
301}
302
303
304static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
305 const u8 **next)
306{
307 struct asn1_hdr hdr;
308 const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end;
309 struct asn1_oid oid;
310 char **fieldp;
311
312 /*
313 * Name ::= CHOICE { RDNSequence }
314 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
315 * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
316 * AttributeTypeAndValue ::= SEQUENCE {
317 * type AttributeType,
318 * value AttributeValue
319 * }
320 * AttributeType ::= OBJECT IDENTIFIER
321 * AttributeValue ::= ANY DEFINED BY AttributeType
322 */
323
324 if (asn1_get_next(buf, len, &hdr) < 0 ||
325 hdr.class != ASN1_CLASS_UNIVERSAL ||
326 hdr.tag != ASN1_TAG_SEQUENCE) {
327 wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
328 "(Name / RDNSequencer) - found class %d tag 0x%x",
329 hdr.class, hdr.tag);
330 return -1;
331 }
332 pos = hdr.payload;
333
334 if (pos + hdr.length > buf + len)
335 return -1;
336
337 end = *next = pos + hdr.length;
338
339 while (pos < end) {
340 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
341 hdr.class != ASN1_CLASS_UNIVERSAL ||
342 hdr.tag != ASN1_TAG_SET) {
343 wpa_printf(MSG_DEBUG, "X509: Expected SET "
344 "(RelativeDistinguishedName) - found class "
345 "%d tag 0x%x", hdr.class, hdr.tag);
346 x509_free_name(name);
347 return -1;
348 }
349
350 set_pos = hdr.payload;
351 pos = set_end = hdr.payload + hdr.length;
352
353 if (asn1_get_next(set_pos, set_end - set_pos, &hdr) < 0 ||
354 hdr.class != ASN1_CLASS_UNIVERSAL ||
355 hdr.tag != ASN1_TAG_SEQUENCE) {
356 wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
357 "(AttributeTypeAndValue) - found class %d "
358 "tag 0x%x", hdr.class, hdr.tag);
359 x509_free_name(name);
360 return -1;
361 }
362
363 seq_pos = hdr.payload;
364 seq_end = hdr.payload + hdr.length;
365
366 if (asn1_get_oid(seq_pos, seq_end - seq_pos, &oid, &seq_pos)) {
367 x509_free_name(name);
368 return -1;
369 }
370
371 if (asn1_get_next(seq_pos, seq_end - seq_pos, &hdr) < 0 ||
372 hdr.class != ASN1_CLASS_UNIVERSAL) {
373 wpa_printf(MSG_DEBUG, "X509: Failed to parse "
374 "AttributeValue");
375 x509_free_name(name);
376 return -1;
377 }
378
379 /* RFC 3280:
380 * MUST: country, organization, organizational-unit,
381 * distinguished name qualifier, state or province name,
382 * common name, serial number.
383 * SHOULD: locality, title, surname, given name, initials,
384 * pseudonym, generation qualifier.
385 * MUST: domainComponent (RFC 2247).
386 */
387 fieldp = NULL;
388 if (oid.len == 4 &&
389 oid.oid[0] == 2 && oid.oid[1] == 5 && oid.oid[2] == 4) {
390 /* id-at ::= 2.5.4 */
391 switch (oid.oid[3]) {
392 case 3:
393 /* commonName */
394 fieldp = &name->cn;
395 break;
396 case 6:
397 /* countryName */
398 fieldp = &name->c;
399 break;
400 case 7:
401 /* localityName */
402 fieldp = &name->l;
403 break;
404 case 8:
405 /* stateOrProvinceName */
406 fieldp = &name->st;
407 break;
408 case 10:
409 /* organizationName */
410 fieldp = &name->o;
411 break;
412 case 11:
413 /* organizationalUnitName */
414 fieldp = &name->ou;
415 break;
416 }
417 } else if (oid.len == 7 &&
418 oid.oid[0] == 1 && oid.oid[1] == 2 &&
419 oid.oid[2] == 840 && oid.oid[3] == 113549 &&
420 oid.oid[4] == 1 && oid.oid[5] == 9 &&
421 oid.oid[6] == 1) {
422 /* 1.2.840.113549.1.9.1 - e-mailAddress */
423 fieldp = &name->email;
424 }
425
426 if (fieldp == NULL) {
427 wpa_hexdump(MSG_DEBUG, "X509: Unrecognized OID",
428 (u8 *) oid.oid,
429 oid.len * sizeof(oid.oid[0]));
430 wpa_hexdump_ascii(MSG_MSGDUMP, "X509: Attribute Data",
431 hdr.payload, hdr.length);
432 continue;
433 }
434
435 os_free(*fieldp);
436 *fieldp = os_malloc(hdr.length + 1);
437 if (*fieldp == NULL) {
438 x509_free_name(name);
439 return -1;
440 }
441 os_memcpy(*fieldp, hdr.payload, hdr.length);
442 (*fieldp)[hdr.length] = '\0';
ad469aec
JM
443 if (os_strlen(*fieldp) != hdr.length) {
444 wpa_printf(MSG_INFO, "X509: Reject certificate with "
445 "embedded NUL byte in a string (%s[NUL])",
446 *fieldp);
447 x509_free_name(name);
448 return -1;
449 }
6fc6879b
JM
450 }
451
452 return 0;
453}
454
455
456/**
457 * x509_name_string - Convert an X.509 certificate name into a string
458 * @name: Name to convert
459 * @buf: Buffer for the string
460 * @len: Maximum buffer length
461 */
462void x509_name_string(struct x509_name *name, char *buf, size_t len)
463{
464 char *pos, *end;
465 int ret;
466
467 if (len == 0)
468 return;
469
470 pos = buf;
471 end = buf + len;
472
473 if (name->c) {
474 ret = os_snprintf(pos, end - pos, "C=%s, ", name->c);
475 if (ret < 0 || ret >= end - pos)
476 goto done;
477 pos += ret;
478 }
479 if (name->st) {
480 ret = os_snprintf(pos, end - pos, "ST=%s, ", name->st);
481 if (ret < 0 || ret >= end - pos)
482 goto done;
483 pos += ret;
484 }
485 if (name->l) {
486 ret = os_snprintf(pos, end - pos, "L=%s, ", name->l);
487 if (ret < 0 || ret >= end - pos)
488 goto done;
489 pos += ret;
490 }
491 if (name->o) {
492 ret = os_snprintf(pos, end - pos, "O=%s, ", name->o);
493 if (ret < 0 || ret >= end - pos)
494 goto done;
495 pos += ret;
496 }
497 if (name->ou) {
498 ret = os_snprintf(pos, end - pos, "OU=%s, ", name->ou);
499 if (ret < 0 || ret >= end - pos)
500 goto done;
501 pos += ret;
502 }
503 if (name->cn) {
504 ret = os_snprintf(pos, end - pos, "CN=%s, ", name->cn);
505 if (ret < 0 || ret >= end - pos)
506 goto done;
507 pos += ret;
508 }
509
510 if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') {
511 *pos-- = '\0';
512 *pos-- = '\0';
513 }
514
515 if (name->email) {
516 ret = os_snprintf(pos, end - pos, "/emailAddress=%s",
517 name->email);
518 if (ret < 0 || ret >= end - pos)
519 goto done;
520 pos += ret;
521 }
522
523done:
524 end[-1] = '\0';
525}
526
527
528static int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag,
529 os_time_t *val)
530{
531 const char *pos;
532 int year, month, day, hour, min, sec;
533
534 /*
535 * Time ::= CHOICE {
536 * utcTime UTCTime,
537 * generalTime GeneralizedTime
538 * }
539 *
540 * UTCTime: YYMMDDHHMMSSZ
541 * GeneralizedTime: YYYYMMDDHHMMSSZ
542 */
543
544 pos = (const char *) buf;
545
546 switch (asn1_tag) {
547 case ASN1_TAG_UTCTIME:
548 if (len != 13 || buf[12] != 'Z') {
549 wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized "
550 "UTCTime format", buf, len);
551 return -1;
552 }
553 if (sscanf(pos, "%02d", &year) != 1) {
554 wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse "
555 "UTCTime year", buf, len);
556 return -1;
557 }
558 if (year < 50)
559 year += 2000;
560 else
561 year += 1900;
562 pos += 2;
563 break;
564 case ASN1_TAG_GENERALIZEDTIME:
565 if (len != 15 || buf[14] != 'Z') {
566 wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized "
567 "GeneralizedTime format", buf, len);
568 return -1;
569 }
570 if (sscanf(pos, "%04d", &year) != 1) {
571 wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse "
572 "GeneralizedTime year", buf, len);
573 return -1;
574 }
575 pos += 4;
576 break;
577 default:
578 wpa_printf(MSG_DEBUG, "X509: Expected UTCTime or "
579 "GeneralizedTime - found tag 0x%x", asn1_tag);
580 return -1;
581 }
582
583 if (sscanf(pos, "%02d", &month) != 1) {
584 wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time "
585 "(month)", buf, len);
586 return -1;
587 }
588 pos += 2;
589
590 if (sscanf(pos, "%02d", &day) != 1) {
591 wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time "
592 "(day)", buf, len);
593 return -1;
594 }
595 pos += 2;
596
597 if (sscanf(pos, "%02d", &hour) != 1) {
598 wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time "
599 "(hour)", buf, len);
600 return -1;
601 }
602 pos += 2;
603
604 if (sscanf(pos, "%02d", &min) != 1) {
605 wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time "
606 "(min)", buf, len);
607 return -1;
608 }
609 pos += 2;
610
611 if (sscanf(pos, "%02d", &sec) != 1) {
612 wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time "
613 "(sec)", buf, len);
614 return -1;
615 }
616
617 if (os_mktime(year, month, day, hour, min, sec, val) < 0) {
618 wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time",
619 buf, len);
620 if (year < 1970) {
621 /*
622 * At least some test certificates have been configured
623 * to use dates prior to 1970. Set the date to
624 * beginning of 1970 to handle these case.
625 */
626 wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - "
627 "assume epoch as the time", year);
628 *val = 0;
629 return 0;
630 }
631 return -1;
632 }
633
634 return 0;
635}
636
637
638static int x509_parse_validity(const u8 *buf, size_t len,
639 struct x509_certificate *cert, const u8 **next)
640{
641 struct asn1_hdr hdr;
642 const u8 *pos;
643 size_t plen;
644
645 /*
646 * Validity ::= SEQUENCE {
647 * notBefore Time,
648 * notAfter Time
649 * }
650 *
651 * RFC 3280, 4.1.2.5:
652 * CAs conforming to this profile MUST always encode certificate
653 * validity dates through the year 2049 as UTCTime; certificate
654 * validity dates in 2050 or later MUST be encoded as GeneralizedTime.
655 */
656
657 if (asn1_get_next(buf, len, &hdr) < 0 ||
658 hdr.class != ASN1_CLASS_UNIVERSAL ||
659 hdr.tag != ASN1_TAG_SEQUENCE) {
660 wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
661 "(Validity) - found class %d tag 0x%x",
662 hdr.class, hdr.tag);
663 return -1;
664 }
665 pos = hdr.payload;
666 plen = hdr.length;
667
668 if (pos + plen > buf + len)
669 return -1;
670
671 *next = pos + plen;
672
673 if (asn1_get_next(pos, plen, &hdr) < 0 ||
674 hdr.class != ASN1_CLASS_UNIVERSAL ||
675 x509_parse_time(hdr.payload, hdr.length, hdr.tag,
676 &cert->not_before) < 0) {
677 wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notBefore "
678 "Time", hdr.payload, hdr.length);
679 return -1;
680 }
681
682 pos = hdr.payload + hdr.length;
683 plen = *next - pos;
684
685 if (asn1_get_next(pos, plen, &hdr) < 0 ||
686 hdr.class != ASN1_CLASS_UNIVERSAL ||
687 x509_parse_time(hdr.payload, hdr.length, hdr.tag,
688 &cert->not_after) < 0) {
689 wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notAfter "
690 "Time", hdr.payload, hdr.length);
691 return -1;
692 }
693
694 wpa_printf(MSG_MSGDUMP, "X509: Validity: notBefore: %lu notAfter: %lu",
695 (unsigned long) cert->not_before,
696 (unsigned long) cert->not_after);
697
698 return 0;
699}
700
701
702static int x509_id_ce_oid(struct asn1_oid *oid)
703{
704 /* id-ce arc from X.509 for standard X.509v3 extensions */
705 return oid->len >= 4 &&
706 oid->oid[0] == 2 /* joint-iso-ccitt */ &&
707 oid->oid[1] == 5 /* ds */ &&
708 oid->oid[2] == 29 /* id-ce */;
709}
710
711
712static int x509_parse_ext_key_usage(struct x509_certificate *cert,
713 const u8 *pos, size_t len)
714{
715 struct asn1_hdr hdr;
716
717 /*
718 * KeyUsage ::= BIT STRING {
719 * digitalSignature (0),
720 * nonRepudiation (1),
721 * keyEncipherment (2),
722 * dataEncipherment (3),
723 * keyAgreement (4),
724 * keyCertSign (5),
725 * cRLSign (6),
726 * encipherOnly (7),
727 * decipherOnly (8) }
728 */
729
730 if (asn1_get_next(pos, len, &hdr) < 0 ||
731 hdr.class != ASN1_CLASS_UNIVERSAL ||
732 hdr.tag != ASN1_TAG_BITSTRING ||
733 hdr.length < 1) {
734 wpa_printf(MSG_DEBUG, "X509: Expected BIT STRING in "
735 "KeyUsage; found %d tag 0x%x len %d",
736 hdr.class, hdr.tag, hdr.length);
737 return -1;
738 }
739
740 cert->extensions_present |= X509_EXT_KEY_USAGE;
741 cert->key_usage = asn1_bit_string_to_long(hdr.payload, hdr.length);
742
743 wpa_printf(MSG_DEBUG, "X509: KeyUsage 0x%lx", cert->key_usage);
744
745 return 0;
746}
747
748
749static int x509_parse_ext_basic_constraints(struct x509_certificate *cert,
750 const u8 *pos, size_t len)
751{
752 struct asn1_hdr hdr;
753 unsigned long value;
754 size_t left;
755
756 /*
757 * BasicConstraints ::= SEQUENCE {
758 * cA BOOLEAN DEFAULT FALSE,
759 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
760 */
761
762 if (asn1_get_next(pos, len, &hdr) < 0 ||
763 hdr.class != ASN1_CLASS_UNIVERSAL ||
764 hdr.tag != ASN1_TAG_SEQUENCE) {
765 wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in "
766 "BasicConstraints; found %d tag 0x%x",
767 hdr.class, hdr.tag);
768 return -1;
769 }
770
771 cert->extensions_present |= X509_EXT_BASIC_CONSTRAINTS;
772
773 if (hdr.length == 0)
774 return 0;
775
776 if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
777 hdr.class != ASN1_CLASS_UNIVERSAL) {
778 wpa_printf(MSG_DEBUG, "X509: Failed to parse "
779 "BasicConstraints");
780 return -1;
781 }
782
783 if (hdr.tag == ASN1_TAG_BOOLEAN) {
784 if (hdr.length != 1) {
785 wpa_printf(MSG_DEBUG, "X509: Unexpected "
786 "Boolean length (%u) in BasicConstraints",
787 hdr.length);
788 return -1;
789 }
790 cert->ca = hdr.payload[0];
791
792 if (hdr.payload + hdr.length == pos + len) {
793 wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d",
794 cert->ca);
795 return 0;
796 }
797
798 if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length,
799 &hdr) < 0 ||
800 hdr.class != ASN1_CLASS_UNIVERSAL) {
801 wpa_printf(MSG_DEBUG, "X509: Failed to parse "
802 "BasicConstraints");
803 return -1;
804 }
805 }
806
807 if (hdr.tag != ASN1_TAG_INTEGER) {
808 wpa_printf(MSG_DEBUG, "X509: Expected INTEGER in "
809 "BasicConstraints; found class %d tag 0x%x",
810 hdr.class, hdr.tag);
811 return -1;
812 }
813
814 pos = hdr.payload;
815 left = hdr.length;
816 value = 0;
817 while (left) {
818 value <<= 8;
819 value |= *pos++;
820 left--;
821 }
822
823 cert->path_len_constraint = value;
824 cert->extensions_present |= X509_EXT_PATH_LEN_CONSTRAINT;
825
826 wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d "
827 "pathLenConstraint=%lu",
828 cert->ca, cert->path_len_constraint);
829
830 return 0;
831}
832
833
efe22727
JM
834static int x509_parse_alt_name_rfc8222(struct x509_name *name,
835 const u8 *pos, size_t len)
836{
837 /* rfc822Name IA5String */
838 wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - rfc822Name", pos, len);
839 os_free(name->alt_email);
840 name->alt_email = os_zalloc(len + 1);
841 if (name->alt_email == NULL)
842 return -1;
843 os_memcpy(name->alt_email, pos, len);
ad469aec
JM
844 if (os_strlen(name->alt_email) != len) {
845 wpa_printf(MSG_INFO, "X509: Reject certificate with "
846 "embedded NUL byte in rfc822Name (%s[NUL])",
847 name->alt_email);
848 os_free(name->alt_email);
849 name->alt_email = NULL;
850 return -1;
851 }
efe22727
JM
852 return 0;
853}
854
855
856static int x509_parse_alt_name_dns(struct x509_name *name,
857 const u8 *pos, size_t len)
858{
859 /* dNSName IA5String */
860 wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - dNSName", pos, len);
861 os_free(name->dns);
862 name->dns = os_zalloc(len + 1);
863 if (name->dns == NULL)
864 return -1;
865 os_memcpy(name->dns, pos, len);
ad469aec
JM
866 if (os_strlen(name->dns) != len) {
867 wpa_printf(MSG_INFO, "X509: Reject certificate with "
868 "embedded NUL byte in dNSName (%s[NUL])",
869 name->dns);
870 os_free(name->dns);
871 name->dns = NULL;
872 return -1;
873 }
efe22727
JM
874 return 0;
875}
876
877
878static int x509_parse_alt_name_uri(struct x509_name *name,
879 const u8 *pos, size_t len)
880{
881 /* uniformResourceIdentifier IA5String */
882 wpa_hexdump_ascii(MSG_MSGDUMP,
883 "X509: altName - uniformResourceIdentifier",
884 pos, len);
885 os_free(name->uri);
886 name->uri = os_zalloc(len + 1);
887 if (name->uri == NULL)
888 return -1;
889 os_memcpy(name->uri, pos, len);
ad469aec
JM
890 if (os_strlen(name->uri) != len) {
891 wpa_printf(MSG_INFO, "X509: Reject certificate with "
892 "embedded NUL byte in uniformResourceIdentifier "
893 "(%s[NUL])", name->uri);
894 os_free(name->uri);
895 name->uri = NULL;
896 return -1;
897 }
efe22727
JM
898 return 0;
899}
900
901
902static int x509_parse_alt_name_ip(struct x509_name *name,
903 const u8 *pos, size_t len)
904{
905 /* iPAddress OCTET STRING */
906 wpa_hexdump(MSG_MSGDUMP, "X509: altName - iPAddress", pos, len);
907 os_free(name->ip);
908 name->ip = os_malloc(len);
909 if (name->ip == NULL)
910 return -1;
911 os_memcpy(name->ip, pos, len);
912 name->ip_len = len;
913 return 0;
914}
915
916
917static int x509_parse_alt_name_rid(struct x509_name *name,
918 const u8 *pos, size_t len)
919{
920 char buf[80];
921
922 /* registeredID OBJECT IDENTIFIER */
923 if (asn1_parse_oid(pos, len, &name->rid) < 0)
924 return -1;
925
926 asn1_oid_to_str(&name->rid, buf, sizeof(buf));
927 wpa_printf(MSG_MSGDUMP, "X509: altName - registeredID: %s", buf);
928
929 return 0;
930}
931
932
933static int x509_parse_ext_alt_name(struct x509_name *name,
934 const u8 *pos, size_t len)
935{
936 struct asn1_hdr hdr;
937 const u8 *p, *end;
938
939 /*
940 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
941 *
942 * GeneralName ::= CHOICE {
943 * otherName [0] OtherName,
944 * rfc822Name [1] IA5String,
945 * dNSName [2] IA5String,
946 * x400Address [3] ORAddress,
947 * directoryName [4] Name,
948 * ediPartyName [5] EDIPartyName,
949 * uniformResourceIdentifier [6] IA5String,
950 * iPAddress [7] OCTET STRING,
951 * registeredID [8] OBJECT IDENTIFIER }
952 *
953 * OtherName ::= SEQUENCE {
954 * type-id OBJECT IDENTIFIER,
955 * value [0] EXPLICIT ANY DEFINED BY type-id }
956 *
957 * EDIPartyName ::= SEQUENCE {
958 * nameAssigner [0] DirectoryString OPTIONAL,
959 * partyName [1] DirectoryString }
960 */
961
962 for (p = pos, end = pos + len; p < end; p = hdr.payload + hdr.length) {
963 int res;
964
965 if (asn1_get_next(p, end - p, &hdr) < 0) {
966 wpa_printf(MSG_DEBUG, "X509: Failed to parse "
967 "SubjectAltName item");
968 return -1;
969 }
970
971 if (hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC)
972 continue;
973
974 switch (hdr.tag) {
975 case 1:
976 res = x509_parse_alt_name_rfc8222(name, hdr.payload,
977 hdr.length);
978 break;
979 case 2:
980 res = x509_parse_alt_name_dns(name, hdr.payload,
981 hdr.length);
982 break;
983 case 6:
984 res = x509_parse_alt_name_uri(name, hdr.payload,
985 hdr.length);
986 break;
987 case 7:
988 res = x509_parse_alt_name_ip(name, hdr.payload,
989 hdr.length);
990 break;
991 case 8:
992 res = x509_parse_alt_name_rid(name, hdr.payload,
993 hdr.length);
994 break;
995 case 0: /* TODO: otherName */
996 case 3: /* TODO: x500Address */
997 case 4: /* TODO: directoryName */
998 case 5: /* TODO: ediPartyName */
999 default:
1000 res = 0;
1001 break;
1002 }
1003 if (res < 0)
1004 return res;
1005 }
1006
1007 return 0;
1008}
1009
1010
1011static int x509_parse_ext_subject_alt_name(struct x509_certificate *cert,
1012 const u8 *pos, size_t len)
1013{
1014 struct asn1_hdr hdr;
1015
1016 /* SubjectAltName ::= GeneralNames */
1017
1018 if (asn1_get_next(pos, len, &hdr) < 0 ||
1019 hdr.class != ASN1_CLASS_UNIVERSAL ||
1020 hdr.tag != ASN1_TAG_SEQUENCE) {
1021 wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in "
1022 "SubjectAltName; found %d tag 0x%x",
1023 hdr.class, hdr.tag);
1024 return -1;
1025 }
1026
1027 wpa_printf(MSG_DEBUG, "X509: SubjectAltName");
1028 cert->extensions_present |= X509_EXT_SUBJECT_ALT_NAME;
1029
1030 if (hdr.length == 0)
1031 return 0;
1032
1033 return x509_parse_ext_alt_name(&cert->subject, hdr.payload,
1034 hdr.length);
1035}
1036
1037
1038static int x509_parse_ext_issuer_alt_name(struct x509_certificate *cert,
1039 const u8 *pos, size_t len)
1040{
1041 struct asn1_hdr hdr;
1042
1043 /* IssuerAltName ::= GeneralNames */
1044
1045 if (asn1_get_next(pos, len, &hdr) < 0 ||
1046 hdr.class != ASN1_CLASS_UNIVERSAL ||
1047 hdr.tag != ASN1_TAG_SEQUENCE) {
1048 wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in "
1049 "IssuerAltName; found %d tag 0x%x",
1050 hdr.class, hdr.tag);
1051 return -1;
1052 }
1053
1054 wpa_printf(MSG_DEBUG, "X509: IssuerAltName");
1055 cert->extensions_present |= X509_EXT_ISSUER_ALT_NAME;
1056
1057 if (hdr.length == 0)
1058 return 0;
1059
1060 return x509_parse_ext_alt_name(&cert->issuer, hdr.payload,
1061 hdr.length);
1062}
1063
1064
6fc6879b
JM
1065static int x509_parse_extension_data(struct x509_certificate *cert,
1066 struct asn1_oid *oid,
1067 const u8 *pos, size_t len)
1068{
1069 if (!x509_id_ce_oid(oid))
1070 return 1;
1071
1072 /* TODO: add other extensions required by RFC 3280, Ch 4.2:
1073 * certificate policies (section 4.2.1.5)
6fc6879b
JM
1074 * name constraints (section 4.2.1.11)
1075 * policy constraints (section 4.2.1.12)
1076 * extended key usage (section 4.2.1.13)
1077 * inhibit any-policy (section 4.2.1.15)
1078 */
1079 switch (oid->oid[3]) {
1080 case 15: /* id-ce-keyUsage */
1081 return x509_parse_ext_key_usage(cert, pos, len);
efe22727
JM
1082 case 17: /* id-ce-subjectAltName */
1083 return x509_parse_ext_subject_alt_name(cert, pos, len);
1084 case 18: /* id-ce-issuerAltName */
1085 return x509_parse_ext_issuer_alt_name(cert, pos, len);
6fc6879b
JM
1086 case 19: /* id-ce-basicConstraints */
1087 return x509_parse_ext_basic_constraints(cert, pos, len);
1088 default:
1089 return 1;
1090 }
1091}
1092
1093
1094static int x509_parse_extension(struct x509_certificate *cert,
1095 const u8 *pos, size_t len, const u8 **next)
1096{
1097 const u8 *end;
1098 struct asn1_hdr hdr;
1099 struct asn1_oid oid;
1100 int critical_ext = 0, res;
1101 char buf[80];
1102
1103 /*
1104 * Extension ::= SEQUENCE {
1105 * extnID OBJECT IDENTIFIER,
1106 * critical BOOLEAN DEFAULT FALSE,
1107 * extnValue OCTET STRING
1108 * }
1109 */
1110
1111 if (asn1_get_next(pos, len, &hdr) < 0 ||
1112 hdr.class != ASN1_CLASS_UNIVERSAL ||
1113 hdr.tag != ASN1_TAG_SEQUENCE) {
1114 wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in "
1115 "Extensions: class %d tag 0x%x; expected SEQUENCE",
1116 hdr.class, hdr.tag);
1117 return -1;
1118 }
1119 pos = hdr.payload;
1120 *next = end = pos + hdr.length;
1121
1122 if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) {
1123 wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data for "
1124 "Extension (expected OID)");
1125 return -1;
1126 }
1127
1128 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1129 hdr.class != ASN1_CLASS_UNIVERSAL ||
1130 (hdr.tag != ASN1_TAG_BOOLEAN &&
1131 hdr.tag != ASN1_TAG_OCTETSTRING)) {
1132 wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in "
1133 "Extensions: class %d tag 0x%x; expected BOOLEAN "
1134 "or OCTET STRING", hdr.class, hdr.tag);
1135 return -1;
1136 }
1137
1138 if (hdr.tag == ASN1_TAG_BOOLEAN) {
1139 if (hdr.length != 1) {
1140 wpa_printf(MSG_DEBUG, "X509: Unexpected "
1141 "Boolean length (%u)", hdr.length);
1142 return -1;
1143 }
1144 critical_ext = hdr.payload[0];
1145 pos = hdr.payload;
1146 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1147 (hdr.class != ASN1_CLASS_UNIVERSAL &&
1148 hdr.class != ASN1_CLASS_PRIVATE) ||
1149 hdr.tag != ASN1_TAG_OCTETSTRING) {
1150 wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header "
1151 "in Extensions: class %d tag 0x%x; "
1152 "expected OCTET STRING",
1153 hdr.class, hdr.tag);
1154 return -1;
1155 }
1156 }
1157
1158 asn1_oid_to_str(&oid, buf, sizeof(buf));
1159 wpa_printf(MSG_DEBUG, "X509: Extension: extnID=%s critical=%d",
1160 buf, critical_ext);
1161 wpa_hexdump(MSG_MSGDUMP, "X509: extnValue", hdr.payload, hdr.length);
1162
1163 res = x509_parse_extension_data(cert, &oid, hdr.payload, hdr.length);
1164 if (res < 0)
1165 return res;
1166 if (res == 1 && critical_ext) {
1167 wpa_printf(MSG_INFO, "X509: Unknown critical extension %s",
1168 buf);
1169 return -1;
1170 }
1171
1172 return 0;
1173}
1174
1175
1176static int x509_parse_extensions(struct x509_certificate *cert,
1177 const u8 *pos, size_t len)
1178{
1179 const u8 *end;
1180 struct asn1_hdr hdr;
1181
1182 /* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */
1183
1184 if (asn1_get_next(pos, len, &hdr) < 0 ||
1185 hdr.class != ASN1_CLASS_UNIVERSAL ||
1186 hdr.tag != ASN1_TAG_SEQUENCE) {
1187 wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data "
1188 "for Extensions: class %d tag 0x%x; "
1189 "expected SEQUENCE", hdr.class, hdr.tag);
1190 return -1;
1191 }
1192
1193 pos = hdr.payload;
1194 end = pos + hdr.length;
1195
1196 while (pos < end) {
1197 if (x509_parse_extension(cert, pos, end - pos, &pos)
1198 < 0)
1199 return -1;
1200 }
1201
1202 return 0;
1203}
1204
1205
1206static int x509_parse_tbs_certificate(const u8 *buf, size_t len,
1207 struct x509_certificate *cert,
1208 const u8 **next)
1209{
1210 struct asn1_hdr hdr;
1211 const u8 *pos, *end;
1212 size_t left;
1213 char sbuf[128];
1214 unsigned long value;
1215
1216 /* tbsCertificate TBSCertificate ::= SEQUENCE */
1217 if (asn1_get_next(buf, len, &hdr) < 0 ||
1218 hdr.class != ASN1_CLASS_UNIVERSAL ||
1219 hdr.tag != ASN1_TAG_SEQUENCE) {
1220 wpa_printf(MSG_DEBUG, "X509: tbsCertificate did not start "
1221 "with a valid SEQUENCE - found class %d tag 0x%x",
1222 hdr.class, hdr.tag);
1223 return -1;
1224 }
1225 pos = hdr.payload;
1226 end = *next = pos + hdr.length;
1227
1228 /*
1229 * version [0] EXPLICIT Version DEFAULT v1
1230 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
1231 */
1232 if (asn1_get_next(pos, end - pos, &hdr) < 0)
1233 return -1;
1234 pos = hdr.payload;
1235
1236 if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC) {
1237 if (asn1_get_next(pos, end - pos, &hdr) < 0)
1238 return -1;
1239
1240 if (hdr.class != ASN1_CLASS_UNIVERSAL ||
1241 hdr.tag != ASN1_TAG_INTEGER) {
1242 wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for "
1243 "version field - found class %d tag 0x%x",
1244 hdr.class, hdr.tag);
1245 return -1;
1246 }
1247 if (hdr.length != 1) {
1248 wpa_printf(MSG_DEBUG, "X509: Unexpected version field "
1249 "length %u (expected 1)", hdr.length);
1250 return -1;
1251 }
1252 pos = hdr.payload;
1253 left = hdr.length;
1254 value = 0;
1255 while (left) {
1256 value <<= 8;
1257 value |= *pos++;
1258 left--;
1259 }
1260
1261 cert->version = value;
1262 if (cert->version != X509_CERT_V1 &&
1263 cert->version != X509_CERT_V2 &&
1264 cert->version != X509_CERT_V3) {
1265 wpa_printf(MSG_DEBUG, "X509: Unsupported version %d",
1266 cert->version + 1);
1267 return -1;
1268 }
1269
1270 if (asn1_get_next(pos, end - pos, &hdr) < 0)
1271 return -1;
1272 } else
1273 cert->version = X509_CERT_V1;
1274 wpa_printf(MSG_MSGDUMP, "X509: Version X.509v%d", cert->version + 1);
1275
1276 /* serialNumber CertificateSerialNumber ::= INTEGER */
1277 if (hdr.class != ASN1_CLASS_UNIVERSAL ||
1278 hdr.tag != ASN1_TAG_INTEGER) {
1279 wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for "
1280 "serialNumber; class=%d tag=0x%x",
1281 hdr.class, hdr.tag);
1282 return -1;
1283 }
1284
1285 pos = hdr.payload;
1286 left = hdr.length;
1287 while (left) {
1288 cert->serial_number <<= 8;
1289 cert->serial_number |= *pos++;
1290 left--;
1291 }
1292 wpa_printf(MSG_MSGDUMP, "X509: serialNumber %lu", cert->serial_number);
1293
1294 /* signature AlgorithmIdentifier */
1295 if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature,
1296 &pos))
1297 return -1;
1298
1299 /* issuer Name */
1300 if (x509_parse_name(pos, end - pos, &cert->issuer, &pos))
1301 return -1;
1302 x509_name_string(&cert->issuer, sbuf, sizeof(sbuf));
1303 wpa_printf(MSG_MSGDUMP, "X509: issuer %s", sbuf);
1304
1305 /* validity Validity */
1306 if (x509_parse_validity(pos, end - pos, cert, &pos))
1307 return -1;
1308
1309 /* subject Name */
1310 if (x509_parse_name(pos, end - pos, &cert->subject, &pos))
1311 return -1;
1312 x509_name_string(&cert->subject, sbuf, sizeof(sbuf));
1313 wpa_printf(MSG_MSGDUMP, "X509: subject %s", sbuf);
1314
1315 /* subjectPublicKeyInfo SubjectPublicKeyInfo */
1316 if (x509_parse_public_key(pos, end - pos, cert, &pos))
1317 return -1;
1318
1319 if (pos == end)
1320 return 0;
1321
1322 if (cert->version == X509_CERT_V1)
1323 return 0;
1324
1325 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1326 hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
1327 wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific"
1328 " tag to parse optional tbsCertificate "
1329 "field(s); parsed class %d tag 0x%x",
1330 hdr.class, hdr.tag);
1331 return -1;
1332 }
1333
1334 if (hdr.tag == 1) {
1335 /* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL */
1336 wpa_printf(MSG_DEBUG, "X509: issuerUniqueID");
1337 /* TODO: parse UniqueIdentifier ::= BIT STRING */
1338
1339 if (hdr.payload + hdr.length == end)
1340 return 0;
1341
1342 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1343 hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
1344 wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific"
1345 " tag to parse optional tbsCertificate "
1346 "field(s); parsed class %d tag 0x%x",
1347 hdr.class, hdr.tag);
1348 return -1;
1349 }
1350 }
1351
1352 if (hdr.tag == 2) {
1353 /* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL */
1354 wpa_printf(MSG_DEBUG, "X509: subjectUniqueID");
1355 /* TODO: parse UniqueIdentifier ::= BIT STRING */
1356
1357 if (hdr.payload + hdr.length == end)
1358 return 0;
1359
1360 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1361 hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
1362 wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific"
1363 " tag to parse optional tbsCertificate "
1364 "field(s); parsed class %d tag 0x%x",
1365 hdr.class, hdr.tag);
1366 return -1;
1367 }
1368 }
1369
1370 if (hdr.tag != 3) {
1371 wpa_printf(MSG_DEBUG, "X509: Ignored unexpected "
1372 "Context-Specific tag %d in optional "
1373 "tbsCertificate fields", hdr.tag);
1374 return 0;
1375 }
1376
1377 /* extensions [3] EXPLICIT Extensions OPTIONAL */
1378
1379 if (cert->version != X509_CERT_V3) {
1380 wpa_printf(MSG_DEBUG, "X509: X.509%d certificate and "
1381 "Extensions data which are only allowed for "
1382 "version 3", cert->version + 1);
1383 return -1;
1384 }
1385
1386 if (x509_parse_extensions(cert, hdr.payload, hdr.length) < 0)
1387 return -1;
1388
1389 pos = hdr.payload + hdr.length;
1390 if (pos < end) {
1391 wpa_hexdump(MSG_DEBUG,
1392 "X509: Ignored extra tbsCertificate data",
1393 pos, end - pos);
1394 }
1395
1396 return 0;
1397}
1398
1399
1400static int x509_rsadsi_oid(struct asn1_oid *oid)
1401{
1402 return oid->len >= 4 &&
1403 oid->oid[0] == 1 /* iso */ &&
1404 oid->oid[1] == 2 /* member-body */ &&
1405 oid->oid[2] == 840 /* us */ &&
1406 oid->oid[3] == 113549 /* rsadsi */;
1407}
1408
1409
1410static int x509_pkcs_oid(struct asn1_oid *oid)
1411{
1412 return oid->len >= 5 &&
1413 x509_rsadsi_oid(oid) &&
1414 oid->oid[4] == 1 /* pkcs */;
1415}
1416
1417
1418static int x509_digest_oid(struct asn1_oid *oid)
1419{
1420 return oid->len >= 5 &&
1421 x509_rsadsi_oid(oid) &&
1422 oid->oid[4] == 2 /* digestAlgorithm */;
1423}
1424
1425
1426static int x509_sha1_oid(struct asn1_oid *oid)
1427{
1428 return oid->len == 6 &&
1429 oid->oid[0] == 1 /* iso */ &&
1430 oid->oid[1] == 3 /* identified-organization */ &&
1431 oid->oid[2] == 14 /* oiw */ &&
1432 oid->oid[3] == 3 /* secsig */ &&
1433 oid->oid[4] == 2 /* algorithms */ &&
1434 oid->oid[5] == 26 /* id-sha1 */;
1435}
1436
1437
1d8ce433
JM
1438static int x509_sha256_oid(struct asn1_oid *oid)
1439{
1440 return oid->len == 9 &&
1441 oid->oid[0] == 2 /* joint-iso-itu-t */ &&
1442 oid->oid[1] == 16 /* country */ &&
1443 oid->oid[2] == 840 /* us */ &&
1444 oid->oid[3] == 1 /* organization */ &&
1445 oid->oid[4] == 101 /* gov */ &&
1446 oid->oid[5] == 3 /* csor */ &&
1447 oid->oid[6] == 4 /* nistAlgorithm */ &&
1448 oid->oid[7] == 2 /* hashAlgs */ &&
1449 oid->oid[8] == 1 /* sha256 */;
1450}
1451
1452
6fc6879b
JM
1453/**
1454 * x509_certificate_parse - Parse a X.509 certificate in DER format
1455 * @buf: Pointer to the X.509 certificate in DER format
1456 * @len: Buffer length
1457 * Returns: Pointer to the parsed certificate or %NULL on failure
1458 *
1459 * Caller is responsible for freeing the returned certificate by calling
1460 * x509_certificate_free().
1461 */
1462struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len)
1463{
1464 struct asn1_hdr hdr;
1465 const u8 *pos, *end, *hash_start;
1466 struct x509_certificate *cert;
1467
1468 cert = os_zalloc(sizeof(*cert) + len);
1469 if (cert == NULL)
1470 return NULL;
1471 os_memcpy(cert + 1, buf, len);
1472 cert->cert_start = (u8 *) (cert + 1);
1473 cert->cert_len = len;
1474
1475 pos = buf;
1476 end = buf + len;
1477
1478 /* RFC 3280 - X.509 v3 certificate / ASN.1 DER */
1479
1480 /* Certificate ::= SEQUENCE */
1481 if (asn1_get_next(pos, len, &hdr) < 0 ||
1482 hdr.class != ASN1_CLASS_UNIVERSAL ||
1483 hdr.tag != ASN1_TAG_SEQUENCE) {
1484 wpa_printf(MSG_DEBUG, "X509: Certificate did not start with "
1485 "a valid SEQUENCE - found class %d tag 0x%x",
1486 hdr.class, hdr.tag);
1487 x509_certificate_free(cert);
1488 return NULL;
1489 }
1490 pos = hdr.payload;
1491
1492 if (pos + hdr.length > end) {
1493 x509_certificate_free(cert);
1494 return NULL;
1495 }
1496
1497 if (pos + hdr.length < end) {
1498 wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER "
1499 "encoded certificate",
1500 pos + hdr.length, end - pos + hdr.length);
1501 end = pos + hdr.length;
1502 }
1503
1504 hash_start = pos;
1505 cert->tbs_cert_start = cert->cert_start + (hash_start - buf);
1506 if (x509_parse_tbs_certificate(pos, end - pos, cert, &pos)) {
1507 x509_certificate_free(cert);
1508 return NULL;
1509 }
1510 cert->tbs_cert_len = pos - hash_start;
1511
1512 /* signatureAlgorithm AlgorithmIdentifier */
1513 if (x509_parse_algorithm_identifier(pos, end - pos,
1514 &cert->signature_alg, &pos)) {
1515 x509_certificate_free(cert);
1516 return NULL;
1517 }
1518
1519 /* signatureValue BIT STRING */
1520 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1521 hdr.class != ASN1_CLASS_UNIVERSAL ||
1522 hdr.tag != ASN1_TAG_BITSTRING) {
1523 wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING "
1524 "(signatureValue) - found class %d tag 0x%x",
1525 hdr.class, hdr.tag);
1526 x509_certificate_free(cert);
1527 return NULL;
1528 }
1529 if (hdr.length < 1) {
1530 x509_certificate_free(cert);
1531 return NULL;
1532 }
1533 pos = hdr.payload;
1534 if (*pos) {
1535 wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits",
1536 *pos);
1537 /* PKCS #1 v1.5 10.2.1:
1538 * It is an error if the length in bits of the signature S is
1539 * not a multiple of eight.
1540 */
1541 x509_certificate_free(cert);
1542 return NULL;
1543 }
1544 os_free(cert->sign_value);
1545 cert->sign_value = os_malloc(hdr.length - 1);
1546 if (cert->sign_value == NULL) {
1547 wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for "
1548 "signatureValue");
1549 x509_certificate_free(cert);
1550 return NULL;
1551 }
1552 os_memcpy(cert->sign_value, pos + 1, hdr.length - 1);
1553 cert->sign_value_len = hdr.length - 1;
1554 wpa_hexdump(MSG_MSGDUMP, "X509: signature",
1555 cert->sign_value, cert->sign_value_len);
1556
1557 return cert;
1558}
1559
1560
1561/**
1562 * x509_certificate_check_signature - Verify certificate signature
1563 * @issuer: Issuer certificate
1564 * @cert: Certificate to be verified
1565 * Returns: 0 if cert has a valid signature that was signed by the issuer,
1566 * -1 if not
1567 */
1568int x509_certificate_check_signature(struct x509_certificate *issuer,
1569 struct x509_certificate *cert)
1570{
1571 struct crypto_public_key *pk;
1572 u8 *data;
1573 const u8 *pos, *end, *next, *da_end;
1574 size_t data_len;
1575 struct asn1_hdr hdr;
1576 struct asn1_oid oid;
1d8ce433 1577 u8 hash[32];
6fc6879b
JM
1578 size_t hash_len;
1579
1580 if (!x509_pkcs_oid(&cert->signature.oid) ||
1581 cert->signature.oid.len != 7 ||
1582 cert->signature.oid.oid[5] != 1 /* pkcs-1 */) {
1583 wpa_printf(MSG_DEBUG, "X509: Unrecognized signature "
1584 "algorithm");
1585 return -1;
1586 }
1587
1588 pk = crypto_public_key_import(issuer->public_key,
1589 issuer->public_key_len);
1590 if (pk == NULL)
1591 return -1;
1592
1593 data_len = cert->sign_value_len;
1594 data = os_malloc(data_len);
1595 if (data == NULL) {
1596 crypto_public_key_free(pk);
1597 return -1;
1598 }
1599
1600 if (crypto_public_key_decrypt_pkcs1(pk, cert->sign_value,
1601 cert->sign_value_len, data,
1602 &data_len) < 0) {
1603 wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature");
1604 crypto_public_key_free(pk);
1605 os_free(data);
1606 return -1;
1607 }
1608 crypto_public_key_free(pk);
1609
1610 wpa_hexdump(MSG_MSGDUMP, "X509: Signature data D", data, data_len);
1611
1612 /*
1613 * PKCS #1 v1.5, 10.1.2:
1614 *
1615 * DigestInfo ::= SEQUENCE {
1616 * digestAlgorithm DigestAlgorithmIdentifier,
1617 * digest Digest
1618 * }
1619 *
1620 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
1621 *
1622 * Digest ::= OCTET STRING
1623 *
1624 */
1625 if (asn1_get_next(data, data_len, &hdr) < 0 ||
1626 hdr.class != ASN1_CLASS_UNIVERSAL ||
1627 hdr.tag != ASN1_TAG_SEQUENCE) {
1628 wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
1629 "(DigestInfo) - found class %d tag 0x%x",
1630 hdr.class, hdr.tag);
1631 os_free(data);
1632 return -1;
1633 }
1634
1635 pos = hdr.payload;
1636 end = pos + hdr.length;
1637
1638 /*
1639 * X.509:
1640 * AlgorithmIdentifier ::= SEQUENCE {
1641 * algorithm OBJECT IDENTIFIER,
1642 * parameters ANY DEFINED BY algorithm OPTIONAL
1643 * }
1644 */
1645
1646 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1647 hdr.class != ASN1_CLASS_UNIVERSAL ||
1648 hdr.tag != ASN1_TAG_SEQUENCE) {
1649 wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
1650 "(AlgorithmIdentifier) - found class %d tag 0x%x",
1651 hdr.class, hdr.tag);
1652 os_free(data);
1653 return -1;
1654 }
1655 da_end = hdr.payload + hdr.length;
1656
1657 if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) {
1658 wpa_printf(MSG_DEBUG, "X509: Failed to parse digestAlgorithm");
1659 os_free(data);
1660 return -1;
1661 }
1662
1663 if (x509_sha1_oid(&oid)) {
1664 if (cert->signature.oid.oid[6] !=
1665 5 /* sha-1WithRSAEncryption */) {
1666 wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 "
1667 "does not match with certificate "
1668 "signatureAlgorithm (%lu)",
1669 cert->signature.oid.oid[6]);
1670 os_free(data);
1671 return -1;
1672 }
1673 goto skip_digest_oid;
1674 }
1675
1d8ce433
JM
1676 if (x509_sha256_oid(&oid)) {
1677 if (cert->signature.oid.oid[6] !=
1678 11 /* sha2561WithRSAEncryption */) {
1679 wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA256 "
1680 "does not match with certificate "
1681 "signatureAlgorithm (%lu)",
1682 cert->signature.oid.oid[6]);
1683 os_free(data);
1684 return -1;
1685 }
1686 goto skip_digest_oid;
1687 }
1688
6fc6879b
JM
1689 if (!x509_digest_oid(&oid)) {
1690 wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm");
1691 os_free(data);
1692 return -1;
1693 }
1694 switch (oid.oid[5]) {
1695 case 5: /* md5 */
1696 if (cert->signature.oid.oid[6] != 4 /* md5WithRSAEncryption */)
1697 {
1698 wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does "
1699 "not match with certificate "
1700 "signatureAlgorithm (%lu)",
1701 cert->signature.oid.oid[6]);
1702 os_free(data);
1703 return -1;
1704 }
1705 break;
1706 case 2: /* md2 */
1707 case 4: /* md4 */
1708 default:
1709 wpa_printf(MSG_DEBUG, "X509: Unsupported digestAlgorithm "
1710 "(%lu)", oid.oid[5]);
1711 os_free(data);
1712 return -1;
1713 }
1714
1715skip_digest_oid:
1716 /* Digest ::= OCTET STRING */
1717 pos = da_end;
1718 end = data + data_len;
1719
1720 if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1721 hdr.class != ASN1_CLASS_UNIVERSAL ||
1722 hdr.tag != ASN1_TAG_OCTETSTRING) {
1723 wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING "
1724 "(Digest) - found class %d tag 0x%x",
1725 hdr.class, hdr.tag);
1726 os_free(data);
1727 return -1;
1728 }
1729 wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest",
1730 hdr.payload, hdr.length);
1731
1732 switch (cert->signature.oid.oid[6]) {
1733 case 4: /* md5WithRSAEncryption */
1734 md5_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len,
1735 hash);
1736 hash_len = 16;
1737 wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)",
1738 hash, hash_len);
1739 break;
1740 case 5: /* sha-1WithRSAEncryption */
1741 sha1_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len,
1742 hash);
1743 hash_len = 20;
1744 wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)",
1745 hash, hash_len);
1746 break;
6fc6879b 1747 case 11: /* sha256WithRSAEncryption */
1d8ce433
JM
1748#ifdef NEED_SHA256
1749 sha256_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len,
1750 hash);
1751 hash_len = 32;
1752 wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)",
1753 hash, hash_len);
1754 break;
1755#else /* NEED_SHA256 */
1756 wpa_printf(MSG_INFO, "X509: SHA256 support disabled");
1757 os_free(data);
1758 return -1;
1759#endif /* NEED_SHA256 */
1760 case 2: /* md2WithRSAEncryption */
6fc6879b
JM
1761 case 12: /* sha384WithRSAEncryption */
1762 case 13: /* sha512WithRSAEncryption */
1763 default:
1764 wpa_printf(MSG_INFO, "X509: Unsupported certificate signature "
1765 "algorithm (%lu)", cert->signature.oid.oid[6]);
1766 os_free(data);
1767 return -1;
1768 }
1769
1770 if (hdr.length != hash_len ||
1771 os_memcmp(hdr.payload, hash, hdr.length) != 0) {
1772 wpa_printf(MSG_INFO, "X509: Certificate Digest does not match "
1773 "with calculated tbsCertificate hash");
1774 os_free(data);
1775 return -1;
1776 }
1777
1778 os_free(data);
1779
1780 wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with "
1781 "calculated tbsCertificate hash");
1782
1783 return 0;
1784}
1785
1786
1787static int x509_valid_issuer(const struct x509_certificate *cert)
1788{
1789 if ((cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS) &&
1790 !cert->ca) {
1791 wpa_printf(MSG_DEBUG, "X509: Non-CA certificate used as an "
1792 "issuer");
1793 return -1;
1794 }
1795
1796 if (cert->version == X509_CERT_V3 &&
1797 !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) {
1798 wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not "
1799 "include BasicConstraints extension");
1800 return -1;
1801 }
1802
1803 if ((cert->extensions_present & X509_EXT_KEY_USAGE) &&
1804 !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) {
1805 wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have "
1806 "keyCertSign bit in Key Usage");
1807 return -1;
1808 }
1809
1810 return 0;
1811}
1812
1813
1814/**
1815 * x509_certificate_chain_validate - Validate X.509 certificate chain
1816 * @trusted: List of trusted certificates
1817 * @chain: Certificate chain to be validated (first chain must be issued by
1818 * signed by the second certificate in the chain and so on)
1819 * @reason: Buffer for returning failure reason (X509_VALIDATE_*)
1820 * Returns: 0 if chain is valid, -1 if not
1821 */
1822int x509_certificate_chain_validate(struct x509_certificate *trusted,
1823 struct x509_certificate *chain,
1824 int *reason)
1825{
1826 long unsigned idx;
1827 int chain_trusted = 0;
1828 struct x509_certificate *cert, *trust;
1829 char buf[128];
1830 struct os_time now;
1831
1832 *reason = X509_VALIDATE_OK;
1833
1834 wpa_printf(MSG_DEBUG, "X509: Validate certificate chain");
1835 os_get_time(&now);
1836
1837 for (cert = chain, idx = 0; cert; cert = cert->next, idx++) {
1838 x509_name_string(&cert->subject, buf, sizeof(buf));
1839 wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf);
1840
1841 if (chain_trusted)
1842 continue;
1843
1844 if ((unsigned long) now.sec <
1845 (unsigned long) cert->not_before ||
1846 (unsigned long) now.sec >
1847 (unsigned long) cert->not_after) {
1848 wpa_printf(MSG_INFO, "X509: Certificate not valid "
1849 "(now=%lu not_before=%lu not_after=%lu)",
1850 now.sec, cert->not_before, cert->not_after);
1851 *reason = X509_VALIDATE_CERTIFICATE_EXPIRED;
1852 return -1;
1853 }
1854
1855 if (cert->next) {
1856 if (x509_name_compare(&cert->issuer,
1857 &cert->next->subject) != 0) {
1858 wpa_printf(MSG_DEBUG, "X509: Certificate "
1859 "chain issuer name mismatch");
1860 x509_name_string(&cert->issuer, buf,
1861 sizeof(buf));
1862 wpa_printf(MSG_DEBUG, "X509: cert issuer: %s",
1863 buf);
1864 x509_name_string(&cert->next->subject, buf,
1865 sizeof(buf));
1866 wpa_printf(MSG_DEBUG, "X509: next cert "
1867 "subject: %s", buf);
1868 *reason = X509_VALIDATE_CERTIFICATE_UNKNOWN;
1869 return -1;
1870 }
1871
1872 if (x509_valid_issuer(cert->next) < 0) {
1873 *reason = X509_VALIDATE_BAD_CERTIFICATE;
1874 return -1;
1875 }
1876
1877 if ((cert->next->extensions_present &
1878 X509_EXT_PATH_LEN_CONSTRAINT) &&
1879 idx > cert->next->path_len_constraint) {
1880 wpa_printf(MSG_DEBUG, "X509: pathLenConstraint"
1881 " not met (idx=%lu issuer "
1882 "pathLenConstraint=%lu)", idx,
1883 cert->next->path_len_constraint);
1884 *reason = X509_VALIDATE_BAD_CERTIFICATE;
1885 return -1;
1886 }
1887
1888 if (x509_certificate_check_signature(cert->next, cert)
1889 < 0) {
1890 wpa_printf(MSG_DEBUG, "X509: Invalid "
1891 "certificate signature within "
1892 "chain");
1893 *reason = X509_VALIDATE_BAD_CERTIFICATE;
1894 return -1;
1895 }
1896 }
1897
1898 for (trust = trusted; trust; trust = trust->next) {
1899 if (x509_name_compare(&cert->issuer, &trust->subject)
1900 == 0)
1901 break;
1902 }
1903
1904 if (trust) {
1905 wpa_printf(MSG_DEBUG, "X509: Found issuer from the "
1906 "list of trusted certificates");
1907 if (x509_valid_issuer(trust) < 0) {
1908 *reason = X509_VALIDATE_BAD_CERTIFICATE;
1909 return -1;
1910 }
1911
1912 if (x509_certificate_check_signature(trust, cert) < 0)
1913 {
1914 wpa_printf(MSG_DEBUG, "X509: Invalid "
1915 "certificate signature");
1916 *reason = X509_VALIDATE_BAD_CERTIFICATE;
1917 return -1;
1918 }
1919
1920 wpa_printf(MSG_DEBUG, "X509: Trusted certificate "
1921 "found to complete the chain");
1922 chain_trusted = 1;
1923 }
1924 }
1925
1926 if (!chain_trusted) {
1927 wpa_printf(MSG_DEBUG, "X509: Did not find any of the issuers "
1928 "from the list of trusted certificates");
1929 if (trusted) {
1930 *reason = X509_VALIDATE_UNKNOWN_CA;
1931 return -1;
1932 }
1933 wpa_printf(MSG_DEBUG, "X509: Certificate chain validation "
1934 "disabled - ignore unknown CA issue");
1935 }
1936
1937 wpa_printf(MSG_DEBUG, "X509: Certificate chain valid");
1938
1939 return 0;
1940}
1941
1942
1943/**
1944 * x509_certificate_get_subject - Get a certificate based on Subject name
1945 * @chain: Certificate chain to search through
1946 * @name: Subject name to search for
1947 * Returns: Pointer to the certificate with the given Subject name or
1948 * %NULL on failure
1949 */
1950struct x509_certificate *
1951x509_certificate_get_subject(struct x509_certificate *chain,
1952 struct x509_name *name)
1953{
1954 struct x509_certificate *cert;
1955
1956 for (cert = chain; cert; cert = cert->next) {
1957 if (x509_name_compare(&cert->subject, name) == 0)
1958 return cert;
1959 }
1960 return NULL;
1961}
1962
1963
1964/**
1965 * x509_certificate_self_signed - Is the certificate self-signed?
1966 * @cert: Certificate
1967 * Returns: 1 if certificate is self-signed, 0 if not
1968 */
1969int x509_certificate_self_signed(struct x509_certificate *cert)
1970{
1971 return x509_name_compare(&cert->issuer, &cert->subject) == 0;
1972}
1973
1974#endif /* CONFIG_INTERNAL_X509 */