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