1219820Sjeff/* 2219820Sjeff * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 3219820Sjeff * 2005. 4219820Sjeff */ 5219820Sjeff/* ==================================================================== 6219820Sjeff * Copyright (c) 2005 The OpenSSL Project. All rights reserved. 7219820Sjeff * 8219820Sjeff * Redistribution and use in source and binary forms, with or without 9219820Sjeff * modification, are permitted provided that the following conditions 10219820Sjeff * are met: 11219820Sjeff * 12219820Sjeff * 1. Redistributions of source code must retain the above copyright 13219820Sjeff * notice, this list of conditions and the following disclaimer. 14219820Sjeff * 15219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright 16219820Sjeff * notice, this list of conditions and the following disclaimer in 17219820Sjeff * the documentation and/or other materials provided with the 18219820Sjeff * distribution. 19219820Sjeff * 20219820Sjeff * 3. All advertising materials mentioning features or use of this 21219820Sjeff * software must display the following acknowledgment: 22219820Sjeff * "This product includes software developed by the OpenSSL Project 23219820Sjeff * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24219820Sjeff * 25219820Sjeff * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26219820Sjeff * endorse or promote products derived from this software without 27219820Sjeff * prior written permission. For written permission, please contact 28219820Sjeff * licensing@OpenSSL.org. 29219820Sjeff * 30219820Sjeff * 5. Products derived from this software may not be called "OpenSSL" 31219820Sjeff * nor may "OpenSSL" appear in their names without prior written 32219820Sjeff * permission of the OpenSSL Project. 33219820Sjeff * 34219820Sjeff * 6. Redistributions of any form whatsoever must retain the following 35219820Sjeff * acknowledgment: 36219820Sjeff * "This product includes software developed by the OpenSSL Project 37219820Sjeff * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38219820Sjeff * 39219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40219820Sjeff * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42219820Sjeff * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43219820Sjeff * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44219820Sjeff * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45219820Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46219820Sjeff * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48219820Sjeff * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49219820Sjeff * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50219820Sjeff * OF THE POSSIBILITY OF SUCH DAMAGE. 51219820Sjeff * ==================================================================== 52219820Sjeff * 53219820Sjeff * This product includes cryptographic software written by Eric Young 54219820Sjeff * (eay@cryptsoft.com). This product includes software written by Tim 55219820Sjeff * Hudson (tjh@cryptsoft.com). 56219820Sjeff * 57219820Sjeff */ 58219820Sjeff 59219820Sjeff/* 60219820Sjeff * Support for PVK format keys and related structures (such a PUBLICKEYBLOB 61219820Sjeff * and PRIVATEKEYBLOB). 62219820Sjeff */ 63219820Sjeff 64219820Sjeff#include "cryptlib.h" 65219820Sjeff#include <openssl/pem.h> 66219820Sjeff#include <openssl/rand.h> 67219820Sjeff#include <openssl/bn.h> 68219820Sjeff#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) 69219820Sjeff# include <openssl/dsa.h> 70219820Sjeff# include <openssl/rsa.h> 71219820Sjeff 72219820Sjeff/* 73219820Sjeff * Utility function: read a DWORD (4 byte unsigned integer) in little endian 74219820Sjeff * format 75219820Sjeff */ 76219820Sjeff 77219820Sjeffstatic unsigned int read_ledword(const unsigned char **in) 78219820Sjeff{ 79219820Sjeff const unsigned char *p = *in; 80219820Sjeff unsigned int ret; 81219820Sjeff ret = *p++; 82219820Sjeff ret |= (*p++ << 8); 83219820Sjeff ret |= (*p++ << 16); 84219820Sjeff ret |= (*p++ << 24); 85219820Sjeff *in = p; 86219820Sjeff return ret; 87219820Sjeff} 88219820Sjeff 89219820Sjeff/* 90219820Sjeff * Read a BIGNUM in little endian format. The docs say that this should take 91219820Sjeff * up bitlen/8 bytes. 92219820Sjeff */ 93219820Sjeff 94219820Sjeffstatic int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r) 95219820Sjeff{ 96219820Sjeff const unsigned char *p; 97219820Sjeff unsigned char *tmpbuf, *q; 98219820Sjeff unsigned int i; 99219820Sjeff p = *in + nbyte - 1; 100219820Sjeff tmpbuf = OPENSSL_malloc(nbyte); 101219820Sjeff if (!tmpbuf) 102219820Sjeff return 0; 103219820Sjeff q = tmpbuf; 104219820Sjeff for (i = 0; i < nbyte; i++) 105219820Sjeff *q++ = *p--; 106219820Sjeff *r = BN_bin2bn(tmpbuf, nbyte, NULL); 107219820Sjeff OPENSSL_free(tmpbuf); 108219820Sjeff if (*r) { 109219820Sjeff *in += nbyte; 110219820Sjeff return 1; 111219820Sjeff } else 112219820Sjeff return 0; 113219820Sjeff} 114219820Sjeff 115219820Sjeff/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */ 116219820Sjeff 117219820Sjeff# define MS_PUBLICKEYBLOB 0x6 118219820Sjeff# define MS_PRIVATEKEYBLOB 0x7 119219820Sjeff# define MS_RSA1MAGIC 0x31415352L 120219820Sjeff# define MS_RSA2MAGIC 0x32415352L 121219820Sjeff# define MS_DSS1MAGIC 0x31535344L 122219820Sjeff# define MS_DSS2MAGIC 0x32535344L 123219820Sjeff 124219820Sjeff# define MS_KEYALG_RSA_KEYX 0xa400 125219820Sjeff# define MS_KEYALG_DSS_SIGN 0x2200 126219820Sjeff 127219820Sjeff# define MS_KEYTYPE_KEYX 0x1 128219820Sjeff# define MS_KEYTYPE_SIGN 0x2 129219820Sjeff 130219820Sjeff/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */ 131219820Sjeff# define MS_PVKMAGIC 0xb0b5f11eL 132219820Sjeff/* Salt length for PVK files */ 133219820Sjeff# define PVK_SALTLEN 0x10 134219820Sjeff 135219820Sjeffstatic EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length, 136219820Sjeff unsigned int bitlen, int ispub); 137219820Sjeffstatic EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length, 138219820Sjeff unsigned int bitlen, int ispub); 139219820Sjeff 140219820Sjeffstatic int do_blob_header(const unsigned char **in, unsigned int length, 141219820Sjeff unsigned int *pmagic, unsigned int *pbitlen, 142219820Sjeff int *pisdss, int *pispub) 143219820Sjeff{ 144219820Sjeff const unsigned char *p = *in; 145219820Sjeff if (length < 16) 146219820Sjeff return 0; 147219820Sjeff /* bType */ 148219820Sjeff if (*p == MS_PUBLICKEYBLOB) { 149219820Sjeff if (*pispub == 0) { 150219820Sjeff PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB); 151219820Sjeff return 0; 152219820Sjeff } 153219820Sjeff *pispub = 1; 154219820Sjeff } else if (*p == MS_PRIVATEKEYBLOB) { 155219820Sjeff if (*pispub == 1) { 156219820Sjeff PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB); 157219820Sjeff return 0; 158219820Sjeff } 159219820Sjeff *pispub = 0; 160219820Sjeff } else 161219820Sjeff return 0; 162219820Sjeff p++; 163219820Sjeff /* Version */ 164219820Sjeff if (*p++ != 0x2) { 165219820Sjeff PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_VERSION_NUMBER); 166219820Sjeff return 0; 167219820Sjeff } 168219820Sjeff /* Ignore reserved, aiKeyAlg */ 169219820Sjeff p += 6; 170219820Sjeff *pmagic = read_ledword(&p); 171219820Sjeff *pbitlen = read_ledword(&p); 172219820Sjeff *pisdss = 0; 173219820Sjeff switch (*pmagic) { 174219820Sjeff 175219820Sjeff case MS_DSS1MAGIC: 176219820Sjeff *pisdss = 1; 177219820Sjeff case MS_RSA1MAGIC: 178219820Sjeff if (*pispub == 0) { 179219820Sjeff PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB); 180219820Sjeff return 0; 181219820Sjeff } 182219820Sjeff break; 183219820Sjeff 184219820Sjeff case MS_DSS2MAGIC: 185219820Sjeff *pisdss = 1; 186219820Sjeff case MS_RSA2MAGIC: 187219820Sjeff if (*pispub == 1) { 188219820Sjeff PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB); 189219820Sjeff return 0; 190219820Sjeff } 191219820Sjeff break; 192219820Sjeff 193219820Sjeff default: 194219820Sjeff PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_MAGIC_NUMBER); 195219820Sjeff return -1; 196219820Sjeff } 197219820Sjeff *in = p; 198219820Sjeff return 1; 199219820Sjeff} 200219820Sjeff 201219820Sjeffstatic unsigned int blob_length(unsigned bitlen, int isdss, int ispub) 202219820Sjeff{ 203219820Sjeff unsigned int nbyte, hnbyte; 204219820Sjeff nbyte = (bitlen + 7) >> 3; 205219820Sjeff hnbyte = (bitlen + 15) >> 4; 206219820Sjeff if (isdss) { 207219820Sjeff 208219820Sjeff /* 209219820Sjeff * Expected length: 20 for q + 3 components bitlen each + 24 for seed 210219820Sjeff * structure. 211219820Sjeff */ 212219820Sjeff if (ispub) 213219820Sjeff return 44 + 3 * nbyte; 214219820Sjeff /* 215219820Sjeff * Expected length: 20 for q, priv, 2 bitlen components + 24 for seed 216219820Sjeff * structure. 217219820Sjeff */ 218219820Sjeff else 219219820Sjeff return 64 + 2 * nbyte; 220219820Sjeff } else { 221219820Sjeff /* Expected length: 4 for 'e' + 'n' */ 222219820Sjeff if (ispub) 223219820Sjeff return 4 + nbyte; 224219820Sjeff else 225219820Sjeff /* 226219820Sjeff * Expected length: 4 for 'e' and 7 other components. 2 227219820Sjeff * components are bitlen size, 5 are bitlen/2 228219820Sjeff */ 229219820Sjeff return 4 + 2 * nbyte + 5 * hnbyte; 230219820Sjeff } 231219820Sjeff 232219820Sjeff} 233219820Sjeff 234219820Sjeffstatic EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length, 235219820Sjeff int ispub) 236219820Sjeff{ 237219820Sjeff const unsigned char *p = *in; 238219820Sjeff unsigned int bitlen, magic; 239219820Sjeff int isdss; 240219820Sjeff if (do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0) { 241219820Sjeff PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_HEADER_PARSE_ERROR); 242219820Sjeff return NULL; 243219820Sjeff } 244219820Sjeff length -= 16; 245219820Sjeff if (length < blob_length(bitlen, isdss, ispub)) { 246219820Sjeff PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_TOO_SHORT); 247219820Sjeff return NULL; 248219820Sjeff } 249219820Sjeff if (isdss) 250219820Sjeff return b2i_dss(&p, length, bitlen, ispub); 251219820Sjeff else 252219820Sjeff return b2i_rsa(&p, length, bitlen, ispub); 253219820Sjeff} 254219820Sjeff 255219820Sjeffstatic EVP_PKEY *do_b2i_bio(BIO *in, int ispub) 256219820Sjeff{ 257219820Sjeff const unsigned char *p; 258219820Sjeff unsigned char hdr_buf[16], *buf = NULL; 259219820Sjeff unsigned int bitlen, magic, length; 260219820Sjeff int isdss; 261219820Sjeff EVP_PKEY *ret = NULL; 262219820Sjeff if (BIO_read(in, hdr_buf, 16) != 16) { 263219820Sjeff PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT); 264219820Sjeff return NULL; 265219820Sjeff } 266219820Sjeff p = hdr_buf; 267219820Sjeff if (do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0) 268219820Sjeff return NULL; 269219820Sjeff 270219820Sjeff length = blob_length(bitlen, isdss, ispub); 271219820Sjeff buf = OPENSSL_malloc(length); 272219820Sjeff if (!buf) { 273219820Sjeff PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE); 274219820Sjeff goto err; 275219820Sjeff } 276219820Sjeff p = buf; 277219820Sjeff if (BIO_read(in, buf, length) != (int)length) { 278219820Sjeff PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT); 279219820Sjeff goto err; 280219820Sjeff } 281219820Sjeff 282219820Sjeff if (isdss) 283219820Sjeff ret = b2i_dss(&p, length, bitlen, ispub); 284219820Sjeff else 285219820Sjeff ret = b2i_rsa(&p, length, bitlen, ispub); 286219820Sjeff 287219820Sjeff err: 288219820Sjeff if (buf) 289219820Sjeff OPENSSL_free(buf); 290219820Sjeff return ret; 291219820Sjeff} 292219820Sjeff 293219820Sjeffstatic EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length, 294219820Sjeff unsigned int bitlen, int ispub) 295219820Sjeff{ 296219820Sjeff const unsigned char *p = *in; 297219820Sjeff EVP_PKEY *ret = NULL; 298219820Sjeff DSA *dsa = NULL; 299219820Sjeff BN_CTX *ctx = NULL; 300219820Sjeff unsigned int nbyte; 301219820Sjeff nbyte = (bitlen + 7) >> 3; 302219820Sjeff 303219820Sjeff dsa = DSA_new(); 304219820Sjeff ret = EVP_PKEY_new(); 305219820Sjeff if (!dsa || !ret) 306219820Sjeff goto memerr; 307219820Sjeff if (!read_lebn(&p, nbyte, &dsa->p)) 308219820Sjeff goto memerr; 309219820Sjeff if (!read_lebn(&p, 20, &dsa->q)) 310219820Sjeff goto memerr; 311219820Sjeff if (!read_lebn(&p, nbyte, &dsa->g)) 312219820Sjeff goto memerr; 313219820Sjeff if (ispub) { 314219820Sjeff if (!read_lebn(&p, nbyte, &dsa->pub_key)) 315219820Sjeff goto memerr; 316219820Sjeff } else { 317219820Sjeff if (!read_lebn(&p, 20, &dsa->priv_key)) 318219820Sjeff goto memerr; 319219820Sjeff /* Calculate public key */ 320219820Sjeff if (!(dsa->pub_key = BN_new())) 321219820Sjeff goto memerr; 322219820Sjeff if (!(ctx = BN_CTX_new())) 323219820Sjeff goto memerr; 324219820Sjeff 325219820Sjeff if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) 326219820Sjeff 327219820Sjeff goto memerr; 328219820Sjeff BN_CTX_free(ctx); 329219820Sjeff } 330219820Sjeff 331219820Sjeff EVP_PKEY_set1_DSA(ret, dsa); 332219820Sjeff DSA_free(dsa); 333219820Sjeff *in = p; 334219820Sjeff return ret; 335219820Sjeff 336219820Sjeff memerr: 337219820Sjeff PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE); 338219820Sjeff if (dsa) 339219820Sjeff DSA_free(dsa); 340219820Sjeff if (ret) 341219820Sjeff EVP_PKEY_free(ret); 342219820Sjeff if (ctx) 343219820Sjeff BN_CTX_free(ctx); 344219820Sjeff return NULL; 345219820Sjeff} 346219820Sjeff 347219820Sjeffstatic EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length, 348219820Sjeff unsigned int bitlen, int ispub) 349219820Sjeff{ 350219820Sjeff const unsigned char *p = *in; 351219820Sjeff EVP_PKEY *ret = NULL; 352219820Sjeff RSA *rsa = NULL; 353219820Sjeff unsigned int nbyte, hnbyte; 354219820Sjeff nbyte = (bitlen + 7) >> 3; 355219820Sjeff hnbyte = (bitlen + 15) >> 4; 356219820Sjeff rsa = RSA_new(); 357219820Sjeff ret = EVP_PKEY_new(); 358219820Sjeff if (!rsa || !ret) 359219820Sjeff goto memerr; 360219820Sjeff rsa->e = BN_new(); 361219820Sjeff if (!rsa->e) 362219820Sjeff goto memerr; 363219820Sjeff if (!BN_set_word(rsa->e, read_ledword(&p))) 364219820Sjeff goto memerr; 365219820Sjeff if (!read_lebn(&p, nbyte, &rsa->n)) 366219820Sjeff goto memerr; 367219820Sjeff if (!ispub) { 368219820Sjeff if (!read_lebn(&p, hnbyte, &rsa->p)) 369219820Sjeff goto memerr; 370219820Sjeff if (!read_lebn(&p, hnbyte, &rsa->q)) 371219820Sjeff goto memerr; 372219820Sjeff if (!read_lebn(&p, hnbyte, &rsa->dmp1)) 373219820Sjeff goto memerr; 374219820Sjeff if (!read_lebn(&p, hnbyte, &rsa->dmq1)) 375219820Sjeff goto memerr; 376219820Sjeff if (!read_lebn(&p, hnbyte, &rsa->iqmp)) 377219820Sjeff goto memerr; 378219820Sjeff if (!read_lebn(&p, nbyte, &rsa->d)) 379219820Sjeff goto memerr; 380219820Sjeff } 381219820Sjeff 382219820Sjeff EVP_PKEY_set1_RSA(ret, rsa); 383219820Sjeff RSA_free(rsa); 384219820Sjeff *in = p; 385219820Sjeff return ret; 386219820Sjeff memerr: 387219820Sjeff PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE); 388219820Sjeff if (rsa) 389219820Sjeff RSA_free(rsa); 390219820Sjeff if (ret) 391219820Sjeff EVP_PKEY_free(ret); 392219820Sjeff return NULL; 393219820Sjeff} 394219820Sjeff 395219820SjeffEVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length) 396219820Sjeff{ 397219820Sjeff return do_b2i(in, length, 0); 398219820Sjeff} 399219820Sjeff 400219820SjeffEVP_PKEY *b2i_PublicKey(const unsigned char **in, long length) 401219820Sjeff{ 402219820Sjeff return do_b2i(in, length, 1); 403219820Sjeff} 404219820Sjeff 405219820SjeffEVP_PKEY *b2i_PrivateKey_bio(BIO *in) 406219820Sjeff{ 407219820Sjeff return do_b2i_bio(in, 0); 408219820Sjeff} 409219820Sjeff 410219820SjeffEVP_PKEY *b2i_PublicKey_bio(BIO *in) 411219820Sjeff{ 412219820Sjeff return do_b2i_bio(in, 1); 413219820Sjeff} 414219820Sjeff 415219820Sjeffstatic void write_ledword(unsigned char **out, unsigned int dw) 416219820Sjeff{ 417219820Sjeff unsigned char *p = *out; 418219820Sjeff *p++ = dw & 0xff; 419219820Sjeff *p++ = (dw >> 8) & 0xff; 420219820Sjeff *p++ = (dw >> 16) & 0xff; 421219820Sjeff *p++ = (dw >> 24) & 0xff; 422219820Sjeff *out = p; 423219820Sjeff} 424219820Sjeff 425219820Sjeffstatic void write_lebn(unsigned char **out, const BIGNUM *bn, int len) 426219820Sjeff{ 427219820Sjeff int nb, i; 428219820Sjeff unsigned char *p = *out, *q, c; 429219820Sjeff nb = BN_num_bytes(bn); 430219820Sjeff BN_bn2bin(bn, p); 431219820Sjeff q = p + nb - 1; 432219820Sjeff /* In place byte order reversal */ 433219820Sjeff for (i = 0; i < nb / 2; i++) { 434219820Sjeff c = *p; 435219820Sjeff *p++ = *q; 436219820Sjeff *q-- = c; 437219820Sjeff } 438219820Sjeff *out += nb; 439219820Sjeff /* Pad with zeroes if we have to */ 440219820Sjeff if (len > 0) { 441219820Sjeff len -= nb; 442219820Sjeff if (len > 0) { 443219820Sjeff memset(*out, 0, len); 444219820Sjeff *out += len; 445219820Sjeff } 446219820Sjeff } 447219820Sjeff} 448219820Sjeff 449219820Sjeffstatic int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *magic); 450219820Sjeffstatic int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *magic); 451219820Sjeff 452219820Sjeffstatic void write_rsa(unsigned char **out, RSA *rsa, int ispub); 453219820Sjeffstatic void write_dsa(unsigned char **out, DSA *dsa, int ispub); 454219820Sjeff 455219820Sjeffstatic int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub) 456219820Sjeff{ 457219820Sjeff unsigned char *p; 458219820Sjeff unsigned int bitlen, magic = 0, keyalg; 459219820Sjeff int outlen, noinc = 0; 460219820Sjeff if (pk->type == EVP_PKEY_DSA) { 461219820Sjeff bitlen = check_bitlen_dsa(pk->pkey.dsa, ispub, &magic); 462219820Sjeff keyalg = MS_KEYALG_DSS_SIGN; 463219820Sjeff } else if (pk->type == EVP_PKEY_RSA) { 464219820Sjeff bitlen = check_bitlen_rsa(pk->pkey.rsa, ispub, &magic); 465219820Sjeff keyalg = MS_KEYALG_RSA_KEYX; 466219820Sjeff } else 467219820Sjeff return -1; 468219820Sjeff if (bitlen == 0) 469219820Sjeff return -1; 470219820Sjeff outlen = 16 + blob_length(bitlen, 471219820Sjeff keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub); 472219820Sjeff if (out == NULL) 473219820Sjeff return outlen; 474219820Sjeff if (*out) 475219820Sjeff p = *out; 476219820Sjeff else { 477219820Sjeff p = OPENSSL_malloc(outlen); 478219820Sjeff if (!p) 479219820Sjeff return -1; 480219820Sjeff *out = p; 481219820Sjeff noinc = 1; 482219820Sjeff } 483219820Sjeff if (ispub) 484219820Sjeff *p++ = MS_PUBLICKEYBLOB; 485219820Sjeff else 486219820Sjeff *p++ = MS_PRIVATEKEYBLOB; 487219820Sjeff *p++ = 0x2; 488219820Sjeff *p++ = 0; 489219820Sjeff *p++ = 0; 490219820Sjeff write_ledword(&p, keyalg); 491219820Sjeff write_ledword(&p, magic); 492219820Sjeff write_ledword(&p, bitlen); 493219820Sjeff if (keyalg == MS_KEYALG_DSS_SIGN) 494219820Sjeff write_dsa(&p, pk->pkey.dsa, ispub); 495219820Sjeff else 496219820Sjeff write_rsa(&p, pk->pkey.rsa, ispub); 497219820Sjeff if (!noinc) 498219820Sjeff *out += outlen; 499219820Sjeff return outlen; 500219820Sjeff} 501219820Sjeff 502219820Sjeffstatic int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub) 503219820Sjeff{ 504219820Sjeff unsigned char *tmp = NULL; 505219820Sjeff int outlen, wrlen; 506219820Sjeff outlen = do_i2b(&tmp, pk, ispub); 507219820Sjeff if (outlen < 0) 508219820Sjeff return -1; 509219820Sjeff wrlen = BIO_write(out, tmp, outlen); 510219820Sjeff OPENSSL_free(tmp); 511219820Sjeff if (wrlen == outlen) 512219820Sjeff return outlen; 513219820Sjeff return -1; 514219820Sjeff} 515219820Sjeff 516219820Sjeffstatic int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic) 517219820Sjeff{ 518219820Sjeff int bitlen; 519219820Sjeff bitlen = BN_num_bits(dsa->p); 520219820Sjeff if ((bitlen & 7) || (BN_num_bits(dsa->q) != 160) 521219820Sjeff || (BN_num_bits(dsa->g) > bitlen)) 522219820Sjeff goto badkey; 523219820Sjeff if (ispub) { 524219820Sjeff if (BN_num_bits(dsa->pub_key) > bitlen) 525219820Sjeff goto badkey; 526219820Sjeff *pmagic = MS_DSS1MAGIC; 527219820Sjeff } else { 528219820Sjeff if (BN_num_bits(dsa->priv_key) > 160) 529219820Sjeff goto badkey; 530219820Sjeff *pmagic = MS_DSS2MAGIC; 531219820Sjeff } 532219820Sjeff 533219820Sjeff return bitlen; 534219820Sjeff badkey: 535219820Sjeff PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS); 536219820Sjeff return 0; 537219820Sjeff} 538219820Sjeff 539219820Sjeffstatic int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic) 540219820Sjeff{ 541219820Sjeff int nbyte, hnbyte, bitlen; 542219820Sjeff if (BN_num_bits(rsa->e) > 32) 543219820Sjeff goto badkey; 544219820Sjeff bitlen = BN_num_bits(rsa->n); 545219820Sjeff nbyte = BN_num_bytes(rsa->n); 546219820Sjeff hnbyte = (BN_num_bits(rsa->n) + 15) >> 4; 547219820Sjeff if (ispub) { 548219820Sjeff *pmagic = MS_RSA1MAGIC; 549219820Sjeff return bitlen; 550219820Sjeff } else { 551219820Sjeff *pmagic = MS_RSA2MAGIC; 552219820Sjeff /* 553219820Sjeff * For private key each component must fit within nbyte or hnbyte. 554219820Sjeff */ 555219820Sjeff if (BN_num_bytes(rsa->d) > nbyte) 556219820Sjeff goto badkey; 557219820Sjeff if ((BN_num_bytes(rsa->iqmp) > hnbyte) 558219820Sjeff || (BN_num_bytes(rsa->p) > hnbyte) 559219820Sjeff || (BN_num_bytes(rsa->q) > hnbyte) 560219820Sjeff || (BN_num_bytes(rsa->dmp1) > hnbyte) 561219820Sjeff || (BN_num_bytes(rsa->dmq1) > hnbyte)) 562219820Sjeff goto badkey; 563219820Sjeff } 564219820Sjeff return bitlen; 565219820Sjeff badkey: 566219820Sjeff PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS); 567219820Sjeff return 0; 568219820Sjeff} 569219820Sjeff 570219820Sjeffstatic void write_rsa(unsigned char **out, RSA *rsa, int ispub) 571219820Sjeff{ 572219820Sjeff int nbyte, hnbyte; 573219820Sjeff nbyte = BN_num_bytes(rsa->n); 574219820Sjeff hnbyte = (BN_num_bits(rsa->n) + 15) >> 4; 575219820Sjeff write_lebn(out, rsa->e, 4); 576219820Sjeff write_lebn(out, rsa->n, -1); 577219820Sjeff if (ispub) 578219820Sjeff return; 579219820Sjeff write_lebn(out, rsa->p, hnbyte); 580219820Sjeff write_lebn(out, rsa->q, hnbyte); 581219820Sjeff write_lebn(out, rsa->dmp1, hnbyte); 582219820Sjeff write_lebn(out, rsa->dmq1, hnbyte); 583219820Sjeff write_lebn(out, rsa->iqmp, hnbyte); 584219820Sjeff write_lebn(out, rsa->d, nbyte); 585219820Sjeff} 586219820Sjeff 587219820Sjeffstatic void write_dsa(unsigned char **out, DSA *dsa, int ispub) 588219820Sjeff{ 589219820Sjeff int nbyte; 590219820Sjeff nbyte = BN_num_bytes(dsa->p); 591219820Sjeff write_lebn(out, dsa->p, nbyte); 592219820Sjeff write_lebn(out, dsa->q, 20); 593219820Sjeff write_lebn(out, dsa->g, nbyte); 594219820Sjeff if (ispub) 595219820Sjeff write_lebn(out, dsa->pub_key, nbyte); 596219820Sjeff else 597219820Sjeff write_lebn(out, dsa->priv_key, 20); 598219820Sjeff /* Set "invalid" for seed structure values */ 599219820Sjeff memset(*out, 0xff, 24); 600219820Sjeff *out += 24; 601219820Sjeff return; 602219820Sjeff} 603219820Sjeff 604219820Sjeffint i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk) 605219820Sjeff{ 606219820Sjeff return do_i2b_bio(out, pk, 0); 607219820Sjeff} 608219820Sjeff 609219820Sjeffint i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk) 610219820Sjeff{ 611219820Sjeff return do_i2b_bio(out, pk, 1); 612219820Sjeff} 613219820Sjeff 614219820Sjeff# ifndef OPENSSL_NO_RC4 615219820Sjeff 616219820Sjeffstatic int do_PVK_header(const unsigned char **in, unsigned int length, 617219820Sjeff int skip_magic, 618219820Sjeff unsigned int *psaltlen, unsigned int *pkeylen) 619219820Sjeff{ 620219820Sjeff const unsigned char *p = *in; 621219820Sjeff unsigned int pvk_magic, is_encrypted; 622219820Sjeff if (skip_magic) { 623219820Sjeff if (length < 20) { 624219820Sjeff PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT); 625219820Sjeff return 0; 626219820Sjeff } 627219820Sjeff length -= 20; 628219820Sjeff } else { 629219820Sjeff if (length < 24) { 630219820Sjeff PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT); 631219820Sjeff return 0; 632219820Sjeff } 633219820Sjeff length -= 24; 634219820Sjeff pvk_magic = read_ledword(&p); 635219820Sjeff if (pvk_magic != MS_PVKMAGIC) { 636219820Sjeff PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER); 637219820Sjeff return 0; 638219820Sjeff } 639219820Sjeff } 640219820Sjeff /* Skip reserved */ 641219820Sjeff p += 4; 642219820Sjeff /* 643219820Sjeff * keytype = 644219820Sjeff */ read_ledword(&p); 645219820Sjeff is_encrypted = read_ledword(&p); 646219820Sjeff *psaltlen = read_ledword(&p); 647219820Sjeff *pkeylen = read_ledword(&p); 648219820Sjeff 649219820Sjeff if (is_encrypted && !*psaltlen) { 650219820Sjeff PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER); 651219820Sjeff return 0; 652219820Sjeff } 653219820Sjeff 654219820Sjeff *in = p; 655219820Sjeff return 1; 656219820Sjeff} 657219820Sjeff 658219820Sjeffstatic int derive_pvk_key(unsigned char *key, 659219820Sjeff const unsigned char *salt, unsigned int saltlen, 660219820Sjeff const unsigned char *pass, int passlen) 661219820Sjeff{ 662219820Sjeff EVP_MD_CTX mctx; 663219820Sjeff int rv = 1; 664219820Sjeff EVP_MD_CTX_init(&mctx); 665219820Sjeff if (!EVP_DigestInit_ex(&mctx, EVP_sha1(), NULL) 666219820Sjeff || !EVP_DigestUpdate(&mctx, salt, saltlen) 667219820Sjeff || !EVP_DigestUpdate(&mctx, pass, passlen) 668219820Sjeff || !EVP_DigestFinal_ex(&mctx, key, NULL)) 669219820Sjeff rv = 0; 670219820Sjeff 671219820Sjeff EVP_MD_CTX_cleanup(&mctx); 672219820Sjeff return rv; 673219820Sjeff} 674219820Sjeff 675219820Sjeffstatic EVP_PKEY *do_PVK_body(const unsigned char **in, 676219820Sjeff unsigned int saltlen, unsigned int keylen, 677219820Sjeff pem_password_cb *cb, void *u) 678219820Sjeff{ 679219820Sjeff EVP_PKEY *ret = NULL; 680219820Sjeff const unsigned char *p = *in; 681219820Sjeff unsigned int magic; 682219820Sjeff unsigned char *enctmp = NULL, *q; 683219820Sjeff EVP_CIPHER_CTX cctx; 684219820Sjeff EVP_CIPHER_CTX_init(&cctx); 685219820Sjeff if (saltlen) { 686219820Sjeff char psbuf[PEM_BUFSIZE]; 687219820Sjeff unsigned char keybuf[20]; 688219820Sjeff int enctmplen, inlen; 689219820Sjeff if (cb) 690219820Sjeff inlen = cb(psbuf, PEM_BUFSIZE, 0, u); 691219820Sjeff else 692219820Sjeff inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); 693219820Sjeff if (inlen <= 0) { 694219820Sjeff PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_PASSWORD_READ); 695219820Sjeff return NULL; 696219820Sjeff } 697219820Sjeff enctmp = OPENSSL_malloc(keylen + 8); 698219820Sjeff if (!enctmp) { 699219820Sjeff PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE); 700219820Sjeff return NULL; 701219820Sjeff } 702219820Sjeff if (!derive_pvk_key(keybuf, p, saltlen, 703219820Sjeff (unsigned char *)psbuf, inlen)) 704219820Sjeff return NULL; 705219820Sjeff p += saltlen; 706219820Sjeff /* Copy BLOBHEADER across, decrypt rest */ 707219820Sjeff memcpy(enctmp, p, 8); 708219820Sjeff p += 8; 709219820Sjeff if (keylen < 8) { 710219820Sjeff PEMerr(PEM_F_DO_PVK_BODY, PEM_R_PVK_TOO_SHORT); 711219820Sjeff return NULL; 712219820Sjeff } 713219820Sjeff inlen = keylen - 8; 714219820Sjeff q = enctmp + 8; 715219820Sjeff if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL)) 716219820Sjeff goto err; 717219820Sjeff if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen)) 718219820Sjeff goto err; 719219820Sjeff if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen)) 720219820Sjeff goto err; 721219820Sjeff magic = read_ledword((const unsigned char **)&q); 722219820Sjeff if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { 723219820Sjeff q = enctmp + 8; 724219820Sjeff memset(keybuf + 5, 0, 11); 725219820Sjeff if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL)) 726219820Sjeff goto err; 727219820Sjeff OPENSSL_cleanse(keybuf, 20); 728219820Sjeff if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen)) 729219820Sjeff goto err; 730219820Sjeff if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen)) 731219820Sjeff goto err; 732219820Sjeff magic = read_ledword((const unsigned char **)&q); 733219820Sjeff if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { 734219820Sjeff PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT); 735219820Sjeff goto err; 736219820Sjeff } 737219820Sjeff } else 738219820Sjeff OPENSSL_cleanse(keybuf, 20); 739219820Sjeff p = enctmp; 740219820Sjeff } 741219820Sjeff 742219820Sjeff ret = b2i_PrivateKey(&p, keylen); 743219820Sjeff err: 744219820Sjeff EVP_CIPHER_CTX_cleanup(&cctx); 745219820Sjeff if (enctmp && saltlen) 746219820Sjeff OPENSSL_free(enctmp); 747219820Sjeff return ret; 748219820Sjeff} 749219820Sjeff 750219820SjeffEVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u) 751219820Sjeff{ 752219820Sjeff unsigned char pvk_hdr[24], *buf = NULL; 753219820Sjeff const unsigned char *p; 754219820Sjeff int buflen; 755219820Sjeff EVP_PKEY *ret = NULL; 756219820Sjeff unsigned int saltlen, keylen; 757219820Sjeff if (BIO_read(in, pvk_hdr, 24) != 24) { 758219820Sjeff PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT); 759219820Sjeff return NULL; 760219820Sjeff } 761219820Sjeff p = pvk_hdr; 762219820Sjeff 763219820Sjeff if (!do_PVK_header(&p, 24, 0, &saltlen, &keylen)) 764219820Sjeff return 0; 765219820Sjeff buflen = (int)keylen + saltlen; 766219820Sjeff buf = OPENSSL_malloc(buflen); 767219820Sjeff if (!buf) { 768219820Sjeff PEMerr(PEM_F_B2I_PVK_BIO, ERR_R_MALLOC_FAILURE); 769219820Sjeff return 0; 770219820Sjeff } 771219820Sjeff p = buf; 772219820Sjeff if (BIO_read(in, buf, buflen) != buflen) { 773219820Sjeff PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT); 774219820Sjeff goto err; 775219820Sjeff } 776219820Sjeff ret = do_PVK_body(&p, saltlen, keylen, cb, u); 777219820Sjeff 778219820Sjeff err: 779219820Sjeff if (buf) { 780219820Sjeff OPENSSL_cleanse(buf, buflen); 781219820Sjeff OPENSSL_free(buf); 782219820Sjeff } 783219820Sjeff return ret; 784219820Sjeff} 785219820Sjeff 786219820Sjeffstatic int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel, 787219820Sjeff pem_password_cb *cb, void *u) 788219820Sjeff{ 789219820Sjeff int outlen = 24, pklen; 790219820Sjeff unsigned char *p, *salt = NULL; 791219820Sjeff EVP_CIPHER_CTX cctx; 792219820Sjeff EVP_CIPHER_CTX_init(&cctx); 793219820Sjeff if (enclevel) 794219820Sjeff outlen += PVK_SALTLEN; 795219820Sjeff pklen = do_i2b(NULL, pk, 0); 796219820Sjeff if (pklen < 0) 797219820Sjeff return -1; 798219820Sjeff outlen += pklen; 799219820Sjeff if (!out) 800219820Sjeff return outlen; 801219820Sjeff if (*out) 802219820Sjeff p = *out; 803219820Sjeff else { 804219820Sjeff p = OPENSSL_malloc(outlen); 805219820Sjeff if (!p) { 806219820Sjeff PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE); 807219820Sjeff return -1; 808219820Sjeff } 809219820Sjeff *out = p; 810219820Sjeff } 811219820Sjeff 812219820Sjeff write_ledword(&p, MS_PVKMAGIC); 813219820Sjeff write_ledword(&p, 0); 814219820Sjeff if (pk->type == EVP_PKEY_DSA) 815219820Sjeff write_ledword(&p, MS_KEYTYPE_SIGN); 816219820Sjeff else 817219820Sjeff write_ledword(&p, MS_KEYTYPE_KEYX); 818219820Sjeff write_ledword(&p, enclevel ? 1 : 0); 819219820Sjeff write_ledword(&p, enclevel ? PVK_SALTLEN : 0); 820219820Sjeff write_ledword(&p, pklen); 821219820Sjeff if (enclevel) { 822219820Sjeff if (RAND_bytes(p, PVK_SALTLEN) <= 0) 823219820Sjeff goto error; 824219820Sjeff salt = p; 825219820Sjeff p += PVK_SALTLEN; 826219820Sjeff } 827219820Sjeff do_i2b(&p, pk, 0); 828219820Sjeff if (enclevel == 0) 829219820Sjeff return outlen; 830219820Sjeff else { 831219820Sjeff char psbuf[PEM_BUFSIZE]; 832219820Sjeff unsigned char keybuf[20]; 833219820Sjeff int enctmplen, inlen; 834219820Sjeff if (cb) 835219820Sjeff inlen = cb(psbuf, PEM_BUFSIZE, 1, u); 836219820Sjeff else 837219820Sjeff inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 1, u); 838219820Sjeff if (inlen <= 0) { 839219820Sjeff PEMerr(PEM_F_I2B_PVK, PEM_R_BAD_PASSWORD_READ); 840219820Sjeff goto error; 841219820Sjeff } 842219820Sjeff if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN, 843219820Sjeff (unsigned char *)psbuf, inlen)) 844219820Sjeff goto error; 845219820Sjeff if (enclevel == 1) 846219820Sjeff memset(keybuf + 5, 0, 11); 847219820Sjeff p = salt + PVK_SALTLEN + 8; 848219820Sjeff if (!EVP_EncryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL)) 849219820Sjeff goto error; 850219820Sjeff OPENSSL_cleanse(keybuf, 20); 851219820Sjeff if (!EVP_DecryptUpdate(&cctx, p, &enctmplen, p, pklen - 8)) 852219820Sjeff goto error; 853219820Sjeff if (!EVP_DecryptFinal_ex(&cctx, p + enctmplen, &enctmplen)) 854219820Sjeff goto error; 855219820Sjeff } 856219820Sjeff EVP_CIPHER_CTX_cleanup(&cctx); 857219820Sjeff return outlen; 858219820Sjeff 859219820Sjeff error: 860219820Sjeff EVP_CIPHER_CTX_cleanup(&cctx); 861219820Sjeff return -1; 862219820Sjeff} 863219820Sjeff 864219820Sjeffint i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, 865219820Sjeff pem_password_cb *cb, void *u) 866219820Sjeff{ 867219820Sjeff unsigned char *tmp = NULL; 868219820Sjeff int outlen, wrlen; 869219820Sjeff outlen = i2b_PVK(&tmp, pk, enclevel, cb, u); 870219820Sjeff if (outlen < 0) 871219820Sjeff return -1; 872219820Sjeff wrlen = BIO_write(out, tmp, outlen); 873219820Sjeff OPENSSL_free(tmp); 874219820Sjeff if (wrlen == outlen) { 875219820Sjeff PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE); 876219820Sjeff return outlen; 877219820Sjeff } 878219820Sjeff return -1; 879219820Sjeff} 880219820Sjeff 881219820Sjeff# endif 882219820Sjeff 883219820Sjeff#endif 884219820Sjeff