10957b409SSimon J. Gerraty\ Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
20957b409SSimon J. Gerraty\
30957b409SSimon J. Gerraty\ Permission is hereby granted, free of charge, to any person obtaining
40957b409SSimon J. Gerraty\ a copy of this software and associated documentation files (the
50957b409SSimon J. Gerraty\ "Software"), to deal in the Software without restriction, including
60957b409SSimon J. Gerraty\ without limitation the rights to use, copy, modify, merge, publish,
70957b409SSimon J. Gerraty\ distribute, sublicense, and/or sell copies of the Software, and to
80957b409SSimon J. Gerraty\ permit persons to whom the Software is furnished to do so, subject to
90957b409SSimon J. Gerraty\ the following conditions:
100957b409SSimon J. Gerraty\
110957b409SSimon J. Gerraty\ The above copyright notice and this permission notice shall be
120957b409SSimon J. Gerraty\ included in all copies or substantial portions of the Software.
130957b409SSimon J. Gerraty\
140957b409SSimon J. Gerraty\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
150957b409SSimon J. Gerraty\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
160957b409SSimon J. Gerraty\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
170957b409SSimon J. Gerraty\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
180957b409SSimon J. Gerraty\ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
190957b409SSimon J. Gerraty\ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
200957b409SSimon J. Gerraty\ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
210957b409SSimon J. Gerraty\ SOFTWARE.
220957b409SSimon J. Gerraty
230957b409SSimon J. Gerratypreamble {
240957b409SSimon J. Gerraty
250957b409SSimon J. Gerraty#include "inner.h"
260957b409SSimon J. Gerraty
270957b409SSimon J. Gerraty#define CTX   ((br_skey_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_skey_decoder_context, cpu)))
280957b409SSimon J. Gerraty#define CONTEXT_NAME   br_skey_decoder_context
290957b409SSimon J. Gerraty
300957b409SSimon J. Gerraty/* see bearssl_x509.h */
310957b409SSimon J. Gerratyvoid
320957b409SSimon J. Gerratybr_skey_decoder_init(br_skey_decoder_context *ctx)
330957b409SSimon J. Gerraty{
340957b409SSimon J. Gerraty	memset(ctx, 0, sizeof *ctx);
350957b409SSimon J. Gerraty	ctx->cpu.dp = &ctx->dp_stack[0];
360957b409SSimon J. Gerraty	ctx->cpu.rp = &ctx->rp_stack[0];
370957b409SSimon J. Gerraty	br_skey_decoder_init_main(&ctx->cpu);
380957b409SSimon J. Gerraty	br_skey_decoder_run(&ctx->cpu);
390957b409SSimon J. Gerraty}
400957b409SSimon J. Gerraty
410957b409SSimon J. Gerraty/* see bearssl_x509.h */
420957b409SSimon J. Gerratyvoid
430957b409SSimon J. Gerratybr_skey_decoder_push(br_skey_decoder_context *ctx,
440957b409SSimon J. Gerraty	const void *data, size_t len)
450957b409SSimon J. Gerraty{
460957b409SSimon J. Gerraty	ctx->hbuf = data;
470957b409SSimon J. Gerraty	ctx->hlen = len;
480957b409SSimon J. Gerraty	br_skey_decoder_run(&ctx->cpu);
490957b409SSimon J. Gerraty}
500957b409SSimon J. Gerraty
510957b409SSimon J. Gerraty}
520957b409SSimon J. Gerraty
530957b409SSimon J. Gerratyaddr: key_type
540957b409SSimon J. Gerratyaddr: key_data
550957b409SSimon J. Gerraty
560957b409SSimon J. Gerratycc: read8-low ( -- x ) {
570957b409SSimon J. Gerraty	if (CTX->hlen == 0) {
580957b409SSimon J. Gerraty		T0_PUSHi(-1);
590957b409SSimon J. Gerraty	} else {
600957b409SSimon J. Gerraty		CTX->hlen --;
610957b409SSimon J. Gerraty		T0_PUSH(*CTX->hbuf ++);
620957b409SSimon J. Gerraty	}
630957b409SSimon J. Gerraty}
640957b409SSimon J. Gerraty
650957b409SSimon J. Gerratycc: read-blob-inner ( addr len -- addr len ) {
660957b409SSimon J. Gerraty	uint32_t len = T0_POP();
670957b409SSimon J. Gerraty	uint32_t addr = T0_POP();
680957b409SSimon J. Gerraty	size_t clen = CTX->hlen;
690957b409SSimon J. Gerraty	if (clen > len) {
700957b409SSimon J. Gerraty		clen = (size_t)len;
710957b409SSimon J. Gerraty	}
720957b409SSimon J. Gerraty	if (addr != 0) {
730957b409SSimon J. Gerraty		memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen);
740957b409SSimon J. Gerraty	}
750957b409SSimon J. Gerraty	CTX->hbuf += clen;
760957b409SSimon J. Gerraty	CTX->hlen -= clen;
770957b409SSimon J. Gerraty	T0_PUSH(addr + clen);
780957b409SSimon J. Gerraty	T0_PUSH(len - clen);
790957b409SSimon J. Gerraty}
800957b409SSimon J. Gerraty
810957b409SSimon J. Gerraty\ Get the length of the key_data buffer.
820957b409SSimon J. Gerraty: len-key_data
83*cc9e6590SSimon J. Gerraty	CX 0 8191 { 3 * BR_X509_BUFSIZE_SIG } ;
840957b409SSimon J. Gerraty
850957b409SSimon J. Gerraty\ Get the address and length for the key_data buffer.
860957b409SSimon J. Gerraty: addr-len-key_data ( -- addr len )
870957b409SSimon J. Gerraty	addr-key_data len-key_data ;
880957b409SSimon J. Gerraty
890957b409SSimon J. Gerraty\ Set the private key (RSA).
900957b409SSimon J. Gerratycc: set-rsa-key ( n_bitlen plen qlen dplen dqlen iqlen -- ) {
910957b409SSimon J. Gerraty	size_t iqlen = T0_POP();
920957b409SSimon J. Gerraty	size_t dqlen = T0_POP();
930957b409SSimon J. Gerraty	size_t dplen = T0_POP();
940957b409SSimon J. Gerraty	size_t qlen = T0_POP();
950957b409SSimon J. Gerraty	size_t plen = T0_POP();
960957b409SSimon J. Gerraty	uint32_t n_bitlen = T0_POP();
970957b409SSimon J. Gerraty	size_t off;
980957b409SSimon J. Gerraty
990957b409SSimon J. Gerraty	CTX->key.rsa.n_bitlen = n_bitlen;
1000957b409SSimon J. Gerraty	CTX->key.rsa.p = CTX->key_data;
1010957b409SSimon J. Gerraty	CTX->key.rsa.plen = plen;
1020957b409SSimon J. Gerraty	off = plen;
1030957b409SSimon J. Gerraty	CTX->key.rsa.q = CTX->key_data + off;
1040957b409SSimon J. Gerraty	CTX->key.rsa.qlen = qlen;
1050957b409SSimon J. Gerraty	off += qlen;
1060957b409SSimon J. Gerraty	CTX->key.rsa.dp = CTX->key_data + off;
1070957b409SSimon J. Gerraty	CTX->key.rsa.dplen = dplen;
1080957b409SSimon J. Gerraty	off += dplen;
1090957b409SSimon J. Gerraty	CTX->key.rsa.dq = CTX->key_data + off;
1100957b409SSimon J. Gerraty	CTX->key.rsa.dqlen = dqlen;
1110957b409SSimon J. Gerraty	off += dqlen;
1120957b409SSimon J. Gerraty	CTX->key.rsa.iq = CTX->key_data + off;
1130957b409SSimon J. Gerraty	CTX->key.rsa.iqlen = iqlen;
1140957b409SSimon J. Gerraty}
1150957b409SSimon J. Gerraty
1160957b409SSimon J. Gerraty\ Set the private key (EC).
1170957b409SSimon J. Gerratycc: set-ec-key ( curve xlen -- ) {
1180957b409SSimon J. Gerraty	size_t xlen = T0_POP();
1190957b409SSimon J. Gerraty	uint32_t curve = T0_POP();
1200957b409SSimon J. Gerraty	CTX->key.ec.curve = curve;
1210957b409SSimon J. Gerraty	CTX->key.ec.x = CTX->key_data;
1220957b409SSimon J. Gerraty	CTX->key.ec.xlen = xlen;
1230957b409SSimon J. Gerraty}
1240957b409SSimon J. Gerraty
1250957b409SSimon J. Gerraty\ Get the bit length for an integer (unsigned).
1260957b409SSimon J. Gerraty: int-bit-length ( x -- bitlen )
1270957b409SSimon J. Gerraty	0 swap
1280957b409SSimon J. Gerraty	begin dup while 1 u>> swap 1+ swap repeat
1290957b409SSimon J. Gerraty	drop ;
1300957b409SSimon J. Gerraty
1310957b409SSimon J. Gerraty\ Read an INTEGER into the key_data buffer, but then ignore it.
1320957b409SSimon J. Gerraty: read-integer-ignore ( lim -- lim )
1330957b409SSimon J. Gerraty	addr-len-key_data read-integer drop ;
1340957b409SSimon J. Gerraty
1350957b409SSimon J. Gerraty\ Read an INTEGER into the key_data buffer, at the provided offset.
1360957b409SSimon J. Gerraty\ Returned value is the integer length (in bytes).
1370957b409SSimon J. Gerraty: read-integer-off ( lim off -- lim dlen )
1380957b409SSimon J. Gerraty	dup addr-len-key_data rot - swap rot + swap read-integer ;
1390957b409SSimon J. Gerraty
1400957b409SSimon J. Gerraty\ Decode RSA key, starting with the SEQUENCE tag.
1410957b409SSimon J. Gerraty: decode-RSA ( lim -- lim )
1420957b409SSimon J. Gerraty	read-sequence-open
1430957b409SSimon J. Gerraty
1440957b409SSimon J. Gerraty	\ Version should be 0.
1450957b409SSimon J. Gerraty	read-tag 0x02 check-tag-primitive read-small-int-value if
1460957b409SSimon J. Gerraty		ERR_X509_UNSUPPORTED fail
1470957b409SSimon J. Gerraty	then
1480957b409SSimon J. Gerraty
1490957b409SSimon J. Gerraty	\ Read tag for the modulus; should be INTEGER. Then use the
1500957b409SSimon J. Gerraty	\ decode-RSA-next function for the remainder of the key.
1510957b409SSimon J. Gerraty	read-tag 0x02 check-tag-primitive
1520957b409SSimon J. Gerraty	decode-RSA-next
1530957b409SSimon J. Gerraty
1540957b409SSimon J. Gerraty	\ Close the SEQUENCE.
1550957b409SSimon J. Gerraty	close-elt ;
1560957b409SSimon J. Gerraty
1570957b409SSimon J. Gerraty\ Decode RSA key; the version, and the tag for the modulus, have been
1580957b409SSimon J. Gerraty\ read.
1590957b409SSimon J. Gerraty: decode-RSA-next ( lim -- lim )
1600957b409SSimon J. Gerraty	\ Modulus: we read it but we do not keep it; we merely gather
1610957b409SSimon J. Gerraty	\ the modulus bit length.
1620957b409SSimon J. Gerraty	addr-len-key_data read-integer-next
1630957b409SSimon J. Gerraty	dup ifnot ERR_X509_UNEXPECTED fail then
1640957b409SSimon J. Gerraty	1- 3 << addr-key_data get8 int-bit-length + { n_bitlen }
1650957b409SSimon J. Gerraty
1660957b409SSimon J. Gerraty	\ Public exponent: read but skip.
1670957b409SSimon J. Gerraty	read-integer-ignore
1680957b409SSimon J. Gerraty
1690957b409SSimon J. Gerraty	\ Private exponent: read but skip.
1700957b409SSimon J. Gerraty	read-integer-ignore
1710957b409SSimon J. Gerraty
1720957b409SSimon J. Gerraty	\ First prime factor.
1730957b409SSimon J. Gerraty	addr-len-key_data read-integer dup dup { off plen }
1740957b409SSimon J. Gerraty
1750957b409SSimon J. Gerraty	\ Second prime factor.
1760957b409SSimon J. Gerraty	read-integer-off dup { qlen } off + dup >off
1770957b409SSimon J. Gerraty
1780957b409SSimon J. Gerraty	\ First reduced private exponent.
1790957b409SSimon J. Gerraty	read-integer-off dup { dplen } off + dup >off
1800957b409SSimon J. Gerraty
1810957b409SSimon J. Gerraty	\ Second reduced private exponent.
1820957b409SSimon J. Gerraty	read-integer-off dup { dqlen } off + dup >off
1830957b409SSimon J. Gerraty
1840957b409SSimon J. Gerraty	\ CRT coefficient.
1850957b409SSimon J. Gerraty	read-integer-off { iqlen }
1860957b409SSimon J. Gerraty
1870957b409SSimon J. Gerraty	\ Set RSA key.
1880957b409SSimon J. Gerraty	n_bitlen plen qlen dplen dqlen iqlen set-rsa-key
1890957b409SSimon J. Gerraty
1900957b409SSimon J. Gerraty	\ The caller will close the sequence, thereby validating that there
1910957b409SSimon J. Gerraty	\ is no extra field.
1920957b409SSimon J. Gerraty	;
1930957b409SSimon J. Gerraty
1940957b409SSimon J. Gerraty\ Decode an EC key, starting with the SEQUENCE tag.
1950957b409SSimon J. Gerraty: decode-EC ( lim curve -- lim )
1960957b409SSimon J. Gerraty	{ curve }
1970957b409SSimon J. Gerraty	read-sequence-open
1980957b409SSimon J. Gerraty
1990957b409SSimon J. Gerraty	\ Version should be 1.
2000957b409SSimon J. Gerraty	read-tag 0x02 check-tag-primitive read-small-int-value 1- if
2010957b409SSimon J. Gerraty		ERR_X509_UNSUPPORTED fail
2020957b409SSimon J. Gerraty	then
2030957b409SSimon J. Gerraty
2040957b409SSimon J. Gerraty	\ Read tag for the private key; should be OCTET STRING. Then use the
2050957b409SSimon J. Gerraty	\ decode-EC-next function for the remainder of the key.
2060957b409SSimon J. Gerraty	read-tag 0x04 check-tag-primitive
2070957b409SSimon J. Gerraty	curve decode-EC-next
2080957b409SSimon J. Gerraty
2090957b409SSimon J. Gerraty	\ Close the SEQUENCE.
2100957b409SSimon J. Gerraty	close-elt ;
2110957b409SSimon J. Gerraty
2120957b409SSimon J. Gerraty\ Decode an EC key; the version, and the tag for the OCTET STRING, have
2130957b409SSimon J. Gerraty\ already been read. The curve ID is provided (0 if unknown).
2140957b409SSimon J. Gerraty: decode-EC-next ( lim curve -- lim )
2150957b409SSimon J. Gerraty	{ curve }
2160957b409SSimon J. Gerraty
2170957b409SSimon J. Gerraty	\ Read the private key proper.
2180957b409SSimon J. Gerraty	read-length-open-elt
2190957b409SSimon J. Gerraty	dup dup { xlen } len-key_data > if ERR_X509_UNSUPPORTED fail then
2200957b409SSimon J. Gerraty	addr-key_data read-blob
2210957b409SSimon J. Gerraty
2220957b409SSimon J. Gerraty	\ Next element might be the curve identifier.
2230957b409SSimon J. Gerraty	read-tag-or-end
2240957b409SSimon J. Gerraty	case
2250957b409SSimon J. Gerraty
2260957b409SSimon J. Gerraty		\ End of structure.
2270957b409SSimon J. Gerraty		-1 of drop endof
2280957b409SSimon J. Gerraty
2290957b409SSimon J. Gerraty		\ Curve parameters; we support only named curves.
2300957b409SSimon J. Gerraty		0x20 of
2310957b409SSimon J. Gerraty			check-constructed read-length-open-elt
2320957b409SSimon J. Gerraty			read-curve-ID
2330957b409SSimon J. Gerraty			curve if
2340957b409SSimon J. Gerraty				curve <> if ERR_X509_INVALID_VALUE fail then
2350957b409SSimon J. Gerraty			else
2360957b409SSimon J. Gerraty				>curve
2370957b409SSimon J. Gerraty			then
2380957b409SSimon J. Gerraty			close-elt
2390957b409SSimon J. Gerraty		endof
2400957b409SSimon J. Gerraty
2410957b409SSimon J. Gerraty		\ Public key. We ignore it.
2420957b409SSimon J. Gerraty		0x21 of check-constructed endof
2430957b409SSimon J. Gerraty
2440957b409SSimon J. Gerraty		ERR_X509_UNSUPPORTED fail
2450957b409SSimon J. Gerraty	endcase
2460957b409SSimon J. Gerraty	skip-remaining
2470957b409SSimon J. Gerraty
2480957b409SSimon J. Gerraty	\ The curve must have been defined one way or another.
2490957b409SSimon J. Gerraty	curve ifnot ERR_X509_UNSUPPORTED fail then
2500957b409SSimon J. Gerraty
2510957b409SSimon J. Gerraty	\ Set the EC key.
2520957b409SSimon J. Gerraty	curve xlen set-ec-key
2530957b409SSimon J. Gerraty
2540957b409SSimon J. Gerraty	\ The caller will close the sequence.
2550957b409SSimon J. Gerraty	;
2560957b409SSimon J. Gerraty
2570957b409SSimon J. Gerraty\ Decode a PKCS#8 object. The version and the tag for the AlgorithmIdentifier
2580957b409SSimon J. Gerraty\ structure have already been read. This function returns the key type.
2590957b409SSimon J. Gerraty: decode-PKCS8-next ( lim -- lim keytype )
2600957b409SSimon J. Gerraty	\ Decode the AlgorithmIdentifier.
2610957b409SSimon J. Gerraty	read-length-open-elt
2620957b409SSimon J. Gerraty	read-OID ifnot ERR_X509_UNSUPPORTED fail then
2630957b409SSimon J. Gerraty	{ ; is-rsa curve }
2640957b409SSimon J. Gerraty	choice
2650957b409SSimon J. Gerraty		rsaEncryption eqOID uf
2660957b409SSimon J. Gerraty			\ RSA private key. We ignore the parameters.
2670957b409SSimon J. Gerraty			skip-remaining -1 >is-rsa
2680957b409SSimon J. Gerraty		enduf
2690957b409SSimon J. Gerraty		id-ecPublicKey eqOID uf
2700957b409SSimon J. Gerraty			\ EC private key. Parameters, if present, shall
2710957b409SSimon J. Gerraty			\ identify the curve.
2720957b409SSimon J. Gerraty			0 >is-rsa
2730957b409SSimon J. Gerraty			dup if read-curve-ID else 0 then >curve
2740957b409SSimon J. Gerraty		enduf
2750957b409SSimon J. Gerraty
2760957b409SSimon J. Gerraty		ERR_X509_UNSUPPORTED fail
2770957b409SSimon J. Gerraty	endchoice
2780957b409SSimon J. Gerraty	close-elt
2790957b409SSimon J. Gerraty
2800957b409SSimon J. Gerraty	\ Open private key value and decode it.
2810957b409SSimon J. Gerraty	read-tag 0x04 check-tag-primitive
2820957b409SSimon J. Gerraty	read-length-open-elt
2830957b409SSimon J. Gerraty	is-rsa if
2840957b409SSimon J. Gerraty		decode-RSA
2850957b409SSimon J. Gerraty	else
2860957b409SSimon J. Gerraty		curve decode-EC
2870957b409SSimon J. Gerraty	then
2880957b409SSimon J. Gerraty	close-elt
2890957b409SSimon J. Gerraty
2900957b409SSimon J. Gerraty	\ We ignore any extra field, i.e. attributes or public key.
2910957b409SSimon J. Gerraty	skip-remaining
2920957b409SSimon J. Gerraty
2930957b409SSimon J. Gerraty	\ Return the key type.
2940957b409SSimon J. Gerraty	is-rsa if KEYTYPE_RSA else KEYTYPE_EC then
2950957b409SSimon J. Gerraty	;
2960957b409SSimon J. Gerraty
2970957b409SSimon J. Gerraty\ Decode a private key.
2980957b409SSimon J. Gerraty: main ( -- ! )
2990957b409SSimon J. Gerraty	\ RSA private key format is defined in PKCS#1 (RFC 3447):
3000957b409SSimon J. Gerraty	\   RSAPrivateKey ::= SEQUENCE {
3010957b409SSimon J. Gerraty	\       version   INTEGER, -- 0 or 1
3020957b409SSimon J. Gerraty	\       n         INTEGER,
3030957b409SSimon J. Gerraty	\       e         INTEGER,
3040957b409SSimon J. Gerraty	\       d         INTEGER,
3050957b409SSimon J. Gerraty	\       p         INTEGER,
3060957b409SSimon J. Gerraty	\       q         INTEGER,
3070957b409SSimon J. Gerraty	\       dp        INTEGER,
3080957b409SSimon J. Gerraty	\       dq        INTEGER,
3090957b409SSimon J. Gerraty	\       iq        INTEGER,
3100957b409SSimon J. Gerraty	\       other     OtherPrimeInfos OPTIONAL
3110957b409SSimon J. Gerraty	\   }
3120957b409SSimon J. Gerraty	\ We do not support keys with more than two primes (these have
3130957b409SSimon J. Gerraty	\ version 1); thus, we expect the version field to be 0, and
3140957b409SSimon J. Gerraty	\ the 'other' field to be absent.
3150957b409SSimon J. Gerraty	\
3160957b409SSimon J. Gerraty	\ EC private key format is defined in RFC 5915:
3170957b409SSimon J. Gerraty	\   ECPrivateKey ::= SEQUENCE {
3180957b409SSimon J. Gerraty	\       version      INTEGER,   -- always 1
3190957b409SSimon J. Gerraty	\       privateKey   OCTET STRING,
3200957b409SSimon J. Gerraty	\       parameters   [0] EXPLICIT OBJECT IDENTIFIER OPTIONAL,
3210957b409SSimon J. Gerraty	\       publicKey    [1] EXPLICIT BIT STRING OPTIONAL
3220957b409SSimon J. Gerraty	\   }
3230957b409SSimon J. Gerraty	\ The "parameters" might conceptually be a complex curve description
3240957b409SSimon J. Gerraty	\ structure but we support only named curves. The private key
3250957b409SSimon J. Gerraty	\ contents are the unsigned big-endian encoding of the key value,
3260957b409SSimon J. Gerraty	\ which is exactly what we want.
3270957b409SSimon J. Gerraty	\
3280957b409SSimon J. Gerraty	\ PKCS#8 (unencrypted) is:
3290957b409SSimon J. Gerraty	\   OneAsymmetricKey ::= SEQUENCE {
3300957b409SSimon J. Gerraty	\       version      INTEGER,   -- 0 or 1
3310957b409SSimon J. Gerraty	\       algorithm    AlgorithmIdentifier,
3320957b409SSimon J. Gerraty	\       privateKey   OCTET STRING,
3330957b409SSimon J. Gerraty	\       attributes   [0] IMPLICIT Attributes OPTIONAL,
3340957b409SSimon J. Gerraty	\       publicKey    [1] IMPLICIT BIT STRING OPTIONAL
3350957b409SSimon J. Gerraty	\   }
3360957b409SSimon J. Gerraty	\ The 'publicKey' field is an add-on from RFC 5958 and may be
3370957b409SSimon J. Gerraty	\ present only if the 'version' is v2 (i.e. has value 1). We
3380957b409SSimon J. Gerraty	\ ignore it anyway.
3390957b409SSimon J. Gerraty
3400957b409SSimon J. Gerraty	\ An arbitrary upper limit on the private key size.
3410957b409SSimon J. Gerraty	0xFFFFFF
3420957b409SSimon J. Gerraty
3430957b409SSimon J. Gerraty	\ Open the outer SEQUENCE.
3440957b409SSimon J. Gerraty	read-sequence-open
3450957b409SSimon J. Gerraty
3460957b409SSimon J. Gerraty	\ All our schemas begin with a small INTEGER which is either 0 or
3470957b409SSimon J. Gerraty	\ 1. We don't care which it is.
3480957b409SSimon J. Gerraty	read-tag 0x02 check-tag-primitive read-small-int-value 1 > if
3490957b409SSimon J. Gerraty		ERR_X509_UNSUPPORTED fail
3500957b409SSimon J. Gerraty	then
3510957b409SSimon J. Gerraty
3520957b409SSimon J. Gerraty	\ Get next tag: it should be either an INTEGER (RSA private key),
3530957b409SSimon J. Gerraty	\ an OCTET STRING (EC private key), or a SEQUENCE (for an
3540957b409SSimon J. Gerraty	\ AlgorithmIdentifier, in a PKCS#8 object).
3550957b409SSimon J. Gerraty	read-tag
3560957b409SSimon J. Gerraty	case
3570957b409SSimon J. Gerraty		0x02 of check-primitive decode-RSA-next KEYTYPE_RSA endof
3580957b409SSimon J. Gerraty		0x04 of check-primitive 0 decode-EC-next KEYTYPE_EC endof
3590957b409SSimon J. Gerraty		0x10 of check-constructed decode-PKCS8-next endof
3600957b409SSimon J. Gerraty		ERR_X509_UNSUPPORTED fail
3610957b409SSimon J. Gerraty	endcase
3620957b409SSimon J. Gerraty	{ key-type }
3630957b409SSimon J. Gerraty
3640957b409SSimon J. Gerraty	\ Close the SEQUENCE.
3650957b409SSimon J. Gerraty	close-elt
3660957b409SSimon J. Gerraty
3670957b409SSimon J. Gerraty	\ Set the key type, which marks the decoding as a success.
3680957b409SSimon J. Gerraty	key-type addr-key_type set8
3690957b409SSimon J. Gerraty
3700957b409SSimon J. Gerraty	\ Read one byte, then fail: if the read succeeds, then there is
3710957b409SSimon J. Gerraty	\ some trailing byte.
3720957b409SSimon J. Gerraty	read8-nc ERR_X509_EXTRA_ELEMENT fail
3730957b409SSimon J. Gerraty	;
374