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