/ src / x509 / skey_decoder.t0
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_SIG } ;
 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  	;