xref: /freebsd/contrib/bearssl/src/x509/x509_minimal.t0 (revision 6be3386466ab79a84b48429ae66244f21526d3df)
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
23preamble {
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 *
164void br_x509_minimal_init_main(void *ctx);
165void br_x509_minimal_run(void *ctx);
166 */
167
168/* see bearssl_x509.h */
169void
170br_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
181static void
182xm_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
205static void
206xm_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
221static void
222xm_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
235static void
236xm_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
247static unsigned
248xm_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
265static const br_x509_pkey *
266xm_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 */
284const 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 */
304static void
305hash_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 */
317static int
318eqbigint(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 */
339static int
340eqnocase(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
364static int verify_signature(br_x509_minimal_context *ctx,
365	const br_x509_pkey *pk);
366
367}
368
369postamble {
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 */
376static int
377verify_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
422cc: 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
438addr: cert_length
439addr: num_certs
440
441cc: 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.
467cc: 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.
475cc: zero-server-name ( -- bool ) {
476	T0_PUSHi(-(CTX->server_name == NULL));
477}
478
479addr: key_usages
480addr: cert_sig
481addr: cert_sig_len
482addr: cert_signer_key_type
483addr: cert_sig_hash_oid
484addr: cert_sig_hash_len
485addr: tbs_hash
486addr: min_rsa_size
487
488\ Start TBS hash computation. The hash functions are reinitialised.
489cc: start-tbs-hash ( -- ) {
490	br_multihash_init(&CTX->mhash);
491	CTX->do_mhash = 1;
492}
493
494\ Stop TBS hash computation.
495cc: stop-tbs-hash ( -- ) {
496	CTX->do_mhash = 0;
497}
498
499\ Start DN hash computation.
500cc: 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.
507cc: 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.
513cc: dn-hash-length ( -- len ) {
514	T0_PUSH(DNHASH_LEN);
515}
516
517\ Copy data between two areas in the context.
518cc: 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
525addr: current_dn_hash
526addr: next_dn_hash
527addr: 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
536cc: 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
567cc: 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
590cc: 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.
702cc: 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.
747cc: 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).
785cc: 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).
797cc: 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.
808cc: 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.
869cc: 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.
895cc: 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.
912cc: 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
924cc: 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
935cc: 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.
968OID: basicConstraints      2.5.29.19
969OID: keyUsage              2.5.29.15
970OID: subjectAltName        2.5.29.17
971OID: certificatePolicies   2.5.29.32
972
973\ Policy qualifier "pointer to CPS"
974OID: id-qt-cps             1.3.6.1.5.5.7.2.1
975
976\ Extensions which are ignored when encountered, even if critical.
977OID: authorityKeyIdentifier        2.5.29.35
978OID: subjectKeyIdentifier          2.5.29.14
979OID: issuerAltName                 2.5.29.18
980OID: subjectDirectoryAttributes    2.5.29.9
981OID: crlDistributionPoints         2.5.29.31
982OID: freshestCRL                   2.5.29.46
983OID: authorityInfoAccess           1.3.6.1.5.5.7.1.1
984OID: 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	;
1509