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