pvkfmt.c 23.5 KB
Newer Older
1
/*
H
HJ 已提交
2
 * Copyright 2005-2020 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
{
    const unsigned char *p = *in;
    unsigned int ret;
H
HJ 已提交
32 33 34 35
    ret = (unsigned int)*p++;
    ret |= (unsigned int)*p++ << 8;
    ret |= (unsigned int)*p++ << 16;
    ret |= (unsigned int)*p++ << 24;
36 37 38 39 40 41 42
    *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

D
Dr. Stephen Henson 已提交
69 70 71
/* Maximum length of a blob after header */
# define BLOB_MAX_LENGTH          102400

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

81
static EVP_PKEY *b2i_rsa(const unsigned char **in,
82
                         unsigned int bitlen, int ispub);
83
static EVP_PKEY *b2i_dss(const unsigned char **in,
84
                         unsigned int bitlen, int ispub);
85 86

static int do_blob_header(const unsigned char **in, unsigned int length,
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
                          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;
B
Bernd Edlinger 已提交
123
        /* fall thru */
124 125 126 127 128 129 130 131 132
    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;
B
Bernd Edlinger 已提交
133
        /* fall thru */
134 135 136 137 138 139 140 141 142 143 144 145 146 147
    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;
}
148 149

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

}
181 182

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

static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
{
    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);
D
Dr. Stephen Henson 已提交
219 220 221 222
    if (length > BLOB_MAX_LENGTH) {
        PEMerr(PEM_F_DO_B2I_BIO, PEM_R_HEADER_TOO_LONG);
        return NULL;
    }
223
    buf = OPENSSL_malloc(length);
224
    if (buf == NULL) {
225 226 227 228 229 230 231 232 233 234
        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)
235
        ret = b2i_dss(&p, bitlen, ispub);
236
    else
237
        ret = b2i_rsa(&p, bitlen, ispub);
238 239

 err:
R
Rich Salz 已提交
240
    OPENSSL_free(buf);
241 242
    return ret;
}
243

244
static EVP_PKEY *b2i_dss(const unsigned char **in,
245 246 247 248 249 250 251
                         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 已提交
252 253 254
    BIGNUM *pbn = NULL, *qbn = NULL, *gbn = NULL, *priv_key = NULL;
    BIGNUM *pub_key = NULL;

255 256 257 258
    nbyte = (bitlen + 7) >> 3;

    dsa = DSA_new();
    ret = EVP_PKEY_new();
259
    if (dsa == NULL || ret == NULL)
260
        goto memerr;
M
Matt Caswell 已提交
261
    if (!read_lebn(&p, nbyte, &pbn))
262
        goto memerr;
M
Matt Caswell 已提交
263 264

    if (!read_lebn(&p, 20, &qbn))
265
        goto memerr;
M
Matt Caswell 已提交
266 267

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

270
    if (ispub) {
M
Matt Caswell 已提交
271
        if (!read_lebn(&p, nbyte, &pub_key))
272 273
            goto memerr;
    } else {
M
Matt Caswell 已提交
274
        if (!read_lebn(&p, 20, &priv_key))
275
            goto memerr;
M
Matt Caswell 已提交
276

277 278 279
        /* Set constant time flag before public key calculation */
        BN_set_flags(priv_key, BN_FLG_CONSTTIME);

280
        /* Calculate public key */
M
Matt Caswell 已提交
281 282
        pub_key = BN_new();
        if (pub_key == NULL)
283
            goto memerr;
284
        if ((ctx = BN_CTX_new()) == NULL)
285 286
            goto memerr;

M
Matt Caswell 已提交
287
        if (!BN_mod_exp(pub_key, gbn, priv_key, pbn, ctx))
288
            goto memerr;
M
Matt Caswell 已提交
289

290
        BN_CTX_free(ctx);
291
        ctx = NULL;
292
    }
M
Matt Caswell 已提交
293 294 295 296 297
    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;
298
    pub_key = priv_key = NULL;
299

300 301
    if (!EVP_PKEY_set1_DSA(ret, dsa))
        goto memerr;
302 303 304 305 306 307
    DSA_free(dsa);
    *in = p;
    return ret;

 memerr:
    PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE);
R
Rich Salz 已提交
308
    DSA_free(dsa);
M
Matt Caswell 已提交
309 310 311 312 313
    BN_free(pbn);
    BN_free(qbn);
    BN_free(gbn);
    BN_free(pub_key);
    BN_free(priv_key);
R
Rich Salz 已提交
314
    EVP_PKEY_free(ret);
R
Rich Salz 已提交
315
    BN_CTX_free(ctx);
316 317
    return NULL;
}
318

319
static EVP_PKEY *b2i_rsa(const unsigned char **in,
320 321
                         unsigned int bitlen, int ispub)
{
R
Richard Levitte 已提交
322
    const unsigned char *pin = *in;
323
    EVP_PKEY *ret = NULL;
R
Richard Levitte 已提交
324
    BIGNUM *e = NULL, *n = NULL, *d = NULL;
325
    BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
326 327 328 329 330 331
    RSA *rsa = NULL;
    unsigned int nbyte, hnbyte;
    nbyte = (bitlen + 7) >> 3;
    hnbyte = (bitlen + 15) >> 4;
    rsa = RSA_new();
    ret = EVP_PKEY_new();
332
    if (rsa == NULL || ret == NULL)
333
        goto memerr;
R
Richard Levitte 已提交
334 335
    e = BN_new();
    if (e == NULL)
336
        goto memerr;
R
Richard Levitte 已提交
337
    if (!BN_set_word(e, read_ledword(&pin)))
338
        goto memerr;
R
Richard Levitte 已提交
339
    if (!read_lebn(&pin, nbyte, &n))
340 341
        goto memerr;
    if (!ispub) {
R
Richard Levitte 已提交
342
        if (!read_lebn(&pin, hnbyte, &p))
343
            goto memerr;
R
Richard Levitte 已提交
344
        if (!read_lebn(&pin, hnbyte, &q))
345
            goto memerr;
R
Richard Levitte 已提交
346
        if (!read_lebn(&pin, hnbyte, &dmp1))
347
            goto memerr;
R
Richard Levitte 已提交
348
        if (!read_lebn(&pin, hnbyte, &dmq1))
349
            goto memerr;
R
Richard Levitte 已提交
350
        if (!read_lebn(&pin, hnbyte, &iqmp))
351
            goto memerr;
R
Richard Levitte 已提交
352
        if (!read_lebn(&pin, nbyte, &d))
353
            goto memerr;
354 355 356 357 358 359
        if (!RSA_set0_factors(rsa, p, q))
            goto memerr;
        p = q = NULL;
        if (!RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp))
            goto memerr;
        dmp1 = dmq1 = iqmp = NULL;
360
    }
361 362 363
    if (!RSA_set0_key(rsa, n, e, d))
        goto memerr;
    n = e = d = NULL;
364

365 366
    if (!EVP_PKEY_set1_RSA(ret, rsa))
        goto memerr;
367
    RSA_free(rsa);
R
Richard Levitte 已提交
368
    *in = pin;
369 370 371
    return ret;
 memerr:
    PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE);
372 373 374 375 376 377 378 379
    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 已提交
380
    RSA_free(rsa);
R
Rich Salz 已提交
381
    EVP_PKEY_free(ret);
382 383
    return NULL;
}
384 385

EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length)
386 387 388
{
    return do_b2i(in, length, 0);
}
389 390

EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length)
391 392 393
{
    return do_b2i(in, length, 1);
}
394 395

EVP_PKEY *b2i_PrivateKey_bio(BIO *in)
396 397 398
{
    return do_b2i_bio(in, 0);
}
399 400

EVP_PKEY *b2i_PublicKey_bio(BIO *in)
401 402 403
{
    return do_b2i_bio(in, 1);
}
404 405

static void write_ledword(unsigned char **out, unsigned int dw)
406 407 408 409 410 411 412 413
{
    unsigned char *p = *out;
    *p++ = dw & 0xff;
    *p++ = (dw >> 8) & 0xff;
    *p++ = (dw >> 16) & 0xff;
    *p++ = (dw >> 24) & 0xff;
    *out = p;
}
414 415

static void write_lebn(unsigned char **out, const BIGNUM *bn, int len)
416
{
D
Dr. Stephen Henson 已提交
417 418
    BN_bn2lebinpad(bn, *out, len);
    *out += len;
419
}
420 421 422 423 424 425

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

427
static int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub)
428 429 430 431
{
    unsigned char *p;
    unsigned int bitlen, magic = 0, keyalg;
    int outlen, noinc = 0;
D
Dr. Stephen Henson 已提交
432 433 434
    int pktype = EVP_PKEY_id(pk);
    if (pktype == EVP_PKEY_DSA) {
        bitlen = check_bitlen_dsa(EVP_PKEY_get0_DSA(pk), ispub, &magic);
435
        keyalg = MS_KEYALG_DSS_SIGN;
D
Dr. Stephen Henson 已提交
436 437
    } else if (pktype == EVP_PKEY_RSA) {
        bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic);
438 439 440 441 442 443 444 445 446 447 448 449
        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 {
R
Rich Salz 已提交
450 451
        if ((p = OPENSSL_malloc(outlen)) == NULL) {
            PEMerr(PEM_F_DO_I2B, ERR_R_MALLOC_FAILURE);
452
            return -1;
R
Rich Salz 已提交
453
        }
454 455 456 457 458 459 460 461 462 463 464 465 466 467
        *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 已提交
468
        write_dsa(&p, EVP_PKEY_get0_DSA(pk), ispub);
469
    else
D
Dr. Stephen Henson 已提交
470
        write_rsa(&p, EVP_PKEY_get0_RSA(pk), ispub);
471 472 473 474
    if (!noinc)
        *out += outlen;
    return outlen;
}
475 476

static int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub)
477 478 479 480 481 482 483 484 485 486 487 488
{
    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;
}
489 490

static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic)
491 492
{
    int bitlen;
493 494
    const BIGNUM *p = NULL, *q = NULL, *g = NULL;
    const BIGNUM *pub_key = NULL, *priv_key = NULL;
M
Matt Caswell 已提交
495 496 497 498 499 500

    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))
501 502
        goto badkey;
    if (ispub) {
M
Matt Caswell 已提交
503
        if (BN_num_bits(pub_key) > bitlen)
504 505 506
            goto badkey;
        *pmagic = MS_DSS1MAGIC;
    } else {
M
Matt Caswell 已提交
507
        if (BN_num_bits(priv_key) > 160)
508 509 510 511 512 513 514 515 516
            goto badkey;
        *pmagic = MS_DSS2MAGIC;
    }

    return bitlen;
 badkey:
    PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
    return 0;
}
517 518

static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
519 520
{
    int nbyte, hnbyte, bitlen;
521
    const BIGNUM *e;
R
Richard Levitte 已提交
522

M
Matt Caswell 已提交
523
    RSA_get0_key(rsa, NULL, &e, NULL);
R
Richard Levitte 已提交
524
    if (BN_num_bits(e) > 32)
525
        goto badkey;
R
Richard Levitte 已提交
526 527 528
    bitlen = RSA_bits(rsa);
    nbyte = RSA_size(rsa);
    hnbyte = (bitlen + 15) >> 4;
529 530 531 532
    if (ispub) {
        *pmagic = MS_RSA1MAGIC;
        return bitlen;
    } else {
533
        const BIGNUM *d, *p, *q, *iqmp, *dmp1, *dmq1;
R
Richard Levitte 已提交
534

535
        *pmagic = MS_RSA2MAGIC;
R
Richard Levitte 已提交
536

537 538 539
        /*
         * For private key each component must fit within nbyte or hnbyte.
         */
R
Richard Levitte 已提交
540 541
        RSA_get0_key(rsa, NULL, NULL, &d);
        if (BN_num_bytes(d) > nbyte)
542
            goto badkey;
R
Richard Levitte 已提交
543 544 545 546 547 548 549
        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))
550 551 552 553 554 555 556
            goto badkey;
    }
    return bitlen;
 badkey:
    PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
    return 0;
}
557 558

static void write_rsa(unsigned char **out, RSA *rsa, int ispub)
559 560
{
    int nbyte, hnbyte;
561
    const BIGNUM *n, *d, *e, *p, *q, *iqmp, *dmp1, *dmq1;
R
Richard Levitte 已提交
562 563 564

    nbyte = RSA_size(rsa);
    hnbyte = (RSA_bits(rsa) + 15) >> 4;
M
Matt Caswell 已提交
565
    RSA_get0_key(rsa, &n, &e, &d);
R
Richard Levitte 已提交
566
    write_lebn(out, e, 4);
D
Dr. Stephen Henson 已提交
567
    write_lebn(out, n, nbyte);
568 569
    if (ispub)
        return;
R
Richard Levitte 已提交
570 571 572 573 574 575 576 577
    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);
578 579
}

580
static void write_dsa(unsigned char **out, DSA *dsa, int ispub)
581 582
{
    int nbyte;
583 584
    const BIGNUM *p = NULL, *q = NULL, *g = NULL;
    const BIGNUM *pub_key = NULL, *priv_key = NULL;
M
Matt Caswell 已提交
585 586 587 588 589 590 591

    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);
592
    if (ispub)
M
Matt Caswell 已提交
593
        write_lebn(out, pub_key, nbyte);
594
    else
M
Matt Caswell 已提交
595
        write_lebn(out, priv_key, 20);
596 597 598 599 600
    /* Set "invalid" for seed structure values */
    memset(*out, 0xff, 24);
    *out += 24;
    return;
}
601 602

int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk)
603 604 605
{
    return do_i2b_bio(out, pk, 0);
}
606 607

int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk)
608 609 610
{
    return do_i2b_bio(out, pk, 1);
}
611

612
# ifndef OPENSSL_NO_RC4
D
Dr. Stephen Henson 已提交
613

614
static int do_PVK_header(const unsigned char **in, unsigned int length,
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
                         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);

645 646 647
    if (*pkeylen > PVK_MAX_KEYLEN || *psaltlen > PVK_MAX_SALTLEN)
        return 0;

648 649 650 651 652 653 654 655 656 657 658 659 660
    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 已提交
661
    EVP_MD_CTX *mctx = EVP_MD_CTX_new();
662
    int rv = 1;
663 664 665 666 667
    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))
668 669
        rv = 0;

670
    EVP_MD_CTX_free(mctx);
671 672
    return rv;
}
673 674

static EVP_PKEY *do_PVK_body(const unsigned char **in,
675 676 677 678 679 680 681
                             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;
682
    unsigned char keybuf[20];
R
Rich Salz 已提交
683

684
    EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new();
685 686 687 688 689 690 691
    if (saltlen) {
        char psbuf[PEM_BUFSIZE];
        int enctmplen, inlen;
        if (cb)
            inlen = cb(psbuf, PEM_BUFSIZE, 0, u);
        else
            inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
692
        if (inlen < 0) {
693
            PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_PASSWORD_READ);
694
            goto err;
695 696
        }
        enctmp = OPENSSL_malloc(keylen + 8);
697
        if (enctmp == NULL) {
698
            PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);
699
            goto err;
700 701 702
        }
        if (!derive_pvk_key(keybuf, p, saltlen,
                            (unsigned char *)psbuf, inlen))
703
            goto err;
704 705 706 707 708 709
        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);
710
            goto err;
711 712 713
        }
        inlen = keylen - 8;
        q = enctmp + 8;
714
        if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
715
            goto err;
716
        if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
717
            goto err;
718
        if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen))
719 720 721 722 723
            goto err;
        magic = read_ledword((const unsigned char **)&q);
        if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) {
            q = enctmp + 8;
            memset(keybuf + 5, 0, 11);
724
            if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
725
                goto err;
726
            if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
727
                goto err;
728
            if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen))
729 730 731 732 733 734
                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;
            }
735
        }
736 737 738 739 740
        p = enctmp;
    }

    ret = b2i_PrivateKey(&p, keylen);
 err:
741
    EVP_CIPHER_CTX_free(cctx);
742 743 744 745
    if (enctmp != NULL) {
        OPENSSL_cleanse(keybuf, sizeof(keybuf));
        OPENSSL_free(enctmp);
    }
746 747
    return ret;
}
748 749

EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
{
    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);
766
    if (buf == NULL) {
767 768 769 770 771 772 773 774 775 776 777
        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 已提交
778
    OPENSSL_clear_free(buf, buflen);
779 780 781 782 783 784 785
    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 已提交
786
    unsigned char *p = NULL, *start = NULL, *salt = NULL;
787
    EVP_CIPHER_CTX *cctx = NULL;
788 789 790 791 792 793
    if (enclevel)
        outlen += PVK_SALTLEN;
    pklen = do_i2b(NULL, pk, 0);
    if (pklen < 0)
        return -1;
    outlen += pklen;
794
    if (out == NULL)
795
        return outlen;
796
    if (*out != NULL) {
797
        p = *out;
798
    } else {
M
Matt Caswell 已提交
799
        start = p = OPENSSL_malloc(outlen);
800
        if (p == NULL) {
801 802 803 804 805
            PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE);
            return -1;
        }
    }

806 807
    cctx = EVP_CIPHER_CTX_new();
    if (cctx == NULL)
M
Matt Caswell 已提交
808
        goto error;
809

810 811
    write_ledword(&p, MS_PVKMAGIC);
    write_ledword(&p, 0);
D
Dr. Stephen Henson 已提交
812
    if (EVP_PKEY_id(pk) == EVP_PKEY_DSA)
813 814 815 816 817 818 819 820 821 822 823 824 825
        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);
826
    if (enclevel != 0) {
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
        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;
844
        if (!EVP_EncryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
845 846
            goto error;
        OPENSSL_cleanse(keybuf, 20);
847
        if (!EVP_EncryptUpdate(cctx, p, &enctmplen, p, pklen - 8))
848
            goto error;
849
        if (!EVP_EncryptFinal_ex(cctx, p + enctmplen, &enctmplen))
850 851
            goto error;
    }
852

853
    EVP_CIPHER_CTX_free(cctx);
854 855

    if (*out == NULL)
M
Matt Caswell 已提交
856
        *out = start;
857

858 859 860
    return outlen;

 error:
861
    EVP_CIPHER_CTX_free(cctx);
M
Matt Caswell 已提交
862
    if (*out == NULL)
M
Matt Caswell 已提交
863
        OPENSSL_free(start);
864 865
    return -1;
}
866 867

int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel,
868 869 870 871 872 873 874 875 876 877 878 879
                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) {
        return outlen;
    }
H
HJ 已提交
880
    PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE);
881 882 883 884
    return -1;
}

# endif
D
Dr. Stephen Henson 已提交
885

D
Dr. Stephen Henson 已提交
886
#endif