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 23preamble { 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 */ 31void 32br_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 */ 42void 43br_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 53addr: key_type 54addr: key_data 55 56cc: 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 65cc: 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). 90cc: 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). 117cc: 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 ; 374