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