pvkfmt.c 22.8 KB
Newer Older
1
/*
R
Rich Salz 已提交
2
 * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
8 9
 */

10 11
/*
 * Support for PVK format keys and related structures (such a PUBLICKEYBLOB
12 13 14
 * and PRIVATEKEYBLOB).
 */

15
#include "internal/cryptlib.h"
16 17
#include <openssl/pem.h>
#include <openssl/rand.h>
18
#include <openssl/bn.h>
D
Dr. Stephen Henson 已提交
19
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
20 21
# include <openssl/dsa.h>
# include <openssl/rsa.h>
22

23 24
/*
 * Utility function: read a DWORD (4 byte unsigned integer) in little endian
25 26 27 28
 * format
 */

static unsigned int read_ledword(const unsigned char **in)
29 30 31 32 33 34 35 36 37 38 39 40 41 42
{
    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.
43 44 45
 */

static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
46
{
D
Dr. Stephen Henson 已提交
47 48
    *r = BN_lebin2bn(*in, nbyte, NULL);
    if (*r == NULL)
49
        return 0;
D
Dr. Stephen Henson 已提交
50 51
    *in += nbyte;
    return 1;
52
}
53 54 55

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

56 57 58 59 60 61
# define MS_PUBLICKEYBLOB        0x6
# define MS_PRIVATEKEYBLOB       0x7
# define MS_RSA1MAGIC            0x31415352L
# define MS_RSA2MAGIC            0x32415352L
# define MS_DSS1MAGIC            0x31535344L
# define MS_DSS2MAGIC            0x32535344L
62

63 64
# define MS_KEYALG_RSA_KEYX      0xa400
# define MS_KEYALG_DSS_SIGN      0x2200
65

66 67
# define MS_KEYTYPE_KEYX         0x1
# define MS_KEYTYPE_SIGN         0x2
68 69

/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
70
# define MS_PVKMAGIC             0xb0b5f11eL
71
/* Salt length for PVK files */
72
# define PVK_SALTLEN             0x10
73 74 75 76
/* Maximum length in PVK header */
# define PVK_MAX_KEYLEN          102400
/* Maximum salt length */
# define PVK_MAX_SALTLEN         10240
77

78
static EVP_PKEY *b2i_rsa(const unsigned char **in,
79
                         unsigned int bitlen, int ispub);
80
static EVP_PKEY *b2i_dss(const unsigned char **in,
81
                         unsigned int bitlen, int ispub);
82 83

static int do_blob_header(const unsigned char **in, unsigned int length,
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
                          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;
}
143 144

static unsigned int blob_length(unsigned bitlen, int isdss, int ispub)
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
{
    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;
    }

}
176 177

static EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length,
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
                        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)
193
        return b2i_dss(&p, bitlen, ispub);
194
    else
195
        return b2i_rsa(&p, bitlen, ispub);
196
}
197 198

static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
{
    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);
215
    if (buf == NULL) {
216 217 218 219 220 221 222 223 224 225
        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)
226
        ret = b2i_dss(&p, bitlen, ispub);
227
    else
228
        ret = b2i_rsa(&p, bitlen, ispub);
229 230

 err:
R
Rich Salz 已提交
231
    OPENSSL_free(buf);
232 233
    return ret;
}
234

235
static EVP_PKEY *b2i_dss(const unsigned char **in,
236 237 238 239 240 241 242
                         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 已提交
243 244 245
    BIGNUM *pbn = NULL, *qbn = NULL, *gbn = NULL, *priv_key = NULL;
    BIGNUM *pub_key = NULL;

246 247 248 249
    nbyte = (bitlen + 7) >> 3;

    dsa = DSA_new();
    ret = EVP_PKEY_new();
250
    if (dsa == NULL || ret == NULL)
251
        goto memerr;
M
Matt Caswell 已提交
252
    if (!read_lebn(&p, nbyte, &pbn))
253
        goto memerr;
M
Matt Caswell 已提交
254 255

    if (!read_lebn(&p, 20, &qbn))
256
        goto memerr;
M
Matt Caswell 已提交
257 258

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

261
    if (ispub) {
M
Matt Caswell 已提交
262
        if (!read_lebn(&p, nbyte, &pub_key))
263 264
            goto memerr;
    } else {
M
Matt Caswell 已提交
265
        if (!read_lebn(&p, 20, &priv_key))
266
            goto memerr;
M
Matt Caswell 已提交
267

268
        /* Calculate public key */
M
Matt Caswell 已提交
269 270
        pub_key = BN_new();
        if (pub_key == NULL)
271
            goto memerr;
272
        if ((ctx = BN_CTX_new()) == NULL)
273 274
            goto memerr;

M
Matt Caswell 已提交
275
        if (!BN_mod_exp(pub_key, gbn, priv_key, pbn, ctx))
276
            goto memerr;
M
Matt Caswell 已提交
277

278 279
        BN_CTX_free(ctx);
    }
M
Matt Caswell 已提交
280 281 282 283 284
    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;
285 286 287 288 289 290 291 292

    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 已提交
293
    DSA_free(dsa);
M
Matt Caswell 已提交
294 295 296 297 298
    BN_free(pbn);
    BN_free(qbn);
    BN_free(gbn);
    BN_free(pub_key);
    BN_free(priv_key);
R
Rich Salz 已提交
299
    EVP_PKEY_free(ret);
R
Rich Salz 已提交
300
    BN_CTX_free(ctx);
301 302
    return NULL;
}
303

304
static EVP_PKEY *b2i_rsa(const unsigned char **in,
305 306
                         unsigned int bitlen, int ispub)
{
R
Richard Levitte 已提交
307
    const unsigned char *pin = *in;
308
    EVP_PKEY *ret = NULL;
R
Richard Levitte 已提交
309
    BIGNUM *e = NULL, *n = NULL, *d = NULL;
310
    BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
311 312 313 314 315 316
    RSA *rsa = NULL;
    unsigned int nbyte, hnbyte;
    nbyte = (bitlen + 7) >> 3;
    hnbyte = (bitlen + 15) >> 4;
    rsa = RSA_new();
    ret = EVP_PKEY_new();
317
    if (rsa == NULL || ret == NULL)
318
        goto memerr;
R
Richard Levitte 已提交
319 320
    e = BN_new();
    if (e == NULL)
321
        goto memerr;
R
Richard Levitte 已提交
322
    if (!BN_set_word(e, read_ledword(&pin)))
323
        goto memerr;
R
Richard Levitte 已提交
324
    if (!read_lebn(&pin, nbyte, &n))
325 326
        goto memerr;
    if (!ispub) {
R
Richard Levitte 已提交
327
        if (!read_lebn(&pin, hnbyte, &p))
328
            goto memerr;
R
Richard Levitte 已提交
329
        if (!read_lebn(&pin, hnbyte, &q))
330
            goto memerr;
R
Richard Levitte 已提交
331
        if (!read_lebn(&pin, hnbyte, &dmp1))
332
            goto memerr;
R
Richard Levitte 已提交
333
        if (!read_lebn(&pin, hnbyte, &dmq1))
334
            goto memerr;
R
Richard Levitte 已提交
335
        if (!read_lebn(&pin, hnbyte, &iqmp))
336
            goto memerr;
R
Richard Levitte 已提交
337
        if (!read_lebn(&pin, nbyte, &d))
338
            goto memerr;
R
Richard Levitte 已提交
339 340
        RSA_set0_factors(rsa, p, q);
        RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
341
    }
342
    RSA_set0_key(rsa, n, e, d);
343 344 345

    EVP_PKEY_set1_RSA(ret, rsa);
    RSA_free(rsa);
R
Richard Levitte 已提交
346
    *in = pin;
347 348 349
    return ret;
 memerr:
    PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE);
350 351 352 353 354 355 356 357
    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 已提交
358
    RSA_free(rsa);
R
Rich Salz 已提交
359
    EVP_PKEY_free(ret);
360 361
    return NULL;
}
362 363

EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length)
364 365 366
{
    return do_b2i(in, length, 0);
}
367 368

EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length)
369 370 371
{
    return do_b2i(in, length, 1);
}
372 373

EVP_PKEY *b2i_PrivateKey_bio(BIO *in)
374 375 376
{
    return do_b2i_bio(in, 0);
}
377 378

EVP_PKEY *b2i_PublicKey_bio(BIO *in)
379 380 381
{
    return do_b2i_bio(in, 1);
}
382 383

static void write_ledword(unsigned char **out, unsigned int dw)
384 385 386 387 388 389 390 391
{
    unsigned char *p = *out;
    *p++ = dw & 0xff;
    *p++ = (dw >> 8) & 0xff;
    *p++ = (dw >> 16) & 0xff;
    *p++ = (dw >> 24) & 0xff;
    *out = p;
}
392 393

static void write_lebn(unsigned char **out, const BIGNUM *bn, int len)
394
{
D
Dr. Stephen Henson 已提交
395 396
    BN_bn2lebinpad(bn, *out, len);
    *out += len;
397
}
398 399 400 401 402 403

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);
404

405
static int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub)
406 407 408 409
{
    unsigned char *p;
    unsigned int bitlen, magic = 0, keyalg;
    int outlen, noinc = 0;
D
Dr. Stephen Henson 已提交
410 411 412
    int pktype = EVP_PKEY_id(pk);
    if (pktype == EVP_PKEY_DSA) {
        bitlen = check_bitlen_dsa(EVP_PKEY_get0_DSA(pk), ispub, &magic);
413
        keyalg = MS_KEYALG_DSS_SIGN;
D
Dr. Stephen Henson 已提交
414 415
    } else if (pktype == EVP_PKEY_RSA) {
        bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic);
416 417 418 419 420 421 422 423 424 425 426 427 428
        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);
429
        if (p == NULL)
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
            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 已提交
445
        write_dsa(&p, EVP_PKEY_get0_DSA(pk), ispub);
446
    else
D
Dr. Stephen Henson 已提交
447
        write_rsa(&p, EVP_PKEY_get0_RSA(pk), ispub);
448 449 450 451
    if (!noinc)
        *out += outlen;
    return outlen;
}
452 453

static int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub)
454 455 456 457 458 459 460 461 462 463 464 465
{
    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;
}
466 467

static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic)
468 469
{
    int bitlen;
470 471
    const BIGNUM *p = NULL, *q = NULL, *g = NULL;
    const BIGNUM *pub_key = NULL, *priv_key = NULL;
M
Matt Caswell 已提交
472 473 474 475 476 477

    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))
478 479
        goto badkey;
    if (ispub) {
M
Matt Caswell 已提交
480
        if (BN_num_bits(pub_key) > bitlen)
481 482 483
            goto badkey;
        *pmagic = MS_DSS1MAGIC;
    } else {
M
Matt Caswell 已提交
484
        if (BN_num_bits(priv_key) > 160)
485 486 487 488 489 490 491 492 493
            goto badkey;
        *pmagic = MS_DSS2MAGIC;
    }

    return bitlen;
 badkey:
    PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
    return 0;
}
494 495

static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
496 497
{
    int nbyte, hnbyte, bitlen;
498
    const BIGNUM *e;
R
Richard Levitte 已提交
499 500 501

    RSA_get0_key(rsa, &e, NULL, NULL);
    if (BN_num_bits(e) > 32)
502
        goto badkey;
R
Richard Levitte 已提交
503 504 505
    bitlen = RSA_bits(rsa);
    nbyte = RSA_size(rsa);
    hnbyte = (bitlen + 15) >> 4;
506 507 508 509
    if (ispub) {
        *pmagic = MS_RSA1MAGIC;
        return bitlen;
    } else {
510
        const BIGNUM *d, *p, *q, *iqmp, *dmp1, *dmq1;
R
Richard Levitte 已提交
511

512
        *pmagic = MS_RSA2MAGIC;
R
Richard Levitte 已提交
513

514 515 516
        /*
         * For private key each component must fit within nbyte or hnbyte.
         */
R
Richard Levitte 已提交
517 518
        RSA_get0_key(rsa, NULL, NULL, &d);
        if (BN_num_bytes(d) > nbyte)
519
            goto badkey;
R
Richard Levitte 已提交
520 521 522 523 524 525 526
        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))
527 528 529 530 531 532 533
            goto badkey;
    }
    return bitlen;
 badkey:
    PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
    return 0;
}
534 535

static void write_rsa(unsigned char **out, RSA *rsa, int ispub)
536 537
{
    int nbyte, hnbyte;
538
    const BIGNUM *n, *d, *e, *p, *q, *iqmp, *dmp1, *dmq1;
R
Richard Levitte 已提交
539 540 541 542 543 544

    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);
545 546
    if (ispub)
        return;
R
Richard Levitte 已提交
547 548 549 550 551 552 553 554
    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);
555 556
}

557
static void write_dsa(unsigned char **out, DSA *dsa, int ispub)
558 559
{
    int nbyte;
560 561
    const BIGNUM *p = NULL, *q = NULL, *g = NULL;
    const BIGNUM *pub_key = NULL, *priv_key = NULL;
M
Matt Caswell 已提交
562 563 564 565 566 567 568

    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);
569
    if (ispub)
M
Matt Caswell 已提交
570
        write_lebn(out, pub_key, nbyte);
571
    else
M
Matt Caswell 已提交
572
        write_lebn(out, priv_key, 20);
573 574 575 576 577
    /* Set "invalid" for seed structure values */
    memset(*out, 0xff, 24);
    *out += 24;
    return;
}
578 579

int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk)
580 581 582
{
    return do_i2b_bio(out, pk, 0);
}
583 584

int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk)
585 586 587
{
    return do_i2b_bio(out, pk, 1);
}
588

589
# ifndef OPENSSL_NO_RC4
D
Dr. Stephen Henson 已提交
590

591
static int do_PVK_header(const unsigned char **in, unsigned int length,
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
                         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);

622 623 624
    if (*pkeylen > PVK_MAX_KEYLEN || *psaltlen > PVK_MAX_SALTLEN)
        return 0;

625 626 627 628 629 630 631 632 633 634 635 636 637
    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 已提交
638
    EVP_MD_CTX *mctx = EVP_MD_CTX_new();
639
    int rv = 1;
640 641 642 643 644
    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))
645 646
        rv = 0;

647
    EVP_MD_CTX_free(mctx);
648 649
    return rv;
}
650 651

static EVP_PKEY *do_PVK_body(const unsigned char **in,
652 653 654 655 656 657 658
                             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 已提交
659

660
    EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new();
661 662 663 664 665 666 667 668 669 670
    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);
671
            goto err;
672 673
        }
        enctmp = OPENSSL_malloc(keylen + 8);
674
        if (enctmp == NULL) {
675
            PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);
676
            goto err;
677 678 679
        }
        if (!derive_pvk_key(keybuf, p, saltlen,
                            (unsigned char *)psbuf, inlen))
680
            goto err;
681 682 683 684 685 686
        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);
687
            goto err;
688 689 690
        }
        inlen = keylen - 8;
        q = enctmp + 8;
691
        if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
692
            goto err;
693
        if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
694
            goto err;
695
        if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen))
696 697 698 699 700
            goto err;
        magic = read_ledword((const unsigned char **)&q);
        if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) {
            q = enctmp + 8;
            memset(keybuf + 5, 0, 11);
701
            if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
702 703
                goto err;
            OPENSSL_cleanse(keybuf, 20);
704
            if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
705
                goto err;
706
            if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen))
707 708 709 710 711 712 713 714 715 716 717 718 719
                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:
720
    EVP_CIPHER_CTX_free(cctx);
R
Rich Salz 已提交
721
    OPENSSL_free(enctmp);
722 723
    return ret;
}
724 725

EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
{
    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);
742
    if (buf == NULL) {
743 744 745 746 747 748 749 750 751 752 753
        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 已提交
754
    OPENSSL_clear_free(buf, buflen);
755 756 757 758 759 760 761
    return ret;
}

static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
                   pem_password_cb *cb, void *u)
{
    int outlen = 24, pklen;
M
Matt Caswell 已提交
762
    unsigned char *p = NULL, *salt = NULL;
763
    EVP_CIPHER_CTX *cctx = NULL;
764 765 766 767 768 769
    if (enclevel)
        outlen += PVK_SALTLEN;
    pklen = do_i2b(NULL, pk, 0);
    if (pklen < 0)
        return -1;
    outlen += pklen;
770
    if (out == NULL)
771
        return outlen;
772
    if (*out != NULL) {
773
        p = *out;
774
    } else {
775
        p = OPENSSL_malloc(outlen);
776
        if (p == NULL) {
777 778 779 780 781
            PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE);
            return -1;
        }
    }

782 783
    cctx = EVP_CIPHER_CTX_new();
    if (cctx == NULL)
M
Matt Caswell 已提交
784
        goto error;
785

786 787
    write_ledword(&p, MS_PVKMAGIC);
    write_ledword(&p, 0);
D
Dr. Stephen Henson 已提交
788
    if (EVP_PKEY_id(pk) == EVP_PKEY_DSA)
789 790 791 792 793 794 795 796 797 798 799 800 801
        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);
802
    if (enclevel != 0) {
803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
        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;
820
        if (!EVP_EncryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
821 822
            goto error;
        OPENSSL_cleanse(keybuf, 20);
823
        if (!EVP_DecryptUpdate(cctx, p, &enctmplen, p, pklen - 8))
824
            goto error;
825
        if (!EVP_DecryptFinal_ex(cctx, p + enctmplen, &enctmplen))
826 827
            goto error;
    }
828

829
    EVP_CIPHER_CTX_free(cctx);
830 831 832 833

    if (*out == NULL)
        *out = p;

834 835 836
    return outlen;

 error:
837
    EVP_CIPHER_CTX_free(cctx);
M
Matt Caswell 已提交
838 839
    if (*out == NULL)
        OPENSSL_free(p);
840 841
    return -1;
}
842 843

int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel,
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
                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 已提交
861

D
Dr. Stephen Henson 已提交
862
#endif