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