bce37ad4f12a5bc25ac10b4b833b73945593f449
[BearSSL] / src / x509 / x509_minimal.t0
1 \ Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
2 \
3 \ Permission is hereby granted, free of charge, to any person obtaining
4 \ a copy of this software and associated documentation files (the
5 \ "Software"), to deal in the Software without restriction, including
6 \ without limitation the rights to use, copy, modify, merge, publish,
7 \ distribute, sublicense, and/or sell copies of the Software, and to
8 \ permit persons to whom the Software is furnished to do so, subject to
9 \ the following conditions:
10 \
11 \ The above copyright notice and this permission notice shall be
12 \ included in all copies or substantial portions of the Software.
13 \
14 \ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 \ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 \ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 \ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18 \ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 \ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 \ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 \ SOFTWARE.
22
23 preamble {
24
25 #include "inner.h"
26
27 /*
28 * Implementation Notes
29 * --------------------
30 *
31 * The C code pushes the data by chunks; all decoding is done in the
32 * T0 code. The cert_length value is set to the certificate length when
33 * a new certificate is started; the T0 code picks it up as outer limit,
34 * and decoding functions use it to ensure that no attempt is made at
35 * reading past it. The T0 code also checks that once the certificate is
36 * decoded, there are no trailing bytes.
37 *
38 * The T0 code sets cert_length to 0 when the certificate is fully
39 * decoded.
40 *
41 * The C code must still perform two checks:
42 *
43 * -- If the certificate length is 0, then the T0 code will not be
44 * invoked at all. This invalid condition must thus be reported by the
45 * C code.
46 *
47 * -- When reaching the end of certificate, the C code must verify that
48 * the certificate length has been set to 0, thereby signaling that
49 * the T0 code properly decoded a certificate.
50 *
51 * Processing of a chain works in the following way:
52 *
53 * -- The error flag is set to a non-zero value when validation is
54 * finished. The value is either BR_ERR_X509_OK (validation is
55 * successful) or another non-zero error code. When a non-zero error
56 * code is obtained, the remaining bytes in the current certificate and
57 * the subsequent certificates (if any) are completely ignored.
58 *
59 * -- Each certificate is decoded in due course, with the following
60 * "interesting points":
61 *
62 * -- Start of the TBS: the multihash engine is reset and activated.
63 *
64 * -- Start of the issuer DN: the secondary hash engine is started,
65 * to process the encoded issuer DN.
66 *
67 * -- End of the issuer DN: the secondary hash engine is stopped. The
68 * resulting hash value is computed and then copied into the
69 * next_dn_hash[] buffer.
70 *
71 * -- Start of the subject DN: the secondary hash engine is started,
72 * to process the encoded subject DN.
73 *
74 * -- For the EE certificate only: the Common Name, if any, is matched
75 * against the expected server name.
76 *
77 * -- End of the subject DN: the secondary hash engine is stopped. The
78 * resulting hash value is computed into the pad. It is then processed:
79 *
80 * -- If this is the EE certificate, then the hash is ignored
81 * (except for direct trust processing, see later; the hash is
82 * simply left in current_dn_hash[]).
83 *
84 * -- Otherwise, the hashed subject DN is compared with the saved
85 * hash value (in saved_dn_hash[]). They must match.
86 *
87 * Either way, the next_dn_hash[] value is then copied into the
88 * saved_dn_hash[] value. Thus, at that point, saved_dn_hash[]
89 * contains the hash of the issuer DN for the current certificate,
90 * and current_dn_hash[] contains the hash of the subject DN for the
91 * current certificate.
92 *
93 * -- Public key: it is decoded into the cert_pkey[] buffer. Unknown
94 * key types are reported at that point.
95 *
96 * -- If this is the EE certificate, then the key type is compared
97 * with the expected key type (initialization parameter). The public
98 * key data is copied to ee_pkey_data[]. The key and hashed subject
99 * DN are also compared with the "direct trust" keys; if the key
100 * and DN are matched, then validation ends with a success.
101 *
102 * -- Otherwise, the saved signature (cert_sig[]) is verified
103 * against the saved TBS hash (tbs_hash[]) and that freshly
104 * decoded public key. Failure here ends validation with an error.
105 *
106 * -- Extensions: extension values are processed in due order.
107 *
108 * -- Basic Constraints: for all certificates except EE, must be
109 * present, indicate a CA, and have a path legnth compatible with
110 * the chain length so far.
111 *
112 * -- Key Usage: for the EE, if present, must allow signatures
113 * or encryption/key exchange, as required for the cipher suite.
114 * For non-EE, if present, must have the "certificate sign" bit.
115 *
116 * -- Subject Alt Name: for the EE, dNSName names are matched
117 * against the server name. Ignored for non-EE.
118 *
119 * -- Authority Key Identifier, Subject Key Identifier, Issuer
120 * Alt Name, Subject Directory Attributes, CRL Distribution Points
121 * Freshest CRL, Authority Info Access and Subject Info Access
122 * extensions are always ignored: they either contain only
123 * informative data, or they relate to revocation processing, which
124 * we explicitly do not support.
125 *
126 * -- All other extensions are ignored if non-critical. If a
127 * critical extension other than the ones above is encountered,
128 * then a failure is reported.
129 *
130 * -- End of the TBS: the multihash engine is stopped.
131 *
132 * -- Signature algorithm: the signature algorithm on the
133 * certificate is decoded. A failure is reported if that algorithm
134 * is unknown. The hashed TBS corresponding to the signature hash
135 * function is computed and stored in tbs_hash[] (if not supported,
136 * then a failure is reported). The hash OID and length are stored
137 * in cert_sig_hash_oid and cert_sig_hash_len.
138 *
139 * -- Signature value: the signature value is copied into the
140 * cert_sig[] array.
141 *
142 * -- Certificate end: the hashed issuer DN (saved_dn_hash[]) is
143 * looked up in the trust store (CA trust anchors only); for all
144 * that match, the signature (cert_sig[]) is verified against the
145 * anchor public key (hashed TBS is in tbs_hash[]). If one of these
146 * signatures is valid, then validation ends with a success.
147 *
148 * -- If the chain end is reached without obtaining a validation success,
149 * then validation is reported as failed.
150 */
151
152 #ifndef BR_USE_UNIX_TIME
153 #if defined __unix__ || defined __linux__ \
154 || defined _POSIX_SOURCE || defined _POSIX_C_SOURCE \
155 || (defined __APPLE__ && defined __MACH__)
156 #define BR_USE_UNIX_TIME 1
157 #endif
158 #endif
159
160 #ifndef BR_USE_WIN32_TIME
161 #if defined _WIN32 || defined _WIN64
162 #define BR_USE_WIN32_TIME 1
163 #endif
164 #endif
165
166 #if BR_USE_UNIX_TIME
167 #include <time.h>
168 #endif
169
170 #if BR_USE_WIN32_TIME
171 #include <windows.h>
172 #endif
173
174 /*
175 * The T0 compiler will produce these prototypes declarations in the
176 * header.
177 *
178 void br_x509_minimal_init_main(void *ctx);
179 void br_x509_minimal_run(void *ctx);
180 */
181
182 /* see bearssl_x509.h */
183 void
184 br_x509_minimal_init(br_x509_minimal_context *ctx,
185 const br_hash_class *dn_hash_impl,
186 const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num)
187 {
188 memset(ctx, 0, sizeof *ctx);
189 ctx->vtable = &br_x509_minimal_vtable;
190 ctx->dn_hash_impl = dn_hash_impl;
191 ctx->trust_anchors = trust_anchors;
192 ctx->trust_anchors_num = trust_anchors_num;
193 }
194
195 static void
196 xm_start_chain(const br_x509_class **ctx, const char *server_name)
197 {
198 br_x509_minimal_context *cc;
199 size_t u;
200
201 cc = (br_x509_minimal_context *)ctx;
202 for (u = 0; u < cc->num_name_elts; u ++) {
203 cc->name_elts[u].status = 0;
204 cc->name_elts[u].buf[0] = 0;
205 }
206 memset(&cc->pkey, 0, sizeof cc->pkey);
207 cc->num_certs = 0;
208 cc->err = 0;
209 cc->cpu.dp = cc->dp_stack;
210 cc->cpu.rp = cc->rp_stack;
211 br_x509_minimal_init_main(&cc->cpu);
212 if (server_name == NULL || *server_name == 0) {
213 cc->server_name = NULL;
214 } else {
215 cc->server_name = server_name;
216 }
217 }
218
219 static void
220 xm_start_cert(const br_x509_class **ctx, uint32_t length)
221 {
222 br_x509_minimal_context *cc;
223
224 cc = (br_x509_minimal_context *)ctx;
225 if (cc->err != 0) {
226 return;
227 }
228 if (length == 0) {
229 cc->err = BR_ERR_X509_TRUNCATED;
230 return;
231 }
232 cc->cert_length = length;
233 }
234
235 static void
236 xm_append(const br_x509_class **ctx, const unsigned char *buf, size_t len)
237 {
238 br_x509_minimal_context *cc;
239
240 cc = (br_x509_minimal_context *)ctx;
241 if (cc->err != 0) {
242 return;
243 }
244 cc->hbuf = buf;
245 cc->hlen = len;
246 br_x509_minimal_run(&cc->cpu);
247 }
248
249 static void
250 xm_end_cert(const br_x509_class **ctx)
251 {
252 br_x509_minimal_context *cc;
253
254 cc = (br_x509_minimal_context *)ctx;
255 if (cc->err == 0 && cc->cert_length != 0) {
256 cc->err = BR_ERR_X509_TRUNCATED;
257 }
258 cc->num_certs ++;
259 }
260
261 static unsigned
262 xm_end_chain(const br_x509_class **ctx)
263 {
264 br_x509_minimal_context *cc;
265
266 cc = (br_x509_minimal_context *)ctx;
267 if (cc->err == 0) {
268 if (cc->num_certs == 0) {
269 cc->err = BR_ERR_X509_EMPTY_CHAIN;
270 } else {
271 cc->err = BR_ERR_X509_NOT_TRUSTED;
272 }
273 } else if (cc->err == BR_ERR_X509_OK) {
274 return 0;
275 }
276 return (unsigned)cc->err;
277 }
278
279 static const br_x509_pkey *
280 xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
281 {
282 br_x509_minimal_context *cc;
283
284 cc = (br_x509_minimal_context *)ctx;
285 if (cc->err == BR_ERR_X509_OK
286 || cc->err == BR_ERR_X509_NOT_TRUSTED)
287 {
288 if (usages != NULL) {
289 *usages = cc->key_usages;
290 }
291 return &((br_x509_minimal_context *)ctx)->pkey;
292 } else {
293 return NULL;
294 }
295 }
296
297 /* see bearssl_x509.h */
298 const br_x509_class br_x509_minimal_vtable = {
299 sizeof(br_x509_minimal_context),
300 xm_start_chain,
301 xm_start_cert,
302 xm_append,
303 xm_end_cert,
304 xm_end_chain,
305 xm_get_pkey
306 };
307
308 #define CTX ((br_x509_minimal_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_minimal_context, cpu)))
309 #define CONTEXT_NAME br_x509_minimal_context
310
311 #define DNHASH_LEN ((CTX->dn_hash_impl->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK)
312
313 /*
314 * Hash a DN (from a trust anchor) into the provided buffer. This uses the
315 * DN hash implementation and context structure from the X.509 engine
316 * context.
317 */
318 static void
319 hash_dn(br_x509_minimal_context *ctx, const void *dn, size_t len,
320 unsigned char *out)
321 {
322 ctx->dn_hash_impl->init(&ctx->dn_hash.vtable);
323 ctx->dn_hash_impl->update(&ctx->dn_hash.vtable, dn, len);
324 ctx->dn_hash_impl->out(&ctx->dn_hash.vtable, out);
325 }
326
327 /*
328 * Compare two big integers for equality. The integers use unsigned big-endian
329 * encoding; extra leading bytes (of value 0) are allowed.
330 */
331 static int
332 eqbigint(const unsigned char *b1, size_t len1,
333 const unsigned char *b2, size_t len2)
334 {
335 while (len1 > 0 && *b1 == 0) {
336 b1 ++;
337 len1 --;
338 }
339 while (len2 > 0 && *b2 == 0) {
340 b2 ++;
341 len2 --;
342 }
343 if (len1 != len2) {
344 return 0;
345 }
346 return memcmp(b1, b2, len1) == 0;
347 }
348
349 /*
350 * Compare two strings for equality, in a case-insensitive way. This
351 * function handles casing only for ASCII letters.
352 */
353 static int
354 eqnocase(const void *s1, const void *s2, size_t len)
355 {
356 const unsigned char *buf1, *buf2;
357
358 buf1 = s1;
359 buf2 = s2;
360 while (len -- > 0) {
361 int x1, x2;
362
363 x1 = *buf1 ++;
364 x2 = *buf2 ++;
365 if (x1 >= 'A' && x1 <= 'Z') {
366 x1 += 'a' - 'A';
367 }
368 if (x2 >= 'A' && x2 <= 'Z') {
369 x2 += 'a' - 'A';
370 }
371 if (x1 != x2) {
372 return 0;
373 }
374 }
375 return 1;
376 }
377
378 static int verify_signature(br_x509_minimal_context *ctx,
379 const br_x509_pkey *pk);
380
381 }
382
383 postamble {
384
385 /*
386 * Verify the signature on the certificate with the provided public key.
387 * This function checks the public key type with regards to the expected
388 * type. Returned value is either 0 on success, or a non-zero error code.
389 */
390 static int
391 verify_signature(br_x509_minimal_context *ctx, const br_x509_pkey *pk)
392 {
393 int kt;
394
395 kt = ctx->cert_signer_key_type;
396 if ((pk->key_type & 0x0F) != kt) {
397 return BR_ERR_X509_WRONG_KEY_TYPE;
398 }
399 switch (kt) {
400 unsigned char tmp[64];
401
402 case BR_KEYTYPE_RSA:
403 if (ctx->irsa == 0) {
404 return BR_ERR_X509_UNSUPPORTED;
405 }
406 if (!ctx->irsa(ctx->cert_sig, ctx->cert_sig_len,
407 &t0_datablock[ctx->cert_sig_hash_oid],
408 ctx->cert_sig_hash_len, &pk->key.rsa, tmp))
409 {
410 return BR_ERR_X509_BAD_SIGNATURE;
411 }
412 if (memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) {
413 return BR_ERR_X509_BAD_SIGNATURE;
414 }
415 return 0;
416
417 case BR_KEYTYPE_EC:
418 if (ctx->iecdsa == 0) {
419 return BR_ERR_X509_UNSUPPORTED;
420 }
421 if (!ctx->iecdsa(ctx->iec, ctx->tbs_hash,
422 ctx->cert_sig_hash_len, &pk->key.ec,
423 ctx->cert_sig, ctx->cert_sig_len))
424 {
425 return BR_ERR_X509_BAD_SIGNATURE;
426 }
427 return 0;
428
429 default:
430 return BR_ERR_X509_UNSUPPORTED;
431 }
432 }
433
434 }
435
436 cc: read8-low ( -- x ) {
437 if (CTX->hlen == 0) {
438 T0_PUSHi(-1);
439 } else {
440 unsigned char x = *CTX->hbuf ++;
441 if (CTX->do_mhash) {
442 br_multihash_update(&CTX->mhash, &x, 1);
443 }
444 if (CTX->do_dn_hash) {
445 CTX->dn_hash_impl->update(&CTX->dn_hash.vtable, &x, 1);
446 }
447 CTX->hlen --;
448 T0_PUSH(x);
449 }
450 }
451
452 addr: cert_length
453 addr: num_certs
454
455 cc: read-blob-inner ( addr len -- addr len ) {
456 uint32_t len = T0_POP();
457 uint32_t addr = T0_POP();
458 size_t clen = CTX->hlen;
459 if (clen > len) {
460 clen = (size_t)len;
461 }
462 if (addr != 0) {
463 memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen);
464 }
465 if (CTX->do_mhash) {
466 br_multihash_update(&CTX->mhash, CTX->hbuf, clen);
467 }
468 if (CTX->do_dn_hash) {
469 CTX->dn_hash_impl->update(
470 &CTX->dn_hash.vtable, CTX->hbuf, clen);
471 }
472 CTX->hbuf += clen;
473 CTX->hlen -= clen;
474 T0_PUSH(addr + clen);
475 T0_PUSH(len - clen);
476 }
477
478 \ Compute the TBS hash, using the provided hash ID. The hash value is
479 \ written in the tbs_hash[] array, and the hash length is returned. If
480 \ the requested hash function is not supported, then 0 is returned.
481 cc: compute-tbs-hash ( id -- hashlen ) {
482 int id = T0_POPi();
483 size_t len;
484 len = br_multihash_out(&CTX->mhash, id, CTX->tbs_hash);
485 T0_PUSH(len);
486 }
487
488 \ Push true (-1) if no server name is expected in the EE certificate.
489 cc: zero-server-name ( -- bool ) {
490 T0_PUSHi(-(CTX->server_name == NULL));
491 }
492
493 addr: key_usages
494 addr: cert_sig
495 addr: cert_sig_len
496 addr: cert_signer_key_type
497 addr: cert_sig_hash_oid
498 addr: cert_sig_hash_len
499 addr: tbs_hash
500 addr: min_rsa_size
501
502 \ Start TBS hash computation. The hash functions are reinitialised.
503 cc: start-tbs-hash ( -- ) {
504 br_multihash_init(&CTX->mhash);
505 CTX->do_mhash = 1;
506 }
507
508 \ Stop TBS hash computation.
509 cc: stop-tbs-hash ( -- ) {
510 CTX->do_mhash = 0;
511 }
512
513 \ Start DN hash computation.
514 cc: start-dn-hash ( -- ) {
515 CTX->dn_hash_impl->init(&CTX->dn_hash.vtable);
516 CTX->do_dn_hash = 1;
517 }
518
519 \ Terminate DN hash computation and write the DN hash into the
520 \ current_dn_hash buffer.
521 cc: compute-dn-hash ( -- ) {
522 CTX->dn_hash_impl->out(&CTX->dn_hash.vtable, CTX->current_dn_hash);
523 CTX->do_dn_hash = 0;
524 }
525
526 \ Get the length of hash values obtained with the DN hasher.
527 cc: dn-hash-length ( -- len ) {
528 T0_PUSH(DNHASH_LEN);
529 }
530
531 \ Copy data between two areas in the context.
532 cc: blobcopy ( addr-dst addr-src len -- ) {
533 size_t len = T0_POP();
534 unsigned char *src = (unsigned char *)CTX + T0_POP();
535 unsigned char *dst = (unsigned char *)CTX + T0_POP();
536 memcpy(dst, src, len);
537 }
538
539 addr: current_dn_hash
540 addr: next_dn_hash
541 addr: saved_dn_hash
542
543 \ Read a DN, hashing it into current_dn_hash. The DN contents are not
544 \ inspected (only the outer tag, for SEQUENCE, is checked).
545 : read-DN ( lim -- lim )
546 start-dn-hash
547 read-sequence-open skip-close-elt
548 compute-dn-hash ;
549
550 cc: offset-name-element ( san -- n ) {
551 unsigned san = T0_POP();
552 size_t u;
553
554 for (u = 0; u < CTX->num_name_elts; u ++) {
555 if (CTX->name_elts[u].status == 0) {
556 const unsigned char *oid;
557 size_t len, off;
558
559 oid = CTX->name_elts[u].oid;
560 if (san) {
561 if (oid[0] != 0 || oid[1] != 0) {
562 continue;
563 }
564 off = 2;
565 } else {
566 off = 0;
567 }
568 len = oid[off];
569 if (len != 0 && len == CTX->pad[0]
570 && memcmp(oid + off + 1,
571 CTX->pad + 1, len) == 0)
572 {
573 T0_PUSH(u);
574 T0_RET();
575 }
576 }
577 }
578 T0_PUSHi(-1);
579 }
580
581 cc: copy-name-element ( bool offbuf -- ) {
582 size_t len;
583 int32_t off = T0_POPi();
584 int ok = T0_POPi();
585
586 if (off >= 0) {
587 br_name_element *ne = &CTX->name_elts[off];
588
589 if (ok) {
590 len = CTX->pad[0];
591 if (len < ne->len) {
592 memcpy(ne->buf, CTX->pad + 1, len);
593 ne->buf[len] = 0;
594 ne->status = 1;
595 } else {
596 ne->status = -1;
597 }
598 } else {
599 ne->status = -1;
600 }
601 }
602 }
603
604 cc: copy-name-SAN ( bool tag -- ) {
605 unsigned tag = T0_POP();
606 unsigned ok = T0_POP();
607 size_t u, len;
608
609 len = CTX->pad[0];
610 for (u = 0; u < CTX->num_name_elts; u ++) {
611 br_name_element *ne;
612
613 ne = &CTX->name_elts[u];
614 if (ne->status == 0 && ne->oid[0] == 0 && ne->oid[1] == tag) {
615 if (ok && ne->len > len) {
616 memcpy(ne->buf, CTX->pad + 1, len);
617 ne->buf[len] = 0;
618 ne->status = 1;
619 } else {
620 ne->status = -1;
621 }
622 break;
623 }
624 }
625 }
626
627 \ Read a value, decoding string types. If the string type is recognised
628 \ and the value could be converted to UTF-8 into the pad, then true (-1)
629 \ is returned; in all other cases, false (0) is returned. Either way, the
630 \ object is consumed.
631 : read-string ( lim -- lim bool )
632 read-tag case
633 \ UTF8String
634 12 of check-primitive read-value-UTF8 endof
635 \ NumericString
636 18 of check-primitive read-value-latin1 endof
637 \ PrintableString
638 19 of check-primitive read-value-latin1 endof
639 \ TeletexString
640 20 of check-primitive read-value-latin1 endof
641 \ IA5String
642 22 of check-primitive read-value-latin1 endof
643 \ BMPString
644 30 of check-primitive read-value-UTF16 endof
645 2drop read-length-skip 0 0
646 endcase ;
647
648 \ Read a DN for the EE. The normalized DN hash is computed and stored in the
649 \ current_dn_hash.
650 \ Name elements are gathered. Also, the Common Name is matched against the
651 \ intended server name.
652 \ Returned value is true (-1) if the CN matches the intended server name,
653 \ false (0) otherwise.
654 : read-DN-EE ( lim -- lim bool )
655 \ Flag will be set to true if there is a CN and it matches the
656 \ intended server name.
657 0 { eename-matches }
658
659 \ Activate DN hashing.
660 start-dn-hash
661
662 \ Parse the DN structure: it is a SEQUENCE of SET of
663 \ AttributeTypeAndValue. Each AttributeTypeAndValue is a
664 \ SEQUENCE { OBJECT IDENTIFIER, ANY }.
665 read-sequence-open
666 begin
667 dup while
668
669 read-tag 0x11 check-tag-constructed read-length-open-elt
670 dup ifnot ERR_X509_BAD_DN fail then
671 begin
672 dup while
673
674 read-sequence-open
675
676 \ Read the OID. If the OID could not be read (too
677 \ long) then the first pad byte will be 0.
678 read-OID drop
679
680 \ If it is the Common Name then we'll need to
681 \ match it against the intended server name (if
682 \ applicable).
683 id-at-commonName eqOID { isCN }
684
685 \ Get offset for reception buffer for that element
686 \ (or -1).
687 0 offset-name-element { offbuf }
688
689 \ Try to read the value as a string.
690 read-string
691
692 \ If the value could be decoded as a string,
693 \ copy it and/or match it, as appropriate.
694 dup isCN and if
695 match-server-name if
696 -1 >eename-matches
697 then
698 then
699 offbuf copy-name-element
700
701 \ Close the SEQUENCE
702 close-elt
703
704 repeat
705 close-elt
706 repeat
707 close-elt
708
709 \ Compute DN hash and deactivate DN hashing.
710 compute-dn-hash
711
712 \ Return the CN match flag.
713 eename-matches ;
714
715 \ Get the validation date and time from the context or system.
716 cc: get-system-date ( -- days seconds ) {
717 if (CTX->days == 0 && CTX->seconds == 0) {
718 #if BR_USE_UNIX_TIME
719 time_t x = time(NULL);
720
721 T0_PUSH((uint32_t)(x / 86400) + 719528);
722 T0_PUSH((uint32_t)(x % 86400));
723 #elif BR_USE_WIN32_TIME
724 FILETIME ft;
725 uint64_t x;
726
727 GetSystemTimeAsFileTime(&ft);
728 x = ((uint64_t)ft.dwHighDateTime << 32)
729 + (uint64_t)ft.dwLowDateTime;
730 x = (x / 10000000);
731 T0_PUSH((uint32_t)(x / 86400) + 584754);
732 T0_PUSH((uint32_t)(x % 86400));
733 #else
734 CTX->err = BR_ERR_X509_TIME_UNKNOWN;
735 T0_CO();
736 #endif
737 } else {
738 T0_PUSH(CTX->days);
739 T0_PUSH(CTX->seconds);
740 }
741 }
742
743 \ Compare two dates (days+seconds) together.
744 : before ( days1 seconds1 days2 seconds2 -- bool )
745 { d1 s1 d2 s2 }
746 d1 d2 = if s1 s2 < else d1 d2 < then ;
747
748 : after ( days1 seconds1 days2 seconds2 -- bool )
749 swap2 before ;
750
751 \ Swap the top two elements with the two elements immediately below.
752 : swap2 ( a b c d -- c d a b )
753 3 roll 3 roll ;
754
755 \ Match the name in the pad with the expected server name. Returned value
756 \ is true (-1) on match, false (0) otherwise. If there is no expected
757 \ server name, then 0 is returned.
758 \ Match conditions: either an exact match (case insensitive), or a
759 \ wildcard match, if the found name starts with "*.". We only match a
760 \ starting wildcard, and only against a complete DN name component.
761 cc: match-server-name ( -- bool ) {
762 size_t n1, n2;
763
764 if (CTX->server_name == NULL) {
765 T0_PUSH(0);
766 T0_RET();
767 }
768 n1 = strlen(CTX->server_name);
769 n2 = CTX->pad[0];
770 if (n1 == n2 && eqnocase(&CTX->pad[1], CTX->server_name, n1)) {
771 T0_PUSHi(-1);
772 T0_RET();
773 }
774 if (n2 >= 2 && CTX->pad[1] == '*' && CTX->pad[2] == '.') {
775 size_t u;
776
777 u = 0;
778 while (u < n1 && CTX->server_name[u] != '.') {
779 u ++;
780 }
781 u ++;
782 n1 -= u;
783 if ((n2 - 2) == n1
784 && eqnocase(&CTX->pad[3], CTX->server_name + u, n1))
785 {
786 T0_PUSHi(-1);
787 T0_RET();
788 }
789 }
790 T0_PUSH(0);
791 }
792
793 \ Get the address and length for the pkey_data buffer.
794 : addr-len-pkey_data ( -- addr len )
795 CX 0 8191 { offsetof(br_x509_minimal_context, pkey_data) }
796 CX 0 8191 { BR_X509_BUFSIZE_KEY } ;
797
798 \ Copy the EE public key to the permanent buffer (RSA).
799 cc: copy-ee-rsa-pkey ( nlen elen -- ) {
800 size_t elen = T0_POP();
801 size_t nlen = T0_POP();
802 memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen);
803 CTX->pkey.key_type = BR_KEYTYPE_RSA;
804 CTX->pkey.key.rsa.n = CTX->ee_pkey_data;
805 CTX->pkey.key.rsa.nlen = nlen;
806 CTX->pkey.key.rsa.e = CTX->ee_pkey_data + nlen;
807 CTX->pkey.key.rsa.elen = elen;
808 }
809
810 \ Copy the EE public key to the permanent buffer (EC).
811 cc: copy-ee-ec-pkey ( curve qlen -- ) {
812 size_t qlen = T0_POP();
813 uint32_t curve = T0_POP();
814 memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen);
815 CTX->pkey.key_type = BR_KEYTYPE_EC;
816 CTX->pkey.key.ec.curve = curve;
817 CTX->pkey.key.ec.q = CTX->ee_pkey_data;
818 CTX->pkey.key.ec.qlen = qlen;
819 }
820
821 \ Check whether the current certificate (EE) is directly trusted.
822 cc: check-direct-trust ( -- ) {
823 size_t u;
824
825 for (u = 0; u < CTX->trust_anchors_num; u ++) {
826 const br_x509_trust_anchor *ta;
827 unsigned char hashed_DN[64];
828 int kt;
829
830 ta = &CTX->trust_anchors[u];
831 if (ta->flags & BR_X509_TA_CA) {
832 continue;
833 }
834 hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN);
835 if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) {
836 continue;
837 }
838 kt = CTX->pkey.key_type;
839 if ((ta->pkey.key_type & 0x0F) != kt) {
840 continue;
841 }
842 switch (kt) {
843
844 case BR_KEYTYPE_RSA:
845 if (!eqbigint(CTX->pkey.key.rsa.n,
846 CTX->pkey.key.rsa.nlen,
847 ta->pkey.key.rsa.n,
848 ta->pkey.key.rsa.nlen)
849 || !eqbigint(CTX->pkey.key.rsa.e,
850 CTX->pkey.key.rsa.elen,
851 ta->pkey.key.rsa.e,
852 ta->pkey.key.rsa.elen))
853 {
854 continue;
855 }
856 break;
857
858 case BR_KEYTYPE_EC:
859 if (CTX->pkey.key.ec.curve != ta->pkey.key.ec.curve
860 || CTX->pkey.key.ec.qlen != ta->pkey.key.ec.qlen
861 || memcmp(CTX->pkey.key.ec.q,
862 ta->pkey.key.ec.q,
863 ta->pkey.key.ec.qlen) != 0)
864 {
865 continue;
866 }
867 break;
868
869 default:
870 continue;
871 }
872
873 /*
874 * Direct trust match!
875 */
876 CTX->err = BR_ERR_X509_OK;
877 T0_CO();
878 }
879 }
880
881 \ Check the signature on the certificate with regards to all trusted CA.
882 \ We use the issuer hash (in saved_dn_hash[]) as CA identifier.
883 cc: check-trust-anchor-CA ( -- ) {
884 size_t u;
885
886 for (u = 0; u < CTX->trust_anchors_num; u ++) {
887 const br_x509_trust_anchor *ta;
888 unsigned char hashed_DN[64];
889
890 ta = &CTX->trust_anchors[u];
891 if (!(ta->flags & BR_X509_TA_CA)) {
892 continue;
893 }
894 hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN);
895 if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) {
896 continue;
897 }
898 if (verify_signature(CTX, &ta->pkey) == 0) {
899 CTX->err = BR_ERR_X509_OK;
900 T0_CO();
901 }
902 }
903 }
904
905 \ Verify RSA signature. This uses the public key that was just decoded
906 \ into CTX->pkey_data; the modulus and exponent length are provided as
907 \ parameters. The resulting hash value is compared with the one in
908 \ tbs_hash. Returned value is 0 on success, or a non-zero error code.
909 cc: do-rsa-vrfy ( nlen elen -- err ) {
910 size_t elen = T0_POP();
911 size_t nlen = T0_POP();
912 br_x509_pkey pk;
913
914 pk.key_type = BR_KEYTYPE_RSA;
915 pk.key.rsa.n = CTX->pkey_data;
916 pk.key.rsa.nlen = nlen;
917 pk.key.rsa.e = CTX->pkey_data + nlen;
918 pk.key.rsa.elen = elen;
919 T0_PUSH(verify_signature(CTX, &pk));
920 }
921
922 \ Verify ECDSA signature. This uses the public key that was just decoded
923 \ into CTX->pkey_dayta; the curve ID and public point length are provided
924 \ as parameters. The hash value in tbs_hash is used. Returned value is 0
925 \ on success, or non-zero error code.
926 cc: do-ecdsa-vrfy ( curve qlen -- err ) {
927 size_t qlen = T0_POP();
928 int curve = T0_POP();
929 br_x509_pkey pk;
930
931 pk.key_type = BR_KEYTYPE_EC;
932 pk.key.ec.curve = curve;
933 pk.key.ec.q = CTX->pkey_data;
934 pk.key.ec.qlen = qlen;
935 T0_PUSH(verify_signature(CTX, &pk));
936 }
937
938 cc: print-bytes ( addr len -- ) {
939 extern int printf(const char *fmt, ...);
940 size_t len = T0_POP();
941 unsigned char *buf = (unsigned char *)CTX + T0_POP();
942 size_t u;
943
944 for (u = 0; u < len; u ++) {
945 printf("%02X", buf[u]);
946 }
947 }
948
949 cc: printOID ( -- ) {
950 extern int printf(const char *fmt, ...);
951 size_t u, len;
952
953 len = CTX->pad[0];
954 if (len == 0) {
955 printf("*");
956 T0_RET();
957 }
958 printf("%u.%u", CTX->pad[1] / 40, CTX->pad[1] % 40);
959 u = 2;
960 while (u <= len) {
961 unsigned long ul;
962
963 ul = 0;
964 for (;;) {
965 int x;
966
967 if (u > len) {
968 printf("BAD");
969 T0_RET();
970 }
971 x = CTX->pad[u ++];
972 ul = (ul << 7) + (x & 0x7F);
973 if (!(x & 0x80)) {
974 break;
975 }
976 }
977 printf(".%lu", ul);
978 }
979 }
980
981 \ Extensions with specific processing.
982 OID: basicConstraints 2.5.29.19
983 OID: keyUsage 2.5.29.15
984 OID: subjectAltName 2.5.29.17
985 OID: certificatePolicies 2.5.29.32
986
987 \ Policy qualifier "pointer to CPS"
988 OID: id-qt-cps 1.3.6.1.5.5.7.2.1
989
990 \ Extensions which are ignored when encountered, even if critical.
991 OID: authorityKeyIdentifier 2.5.29.35
992 OID: subjectKeyIdentifier 2.5.29.14
993 OID: issuerAltName 2.5.29.18
994 OID: subjectDirectoryAttributes 2.5.29.9
995 OID: crlDistributionPoints 2.5.29.31
996 OID: freshestCRL 2.5.29.46
997 OID: authorityInfoAccess 1.3.6.1.5.5.7.1.1
998 OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11
999
1000 \ Process a Basic Constraints extension. This should be called only if
1001 \ the certificate is not the EE. We check that the extension contains
1002 \ the "CA" flag, and that the path length, if specified, is compatible
1003 \ with the current chain length.
1004 : process-basicConstraints ( lim -- lim )
1005 read-sequence-open
1006 read-tag-or-end
1007 dup 0x01 = if
1008 read-boolean ifnot ERR_X509_NOT_CA fail then
1009 read-tag-or-end
1010 else
1011 ERR_X509_NOT_CA fail
1012 then
1013 dup 0x02 = if
1014 drop check-primitive read-small-int-value
1015 addr-num_certs get32 1- < if ERR_X509_NOT_CA fail then
1016 read-tag-or-end
1017 then
1018 -1 <> if ERR_X509_UNEXPECTED fail then
1019 drop
1020 close-elt
1021 ;
1022
1023 \ Process a Key Usage extension.
1024 \ For the EE certificate:
1025 \ -- if the key usage contains keyEncipherment (2), dataEncipherment (3)
1026 \ or keyAgreement (4), then the "key exchange" usage is allowed;
1027 \ -- if the key usage contains digitalSignature (0) or nonRepudiation (1),
1028 \ then the "signature" usage is allowed.
1029 \ For CA certificates, the extension must contain keyCertSign (5).
1030 : process-keyUsage ( lim ee -- lim )
1031 { ee }
1032
1033 \ Read tag for the BIT STRING and open it.
1034 read-tag 0x03 check-tag-primitive
1035 read-length-open-elt
1036 \ First byte indicates number of ignored bits in the last byte. It
1037 \ must be between 0 and 7.
1038 read8 { ign }
1039 ign 7 > if ERR_X509_UNEXPECTED fail then
1040 \ Depending on length, we have either 0, 1 or more bytes to read.
1041 dup case
1042 0 of ERR_X509_FORBIDDEN_KEY_USAGE fail endof
1043 1 of read8 ign >> ign << endof
1044 drop read8 0
1045 endcase
1046
1047 \ Check bits.
1048 ee if
1049 \ EE: get usages.
1050 0
1051 over 0x38 and if 0x10 or then
1052 swap 0xC0 and if 0x20 or then
1053 addr-key_usages set8
1054 else
1055 \ Not EE: keyCertSign must be set.
1056 0x04 and ifnot ERR_X509_FORBIDDEN_KEY_USAGE fail then
1057 then
1058
1059 \ We don't care about subsequent bytes.
1060 skip-close-elt ;
1061
1062 \ Process a Certificate Policies extension.
1063 \
1064 \ Since we don't actually support full policies processing, this function
1065 \ only checks that the extension contents can be safely ignored. Indeed,
1066 \ we don't validate against a specific set of policies (in RFC 5280
1067 \ terminology, user-initial-policy-set only contains the special value
1068 \ any-policy). Moreover, we don't support policy constraints (if a
1069 \ critical Policy Constraints extension is encountered, the validation
1070 \ will fail). Therefore, we can safely ignore the contents of this
1071 \ extension, except if it is critical AND one of the policy OID has a
1072 \ qualifier which is distinct from id-qt-cps (because id-qt-cps is
1073 \ specially designated by RFC 5280 has having no mandated action).
1074 \
1075 \ This function is called only if the extension is critical.
1076 : process-certPolicies ( lim -- lim )
1077 \ Extension value is a SEQUENCE OF PolicyInformation.
1078 read-sequence-open
1079 begin dup while
1080 \ PolicyInformation ::= SEQUENCE {
1081 \ policyIdentifier OBJECT IDENTIFIER,
1082 \ policyQualifiers SEQUENCE OF PolicyQualifierInfo OPTIONAL
1083 \ }
1084 read-sequence-open
1085 read-OID drop
1086 dup if
1087 read-sequence-open
1088 begin dup while
1089 \ PolicyQualifierInfo ::= SEQUENCE {
1090 \ policyQualifierId OBJECT IDENTIFIER,
1091 \ qualifier ANY
1092 \ }
1093 read-sequence-open
1094 read-OID drop id-qt-cps eqOID ifnot
1095 ERR_X509_CRITICAL_EXTENSION fail
1096 then
1097 skip-close-elt
1098 repeat
1099 close-elt
1100 then
1101 close-elt
1102 repeat
1103 close-elt ;
1104
1105 \ Process a Subject Alt Name extension. Returned value is a boolean set
1106 \ to true if the expected server name was matched against a dNSName in
1107 \ the extension.
1108 : process-SAN ( lim -- lim bool )
1109 0 { m }
1110 read-sequence-open
1111 begin dup while
1112 \ Read the tag. If the tag is context-0, then parse an
1113 \ 'otherName'. If the tag is context-2, then parse a
1114 \ dNSName. If the tag is context-1 or context-6,
1115 \ parse
1116 read-tag case
1117 \ OtherName
1118 0x20 of
1119 \ OtherName ::= SEQUENCE {
1120 \ type-id OBJECT IDENTIFIER,
1121 \ value [0] EXPLICIT ANY
1122 \ }
1123 check-constructed read-length-open-elt
1124 read-OID drop
1125 -1 offset-name-element { offbuf }
1126 read-tag 0x20 check-tag-constructed
1127 read-length-open-elt
1128 read-string offbuf copy-name-element
1129 close-elt
1130 close-elt
1131 endof
1132 \ rfc822Name (IA5String)
1133 0x21 of
1134 check-primitive
1135 read-value-UTF8 1 copy-name-SAN
1136 endof
1137 \ dNSName (IA5String)
1138 0x22 of
1139 check-primitive
1140 read-value-UTF8
1141 dup if match-server-name m or >m then
1142 2 copy-name-SAN
1143 endof
1144 \ uniformResourceIdentifier (IA5String)
1145 0x26 of
1146 check-primitive
1147 read-value-UTF8 6 copy-name-SAN
1148 endof
1149 2drop read-length-skip 0
1150 endcase
1151
1152 \ We check only names of type dNSName; they use IA5String,
1153 \ which is basically ASCII.
1154 \ read-tag 0x22 = if
1155 \ check-primitive
1156 \ read-small-value drop
1157 \ match-server-name m or >m
1158 \ else
1159 \ drop read-length-skip
1160 \ then
1161 repeat
1162 close-elt
1163 m ;
1164
1165 \ Decode a certificate. The "ee" boolean must be true for the EE.
1166 : decode-certificate ( ee -- )
1167 { ee }
1168
1169 \ Obtain the total certificate length.
1170 addr-cert_length get32
1171
1172 \ Open the outer SEQUENCE.
1173 read-sequence-open
1174
1175 \ TBS
1176 \ Activate hashing.
1177 start-tbs-hash
1178 read-sequence-open
1179
1180 \ First element may be an explicit version. We accept only
1181 \ versions 0 to 2 (certificates v1 to v3).
1182 read-tag dup 0x20 = if
1183 drop check-constructed read-length-open-elt
1184 read-tag
1185 0x02 check-tag-primitive
1186 read-small-int-value
1187 2 > if ERR_X509_UNSUPPORTED fail then
1188 close-elt
1189 read-tag
1190 then
1191
1192 \ Serial number. We just check that the tag is correct.
1193 0x02 check-tag-primitive
1194 read-length-skip
1195
1196 \ Signature algorithm. This structure is redundant with the one
1197 \ on the outside; we just skip it.
1198 read-sequence-open skip-close-elt
1199
1200 \ Issuer name: hashed, then copied into next_dn_hash[].
1201 read-DN
1202 addr-next_dn_hash addr-current_dn_hash dn-hash-length blobcopy
1203
1204 \ Validity dates.
1205 read-sequence-open
1206 read-date get-system-date after if ERR_X509_EXPIRED fail then
1207 read-date get-system-date before if ERR_X509_EXPIRED fail then
1208 close-elt
1209
1210 \ Subject name.
1211 ee if
1212 \ For the EE, we must check whether the Common Name, if
1213 \ any, matches the expected server name.
1214 read-DN-EE { eename }
1215 else
1216 \ For a non-EE certificate, the hashed subject DN must match
1217 \ the saved hashed issuer DN from the previous certificate.
1218 read-DN
1219 addr-current_dn_hash addr-saved_dn_hash dn-hash-length eqblob
1220 ifnot ERR_X509_DN_MISMATCH fail then
1221 then
1222 \ Move the hashed issuer DN for this certificate into the
1223 \ saved_dn_hash[] array.
1224 addr-saved_dn_hash addr-next_dn_hash dn-hash-length blobcopy
1225
1226 \ Public Key.
1227 read-sequence-open
1228 \ Algorithm Identifier. Right now we are only interested in the
1229 \ OID, since we only support RSA keys.
1230 read-sequence-open
1231 read-OID ifnot ERR_X509_UNSUPPORTED fail then
1232 { ; pkey-type }
1233 choice
1234 \ RSA public key.
1235 rsaEncryption eqOID uf
1236 skip-close-elt
1237 \ Public key itself: the BIT STRING contains bytes
1238 \ (no partial byte) and these bytes encode the
1239 \ actual value.
1240 read-bits-open
1241 \ RSA public key is a SEQUENCE of two
1242 \ INTEGER. We get both INTEGER values into
1243 \ the pkey_data[] buffer, if they fit.
1244 read-sequence-open
1245 addr-len-pkey_data
1246 read-integer { nlen }
1247 addr-len-pkey_data swap nlen + swap nlen -
1248 read-integer { elen }
1249 close-elt
1250
1251 \ Check that the public key fits our minimal
1252 \ size requirements. Note that the integer
1253 \ decoder already skipped the leading bytes
1254 \ of value 0, so we are working on the true
1255 \ modulus length here.
1256 addr-min_rsa_size get16 128 + nlen > if
1257 ERR_X509_WEAK_PUBLIC_KEY fail
1258 then
1259 close-elt
1260 KEYTYPE_RSA >pkey-type
1261 enduf
1262
1263 \ EC public key.
1264 id-ecPublicKey eqOID uf
1265 \ We support only named curves, for which the
1266 \ "parameters" field in the AlgorithmIdentifier
1267 \ field should be an OID.
1268 read-OID ifnot ERR_X509_UNSUPPORTED fail then
1269 choice
1270 ansix9p256r1 eqOID uf 23 enduf
1271 ansix9p384r1 eqOID uf 24 enduf
1272 ansix9p521r1 eqOID uf 25 enduf
1273 ERR_X509_UNSUPPORTED fail
1274 endchoice
1275 { curve }
1276 close-elt
1277 read-bits-open
1278 dup { qlen }
1279 dup addr-len-pkey_data rot < if
1280 ERR_X509_LIMIT_EXCEEDED fail
1281 then
1282 read-blob
1283 KEYTYPE_EC >pkey-type
1284 enduf
1285
1286 \ Not a recognised public key type.
1287 ERR_X509_UNSUPPORTED fail
1288 endchoice
1289 close-elt
1290
1291 \ Process public key.
1292 ee if
1293 \ For the EE certificate, copy the key data to the
1294 \ relevant buffer.
1295 pkey-type case
1296 KEYTYPE_RSA of nlen elen copy-ee-rsa-pkey endof
1297 KEYTYPE_EC of curve qlen copy-ee-ec-pkey endof
1298 ERR_X509_UNSUPPORTED fail
1299 endcase
1300 else
1301 \ Verify signature on previous certificate. We invoke
1302 \ the RSA implementation.
1303 pkey-type case
1304 KEYTYPE_RSA of nlen elen do-rsa-vrfy endof
1305 KEYTYPE_EC of curve qlen do-ecdsa-vrfy endof
1306 ERR_X509_UNSUPPORTED fail
1307 endcase
1308 dup if fail then
1309 drop
1310 then
1311
1312 \ This flag will be set to true if the Basic Constraints extension
1313 \ is encountered.
1314 0 { seenBC }
1315
1316 \ Skip issuerUniqueID and subjectUniqueID, and process extensions
1317 \ if present. Extensions are an explicit context tag of value 3
1318 \ around a SEQUENCE OF extensions. Each extension is a SEQUENCE
1319 \ with an OID, an optional boolean, and a value; the value is
1320 \ an OCTET STRING.
1321 read-tag-or-end
1322 0x21 iftag-skip
1323 0x22 iftag-skip
1324 dup 0x23 = if
1325 drop
1326 check-constructed read-length-open-elt
1327 read-sequence-open
1328 begin dup while
1329 0 { critical }
1330 read-sequence-open
1331 read-OID drop
1332 read-tag dup 0x01 = if
1333 read-boolean >critical
1334 read-tag
1335 then
1336 0x04 check-tag-primitive read-length-open-elt
1337 choice
1338 \ Extensions with specific processing.
1339 basicConstraints eqOID uf
1340 ee if
1341 skip-remaining
1342 else
1343 process-basicConstraints
1344 -1 >seenBC
1345 then
1346 enduf
1347 keyUsage eqOID uf
1348 ee process-keyUsage
1349 enduf
1350 subjectAltName eqOID uf
1351 ee if
1352 0 >eename
1353 process-SAN >eename
1354 else
1355 skip-remaining
1356 then
1357 enduf
1358
1359 \ We don't implement full processing of
1360 \ policies. The call below mostly checks
1361 \ that the contents of the Certificate
1362 \ Policies extension can be safely ignored.
1363 certificatePolicies eqOID uf
1364 critical if
1365 process-certPolicies
1366 else
1367 skip-remaining
1368 then
1369 enduf
1370
1371 \ Extensions which are always ignored,
1372 \ even if critical.
1373 authorityKeyIdentifier eqOID uf
1374 skip-remaining
1375 enduf
1376 subjectKeyIdentifier eqOID uf
1377 skip-remaining
1378 enduf
1379 issuerAltName eqOID uf
1380 skip-remaining
1381 enduf
1382 subjectDirectoryAttributes eqOID uf
1383 skip-remaining
1384 enduf
1385 crlDistributionPoints eqOID uf
1386 skip-remaining
1387 enduf
1388 freshestCRL eqOID uf
1389 skip-remaining
1390 enduf
1391 authorityInfoAccess eqOID uf
1392 skip-remaining
1393 enduf
1394 subjectInfoAccess eqOID uf
1395 skip-remaining
1396 enduf
1397
1398 \ Unrecognized extensions trigger a failure
1399 \ if critical; otherwise, they are just
1400 \ ignored.
1401 critical if
1402 ERR_X509_CRITICAL_EXTENSION fail
1403 then
1404 skip-remaining
1405 endchoice
1406 close-elt
1407 close-elt
1408 repeat
1409 close-elt
1410 close-elt
1411 else
1412 -1 = ifnot ERR_X509_UNEXPECTED fail then
1413 drop
1414 then
1415
1416 close-elt
1417 \ Terminate hashing.
1418 stop-tbs-hash
1419
1420 \ For the EE certificate, verify that the intended server name
1421 \ was matched.
1422 ee if
1423 eename zero-server-name or ifnot
1424 ERR_X509_BAD_SERVER_NAME fail
1425 then
1426 then
1427
1428 \ If this is the EE certificate, then direct trust may apply.
1429 \ Note: we do this at this point, not immediately after decoding
1430 \ the public key, because even in case of direct trust we still
1431 \ want to check the server name with regards to the SAN extension.
1432 \ However, we want to check direct trust before trying to decode
1433 \ the signature algorithm, because it should work even if that
1434 \ algorithm is not supported.
1435 ee if check-direct-trust then
1436
1437 \ Non-EE certificates MUST have a Basic Constraints extension
1438 \ (that marks them as being CA).
1439 ee seenBC or ifnot ERR_X509_NOT_CA fail then
1440
1441 \ signature algorithm
1442 read-tag check-sequence read-length-open-elt
1443 \ Read and understand the OID. Right now, we support only
1444 \ RSA with PKCS#1 v1.5 padding, and hash functions SHA-1,
1445 \ SHA-224, SHA-256, SHA-384 and SHA-512. We purposely do NOT
1446 \ support MD5 here.
1447 \ TODO: add support for RSA/PSS
1448 read-OID if
1449 \ Based on the signature OID, we get:
1450 \ -- the signing key type
1451 \ -- the hash function numeric identifier
1452 \ -- the hash function OID
1453 choice
1454 sha1WithRSAEncryption eqOID
1455 uf 2 KEYTYPE_RSA id-sha1 enduf
1456 sha224WithRSAEncryption eqOID
1457 uf 3 KEYTYPE_RSA id-sha224 enduf
1458 sha256WithRSAEncryption eqOID
1459 uf 4 KEYTYPE_RSA id-sha256 enduf
1460 sha384WithRSAEncryption eqOID
1461 uf 5 KEYTYPE_RSA id-sha384 enduf
1462 sha512WithRSAEncryption eqOID
1463 uf 6 KEYTYPE_RSA id-sha512 enduf
1464
1465 ecdsa-with-SHA1 eqOID
1466 uf 2 KEYTYPE_EC id-sha1 enduf
1467 ecdsa-with-SHA224 eqOID
1468 uf 3 KEYTYPE_EC id-sha224 enduf
1469 ecdsa-with-SHA256 eqOID
1470 uf 4 KEYTYPE_EC id-sha256 enduf
1471 ecdsa-with-SHA384 eqOID
1472 uf 5 KEYTYPE_EC id-sha384 enduf
1473 ecdsa-with-SHA512 eqOID
1474 uf 6 KEYTYPE_EC id-sha512 enduf
1475 ERR_X509_UNSUPPORTED fail
1476 endchoice
1477 addr-cert_sig_hash_oid set16
1478 addr-cert_signer_key_type set8
1479
1480 \ Compute the TBS hash into tbs_hash.
1481 compute-tbs-hash
1482 dup ifnot ERR_X509_UNSUPPORTED fail then
1483 addr-cert_sig_hash_len set8
1484 else
1485 ERR_X509_UNSUPPORTED fail
1486 then
1487 \ We ignore the parameters, whether they are present or not,
1488 \ because we got all the information from the OID.
1489 skip-close-elt
1490
1491 \ signature value
1492 read-bits-open
1493 dup CX 0 8191 { BR_X509_BUFSIZE_SIG } > if
1494 ERR_X509_LIMIT_EXCEEDED fail
1495 then
1496 dup addr-cert_sig_len set16
1497 addr-cert_sig read-blob
1498
1499 \ Close the outer SEQUENCE.
1500 close-elt
1501
1502 \ Close the advertised total certificate length. This checks that
1503 \ there is no trailing garbage after the certificate.
1504 close-elt
1505
1506 \ Flag the certificate as fully processed.
1507 0 addr-cert_length set32
1508
1509 \ Check whether the issuer for the current certificate is known
1510 \ as a trusted CA; in which case, verify the signature.
1511 check-trust-anchor-CA ;
1512
1513 : main
1514 \ Unless restricted by a Key Usage extension, all usages are
1515 \ deemed allowed.
1516 0x30 addr-key_usages set8
1517 -1 decode-certificate
1518 co
1519 begin
1520 0 decode-certificate co
1521 again
1522 ;