Fixed some typographic errors in comments.
[BearSSL] / src / x509 / skey_decoder.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 #define CTX ((br_skey_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_skey_decoder_context, cpu)))
28 #define CONTEXT_NAME br_skey_decoder_context
29
30 /* see bearssl_x509.h */
31 void
32 br_skey_decoder_init(br_skey_decoder_context *ctx)
33 {
34 memset(ctx, 0, sizeof *ctx);
35 ctx->cpu.dp = &ctx->dp_stack[0];
36 ctx->cpu.rp = &ctx->rp_stack[0];
37 br_skey_decoder_init_main(&ctx->cpu);
38 br_skey_decoder_run(&ctx->cpu);
39 }
40
41 /* see bearssl_x509.h */
42 void
43 br_skey_decoder_push(br_skey_decoder_context *ctx,
44 const void *data, size_t len)
45 {
46 ctx->hbuf = data;
47 ctx->hlen = len;
48 br_skey_decoder_run(&ctx->cpu);
49 }
50
51 }
52
53 addr: key_type
54 addr: key_data
55
56 cc: read8-low ( -- x ) {
57 if (CTX->hlen == 0) {
58 T0_PUSHi(-1);
59 } else {
60 CTX->hlen --;
61 T0_PUSH(*CTX->hbuf ++);
62 }
63 }
64
65 cc: read-blob-inner ( addr len -- addr len ) {
66 uint32_t len = T0_POP();
67 uint32_t addr = T0_POP();
68 size_t clen = CTX->hlen;
69 if (clen > len) {
70 clen = (size_t)len;
71 }
72 if (addr != 0) {
73 memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen);
74 }
75 CTX->hbuf += clen;
76 CTX->hlen -= clen;
77 T0_PUSH(addr + clen);
78 T0_PUSH(len - clen);
79 }
80
81 \ Get the length of the key_data buffer.
82 : len-key_data
83 CX 0 8191 { 3 * BR_X509_BUFSIZE_KEY } ;
84
85 \ Get the address and length for the key_data buffer.
86 : addr-len-key_data ( -- addr len )
87 addr-key_data len-key_data ;
88
89 \ Set the private key (RSA).
90 cc: set-rsa-key ( n_bitlen plen qlen dplen dqlen iqlen -- ) {
91 size_t iqlen = T0_POP();
92 size_t dqlen = T0_POP();
93 size_t dplen = T0_POP();
94 size_t qlen = T0_POP();
95 size_t plen = T0_POP();
96 uint32_t n_bitlen = T0_POP();
97 size_t off;
98
99 CTX->key.rsa.n_bitlen = n_bitlen;
100 CTX->key.rsa.p = CTX->key_data;
101 CTX->key.rsa.plen = plen;
102 off = plen;
103 CTX->key.rsa.q = CTX->key_data + off;
104 CTX->key.rsa.qlen = qlen;
105 off += qlen;
106 CTX->key.rsa.dp = CTX->key_data + off;
107 CTX->key.rsa.dplen = dplen;
108 off += dplen;
109 CTX->key.rsa.dq = CTX->key_data + off;
110 CTX->key.rsa.dqlen = dqlen;
111 off += dqlen;
112 CTX->key.rsa.iq = CTX->key_data + off;
113 CTX->key.rsa.iqlen = iqlen;
114 }
115
116 \ Set the private key (EC).
117 cc: set-ec-key ( curve xlen -- ) {
118 size_t xlen = T0_POP();
119 uint32_t curve = T0_POP();
120 CTX->key.ec.curve = curve;
121 CTX->key.ec.x = CTX->key_data;
122 CTX->key.ec.xlen = xlen;
123 }
124
125 \ Get the bit length for an integer (unsigned).
126 : int-bit-length ( x -- bitlen )
127 0 swap
128 begin dup while 1 u>> swap 1+ swap repeat
129 drop ;
130
131 \ Read an INTEGER into the key_data buffer, but then ignore it.
132 : read-integer-ignore ( lim -- lim )
133 addr-len-key_data read-integer drop ;
134
135 \ Read an INTEGER into the key_data buffer, at the provided offset.
136 \ Returned value is the integer length (in bytes).
137 : read-integer-off ( lim off -- lim dlen )
138 dup addr-len-key_data rot - swap rot + swap read-integer ;
139
140 \ Decode RSA key, starting with the SEQUENCE tag.
141 : decode-RSA ( lim -- lim )
142 read-sequence-open
143
144 \ Version should be 0.
145 read-tag 0x02 check-tag-primitive read-small-int-value if
146 ERR_X509_UNSUPPORTED fail
147 then
148
149 \ Read tag for the modulus; should be INTEGER. Then use the
150 \ decode-RSA-next function for the remainder of the key.
151 read-tag 0x02 check-tag-primitive
152 decode-RSA-next
153
154 \ Close the SEQUENCE.
155 close-elt ;
156
157 \ Decode RSA key; the version, and the tag for the modulus, have been
158 \ read.
159 : decode-RSA-next ( lim -- lim )
160 \ Modulus: we read it but we do not keep it; we merely gather
161 \ the modulus bit length.
162 addr-len-key_data read-integer-next
163 dup ifnot ERR_X509_UNEXPECTED fail then
164 1- 3 << addr-key_data get8 int-bit-length + { n_bitlen }
165
166 \ Public exponent: read but skip.
167 read-integer-ignore
168
169 \ Private exponent: read but skip.
170 read-integer-ignore
171
172 \ First prime factor.
173 addr-len-key_data read-integer dup dup { off plen }
174
175 \ Second prime factor.
176 read-integer-off dup { qlen } off + dup >off
177
178 \ First reduced private exponent.
179 read-integer-off dup { dplen } off + dup >off
180
181 \ Second reduced private exponent.
182 read-integer-off dup { dqlen } off + dup >off
183
184 \ CRT coefficient.
185 read-integer-off { iqlen }
186
187 \ Set RSA key.
188 n_bitlen plen qlen dplen dqlen iqlen set-rsa-key
189
190 \ The caller will close the sequence, thereby validating that there
191 \ is no extra field.
192 ;
193
194 \ Decode an EC key, starting with the SEQUENCE tag.
195 : decode-EC ( lim curve -- lim )
196 { curve }
197 read-sequence-open
198
199 \ Version should be 1.
200 read-tag 0x02 check-tag-primitive read-small-int-value 1- if
201 ERR_X509_UNSUPPORTED fail
202 then
203
204 \ Read tag for the private key; should be OCTET STRING. Then use the
205 \ decode-EC-next function for the remainder of the key.
206 read-tag 0x04 check-tag-primitive
207 curve decode-EC-next
208
209 \ Close the SEQUENCE.
210 close-elt ;
211
212 \ Decode an EC key; the version, and the tag for the OCTET STRING, have
213 \ already been read. The curve ID is provided (0 if unknown).
214 : decode-EC-next ( lim curve -- lim )
215 { curve }
216
217 \ Read the private key proper.
218 read-length-open-elt
219 dup dup { xlen } len-key_data > if ERR_X509_UNSUPPORTED fail then
220 addr-key_data read-blob
221
222 \ Next element might be the curve identifier.
223 read-tag-or-end
224 case
225
226 \ End of structure.
227 -1 of drop endof
228
229 \ Curve parameters; we support only named curves.
230 0x20 of
231 check-constructed read-length-open-elt
232 read-curve-ID
233 curve if
234 curve <> if ERR_X509_INVALID_VALUE fail then
235 else
236 >curve
237 then
238 close-elt
239 endof
240
241 \ Public key. We ignore it.
242 0x21 of check-constructed endof
243
244 ERR_X509_UNSUPPORTED fail
245 endcase
246 skip-remaining
247
248 \ The curve must have been defined one way or another.
249 curve ifnot ERR_X509_UNSUPPORTED fail then
250
251 \ Set the EC key.
252 curve xlen set-ec-key
253
254 \ The caller will close the sequence.
255 ;
256
257 \ Decode a PKCS#8 object. The version and the tag for the AlgorithmIdentifier
258 \ structure have already been read. This function returns the key type.
259 : decode-PKCS8-next ( lim -- lim keytype )
260 \ Decode the AlgorithmIdentifier.
261 read-length-open-elt
262 read-OID ifnot ERR_X509_UNSUPPORTED fail then
263 { ; is-rsa curve }
264 choice
265 rsaEncryption eqOID uf
266 \ RSA private key. We ignore the parameters.
267 skip-remaining -1 >is-rsa
268 enduf
269 id-ecPublicKey eqOID uf
270 \ EC private key. Parameters, if present, shall
271 \ identify the curve.
272 0 >is-rsa
273 dup if read-curve-ID else 0 then >curve
274 enduf
275
276 ERR_X509_UNSUPPORTED fail
277 endchoice
278 close-elt
279
280 \ Open private key value and decode it.
281 read-tag 0x04 check-tag-primitive
282 read-length-open-elt
283 is-rsa if
284 decode-RSA
285 else
286 curve decode-EC
287 then
288 close-elt
289
290 \ We ignore any extra field, i.e. attributes or public key.
291 skip-remaining
292
293 \ Return the key type.
294 is-rsa if KEYTYPE_RSA else KEYTYPE_EC then
295 ;
296
297 \ Decode a private key.
298 : main ( -- ! )
299 \ RSA private key format is defined in PKCS#1 (RFC 3447):
300 \ RSAPrivateKey ::= SEQUENCE {
301 \ version INTEGER, -- 0 or 1
302 \ n INTEGER,
303 \ e INTEGER,
304 \ d INTEGER,
305 \ p INTEGER,
306 \ q INTEGER,
307 \ dp INTEGER,
308 \ dq INTEGER,
309 \ iq INTEGER,
310 \ other OtherPrimeInfos OPTIONAL
311 \ }
312 \ We do not support keys with more than two primes (these have
313 \ version 1); thus, we expect the version field to be 0, and
314 \ the 'other' field to be absent.
315 \
316 \ EC private key format is defined in RFC 5915:
317 \ ECPrivateKey ::= SEQUENCE {
318 \ version INTEGER, -- always 1
319 \ privateKey OCTET STRING,
320 \ parameters [0] EXPLICIT OBJECT IDENTIFIER OPTIONAL,
321 \ publicKey [1] EXPLICIT BIT STRING OPTIONAL
322 \ }
323 \ The "parameters" might conceptually be a complex curve description
324 \ structure but we support only named curves. The private key
325 \ contents are the unsigned big-endian encoding of the key value,
326 \ which is exactly what we want.
327 \
328 \ PKCS#8 (unencrypted) is:
329 \ OneAsymmetricKey ::= SEQUENCE {
330 \ version INTEGER, -- 0 or 1
331 \ algorithm AlgorithmIdentifier,
332 \ privateKey OCTET STRING,
333 \ attributes [0] IMPLICIT Attributes OPTIONAL,
334 \ publicKey [1] IMPLICIT BIT STRING OPTIONAL
335 \ }
336 \ The 'publicKey' field is an add-on from RFC 5958 and may be
337 \ present only if the 'version' is v2 (i.e. has value 1). We
338 \ ignore it anyway.
339
340 \ An arbitrary upper limit on the private key size.
341 0xFFFFFF
342
343 \ Open the outer SEQUENCE.
344 read-sequence-open
345
346 \ All our schemas begin with a small INTEGER which is either 0 or
347 \ 1. We don't care which it is.
348 read-tag 0x02 check-tag-primitive read-small-int-value 1 > if
349 ERR_X509_UNSUPPORTED fail
350 then
351
352 \ Get next tag: it should be either an INTEGER (RSA private key),
353 \ an OCTET STRING (EC private key), or a SEQUENCE (for an
354 \ AlgorithmIdentifier, in a PKCS#8 object).
355 read-tag
356 case
357 0x02 of check-primitive decode-RSA-next KEYTYPE_RSA endof
358 0x04 of check-primitive 0 decode-EC-next KEYTYPE_EC endof
359 0x10 of check-constructed decode-PKCS8-next endof
360 ERR_X509_UNSUPPORTED fail
361 endcase
362 { key-type }
363
364 \ Close the SEQUENCE.
365 close-elt
366
367 \ Set the key type, which marks the decoding as a success.
368 key-type addr-key_type set8
369
370 \ Read one byte, then fail: if the read succeeds, then there is
371 \ some trailing byte.
372 read8-nc ERR_X509_EXTRA_ELEMENT fail
373 ;