1280297Sjkim/* 2280297Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 3280297Sjkim * 2005. 4238384Sjkim */ 5238384Sjkim/* ==================================================================== 6352193Sjkim * Copyright (c) 2005-2019 The OpenSSL Project. All rights reserved. 7238384Sjkim * 8238384Sjkim * Redistribution and use in source and binary forms, with or without 9238384Sjkim * modification, are permitted provided that the following conditions 10238384Sjkim * are met: 11238384Sjkim * 12238384Sjkim * 1. Redistributions of source code must retain the above copyright 13280297Sjkim * notice, this list of conditions and the following disclaimer. 14238384Sjkim * 15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 16238384Sjkim * notice, this list of conditions and the following disclaimer in 17238384Sjkim * the documentation and/or other materials provided with the 18238384Sjkim * distribution. 19238384Sjkim * 20238384Sjkim * 3. All advertising materials mentioning features or use of this 21238384Sjkim * software must display the following acknowledgment: 22238384Sjkim * "This product includes software developed by the OpenSSL Project 23238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24238384Sjkim * 25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26238384Sjkim * endorse or promote products derived from this software without 27238384Sjkim * prior written permission. For written permission, please contact 28238384Sjkim * licensing@OpenSSL.org. 29238384Sjkim * 30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 31238384Sjkim * nor may "OpenSSL" appear in their names without prior written 32238384Sjkim * permission of the OpenSSL Project. 33238384Sjkim * 34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 35238384Sjkim * acknowledgment: 36238384Sjkim * "This product includes software developed by the OpenSSL Project 37238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38238384Sjkim * 39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 51238384Sjkim * ==================================================================== 52238384Sjkim * 53238384Sjkim * This product includes cryptographic software written by Eric Young 54238384Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 55238384Sjkim * Hudson (tjh@cryptsoft.com). 56238384Sjkim * 57238384Sjkim */ 58238384Sjkim 59280297Sjkim/* 60280297Sjkim * Support for PVK format keys and related structures (such a PUBLICKEYBLOB 61238384Sjkim * and PRIVATEKEYBLOB). 62238384Sjkim */ 63238384Sjkim 64238384Sjkim#include "cryptlib.h" 65238384Sjkim#include <openssl/pem.h> 66238384Sjkim#include <openssl/rand.h> 67238384Sjkim#include <openssl/bn.h> 68238384Sjkim#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) 69280297Sjkim# include <openssl/dsa.h> 70280297Sjkim# include <openssl/rsa.h> 71238384Sjkim 72280297Sjkim/* 73280297Sjkim * Utility function: read a DWORD (4 byte unsigned integer) in little endian 74238384Sjkim * format 75238384Sjkim */ 76238384Sjkim 77238384Sjkimstatic unsigned int read_ledword(const unsigned char **in) 78280297Sjkim{ 79280297Sjkim const unsigned char *p = *in; 80280297Sjkim unsigned int ret; 81280297Sjkim ret = *p++; 82280297Sjkim ret |= (*p++ << 8); 83280297Sjkim ret |= (*p++ << 16); 84280297Sjkim ret |= (*p++ << 24); 85280297Sjkim *in = p; 86280297Sjkim return ret; 87280297Sjkim} 88238384Sjkim 89280297Sjkim/* 90280297Sjkim * Read a BIGNUM in little endian format. The docs say that this should take 91280297Sjkim * up bitlen/8 bytes. 92238384Sjkim */ 93238384Sjkim 94238384Sjkimstatic int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r) 95280297Sjkim{ 96280297Sjkim const unsigned char *p; 97280297Sjkim unsigned char *tmpbuf, *q; 98280297Sjkim unsigned int i; 99280297Sjkim p = *in + nbyte - 1; 100280297Sjkim tmpbuf = OPENSSL_malloc(nbyte); 101280297Sjkim if (!tmpbuf) 102280297Sjkim return 0; 103280297Sjkim q = tmpbuf; 104280297Sjkim for (i = 0; i < nbyte; i++) 105280297Sjkim *q++ = *p--; 106280297Sjkim *r = BN_bin2bn(tmpbuf, nbyte, NULL); 107280297Sjkim OPENSSL_free(tmpbuf); 108280297Sjkim if (*r) { 109280297Sjkim *in += nbyte; 110280297Sjkim return 1; 111280297Sjkim } else 112280297Sjkim return 0; 113280297Sjkim} 114238384Sjkim 115238384Sjkim/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */ 116238384Sjkim 117280297Sjkim# define MS_PUBLICKEYBLOB 0x6 118280297Sjkim# define MS_PRIVATEKEYBLOB 0x7 119280297Sjkim# define MS_RSA1MAGIC 0x31415352L 120280297Sjkim# define MS_RSA2MAGIC 0x32415352L 121280297Sjkim# define MS_DSS1MAGIC 0x31535344L 122280297Sjkim# define MS_DSS2MAGIC 0x32535344L 123238384Sjkim 124280297Sjkim# define MS_KEYALG_RSA_KEYX 0xa400 125280297Sjkim# define MS_KEYALG_DSS_SIGN 0x2200 126238384Sjkim 127280297Sjkim# define MS_KEYTYPE_KEYX 0x1 128280297Sjkim# define MS_KEYTYPE_SIGN 0x2 129238384Sjkim 130306195Sjkim/* Maximum length of a blob after header */ 131306195Sjkim# define BLOB_MAX_LENGTH 102400 132306195Sjkim 133238384Sjkim/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */ 134280297Sjkim# define MS_PVKMAGIC 0xb0b5f11eL 135238384Sjkim/* Salt length for PVK files */ 136280297Sjkim# define PVK_SALTLEN 0x10 137298998Sjkim/* Maximum length in PVK header */ 138298998Sjkim# define PVK_MAX_KEYLEN 102400 139298998Sjkim/* Maximum salt length */ 140298998Sjkim# define PVK_MAX_SALTLEN 10240 141238384Sjkim 142238384Sjkimstatic EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length, 143280297Sjkim unsigned int bitlen, int ispub); 144238384Sjkimstatic EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length, 145280297Sjkim unsigned int bitlen, int ispub); 146238384Sjkim 147238384Sjkimstatic int do_blob_header(const unsigned char **in, unsigned int length, 148280297Sjkim unsigned int *pmagic, unsigned int *pbitlen, 149280297Sjkim int *pisdss, int *pispub) 150280297Sjkim{ 151280297Sjkim const unsigned char *p = *in; 152280297Sjkim if (length < 16) 153280297Sjkim return 0; 154280297Sjkim /* bType */ 155280297Sjkim if (*p == MS_PUBLICKEYBLOB) { 156280297Sjkim if (*pispub == 0) { 157280297Sjkim PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB); 158280297Sjkim return 0; 159280297Sjkim } 160280297Sjkim *pispub = 1; 161280297Sjkim } else if (*p == MS_PRIVATEKEYBLOB) { 162280297Sjkim if (*pispub == 1) { 163280297Sjkim PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB); 164280297Sjkim return 0; 165280297Sjkim } 166280297Sjkim *pispub = 0; 167280297Sjkim } else 168280297Sjkim return 0; 169280297Sjkim p++; 170280297Sjkim /* Version */ 171280297Sjkim if (*p++ != 0x2) { 172280297Sjkim PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_VERSION_NUMBER); 173280297Sjkim return 0; 174280297Sjkim } 175280297Sjkim /* Ignore reserved, aiKeyAlg */ 176280297Sjkim p += 6; 177280297Sjkim *pmagic = read_ledword(&p); 178280297Sjkim *pbitlen = read_ledword(&p); 179280297Sjkim *pisdss = 0; 180280297Sjkim switch (*pmagic) { 181238384Sjkim 182280297Sjkim case MS_DSS1MAGIC: 183280297Sjkim *pisdss = 1; 184280297Sjkim case MS_RSA1MAGIC: 185280297Sjkim if (*pispub == 0) { 186280297Sjkim PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB); 187280297Sjkim return 0; 188280297Sjkim } 189280297Sjkim break; 190238384Sjkim 191280297Sjkim case MS_DSS2MAGIC: 192280297Sjkim *pisdss = 1; 193280297Sjkim case MS_RSA2MAGIC: 194280297Sjkim if (*pispub == 1) { 195280297Sjkim PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB); 196280297Sjkim return 0; 197280297Sjkim } 198280297Sjkim break; 199238384Sjkim 200280297Sjkim default: 201280297Sjkim PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_MAGIC_NUMBER); 202280297Sjkim return -1; 203280297Sjkim } 204280297Sjkim *in = p; 205280297Sjkim return 1; 206280297Sjkim} 207238384Sjkim 208238384Sjkimstatic unsigned int blob_length(unsigned bitlen, int isdss, int ispub) 209280297Sjkim{ 210280297Sjkim unsigned int nbyte, hnbyte; 211280297Sjkim nbyte = (bitlen + 7) >> 3; 212280297Sjkim hnbyte = (bitlen + 15) >> 4; 213280297Sjkim if (isdss) { 214238384Sjkim 215280297Sjkim /* 216280297Sjkim * Expected length: 20 for q + 3 components bitlen each + 24 for seed 217280297Sjkim * structure. 218280297Sjkim */ 219280297Sjkim if (ispub) 220280297Sjkim return 44 + 3 * nbyte; 221280297Sjkim /* 222280297Sjkim * Expected length: 20 for q, priv, 2 bitlen components + 24 for seed 223280297Sjkim * structure. 224280297Sjkim */ 225280297Sjkim else 226280297Sjkim return 64 + 2 * nbyte; 227280297Sjkim } else { 228280297Sjkim /* Expected length: 4 for 'e' + 'n' */ 229280297Sjkim if (ispub) 230280297Sjkim return 4 + nbyte; 231280297Sjkim else 232280297Sjkim /* 233280297Sjkim * Expected length: 4 for 'e' and 7 other components. 2 234280297Sjkim * components are bitlen size, 5 are bitlen/2 235280297Sjkim */ 236280297Sjkim return 4 + 2 * nbyte + 5 * hnbyte; 237280297Sjkim } 238238384Sjkim 239280297Sjkim} 240238384Sjkim 241238384Sjkimstatic EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length, 242280297Sjkim int ispub) 243280297Sjkim{ 244280297Sjkim const unsigned char *p = *in; 245280297Sjkim unsigned int bitlen, magic; 246280297Sjkim int isdss; 247280297Sjkim if (do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0) { 248280297Sjkim PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_HEADER_PARSE_ERROR); 249280297Sjkim return NULL; 250280297Sjkim } 251280297Sjkim length -= 16; 252280297Sjkim if (length < blob_length(bitlen, isdss, ispub)) { 253280297Sjkim PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_TOO_SHORT); 254280297Sjkim return NULL; 255280297Sjkim } 256280297Sjkim if (isdss) 257280297Sjkim return b2i_dss(&p, length, bitlen, ispub); 258280297Sjkim else 259280297Sjkim return b2i_rsa(&p, length, bitlen, ispub); 260280297Sjkim} 261238384Sjkim 262238384Sjkimstatic EVP_PKEY *do_b2i_bio(BIO *in, int ispub) 263280297Sjkim{ 264280297Sjkim const unsigned char *p; 265280297Sjkim unsigned char hdr_buf[16], *buf = NULL; 266280297Sjkim unsigned int bitlen, magic, length; 267280297Sjkim int isdss; 268280297Sjkim EVP_PKEY *ret = NULL; 269280297Sjkim if (BIO_read(in, hdr_buf, 16) != 16) { 270280297Sjkim PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT); 271280297Sjkim return NULL; 272280297Sjkim } 273280297Sjkim p = hdr_buf; 274280297Sjkim if (do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0) 275280297Sjkim return NULL; 276238384Sjkim 277280297Sjkim length = blob_length(bitlen, isdss, ispub); 278306195Sjkim if (length > BLOB_MAX_LENGTH) { 279306195Sjkim PEMerr(PEM_F_DO_B2I_BIO, PEM_R_HEADER_TOO_LONG); 280306195Sjkim return NULL; 281306195Sjkim } 282280297Sjkim buf = OPENSSL_malloc(length); 283280297Sjkim if (!buf) { 284280297Sjkim PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE); 285280297Sjkim goto err; 286280297Sjkim } 287280297Sjkim p = buf; 288280297Sjkim if (BIO_read(in, buf, length) != (int)length) { 289280297Sjkim PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT); 290280297Sjkim goto err; 291280297Sjkim } 292238384Sjkim 293280297Sjkim if (isdss) 294280297Sjkim ret = b2i_dss(&p, length, bitlen, ispub); 295280297Sjkim else 296280297Sjkim ret = b2i_rsa(&p, length, bitlen, ispub); 297238384Sjkim 298280297Sjkim err: 299280297Sjkim if (buf) 300280297Sjkim OPENSSL_free(buf); 301280297Sjkim return ret; 302280297Sjkim} 303238384Sjkim 304238384Sjkimstatic EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length, 305280297Sjkim unsigned int bitlen, int ispub) 306280297Sjkim{ 307280297Sjkim const unsigned char *p = *in; 308280297Sjkim EVP_PKEY *ret = NULL; 309280297Sjkim DSA *dsa = NULL; 310280297Sjkim BN_CTX *ctx = NULL; 311280297Sjkim unsigned int nbyte; 312280297Sjkim nbyte = (bitlen + 7) >> 3; 313238384Sjkim 314280297Sjkim dsa = DSA_new(); 315280297Sjkim ret = EVP_PKEY_new(); 316280297Sjkim if (!dsa || !ret) 317280297Sjkim goto memerr; 318280297Sjkim if (!read_lebn(&p, nbyte, &dsa->p)) 319280297Sjkim goto memerr; 320280297Sjkim if (!read_lebn(&p, 20, &dsa->q)) 321280297Sjkim goto memerr; 322280297Sjkim if (!read_lebn(&p, nbyte, &dsa->g)) 323280297Sjkim goto memerr; 324280297Sjkim if (ispub) { 325280297Sjkim if (!read_lebn(&p, nbyte, &dsa->pub_key)) 326280297Sjkim goto memerr; 327280297Sjkim } else { 328280297Sjkim if (!read_lebn(&p, 20, &dsa->priv_key)) 329280297Sjkim goto memerr; 330352193Sjkim /* Set constant time flag before public key calculation */ 331352193Sjkim BN_set_flags(dsa->priv_key, BN_FLG_CONSTTIME); 332280297Sjkim /* Calculate public key */ 333280297Sjkim if (!(dsa->pub_key = BN_new())) 334280297Sjkim goto memerr; 335280297Sjkim if (!(ctx = BN_CTX_new())) 336280297Sjkim goto memerr; 337238384Sjkim 338280297Sjkim if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) 339238384Sjkim 340280297Sjkim goto memerr; 341280297Sjkim BN_CTX_free(ctx); 342280297Sjkim } 343238384Sjkim 344280297Sjkim EVP_PKEY_set1_DSA(ret, dsa); 345280297Sjkim DSA_free(dsa); 346280297Sjkim *in = p; 347280297Sjkim return ret; 348280297Sjkim 349280297Sjkim memerr: 350280297Sjkim PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE); 351280297Sjkim if (dsa) 352280297Sjkim DSA_free(dsa); 353280297Sjkim if (ret) 354280297Sjkim EVP_PKEY_free(ret); 355280297Sjkim if (ctx) 356280297Sjkim BN_CTX_free(ctx); 357280297Sjkim return NULL; 358280297Sjkim} 359280297Sjkim 360238384Sjkimstatic EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length, 361280297Sjkim unsigned int bitlen, int ispub) 362280297Sjkim{ 363280297Sjkim const unsigned char *p = *in; 364280297Sjkim EVP_PKEY *ret = NULL; 365280297Sjkim RSA *rsa = NULL; 366280297Sjkim unsigned int nbyte, hnbyte; 367280297Sjkim nbyte = (bitlen + 7) >> 3; 368280297Sjkim hnbyte = (bitlen + 15) >> 4; 369280297Sjkim rsa = RSA_new(); 370280297Sjkim ret = EVP_PKEY_new(); 371280297Sjkim if (!rsa || !ret) 372280297Sjkim goto memerr; 373280297Sjkim rsa->e = BN_new(); 374280297Sjkim if (!rsa->e) 375280297Sjkim goto memerr; 376280297Sjkim if (!BN_set_word(rsa->e, read_ledword(&p))) 377280297Sjkim goto memerr; 378280297Sjkim if (!read_lebn(&p, nbyte, &rsa->n)) 379280297Sjkim goto memerr; 380280297Sjkim if (!ispub) { 381280297Sjkim if (!read_lebn(&p, hnbyte, &rsa->p)) 382280297Sjkim goto memerr; 383280297Sjkim if (!read_lebn(&p, hnbyte, &rsa->q)) 384280297Sjkim goto memerr; 385280297Sjkim if (!read_lebn(&p, hnbyte, &rsa->dmp1)) 386280297Sjkim goto memerr; 387280297Sjkim if (!read_lebn(&p, hnbyte, &rsa->dmq1)) 388280297Sjkim goto memerr; 389280297Sjkim if (!read_lebn(&p, hnbyte, &rsa->iqmp)) 390280297Sjkim goto memerr; 391280297Sjkim if (!read_lebn(&p, nbyte, &rsa->d)) 392280297Sjkim goto memerr; 393280297Sjkim } 394238384Sjkim 395280297Sjkim EVP_PKEY_set1_RSA(ret, rsa); 396280297Sjkim RSA_free(rsa); 397280297Sjkim *in = p; 398280297Sjkim return ret; 399280297Sjkim memerr: 400280297Sjkim PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE); 401280297Sjkim if (rsa) 402280297Sjkim RSA_free(rsa); 403280297Sjkim if (ret) 404280297Sjkim EVP_PKEY_free(ret); 405280297Sjkim return NULL; 406280297Sjkim} 407238384Sjkim 408238384SjkimEVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length) 409280297Sjkim{ 410280297Sjkim return do_b2i(in, length, 0); 411280297Sjkim} 412238384Sjkim 413238384SjkimEVP_PKEY *b2i_PublicKey(const unsigned char **in, long length) 414280297Sjkim{ 415280297Sjkim return do_b2i(in, length, 1); 416280297Sjkim} 417238384Sjkim 418238384SjkimEVP_PKEY *b2i_PrivateKey_bio(BIO *in) 419280297Sjkim{ 420280297Sjkim return do_b2i_bio(in, 0); 421280297Sjkim} 422238384Sjkim 423238384SjkimEVP_PKEY *b2i_PublicKey_bio(BIO *in) 424280297Sjkim{ 425280297Sjkim return do_b2i_bio(in, 1); 426280297Sjkim} 427238384Sjkim 428238384Sjkimstatic void write_ledword(unsigned char **out, unsigned int dw) 429280297Sjkim{ 430280297Sjkim unsigned char *p = *out; 431280297Sjkim *p++ = dw & 0xff; 432280297Sjkim *p++ = (dw >> 8) & 0xff; 433280297Sjkim *p++ = (dw >> 16) & 0xff; 434280297Sjkim *p++ = (dw >> 24) & 0xff; 435280297Sjkim *out = p; 436280297Sjkim} 437238384Sjkim 438238384Sjkimstatic void write_lebn(unsigned char **out, const BIGNUM *bn, int len) 439280297Sjkim{ 440280297Sjkim int nb, i; 441280297Sjkim unsigned char *p = *out, *q, c; 442280297Sjkim nb = BN_num_bytes(bn); 443280297Sjkim BN_bn2bin(bn, p); 444280297Sjkim q = p + nb - 1; 445280297Sjkim /* In place byte order reversal */ 446280297Sjkim for (i = 0; i < nb / 2; i++) { 447280297Sjkim c = *p; 448280297Sjkim *p++ = *q; 449280297Sjkim *q-- = c; 450280297Sjkim } 451280297Sjkim *out += nb; 452280297Sjkim /* Pad with zeroes if we have to */ 453280297Sjkim if (len > 0) { 454280297Sjkim len -= nb; 455280297Sjkim if (len > 0) { 456280297Sjkim memset(*out, 0, len); 457280297Sjkim *out += len; 458280297Sjkim } 459280297Sjkim } 460280297Sjkim} 461238384Sjkim 462238384Sjkimstatic int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *magic); 463238384Sjkimstatic int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *magic); 464238384Sjkim 465238384Sjkimstatic void write_rsa(unsigned char **out, RSA *rsa, int ispub); 466238384Sjkimstatic void write_dsa(unsigned char **out, DSA *dsa, int ispub); 467280297Sjkim 468238384Sjkimstatic int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub) 469280297Sjkim{ 470280297Sjkim unsigned char *p; 471280297Sjkim unsigned int bitlen, magic = 0, keyalg; 472280297Sjkim int outlen, noinc = 0; 473280297Sjkim if (pk->type == EVP_PKEY_DSA) { 474280297Sjkim bitlen = check_bitlen_dsa(pk->pkey.dsa, ispub, &magic); 475280297Sjkim keyalg = MS_KEYALG_DSS_SIGN; 476280297Sjkim } else if (pk->type == EVP_PKEY_RSA) { 477280297Sjkim bitlen = check_bitlen_rsa(pk->pkey.rsa, ispub, &magic); 478280297Sjkim keyalg = MS_KEYALG_RSA_KEYX; 479280297Sjkim } else 480280297Sjkim return -1; 481280297Sjkim if (bitlen == 0) 482280297Sjkim return -1; 483280297Sjkim outlen = 16 + blob_length(bitlen, 484280297Sjkim keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub); 485280297Sjkim if (out == NULL) 486280297Sjkim return outlen; 487280297Sjkim if (*out) 488280297Sjkim p = *out; 489280297Sjkim else { 490280297Sjkim p = OPENSSL_malloc(outlen); 491280297Sjkim if (!p) 492280297Sjkim return -1; 493280297Sjkim *out = p; 494280297Sjkim noinc = 1; 495280297Sjkim } 496280297Sjkim if (ispub) 497280297Sjkim *p++ = MS_PUBLICKEYBLOB; 498280297Sjkim else 499280297Sjkim *p++ = MS_PRIVATEKEYBLOB; 500280297Sjkim *p++ = 0x2; 501280297Sjkim *p++ = 0; 502280297Sjkim *p++ = 0; 503280297Sjkim write_ledword(&p, keyalg); 504280297Sjkim write_ledword(&p, magic); 505280297Sjkim write_ledword(&p, bitlen); 506280297Sjkim if (keyalg == MS_KEYALG_DSS_SIGN) 507280297Sjkim write_dsa(&p, pk->pkey.dsa, ispub); 508280297Sjkim else 509280297Sjkim write_rsa(&p, pk->pkey.rsa, ispub); 510280297Sjkim if (!noinc) 511280297Sjkim *out += outlen; 512280297Sjkim return outlen; 513280297Sjkim} 514238384Sjkim 515238384Sjkimstatic int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub) 516280297Sjkim{ 517280297Sjkim unsigned char *tmp = NULL; 518280297Sjkim int outlen, wrlen; 519280297Sjkim outlen = do_i2b(&tmp, pk, ispub); 520280297Sjkim if (outlen < 0) 521280297Sjkim return -1; 522280297Sjkim wrlen = BIO_write(out, tmp, outlen); 523280297Sjkim OPENSSL_free(tmp); 524280297Sjkim if (wrlen == outlen) 525280297Sjkim return outlen; 526280297Sjkim return -1; 527280297Sjkim} 528238384Sjkim 529238384Sjkimstatic int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic) 530280297Sjkim{ 531280297Sjkim int bitlen; 532280297Sjkim bitlen = BN_num_bits(dsa->p); 533280297Sjkim if ((bitlen & 7) || (BN_num_bits(dsa->q) != 160) 534280297Sjkim || (BN_num_bits(dsa->g) > bitlen)) 535280297Sjkim goto badkey; 536280297Sjkim if (ispub) { 537280297Sjkim if (BN_num_bits(dsa->pub_key) > bitlen) 538280297Sjkim goto badkey; 539280297Sjkim *pmagic = MS_DSS1MAGIC; 540280297Sjkim } else { 541280297Sjkim if (BN_num_bits(dsa->priv_key) > 160) 542280297Sjkim goto badkey; 543280297Sjkim *pmagic = MS_DSS2MAGIC; 544280297Sjkim } 545238384Sjkim 546280297Sjkim return bitlen; 547280297Sjkim badkey: 548280297Sjkim PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS); 549280297Sjkim return 0; 550280297Sjkim} 551280297Sjkim 552238384Sjkimstatic int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic) 553280297Sjkim{ 554280297Sjkim int nbyte, hnbyte, bitlen; 555280297Sjkim if (BN_num_bits(rsa->e) > 32) 556280297Sjkim goto badkey; 557280297Sjkim bitlen = BN_num_bits(rsa->n); 558280297Sjkim nbyte = BN_num_bytes(rsa->n); 559280297Sjkim hnbyte = (BN_num_bits(rsa->n) + 15) >> 4; 560280297Sjkim if (ispub) { 561280297Sjkim *pmagic = MS_RSA1MAGIC; 562280297Sjkim return bitlen; 563280297Sjkim } else { 564280297Sjkim *pmagic = MS_RSA2MAGIC; 565280297Sjkim /* 566280297Sjkim * For private key each component must fit within nbyte or hnbyte. 567280297Sjkim */ 568280297Sjkim if (BN_num_bytes(rsa->d) > nbyte) 569280297Sjkim goto badkey; 570280297Sjkim if ((BN_num_bytes(rsa->iqmp) > hnbyte) 571280297Sjkim || (BN_num_bytes(rsa->p) > hnbyte) 572280297Sjkim || (BN_num_bytes(rsa->q) > hnbyte) 573280297Sjkim || (BN_num_bytes(rsa->dmp1) > hnbyte) 574280297Sjkim || (BN_num_bytes(rsa->dmq1) > hnbyte)) 575280297Sjkim goto badkey; 576280297Sjkim } 577280297Sjkim return bitlen; 578280297Sjkim badkey: 579280297Sjkim PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS); 580280297Sjkim return 0; 581280297Sjkim} 582238384Sjkim 583238384Sjkimstatic void write_rsa(unsigned char **out, RSA *rsa, int ispub) 584280297Sjkim{ 585280297Sjkim int nbyte, hnbyte; 586280297Sjkim nbyte = BN_num_bytes(rsa->n); 587280297Sjkim hnbyte = (BN_num_bits(rsa->n) + 15) >> 4; 588280297Sjkim write_lebn(out, rsa->e, 4); 589280297Sjkim write_lebn(out, rsa->n, -1); 590280297Sjkim if (ispub) 591280297Sjkim return; 592280297Sjkim write_lebn(out, rsa->p, hnbyte); 593280297Sjkim write_lebn(out, rsa->q, hnbyte); 594280297Sjkim write_lebn(out, rsa->dmp1, hnbyte); 595280297Sjkim write_lebn(out, rsa->dmq1, hnbyte); 596280297Sjkim write_lebn(out, rsa->iqmp, hnbyte); 597280297Sjkim write_lebn(out, rsa->d, nbyte); 598280297Sjkim} 599238384Sjkim 600238384Sjkimstatic void write_dsa(unsigned char **out, DSA *dsa, int ispub) 601280297Sjkim{ 602280297Sjkim int nbyte; 603280297Sjkim nbyte = BN_num_bytes(dsa->p); 604280297Sjkim write_lebn(out, dsa->p, nbyte); 605280297Sjkim write_lebn(out, dsa->q, 20); 606280297Sjkim write_lebn(out, dsa->g, nbyte); 607280297Sjkim if (ispub) 608280297Sjkim write_lebn(out, dsa->pub_key, nbyte); 609280297Sjkim else 610280297Sjkim write_lebn(out, dsa->priv_key, 20); 611280297Sjkim /* Set "invalid" for seed structure values */ 612280297Sjkim memset(*out, 0xff, 24); 613280297Sjkim *out += 24; 614280297Sjkim return; 615280297Sjkim} 616238384Sjkim 617238384Sjkimint i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk) 618280297Sjkim{ 619280297Sjkim return do_i2b_bio(out, pk, 0); 620280297Sjkim} 621238384Sjkim 622238384Sjkimint i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk) 623280297Sjkim{ 624280297Sjkim return do_i2b_bio(out, pk, 1); 625280297Sjkim} 626238384Sjkim 627280297Sjkim# ifndef OPENSSL_NO_RC4 628238384Sjkim 629238384Sjkimstatic int do_PVK_header(const unsigned char **in, unsigned int length, 630280297Sjkim int skip_magic, 631280297Sjkim unsigned int *psaltlen, unsigned int *pkeylen) 632280297Sjkim{ 633280297Sjkim const unsigned char *p = *in; 634280297Sjkim unsigned int pvk_magic, is_encrypted; 635280297Sjkim if (skip_magic) { 636280297Sjkim if (length < 20) { 637280297Sjkim PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT); 638280297Sjkim return 0; 639280297Sjkim } 640280297Sjkim } else { 641280297Sjkim if (length < 24) { 642280297Sjkim PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT); 643280297Sjkim return 0; 644280297Sjkim } 645280297Sjkim pvk_magic = read_ledword(&p); 646280297Sjkim if (pvk_magic != MS_PVKMAGIC) { 647280297Sjkim PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER); 648280297Sjkim return 0; 649280297Sjkim } 650280297Sjkim } 651280297Sjkim /* Skip reserved */ 652280297Sjkim p += 4; 653280297Sjkim /* 654280297Sjkim * keytype = 655280297Sjkim */ read_ledword(&p); 656280297Sjkim is_encrypted = read_ledword(&p); 657280297Sjkim *psaltlen = read_ledword(&p); 658280297Sjkim *pkeylen = read_ledword(&p); 659238384Sjkim 660298998Sjkim if (*pkeylen > PVK_MAX_KEYLEN || *psaltlen > PVK_MAX_SALTLEN) 661298998Sjkim return 0; 662298998Sjkim 663280297Sjkim if (is_encrypted && !*psaltlen) { 664280297Sjkim PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER); 665280297Sjkim return 0; 666280297Sjkim } 667238384Sjkim 668280297Sjkim *in = p; 669280297Sjkim return 1; 670280297Sjkim} 671238384Sjkim 672280297Sjkimstatic int derive_pvk_key(unsigned char *key, 673280297Sjkim const unsigned char *salt, unsigned int saltlen, 674280297Sjkim const unsigned char *pass, int passlen) 675280297Sjkim{ 676280297Sjkim EVP_MD_CTX mctx; 677280297Sjkim int rv = 1; 678280297Sjkim EVP_MD_CTX_init(&mctx); 679280297Sjkim if (!EVP_DigestInit_ex(&mctx, EVP_sha1(), NULL) 680280297Sjkim || !EVP_DigestUpdate(&mctx, salt, saltlen) 681280297Sjkim || !EVP_DigestUpdate(&mctx, pass, passlen) 682280297Sjkim || !EVP_DigestFinal_ex(&mctx, key, NULL)) 683280297Sjkim rv = 0; 684238384Sjkim 685280297Sjkim EVP_MD_CTX_cleanup(&mctx); 686280297Sjkim return rv; 687280297Sjkim} 688238384Sjkim 689238384Sjkimstatic EVP_PKEY *do_PVK_body(const unsigned char **in, 690280297Sjkim unsigned int saltlen, unsigned int keylen, 691280297Sjkim pem_password_cb *cb, void *u) 692280297Sjkim{ 693280297Sjkim EVP_PKEY *ret = NULL; 694280297Sjkim const unsigned char *p = *in; 695280297Sjkim unsigned int magic; 696280297Sjkim unsigned char *enctmp = NULL, *q; 697280297Sjkim EVP_CIPHER_CTX cctx; 698280297Sjkim EVP_CIPHER_CTX_init(&cctx); 699280297Sjkim if (saltlen) { 700280297Sjkim char psbuf[PEM_BUFSIZE]; 701280297Sjkim unsigned char keybuf[20]; 702280297Sjkim int enctmplen, inlen; 703280297Sjkim if (cb) 704280297Sjkim inlen = cb(psbuf, PEM_BUFSIZE, 0, u); 705280297Sjkim else 706280297Sjkim inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); 707337982Sjkim if (inlen < 0) { 708280297Sjkim PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_PASSWORD_READ); 709291719Sjkim goto err; 710280297Sjkim } 711280297Sjkim enctmp = OPENSSL_malloc(keylen + 8); 712280297Sjkim if (!enctmp) { 713280297Sjkim PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE); 714291719Sjkim goto err; 715280297Sjkim } 716280297Sjkim if (!derive_pvk_key(keybuf, p, saltlen, 717280297Sjkim (unsigned char *)psbuf, inlen)) 718291719Sjkim goto err; 719280297Sjkim p += saltlen; 720280297Sjkim /* Copy BLOBHEADER across, decrypt rest */ 721280297Sjkim memcpy(enctmp, p, 8); 722280297Sjkim p += 8; 723280297Sjkim if (keylen < 8) { 724280297Sjkim PEMerr(PEM_F_DO_PVK_BODY, PEM_R_PVK_TOO_SHORT); 725291719Sjkim goto err; 726280297Sjkim } 727280297Sjkim inlen = keylen - 8; 728280297Sjkim q = enctmp + 8; 729280297Sjkim if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL)) 730280297Sjkim goto err; 731280297Sjkim if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen)) 732280297Sjkim goto err; 733280297Sjkim if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen)) 734280297Sjkim goto err; 735280297Sjkim magic = read_ledword((const unsigned char **)&q); 736280297Sjkim if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { 737280297Sjkim q = enctmp + 8; 738280297Sjkim memset(keybuf + 5, 0, 11); 739280297Sjkim if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL)) 740280297Sjkim goto err; 741280297Sjkim OPENSSL_cleanse(keybuf, 20); 742280297Sjkim if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen)) 743280297Sjkim goto err; 744280297Sjkim if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen)) 745280297Sjkim goto err; 746280297Sjkim magic = read_ledword((const unsigned char **)&q); 747280297Sjkim if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { 748280297Sjkim PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT); 749280297Sjkim goto err; 750280297Sjkim } 751280297Sjkim } else 752280297Sjkim OPENSSL_cleanse(keybuf, 20); 753280297Sjkim p = enctmp; 754280297Sjkim } 755238384Sjkim 756280297Sjkim ret = b2i_PrivateKey(&p, keylen); 757280297Sjkim err: 758280297Sjkim EVP_CIPHER_CTX_cleanup(&cctx); 759280297Sjkim if (enctmp && saltlen) 760280297Sjkim OPENSSL_free(enctmp); 761280297Sjkim return ret; 762280297Sjkim} 763238384Sjkim 764238384SjkimEVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u) 765280297Sjkim{ 766280297Sjkim unsigned char pvk_hdr[24], *buf = NULL; 767280297Sjkim const unsigned char *p; 768280297Sjkim int buflen; 769280297Sjkim EVP_PKEY *ret = NULL; 770280297Sjkim unsigned int saltlen, keylen; 771280297Sjkim if (BIO_read(in, pvk_hdr, 24) != 24) { 772280297Sjkim PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT); 773280297Sjkim return NULL; 774280297Sjkim } 775280297Sjkim p = pvk_hdr; 776238384Sjkim 777280297Sjkim if (!do_PVK_header(&p, 24, 0, &saltlen, &keylen)) 778280297Sjkim return 0; 779280297Sjkim buflen = (int)keylen + saltlen; 780280297Sjkim buf = OPENSSL_malloc(buflen); 781280297Sjkim if (!buf) { 782280297Sjkim PEMerr(PEM_F_B2I_PVK_BIO, ERR_R_MALLOC_FAILURE); 783280297Sjkim return 0; 784280297Sjkim } 785280297Sjkim p = buf; 786280297Sjkim if (BIO_read(in, buf, buflen) != buflen) { 787280297Sjkim PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT); 788280297Sjkim goto err; 789280297Sjkim } 790280297Sjkim ret = do_PVK_body(&p, saltlen, keylen, cb, u); 791238384Sjkim 792280297Sjkim err: 793280297Sjkim if (buf) { 794280297Sjkim OPENSSL_cleanse(buf, buflen); 795280297Sjkim OPENSSL_free(buf); 796280297Sjkim } 797280297Sjkim return ret; 798280297Sjkim} 799238384Sjkim 800280297Sjkimstatic int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel, 801280297Sjkim pem_password_cb *cb, void *u) 802280297Sjkim{ 803280297Sjkim int outlen = 24, pklen; 804280297Sjkim unsigned char *p, *salt = NULL; 805280297Sjkim EVP_CIPHER_CTX cctx; 806280297Sjkim EVP_CIPHER_CTX_init(&cctx); 807280297Sjkim if (enclevel) 808280297Sjkim outlen += PVK_SALTLEN; 809280297Sjkim pklen = do_i2b(NULL, pk, 0); 810280297Sjkim if (pklen < 0) 811280297Sjkim return -1; 812280297Sjkim outlen += pklen; 813280297Sjkim if (!out) 814280297Sjkim return outlen; 815280297Sjkim if (*out) 816280297Sjkim p = *out; 817280297Sjkim else { 818280297Sjkim p = OPENSSL_malloc(outlen); 819280297Sjkim if (!p) { 820280297Sjkim PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE); 821280297Sjkim return -1; 822280297Sjkim } 823280297Sjkim *out = p; 824280297Sjkim } 825238384Sjkim 826280297Sjkim write_ledword(&p, MS_PVKMAGIC); 827280297Sjkim write_ledword(&p, 0); 828280297Sjkim if (pk->type == EVP_PKEY_DSA) 829280297Sjkim write_ledword(&p, MS_KEYTYPE_SIGN); 830280297Sjkim else 831280297Sjkim write_ledword(&p, MS_KEYTYPE_KEYX); 832280297Sjkim write_ledword(&p, enclevel ? 1 : 0); 833280297Sjkim write_ledword(&p, enclevel ? PVK_SALTLEN : 0); 834280297Sjkim write_ledword(&p, pklen); 835280297Sjkim if (enclevel) { 836280297Sjkim if (RAND_bytes(p, PVK_SALTLEN) <= 0) 837280297Sjkim goto error; 838280297Sjkim salt = p; 839280297Sjkim p += PVK_SALTLEN; 840280297Sjkim } 841280297Sjkim do_i2b(&p, pk, 0); 842280297Sjkim if (enclevel == 0) 843280297Sjkim return outlen; 844280297Sjkim else { 845280297Sjkim char psbuf[PEM_BUFSIZE]; 846280297Sjkim unsigned char keybuf[20]; 847280297Sjkim int enctmplen, inlen; 848280297Sjkim if (cb) 849280297Sjkim inlen = cb(psbuf, PEM_BUFSIZE, 1, u); 850280297Sjkim else 851280297Sjkim inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 1, u); 852280297Sjkim if (inlen <= 0) { 853280297Sjkim PEMerr(PEM_F_I2B_PVK, PEM_R_BAD_PASSWORD_READ); 854280297Sjkim goto error; 855280297Sjkim } 856280297Sjkim if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN, 857280297Sjkim (unsigned char *)psbuf, inlen)) 858280297Sjkim goto error; 859280297Sjkim if (enclevel == 1) 860280297Sjkim memset(keybuf + 5, 0, 11); 861280297Sjkim p = salt + PVK_SALTLEN + 8; 862280297Sjkim if (!EVP_EncryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL)) 863280297Sjkim goto error; 864280297Sjkim OPENSSL_cleanse(keybuf, 20); 865280297Sjkim if (!EVP_DecryptUpdate(&cctx, p, &enctmplen, p, pklen - 8)) 866280297Sjkim goto error; 867280297Sjkim if (!EVP_DecryptFinal_ex(&cctx, p + enctmplen, &enctmplen)) 868280297Sjkim goto error; 869280297Sjkim } 870280297Sjkim EVP_CIPHER_CTX_cleanup(&cctx); 871280297Sjkim return outlen; 872238384Sjkim 873280297Sjkim error: 874280297Sjkim EVP_CIPHER_CTX_cleanup(&cctx); 875280297Sjkim return -1; 876280297Sjkim} 877238384Sjkim 878238384Sjkimint i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, 879280297Sjkim pem_password_cb *cb, void *u) 880280297Sjkim{ 881280297Sjkim unsigned char *tmp = NULL; 882280297Sjkim int outlen, wrlen; 883280297Sjkim outlen = i2b_PVK(&tmp, pk, enclevel, cb, u); 884280297Sjkim if (outlen < 0) 885280297Sjkim return -1; 886280297Sjkim wrlen = BIO_write(out, tmp, outlen); 887280297Sjkim OPENSSL_free(tmp); 888280297Sjkim if (wrlen == outlen) { 889280297Sjkim PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE); 890280297Sjkim return outlen; 891280297Sjkim } 892280297Sjkim return -1; 893280297Sjkim} 894238384Sjkim 895280297Sjkim# endif 896238384Sjkim 897238384Sjkim#endif 898