pvkfmt.c 24.9 KB
Newer Older
1 2 3
/*
 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
 * 2005.
4 5 6 7 8 9 10 11 12
 */
/* ====================================================================
 * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    licensing@OpenSSL.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */

59 60
/*
 * Support for PVK format keys and related structures (such a PUBLICKEYBLOB
61 62 63
 * and PRIVATEKEYBLOB).
 */

64
#include "internal/cryptlib.h"
65 66
#include <openssl/pem.h>
#include <openssl/rand.h>
67
#include <openssl/bn.h>
D
Dr. Stephen Henson 已提交
68
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
69 70
# include <openssl/dsa.h>
# include <openssl/rsa.h>
71

72 73
/*
 * Utility function: read a DWORD (4 byte unsigned integer) in little endian
74 75 76 77
 * format
 */

static unsigned int read_ledword(const unsigned char **in)
78 79 80 81 82 83 84 85 86 87 88 89 90 91
{
    const unsigned char *p = *in;
    unsigned int ret;
    ret = *p++;
    ret |= (*p++ << 8);
    ret |= (*p++ << 16);
    ret |= (*p++ << 24);
    *in = p;
    return ret;
}

/*
 * Read a BIGNUM in little endian format. The docs say that this should take
 * up bitlen/8 bytes.
92 93 94
 */

static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
95
{
D
Dr. Stephen Henson 已提交
96 97
    *r = BN_lebin2bn(*in, nbyte, NULL);
    if (*r == NULL)
98
        return 0;
D
Dr. Stephen Henson 已提交
99 100
    *in += nbyte;
    return 1;
101
}
102 103 104

/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */

105 106 107 108 109 110
# define MS_PUBLICKEYBLOB        0x6
# define MS_PRIVATEKEYBLOB       0x7
# define MS_RSA1MAGIC            0x31415352L
# define MS_RSA2MAGIC            0x32415352L
# define MS_DSS1MAGIC            0x31535344L
# define MS_DSS2MAGIC            0x32535344L
111

112 113
# define MS_KEYALG_RSA_KEYX      0xa400
# define MS_KEYALG_DSS_SIGN      0x2200
114

115 116
# define MS_KEYTYPE_KEYX         0x1
# define MS_KEYTYPE_SIGN         0x2
117 118

/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
119
# define MS_PVKMAGIC             0xb0b5f11eL
120
/* Salt length for PVK files */
121
# define PVK_SALTLEN             0x10
122 123 124 125
/* Maximum length in PVK header */
# define PVK_MAX_KEYLEN          102400
/* Maximum salt length */
# define PVK_MAX_SALTLEN         10240
126

127
static EVP_PKEY *b2i_rsa(const unsigned char **in,
128
                         unsigned int bitlen, int ispub);
129
static EVP_PKEY *b2i_dss(const unsigned char **in,
130
                         unsigned int bitlen, int ispub);
131 132

static int do_blob_header(const unsigned char **in, unsigned int length,
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
                          unsigned int *pmagic, unsigned int *pbitlen,
                          int *pisdss, int *pispub)
{
    const unsigned char *p = *in;
    if (length < 16)
        return 0;
    /* bType */
    if (*p == MS_PUBLICKEYBLOB) {
        if (*pispub == 0) {
            PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
            return 0;
        }
        *pispub = 1;
    } else if (*p == MS_PRIVATEKEYBLOB) {
        if (*pispub == 1) {
            PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
            return 0;
        }
        *pispub = 0;
    } else
        return 0;
    p++;
    /* Version */
    if (*p++ != 0x2) {
        PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_VERSION_NUMBER);
        return 0;
    }
    /* Ignore reserved, aiKeyAlg */
    p += 6;
    *pmagic = read_ledword(&p);
    *pbitlen = read_ledword(&p);
    *pisdss = 0;
    switch (*pmagic) {

    case MS_DSS1MAGIC:
        *pisdss = 1;
    case MS_RSA1MAGIC:
        if (*pispub == 0) {
            PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
            return 0;
        }
        break;

    case MS_DSS2MAGIC:
        *pisdss = 1;
    case MS_RSA2MAGIC:
        if (*pispub == 1) {
            PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
            return 0;
        }
        break;

    default:
        PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_MAGIC_NUMBER);
        return -1;
    }
    *in = p;
    return 1;
}
192 193

static unsigned int blob_length(unsigned bitlen, int isdss, int ispub)
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
{
    unsigned int nbyte, hnbyte;
    nbyte = (bitlen + 7) >> 3;
    hnbyte = (bitlen + 15) >> 4;
    if (isdss) {

        /*
         * Expected length: 20 for q + 3 components bitlen each + 24 for seed
         * structure.
         */
        if (ispub)
            return 44 + 3 * nbyte;
        /*
         * Expected length: 20 for q, priv, 2 bitlen components + 24 for seed
         * structure.
         */
        else
            return 64 + 2 * nbyte;
    } else {
        /* Expected length: 4 for 'e' + 'n' */
        if (ispub)
            return 4 + nbyte;
        else
            /*
             * Expected length: 4 for 'e' and 7 other components. 2
             * components are bitlen size, 5 are bitlen/2
             */
            return 4 + 2 * nbyte + 5 * hnbyte;
    }

}
225 226

static EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length,
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
                        int ispub)
{
    const unsigned char *p = *in;
    unsigned int bitlen, magic;
    int isdss;
    if (do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0) {
        PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_HEADER_PARSE_ERROR);
        return NULL;
    }
    length -= 16;
    if (length < blob_length(bitlen, isdss, ispub)) {
        PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_TOO_SHORT);
        return NULL;
    }
    if (isdss)
242
        return b2i_dss(&p, bitlen, ispub);
243
    else
244
        return b2i_rsa(&p, bitlen, ispub);
245
}
246 247

static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
{
    const unsigned char *p;
    unsigned char hdr_buf[16], *buf = NULL;
    unsigned int bitlen, magic, length;
    int isdss;
    EVP_PKEY *ret = NULL;
    if (BIO_read(in, hdr_buf, 16) != 16) {
        PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT);
        return NULL;
    }
    p = hdr_buf;
    if (do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0)
        return NULL;

    length = blob_length(bitlen, isdss, ispub);
    buf = OPENSSL_malloc(length);
264
    if (buf == NULL) {
265 266 267 268 269 270 271 272 273 274
        PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    p = buf;
    if (BIO_read(in, buf, length) != (int)length) {
        PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT);
        goto err;
    }

    if (isdss)
275
        ret = b2i_dss(&p, bitlen, ispub);
276
    else
277
        ret = b2i_rsa(&p, bitlen, ispub);
278 279

 err:
R
Rich Salz 已提交
280
    OPENSSL_free(buf);
281 282
    return ret;
}
283

284
static EVP_PKEY *b2i_dss(const unsigned char **in,
285 286 287 288 289 290 291
                         unsigned int bitlen, int ispub)
{
    const unsigned char *p = *in;
    EVP_PKEY *ret = NULL;
    DSA *dsa = NULL;
    BN_CTX *ctx = NULL;
    unsigned int nbyte;
M
Matt Caswell 已提交
292 293 294
    BIGNUM *pbn = NULL, *qbn = NULL, *gbn = NULL, *priv_key = NULL;
    BIGNUM *pub_key = NULL;

295 296 297 298
    nbyte = (bitlen + 7) >> 3;

    dsa = DSA_new();
    ret = EVP_PKEY_new();
299
    if (dsa == NULL || ret == NULL)
300
        goto memerr;
M
Matt Caswell 已提交
301
    if (!read_lebn(&p, nbyte, &pbn))
302
        goto memerr;
M
Matt Caswell 已提交
303 304

    if (!read_lebn(&p, 20, &qbn))
305
        goto memerr;
M
Matt Caswell 已提交
306 307

    if (!read_lebn(&p, nbyte, &gbn))
308
        goto memerr;
M
Matt Caswell 已提交
309

310
    if (ispub) {
M
Matt Caswell 已提交
311
        if (!read_lebn(&p, nbyte, &pub_key))
312 313
            goto memerr;
    } else {
M
Matt Caswell 已提交
314
        if (!read_lebn(&p, 20, &priv_key))
315
            goto memerr;
M
Matt Caswell 已提交
316

317
        /* Calculate public key */
M
Matt Caswell 已提交
318 319
        pub_key = BN_new();
        if (pub_key == NULL)
320
            goto memerr;
321
        if ((ctx = BN_CTX_new()) == NULL)
322 323
            goto memerr;

M
Matt Caswell 已提交
324
        if (!BN_mod_exp(pub_key, gbn, priv_key, pbn, ctx))
325
            goto memerr;
M
Matt Caswell 已提交
326

327 328
        BN_CTX_free(ctx);
    }
M
Matt Caswell 已提交
329 330 331 332 333
    if (!DSA_set0_pqg(dsa, pbn, qbn, gbn))
        goto memerr;
    pbn = qbn = gbn = NULL;
    if (!DSA_set0_key(dsa, pub_key, priv_key))
        goto memerr;
334 335 336 337 338 339 340 341

    EVP_PKEY_set1_DSA(ret, dsa);
    DSA_free(dsa);
    *in = p;
    return ret;

 memerr:
    PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE);
R
Rich Salz 已提交
342
    DSA_free(dsa);
M
Matt Caswell 已提交
343 344 345 346 347
    BN_free(pbn);
    BN_free(qbn);
    BN_free(gbn);
    BN_free(pub_key);
    BN_free(priv_key);
R
Rich Salz 已提交
348
    EVP_PKEY_free(ret);
R
Rich Salz 已提交
349
    BN_CTX_free(ctx);
350 351
    return NULL;
}
352

353
static EVP_PKEY *b2i_rsa(const unsigned char **in,
354 355
                         unsigned int bitlen, int ispub)
{
R
Richard Levitte 已提交
356
    const unsigned char *pin = *in;
357
    EVP_PKEY *ret = NULL;
R
Richard Levitte 已提交
358
    BIGNUM *e = NULL, *n = NULL, *d = NULL;
359
    BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
360 361 362 363 364 365
    RSA *rsa = NULL;
    unsigned int nbyte, hnbyte;
    nbyte = (bitlen + 7) >> 3;
    hnbyte = (bitlen + 15) >> 4;
    rsa = RSA_new();
    ret = EVP_PKEY_new();
366
    if (rsa == NULL || ret == NULL)
367
        goto memerr;
R
Richard Levitte 已提交
368 369
    e = BN_new();
    if (e == NULL)
370
        goto memerr;
R
Richard Levitte 已提交
371
    if (!BN_set_word(e, read_ledword(&pin)))
372
        goto memerr;
R
Richard Levitte 已提交
373
    if (!read_lebn(&pin, nbyte, &n))
374 375
        goto memerr;
    if (!ispub) {
R
Richard Levitte 已提交
376
        if (!read_lebn(&pin, hnbyte, &p))
377
            goto memerr;
R
Richard Levitte 已提交
378
        if (!read_lebn(&pin, hnbyte, &q))
379
            goto memerr;
R
Richard Levitte 已提交
380
        if (!read_lebn(&pin, hnbyte, &dmp1))
381
            goto memerr;
R
Richard Levitte 已提交
382
        if (!read_lebn(&pin, hnbyte, &dmq1))
383
            goto memerr;
R
Richard Levitte 已提交
384
        if (!read_lebn(&pin, hnbyte, &iqmp))
385
            goto memerr;
R
Richard Levitte 已提交
386
        if (!read_lebn(&pin, nbyte, &d))
387
            goto memerr;
R
Richard Levitte 已提交
388 389
        RSA_set0_factors(rsa, p, q);
        RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
390
    }
R
Richard Levitte 已提交
391
    RSA_set0_key(rsa, e, n, d);
392 393 394

    EVP_PKEY_set1_RSA(ret, rsa);
    RSA_free(rsa);
R
Richard Levitte 已提交
395
    *in = pin;
396 397 398
    return ret;
 memerr:
    PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE);
399 400 401 402 403 404 405 406
    BN_free(e);
    BN_free(n);
    BN_free(p);
    BN_free(q);
    BN_free(dmp1);
    BN_free(dmq1);
    BN_free(iqmp);
    BN_free(d);
R
Rich Salz 已提交
407
    RSA_free(rsa);
R
Rich Salz 已提交
408
    EVP_PKEY_free(ret);
409 410
    return NULL;
}
411 412

EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length)
413 414 415
{
    return do_b2i(in, length, 0);
}
416 417

EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length)
418 419 420
{
    return do_b2i(in, length, 1);
}
421 422

EVP_PKEY *b2i_PrivateKey_bio(BIO *in)
423 424 425
{
    return do_b2i_bio(in, 0);
}
426 427

EVP_PKEY *b2i_PublicKey_bio(BIO *in)
428 429 430
{
    return do_b2i_bio(in, 1);
}
431 432

static void write_ledword(unsigned char **out, unsigned int dw)
433 434 435 436 437 438 439 440
{
    unsigned char *p = *out;
    *p++ = dw & 0xff;
    *p++ = (dw >> 8) & 0xff;
    *p++ = (dw >> 16) & 0xff;
    *p++ = (dw >> 24) & 0xff;
    *out = p;
}
441 442

static void write_lebn(unsigned char **out, const BIGNUM *bn, int len)
443
{
D
Dr. Stephen Henson 已提交
444 445
    BN_bn2lebinpad(bn, *out, len);
    *out += len;
446
}
447 448 449 450 451 452

static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *magic);
static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *magic);

static void write_rsa(unsigned char **out, RSA *rsa, int ispub);
static void write_dsa(unsigned char **out, DSA *dsa, int ispub);
453

454
static int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub)
455 456 457 458
{
    unsigned char *p;
    unsigned int bitlen, magic = 0, keyalg;
    int outlen, noinc = 0;
D
Dr. Stephen Henson 已提交
459 460 461
    int pktype = EVP_PKEY_id(pk);
    if (pktype == EVP_PKEY_DSA) {
        bitlen = check_bitlen_dsa(EVP_PKEY_get0_DSA(pk), ispub, &magic);
462
        keyalg = MS_KEYALG_DSS_SIGN;
D
Dr. Stephen Henson 已提交
463 464
    } else if (pktype == EVP_PKEY_RSA) {
        bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic);
465 466 467 468 469 470 471 472 473 474 475 476 477
        keyalg = MS_KEYALG_RSA_KEYX;
    } else
        return -1;
    if (bitlen == 0)
        return -1;
    outlen = 16 + blob_length(bitlen,
                              keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub);
    if (out == NULL)
        return outlen;
    if (*out)
        p = *out;
    else {
        p = OPENSSL_malloc(outlen);
478
        if (p == NULL)
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
            return -1;
        *out = p;
        noinc = 1;
    }
    if (ispub)
        *p++ = MS_PUBLICKEYBLOB;
    else
        *p++ = MS_PRIVATEKEYBLOB;
    *p++ = 0x2;
    *p++ = 0;
    *p++ = 0;
    write_ledword(&p, keyalg);
    write_ledword(&p, magic);
    write_ledword(&p, bitlen);
    if (keyalg == MS_KEYALG_DSS_SIGN)
D
Dr. Stephen Henson 已提交
494
        write_dsa(&p, EVP_PKEY_get0_DSA(pk), ispub);
495
    else
D
Dr. Stephen Henson 已提交
496
        write_rsa(&p, EVP_PKEY_get0_RSA(pk), ispub);
497 498 499 500
    if (!noinc)
        *out += outlen;
    return outlen;
}
501 502

static int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub)
503 504 505 506 507 508 509 510 511 512 513 514
{
    unsigned char *tmp = NULL;
    int outlen, wrlen;
    outlen = do_i2b(&tmp, pk, ispub);
    if (outlen < 0)
        return -1;
    wrlen = BIO_write(out, tmp, outlen);
    OPENSSL_free(tmp);
    if (wrlen == outlen)
        return outlen;
    return -1;
}
515 516

static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic)
517 518
{
    int bitlen;
M
Matt Caswell 已提交
519 520 521 522 523 524 525
    BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;

    DSA_get0_pqg(dsa, &p, &q, &g);
    DSA_get0_key(dsa, &pub_key, &priv_key);
    bitlen = BN_num_bits(p);
    if ((bitlen & 7) || (BN_num_bits(q) != 160)
        || (BN_num_bits(g) > bitlen))
526 527
        goto badkey;
    if (ispub) {
M
Matt Caswell 已提交
528
        if (BN_num_bits(pub_key) > bitlen)
529 530 531
            goto badkey;
        *pmagic = MS_DSS1MAGIC;
    } else {
M
Matt Caswell 已提交
532
        if (BN_num_bits(priv_key) > 160)
533 534 535 536 537 538 539 540 541
            goto badkey;
        *pmagic = MS_DSS2MAGIC;
    }

    return bitlen;
 badkey:
    PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
    return 0;
}
542 543

static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
544 545
{
    int nbyte, hnbyte, bitlen;
R
Richard Levitte 已提交
546 547 548 549
    BIGNUM *e;

    RSA_get0_key(rsa, &e, NULL, NULL);
    if (BN_num_bits(e) > 32)
550
        goto badkey;
R
Richard Levitte 已提交
551 552 553
    bitlen = RSA_bits(rsa);
    nbyte = RSA_size(rsa);
    hnbyte = (bitlen + 15) >> 4;
554 555 556 557
    if (ispub) {
        *pmagic = MS_RSA1MAGIC;
        return bitlen;
    } else {
R
Richard Levitte 已提交
558 559
        BIGNUM *d, *p, *q, *iqmp, *dmp1, *dmq1;

560
        *pmagic = MS_RSA2MAGIC;
R
Richard Levitte 已提交
561

562 563 564
        /*
         * For private key each component must fit within nbyte or hnbyte.
         */
R
Richard Levitte 已提交
565 566
        RSA_get0_key(rsa, NULL, NULL, &d);
        if (BN_num_bytes(d) > nbyte)
567
            goto badkey;
R
Richard Levitte 已提交
568 569 570 571 572 573 574
        RSA_get0_factors(rsa, &p, &q);
        RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
        if ((BN_num_bytes(iqmp) > hnbyte)
            || (BN_num_bytes(p) > hnbyte)
            || (BN_num_bytes(q) > hnbyte)
            || (BN_num_bytes(dmp1) > hnbyte)
            || (BN_num_bytes(dmq1) > hnbyte))
575 576 577 578 579 580 581
            goto badkey;
    }
    return bitlen;
 badkey:
    PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
    return 0;
}
582 583

static void write_rsa(unsigned char **out, RSA *rsa, int ispub)
584 585
{
    int nbyte, hnbyte;
R
Richard Levitte 已提交
586 587 588 589 590 591 592
    BIGNUM *n, *d, *e, *p, *q, *iqmp, *dmp1, *dmq1;

    nbyte = RSA_size(rsa);
    hnbyte = (RSA_bits(rsa) + 15) >> 4;
    RSA_get0_key(rsa, &e, &n, &d);
    write_lebn(out, e, 4);
    write_lebn(out, n, -1);
593 594
    if (ispub)
        return;
R
Richard Levitte 已提交
595 596 597 598 599 600 601 602
    RSA_get0_factors(rsa, &p, &q);
    RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
    write_lebn(out, p, hnbyte);
    write_lebn(out, q, hnbyte);
    write_lebn(out, dmp1, hnbyte);
    write_lebn(out, dmq1, hnbyte);
    write_lebn(out, iqmp, hnbyte);
    write_lebn(out, d, nbyte);
603 604
}

605
static void write_dsa(unsigned char **out, DSA *dsa, int ispub)
606 607
{
    int nbyte;
M
Matt Caswell 已提交
608 609 610 611 612 613 614 615
    BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;

    DSA_get0_pqg(dsa, &p, &q, &g);
    DSA_get0_key(dsa, &pub_key, &priv_key);
    nbyte = BN_num_bytes(p);
    write_lebn(out, p, nbyte);
    write_lebn(out, q, 20);
    write_lebn(out, g, nbyte);
616
    if (ispub)
M
Matt Caswell 已提交
617
        write_lebn(out, pub_key, nbyte);
618
    else
M
Matt Caswell 已提交
619
        write_lebn(out, priv_key, 20);
620 621 622 623 624
    /* Set "invalid" for seed structure values */
    memset(*out, 0xff, 24);
    *out += 24;
    return;
}
625 626

int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk)
627 628 629
{
    return do_i2b_bio(out, pk, 0);
}
630 631

int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk)
632 633 634
{
    return do_i2b_bio(out, pk, 1);
}
635

636
# ifndef OPENSSL_NO_RC4
D
Dr. Stephen Henson 已提交
637

638
static int do_PVK_header(const unsigned char **in, unsigned int length,
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668
                         int skip_magic,
                         unsigned int *psaltlen, unsigned int *pkeylen)
{
    const unsigned char *p = *in;
    unsigned int pvk_magic, is_encrypted;
    if (skip_magic) {
        if (length < 20) {
            PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
            return 0;
        }
    } else {
        if (length < 24) {
            PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
            return 0;
        }
        pvk_magic = read_ledword(&p);
        if (pvk_magic != MS_PVKMAGIC) {
            PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER);
            return 0;
        }
    }
    /* Skip reserved */
    p += 4;
    /*
     * keytype =
     */ read_ledword(&p);
    is_encrypted = read_ledword(&p);
    *psaltlen = read_ledword(&p);
    *pkeylen = read_ledword(&p);

669 670 671
    if (*pkeylen > PVK_MAX_KEYLEN || *psaltlen > PVK_MAX_SALTLEN)
        return 0;

672 673 674 675 676 677 678 679 680 681 682 683 684
    if (is_encrypted && !*psaltlen) {
        PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER);
        return 0;
    }

    *in = p;
    return 1;
}

static int derive_pvk_key(unsigned char *key,
                          const unsigned char *salt, unsigned int saltlen,
                          const unsigned char *pass, int passlen)
{
R
Richard Levitte 已提交
685
    EVP_MD_CTX *mctx = EVP_MD_CTX_new();
686
    int rv = 1;
687 688 689 690 691
    if (mctx == NULL
        || !EVP_DigestInit_ex(mctx, EVP_sha1(), NULL)
        || !EVP_DigestUpdate(mctx, salt, saltlen)
        || !EVP_DigestUpdate(mctx, pass, passlen)
        || !EVP_DigestFinal_ex(mctx, key, NULL))
692 693
        rv = 0;

694
    EVP_MD_CTX_free(mctx);
695 696
    return rv;
}
697 698

static EVP_PKEY *do_PVK_body(const unsigned char **in,
699 700 701 702 703 704 705
                             unsigned int saltlen, unsigned int keylen,
                             pem_password_cb *cb, void *u)
{
    EVP_PKEY *ret = NULL;
    const unsigned char *p = *in;
    unsigned int magic;
    unsigned char *enctmp = NULL, *q;
R
Rich Salz 已提交
706

707
    EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new();
708 709 710 711 712 713 714 715 716 717
    if (saltlen) {
        char psbuf[PEM_BUFSIZE];
        unsigned char keybuf[20];
        int enctmplen, inlen;
        if (cb)
            inlen = cb(psbuf, PEM_BUFSIZE, 0, u);
        else
            inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
        if (inlen <= 0) {
            PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_PASSWORD_READ);
718
            goto err;
719 720
        }
        enctmp = OPENSSL_malloc(keylen + 8);
721
        if (enctmp == NULL) {
722
            PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);
723
            goto err;
724 725 726
        }
        if (!derive_pvk_key(keybuf, p, saltlen,
                            (unsigned char *)psbuf, inlen))
727
            goto err;
728 729 730 731 732 733
        p += saltlen;
        /* Copy BLOBHEADER across, decrypt rest */
        memcpy(enctmp, p, 8);
        p += 8;
        if (keylen < 8) {
            PEMerr(PEM_F_DO_PVK_BODY, PEM_R_PVK_TOO_SHORT);
734
            goto err;
735 736 737
        }
        inlen = keylen - 8;
        q = enctmp + 8;
738
        if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
739
            goto err;
740
        if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
741
            goto err;
742
        if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen))
743 744 745 746 747
            goto err;
        magic = read_ledword((const unsigned char **)&q);
        if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) {
            q = enctmp + 8;
            memset(keybuf + 5, 0, 11);
748
            if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
749 750
                goto err;
            OPENSSL_cleanse(keybuf, 20);
751
            if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
752
                goto err;
753
            if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen))
754 755 756 757 758 759 760 761 762 763 764 765 766
                goto err;
            magic = read_ledword((const unsigned char **)&q);
            if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) {
                PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT);
                goto err;
            }
        } else
            OPENSSL_cleanse(keybuf, 20);
        p = enctmp;
    }

    ret = b2i_PrivateKey(&p, keylen);
 err:
767
    EVP_CIPHER_CTX_free(cctx);
R
Rich Salz 已提交
768
    OPENSSL_free(enctmp);
769 770
    return ret;
}
771 772

EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
{
    unsigned char pvk_hdr[24], *buf = NULL;
    const unsigned char *p;
    int buflen;
    EVP_PKEY *ret = NULL;
    unsigned int saltlen, keylen;
    if (BIO_read(in, pvk_hdr, 24) != 24) {
        PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT);
        return NULL;
    }
    p = pvk_hdr;

    if (!do_PVK_header(&p, 24, 0, &saltlen, &keylen))
        return 0;
    buflen = (int)keylen + saltlen;
    buf = OPENSSL_malloc(buflen);
789
    if (buf == NULL) {
790 791 792 793 794 795 796 797 798 799 800
        PEMerr(PEM_F_B2I_PVK_BIO, ERR_R_MALLOC_FAILURE);
        return 0;
    }
    p = buf;
    if (BIO_read(in, buf, buflen) != buflen) {
        PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT);
        goto err;
    }
    ret = do_PVK_body(&p, saltlen, keylen, cb, u);

 err:
R
Rich Salz 已提交
801
    OPENSSL_clear_free(buf, buflen);
802 803 804 805 806 807 808 809
    return ret;
}

static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
                   pem_password_cb *cb, void *u)
{
    int outlen = 24, pklen;
    unsigned char *p, *salt = NULL;
810
    EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new();
811 812 813 814 815 816 817 818 819 820 821 822
    if (enclevel)
        outlen += PVK_SALTLEN;
    pklen = do_i2b(NULL, pk, 0);
    if (pklen < 0)
        return -1;
    outlen += pklen;
    if (!out)
        return outlen;
    if (*out)
        p = *out;
    else {
        p = OPENSSL_malloc(outlen);
823
        if (p == NULL) {
824 825 826 827 828 829 830 831
            PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE);
            return -1;
        }
        *out = p;
    }

    write_ledword(&p, MS_PVKMAGIC);
    write_ledword(&p, 0);
D
Dr. Stephen Henson 已提交
832
    if (EVP_PKEY_id(pk) == EVP_PKEY_DSA)
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
        write_ledword(&p, MS_KEYTYPE_SIGN);
    else
        write_ledword(&p, MS_KEYTYPE_KEYX);
    write_ledword(&p, enclevel ? 1 : 0);
    write_ledword(&p, enclevel ? PVK_SALTLEN : 0);
    write_ledword(&p, pklen);
    if (enclevel) {
        if (RAND_bytes(p, PVK_SALTLEN) <= 0)
            goto error;
        salt = p;
        p += PVK_SALTLEN;
    }
    do_i2b(&p, pk, 0);
    if (enclevel == 0)
        return outlen;
    else {
        char psbuf[PEM_BUFSIZE];
        unsigned char keybuf[20];
        int enctmplen, inlen;
        if (cb)
            inlen = cb(psbuf, PEM_BUFSIZE, 1, u);
        else
            inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 1, u);
        if (inlen <= 0) {
            PEMerr(PEM_F_I2B_PVK, PEM_R_BAD_PASSWORD_READ);
            goto error;
        }
        if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN,
                            (unsigned char *)psbuf, inlen))
            goto error;
        if (enclevel == 1)
            memset(keybuf + 5, 0, 11);
        p = salt + PVK_SALTLEN + 8;
866
        if (!EVP_EncryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
867 868
            goto error;
        OPENSSL_cleanse(keybuf, 20);
869
        if (!EVP_DecryptUpdate(cctx, p, &enctmplen, p, pklen - 8))
870
            goto error;
871
        if (!EVP_DecryptFinal_ex(cctx, p + enctmplen, &enctmplen))
872 873
            goto error;
    }
874
    EVP_CIPHER_CTX_free(cctx);
875 876 877
    return outlen;

 error:
878
    EVP_CIPHER_CTX_free(cctx);
879 880
    return -1;
}
881 882

int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel,
883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899
                pem_password_cb *cb, void *u)
{
    unsigned char *tmp = NULL;
    int outlen, wrlen;
    outlen = i2b_PVK(&tmp, pk, enclevel, cb, u);
    if (outlen < 0)
        return -1;
    wrlen = BIO_write(out, tmp, outlen);
    OPENSSL_free(tmp);
    if (wrlen == outlen) {
        PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE);
        return outlen;
    }
    return -1;
}

# endif
D
Dr. Stephen Henson 已提交
900

D
Dr. Stephen Henson 已提交
901
#endif