aboutsummaryrefslogtreecommitdiffstats
path: root/test/monniaux/BearSSL/src/x509/x509_decoder.t0
blob: 0bf276fba6abaf1e327a7e5bed47779517d406a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
\ Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
\
\ Permission is hereby granted, free of charge, to any person obtaining 
\ a copy of this software and associated documentation files (the
\ "Software"), to deal in the Software without restriction, including
\ without limitation the rights to use, copy, modify, merge, publish,
\ distribute, sublicense, and/or sell copies of the Software, and to
\ permit persons to whom the Software is furnished to do so, subject to
\ the following conditions:
\
\ The above copyright notice and this permission notice shall be 
\ included in all copies or substantial portions of the Software.
\
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\ SOFTWARE.

preamble {

#include "inner.h"

#define CTX   ((br_x509_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_decoder_context, cpu)))
#define CONTEXT_NAME   br_x509_decoder_context

/* see bearssl_x509.h */
void
br_x509_decoder_init(br_x509_decoder_context *ctx,
	void (*append_dn)(void *ctx, const void *buf, size_t len),
	void *append_dn_ctx)
{
	memset(ctx, 0, sizeof *ctx);
	/* obsolete
	ctx->err = 0;
	ctx->hbuf = NULL;
	ctx->hlen = 0;
	*/
	ctx->append_dn = append_dn;
	ctx->append_dn_ctx = append_dn_ctx;
	ctx->cpu.dp = &ctx->dp_stack[0];
	ctx->cpu.rp = &ctx->rp_stack[0];
	br_x509_decoder_init_main(&ctx->cpu);
	br_x509_decoder_run(&ctx->cpu);
}

/* see bearssl_x509.h */
void
br_x509_decoder_push(br_x509_decoder_context *ctx,
	const void *data, size_t len)
{
	ctx->hbuf = data;
	ctx->hlen = len;
	br_x509_decoder_run(&ctx->cpu);
}

}

addr: decoded
addr: notbefore_days
addr: notbefore_seconds
addr: notafter_days
addr: notafter_seconds
addr: isCA
addr: copy_dn
addr: signer_key_type
addr: signer_hash_id

cc: read8-low ( -- x ) {
	if (CTX->hlen == 0) {
		T0_PUSHi(-1);
	} else {
		unsigned char x = *CTX->hbuf ++;
		if (CTX->copy_dn && CTX->append_dn) {
			CTX->append_dn(CTX->append_dn_ctx, &x, 1);
		}
		CTX->hlen --;
		T0_PUSH(x);
	}
}

cc: read-blob-inner ( addr len -- addr len ) {
	uint32_t len = T0_POP();
	uint32_t addr = T0_POP();
	size_t clen = CTX->hlen;
	if (clen > len) {
		clen = (size_t)len;
	}
	if (addr != 0) {
		memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen);
	}
	if (CTX->copy_dn && CTX->append_dn) {
		CTX->append_dn(CTX->append_dn_ctx, CTX->hbuf, clen);
	}
	CTX->hbuf += clen;
	CTX->hlen -= clen;
	T0_PUSH(addr + clen);
	T0_PUSH(len - clen);
}

\ Get the address and length for the pkey_data buffer.
: addr-len-pkey_data ( -- addr len )
	CX 0 8191 { offsetof(br_x509_decoder_context, pkey_data) }
	CX 0 8191 { BR_X509_BUFSIZE_KEY } ;

\ Copy the public key (RSA) to the permanent buffer.
cc: copy-rsa-pkey ( nlen elen -- ) {
	size_t elen = T0_POP();
	size_t nlen = T0_POP();
	CTX->pkey.key_type = BR_KEYTYPE_RSA;
	CTX->pkey.key.rsa.n = CTX->pkey_data;
	CTX->pkey.key.rsa.nlen = nlen;
	CTX->pkey.key.rsa.e = CTX->pkey_data + nlen;
	CTX->pkey.key.rsa.elen = elen;
}

\ Copy the public key (EC) to the permanent buffer.
cc: copy-ec-pkey ( curve qlen -- ) {
	size_t qlen = T0_POP();
	uint32_t curve = T0_POP();
	CTX->pkey.key_type = BR_KEYTYPE_EC;
	CTX->pkey.key.ec.curve = curve;
	CTX->pkey.key.ec.q = CTX->pkey_data;
	CTX->pkey.key.ec.qlen = qlen;
}

\ Extensions with specific processing.
OID: basicConstraints    2.5.29.19

\ Process a Basic Constraints extension. We want the "CA" flag only.
: process-basicConstraints ( lim -- lim )
	read-sequence-open
	read-tag-or-end dup 0x01 = if
		read-boolean 1 and addr-isCA set8
	else
		2drop
	then
	skip-close-elt
	;

\ Decode a certificate.
: main ( -- ! )

	\ Initialise state flags.
	0 addr-decoded set8
	0 addr-copy_dn set8

	\ An arbitrary limit for the total certificate size.
	0xFFFFFF

	\ Open the outer SEQUENCE.
	read-sequence-open

	\ TBS
	read-sequence-open

	\ First element may be an explicit version. We accept only
	\ versions 0 to 2 (certificates v1 to v3).
	read-tag dup 0x20 = if
		drop check-constructed read-length-open-elt
		read-tag
		0x02 check-tag-primitive
		read-small-int-value
		2 > if ERR_X509_UNSUPPORTED fail then
		close-elt
		read-tag
	then

	\ Serial number. We just check that the tag is correct.
	0x02 check-tag-primitive read-length-skip

	\ Signature algorithm.
	read-sequence-open skip-close-elt

	\ Issuer name.
	read-sequence-open skip-close-elt

	\ Validity dates.
	read-sequence-open
	read-date addr-notbefore_seconds set32 addr-notbefore_days set32
	read-date addr-notafter_seconds set32 addr-notafter_days set32
	close-elt

	\ Subject name.
	1 addr-copy_dn set8
	read-sequence-open skip-close-elt
	0 addr-copy_dn set8

	\ Public Key.
	read-sequence-open
	\ Algorithm Identifier. Right now we are only interested in the
	\ OID, since we only support RSA keys.
	\ TODO: support EC keys
	read-sequence-open
	read-OID ifnot ERR_X509_UNSUPPORTED fail then
	choice
		\ RSA public key.
		rsaEncryption eqOID uf
			skip-close-elt
			\ Public key itself: the BIT STRING contains bytes
			\ (no partial byte) and these bytes encode the
			\ actual value.
			read-bits-open
				\ RSA public key is a SEQUENCE of two
				\ INTEGER. We get both INTEGER values into
				\ the pkey_data[] buffer, if they fit.
				read-sequence-open
				addr-len-pkey_data
				read-integer { nlen }
				addr-len-pkey_data swap nlen + swap nlen -
				read-integer { elen }
				close-elt
			close-elt
			nlen elen copy-rsa-pkey
		enduf

		\ EC public key.
		id-ecPublicKey eqOID uf
			\ We support only named curves, for which the
			\ "parameters" field in the AlgorithmIdentifier
			\ field should be an OID.
			read-curve-ID { curve }
			close-elt
			read-bits-open
			dup { qlen }
			dup addr-len-pkey_data rot < if
				ERR_X509_LIMIT_EXCEEDED fail
			then
			read-blob
			curve qlen copy-ec-pkey
		enduf
		ERR_X509_UNSUPPORTED fail
	endchoice
	close-elt

	\ This flag will be set to true if the Basic Constraints extension
	\ is encountered.
	0 addr-isCA set8

	\ Skip issuerUniqueID and subjectUniqueID, and process extensions
	\ if present. Extensions are an explicit context tag of value 3
	\ around a SEQUENCE OF extensions. Each extension is a SEQUENCE
	\ with an OID, an optional boolean, and a value; the value is
	\ an OCTET STRING.
	read-tag-or-end
	0x21 iftag-skip
	0x22 iftag-skip
	dup 0x23 = if
		drop
		check-constructed read-length-open-elt
		read-sequence-open
		begin dup while
			read-sequence-open
			read-OID drop
			read-tag dup 0x01 = if
				read-boolean drop
				read-tag
			then
			0x04 check-tag-primitive read-length-open-elt
			choice
				\ Extensions with specific processing.
				basicConstraints eqOID uf
					process-basicConstraints
				enduf
				skip-remaining
			endchoice
			close-elt
			close-elt
		repeat
		close-elt
		close-elt
	else
		-1 = ifnot ERR_X509_UNEXPECTED fail then
		drop
	then

	close-elt

	\ signature algorithm
	read-sequence-open
	read-OID if
		choice
			sha1WithRSAEncryption    eqOID uf 2 KEYTYPE_RSA enduf
			sha224WithRSAEncryption  eqOID uf 3 KEYTYPE_RSA enduf
			sha256WithRSAEncryption  eqOID uf 4 KEYTYPE_RSA enduf
			sha384WithRSAEncryption  eqOID uf 5 KEYTYPE_RSA enduf
			sha512WithRSAEncryption  eqOID uf 6 KEYTYPE_RSA enduf

			ecdsa-with-SHA1          eqOID uf 2 KEYTYPE_EC enduf
			ecdsa-with-SHA224        eqOID uf 3 KEYTYPE_EC enduf
			ecdsa-with-SHA256        eqOID uf 4 KEYTYPE_EC enduf
			ecdsa-with-SHA384        eqOID uf 5 KEYTYPE_EC enduf
			ecdsa-with-SHA512        eqOID uf 6 KEYTYPE_EC enduf

			0 0
		endchoice
	else
		0 0
	then
	addr-signer_key_type set8
	addr-signer_hash_id set8
	skip-close-elt
	\ read-sequence-open skip-close-elt

	\ signature value
	read-bits-open skip-close-elt

	\ Close the outer SEQUENCE.
	close-elt
	drop

	\ Mark the decoding as successful.
	1 addr-decoded set8

	\ Read one byte, then fail: if the read succeeds, then there is
	\ some trailing byte.
	read8-nc ERR_X509_EXTRA_ELEMENT fail
	;