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