make EVP_PKEY opaque
[openssl.git] / crypto / pem / pvkfmt.c
index 31ee3654745ce95f2346f393d25dccdd257118af..625b488e34ed01bbb83edafae6978f3a660d23a4 100644 (file)
@@ -1,5 +1,6 @@
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
- * project 2005.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2005.
  */
 /* ====================================================================
  * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
@@ -9,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *
  */
 
-/* Support for PVK format keys and related structures (such a PUBLICKEYBLOB
+/*
+ * Support for PVK format keys and related structures (such a PUBLICKEYBLOB
  * and PRIVATEKEYBLOB).
  */
 
-#include "cryptlib.h"
+#include "internal/cryptlib.h"
 #include <openssl/pem.h>
 #include <openssl/rand.h>
+#include <openssl/bn.h>
+#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
+# include <openssl/dsa.h>
+# include <openssl/rsa.h>
 
-/* Utility function: read a DWORD (4 byte unsigned integer) in little endian
+/*
+ * Utility function: read a DWORD (4 byte unsigned integer) in little endian
  * format
  */
 
 static unsigned int read_ledword(const unsigned char **in)
-       {
-       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.
+{
+    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.
  */
 
 static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
-       {
-       const unsigned char *p;
-       unsigned char *tmpbuf, *q;
-       unsigned int i;
-       p = *in + nbyte - 1;
-       tmpbuf = OPENSSL_malloc(nbyte);
-       if (!tmpbuf)
-               return 0;
-       q = tmpbuf;
-       for (i = 0; i < nbyte; i++)
-               *q++ = *p--;
-       *r = BN_bin2bn(tmpbuf, nbyte, NULL);
-       OPENSSL_free(tmpbuf);
-       if (*r)
-               {
-               *in += nbyte;
-               return 1;
-               }
-       else
-               return 0;
-       }
-
+{
+    const unsigned char *p;
+    unsigned char *tmpbuf, *q;
+    unsigned int i;
+    p = *in + nbyte - 1;
+    tmpbuf = OPENSSL_malloc(nbyte);
+    if (tmpbuf == NULL)
+        return 0;
+    q = tmpbuf;
+    for (i = 0; i < nbyte; i++)
+        *q++ = *p--;
+    *r = BN_bin2bn(tmpbuf, nbyte, NULL);
+    OPENSSL_free(tmpbuf);
+    if (*r) {
+        *in += nbyte;
+        return 1;
+    } else
+        return 0;
+}
 
 /* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */
 
-#define MS_PUBLICKEYBLOB       0x6
-#define MS_PRIVATEKEYBLOB      0x7
-#define MS_RSA1MAGIC           0x31415352L
-#define MS_RSA2MAGIC           0x32415352L
-#define MS_DSS1MAGIC           0x31535344L
-#define MS_DSS2MAGIC           0x32535344L
+# define MS_PUBLICKEYBLOB        0x6
+# define MS_PRIVATEKEYBLOB       0x7
+# define MS_RSA1MAGIC            0x31415352L
+# define MS_RSA2MAGIC            0x32415352L
+# define MS_DSS1MAGIC            0x31535344L
+# define MS_DSS2MAGIC            0x32535344L
 
-#define MS_KEYALG_RSA_KEYX     0xa400
-#define MS_KEYALG_DSS_SIGN     0x2200
+# define MS_KEYALG_RSA_KEYX      0xa400
+# define MS_KEYALG_DSS_SIGN      0x2200
 
-#define MS_KEYTYPE_KEYX                0x1
-#define MS_KEYTYPE_SIGN                0x2
+# define MS_KEYTYPE_KEYX         0x1
+# define MS_KEYTYPE_SIGN         0x2
 
 /* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
-#define MS_PVKMAGIC            0xb0b5f11eL
+# define MS_PVKMAGIC             0xb0b5f11eL
 /* Salt length for PVK files */
-#define PVK_SALTLEN            0x10
+# define PVK_SALTLEN             0x10
 
 static EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length,
-                                               unsigned int bitlen, int ispub);
+                         unsigned int bitlen, int ispub);
 static EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length,
-                                               unsigned int bitlen, int ispub);
+                         unsigned int bitlen, int ispub);
 
 static int do_blob_header(const unsigned char **in, unsigned int length,
-                               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;
-       }
+                          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;
+}
 
 static unsigned int blob_length(unsigned bitlen, int isdss, int ispub)
-       {
-       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;
-               }
-
-       }
+{
+    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;
+    }
+
+}
 
 static EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length,
-                                                               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)
-               return b2i_dss(&p, length, bitlen, ispub);
-       else
-               return b2i_rsa(&p, length, bitlen, ispub);
-       }
+                        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)
+        return b2i_dss(&p, length, bitlen, ispub);
+    else
+        return b2i_rsa(&p, length, bitlen, ispub);
+}
 
 static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
-       {
-       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);
-       if (!buf)
-               {
-               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)
-               ret = b2i_dss(&p, length, bitlen, ispub);
-       else
-               ret = b2i_rsa(&p, length, bitlen, ispub);
-
-       err:
-       if (buf)
-               OPENSSL_free(buf);
-       return ret;
-       }
+{
+    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);
+    if (buf == NULL) {
+        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)
+        ret = b2i_dss(&p, length, bitlen, ispub);
+    else
+        ret = b2i_rsa(&p, length, bitlen, ispub);
+
+ err:
+    OPENSSL_free(buf);
+    return ret;
+}
 
 static EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length,
-                                               unsigned int bitlen, int ispub)
-       {
-       const unsigned char *p = *in;
-       EVP_PKEY *ret = NULL;
-       DSA *dsa = NULL;
-       BN_CTX *ctx = NULL;
-       unsigned int nbyte;
-       nbyte = (bitlen + 7) >> 3;
-
-       dsa = DSA_new();
-       ret = EVP_PKEY_new();
-       if (!dsa || !ret)
-               goto memerr;
-       if (!read_lebn(&p, nbyte, &dsa->p))
-               goto memerr;
-       if (!read_lebn(&p, 20, &dsa->q))
-               goto memerr;
-       if (!read_lebn(&p, nbyte, &dsa->g))
-               goto memerr;
-       if (ispub)
-               {
-               if (!read_lebn(&p, nbyte, &dsa->pub_key))
-                       goto memerr;
-               }
-       else
-               {
-               if (!read_lebn(&p, 20, &dsa->priv_key))
-                       goto memerr;
-               /* Calculate public key */
-               if (!(dsa->pub_key = BN_new()))
-                       goto memerr;
-               if (!(ctx = BN_CTX_new()))
-                       goto memerr;
-                       
-               if (!BN_mod_exp(dsa->pub_key, dsa->g,
-                                                dsa->priv_key, dsa->p, ctx))
-                       
-                       goto memerr;
-               BN_CTX_free(ctx);
-               }
-
-       EVP_PKEY_set1_DSA(ret, dsa);
-       DSA_free(dsa);
-       *in = p;
-       return ret;
-
-       memerr:
-       PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE);
-       if (dsa)
-               DSA_free(dsa);
-       if (ret)
-               EVP_PKEY_free(ret);
-       if (ctx)
-               BN_CTX_free(ctx);
-       return NULL;
-       }
+                         unsigned int bitlen, int ispub)
+{
+    const unsigned char *p = *in;
+    EVP_PKEY *ret = NULL;
+    DSA *dsa = NULL;
+    BN_CTX *ctx = NULL;
+    unsigned int nbyte;
+    nbyte = (bitlen + 7) >> 3;
+
+    dsa = DSA_new();
+    ret = EVP_PKEY_new();
+    if (dsa == NULL || ret == NULL)
+        goto memerr;
+    if (!read_lebn(&p, nbyte, &dsa->p))
+        goto memerr;
+    if (!read_lebn(&p, 20, &dsa->q))
+        goto memerr;
+    if (!read_lebn(&p, nbyte, &dsa->g))
+        goto memerr;
+    if (ispub) {
+        if (!read_lebn(&p, nbyte, &dsa->pub_key))
+            goto memerr;
+    } else {
+        if (!read_lebn(&p, 20, &dsa->priv_key))
+            goto memerr;
+        /* Calculate public key */
+        if ((dsa->pub_key = BN_new()) == NULL)
+            goto memerr;
+        if ((ctx = BN_CTX_new()) == NULL)
+            goto memerr;
+
+        if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx))
+            goto memerr;
+        BN_CTX_free(ctx);
+    }
+
+    EVP_PKEY_set1_DSA(ret, dsa);
+    DSA_free(dsa);
+    *in = p;
+    return ret;
+
+ memerr:
+    PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE);
+    DSA_free(dsa);
+    EVP_PKEY_free(ret);
+    BN_CTX_free(ctx);
+    return NULL;
+}
 
 static EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length,
-                                               unsigned int bitlen, int ispub)
-               
-       {
-       const unsigned char *p = *in;
-       EVP_PKEY *ret = NULL;
-       RSA *rsa = NULL;
-       unsigned int nbyte, hnbyte;
-       nbyte = (bitlen + 7) >> 3;
-       hnbyte = (bitlen + 15) >> 4;
-       rsa = RSA_new();
-       ret = EVP_PKEY_new();
-       if (!rsa || !ret)
-               goto memerr;
-       rsa->e = BN_new();
-       if (!rsa->e)
-               goto memerr;
-       if (!BN_set_word(rsa->e, read_ledword(&p)))
-               goto memerr;
-       if (!read_lebn(&p, nbyte, &rsa->n))
-               goto memerr;
-       if (!ispub)
-               {
-               if (!read_lebn(&p, hnbyte, &rsa->p))
-                       goto memerr;
-               if (!read_lebn(&p, hnbyte, &rsa->q))
-                       goto memerr;
-               if (!read_lebn(&p, hnbyte, &rsa->dmp1))
-                       goto memerr;
-               if (!read_lebn(&p, hnbyte, &rsa->dmq1))
-                       goto memerr;
-               if (!read_lebn(&p, hnbyte, &rsa->iqmp))
-                       goto memerr;
-               if (!read_lebn(&p, nbyte, &rsa->d))
-                       goto memerr;
-               }
-
-       EVP_PKEY_set1_RSA(ret, rsa);
-       RSA_free(rsa);
-       *in = p;
-       return ret;
-       memerr:
-       PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE);
-       if (rsa)
-               RSA_free(rsa);
-       if (ret)
-               EVP_PKEY_free(ret);
-       return NULL;
-       }
+                         unsigned int bitlen, int ispub)
+{
+    const unsigned char *p = *in;
+    EVP_PKEY *ret = NULL;
+    RSA *rsa = NULL;
+    unsigned int nbyte, hnbyte;
+    nbyte = (bitlen + 7) >> 3;
+    hnbyte = (bitlen + 15) >> 4;
+    rsa = RSA_new();
+    ret = EVP_PKEY_new();
+    if (rsa == NULL || ret == NULL)
+        goto memerr;
+    rsa->e = BN_new();
+    if (rsa->e == NULL)
+        goto memerr;
+    if (!BN_set_word(rsa->e, read_ledword(&p)))
+        goto memerr;
+    if (!read_lebn(&p, nbyte, &rsa->n))
+        goto memerr;
+    if (!ispub) {
+        if (!read_lebn(&p, hnbyte, &rsa->p))
+            goto memerr;
+        if (!read_lebn(&p, hnbyte, &rsa->q))
+            goto memerr;
+        if (!read_lebn(&p, hnbyte, &rsa->dmp1))
+            goto memerr;
+        if (!read_lebn(&p, hnbyte, &rsa->dmq1))
+            goto memerr;
+        if (!read_lebn(&p, hnbyte, &rsa->iqmp))
+            goto memerr;
+        if (!read_lebn(&p, nbyte, &rsa->d))
+            goto memerr;
+    }
+
+    EVP_PKEY_set1_RSA(ret, rsa);
+    RSA_free(rsa);
+    *in = p;
+    return ret;
+ memerr:
+    PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE);
+    RSA_free(rsa);
+    EVP_PKEY_free(ret);
+    return NULL;
+}
 
 EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length)
-       {
-       return do_b2i(in, length, 0);
-       }
+{
+    return do_b2i(in, length, 0);
+}
 
 EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length)
-       {
-       return do_b2i(in, length, 1);
-       }
-
+{
+    return do_b2i(in, length, 1);
+}
 
 EVP_PKEY *b2i_PrivateKey_bio(BIO *in)
-       {
-       return do_b2i_bio(in, 0);
-       }
+{
+    return do_b2i_bio(in, 0);
+}
 
 EVP_PKEY *b2i_PublicKey_bio(BIO *in)
-       {
-       return do_b2i_bio(in, 1);
-       }
+{
+    return do_b2i_bio(in, 1);
+}
 
 static void write_ledword(unsigned char **out, unsigned int dw)
-       {
-       unsigned char *p = *out;
-       *p++ = dw & 0xff;
-       *p++ = (dw>>8) & 0xff;
-       *p++ = (dw>>16) & 0xff;
-       *p++ = (dw>>24) & 0xff;
-       *out = p;
-       }
+{
+    unsigned char *p = *out;
+    *p++ = dw & 0xff;
+    *p++ = (dw >> 8) & 0xff;
+    *p++ = (dw >> 16) & 0xff;
+    *p++ = (dw >> 24) & 0xff;
+    *out = p;
+}
 
 static void write_lebn(unsigned char **out, const BIGNUM *bn, int len)
-       {
-       int nb, i;
-       unsigned char *p = *out, *q, c;
-       nb = BN_num_bytes(bn);
-       BN_bn2bin(bn, p);
-       q = p + nb - 1;
-       /* In place byte order reversal */
-       for (i = 0; i < nb/2; i++)
-               {
-               c = *p;
-               *p++ = *q;
-               *q-- = c;
-               }
-       *out += nb;
-       /* Pad with zeroes if we have to */
-       if (len > 0)
-               {
-               len -= nb;
-               if (len > 0)
-                       {
-                       memset(*out, 0, len);
-                       *out += len;
-                       }
-               }
-       }
-
+{
+    int nb, i;
+    unsigned char *p = *out, *q, c;
+    nb = BN_num_bytes(bn);
+    BN_bn2bin(bn, p);
+    q = p + nb - 1;
+    /* In place byte order reversal */
+    for (i = 0; i < nb / 2; i++) {
+        c = *p;
+        *p++ = *q;
+        *q-- = c;
+    }
+    *out += nb;
+    /* Pad with zeroes if we have to */
+    if (len > 0) {
+        len -= nb;
+        if (len > 0) {
+            memset(*out, 0, len);
+            *out += len;
+        }
+    }
+}
 
 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);
-       
+
 static int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub)
-       {
-       unsigned char *p;
-       unsigned int bitlen, magic, keyalg;
-       int outlen, noinc = 0;
-       if (pk->type == EVP_PKEY_DSA)
-               {
-               bitlen = check_bitlen_dsa(pk->pkey.dsa, ispub, &magic);
-               keyalg = MS_KEYALG_DSS_SIGN;
-               }
-       else if (pk->type == EVP_PKEY_RSA)
-               {
-               bitlen = check_bitlen_rsa(pk->pkey.rsa, ispub, &magic);
-               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);
-               if (!p)
-                       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)
-               write_dsa(&p, pk->pkey.dsa, ispub);
-       else
-               write_rsa(&p, pk->pkey.rsa, ispub);
-       if (!noinc)
-               *out += outlen;
-       return outlen;
-       }
+{
+    unsigned char *p;
+    unsigned int bitlen, magic = 0, keyalg;
+    int outlen, noinc = 0;
+    int pktype = EVP_PKEY_id(pk);
+    if (pktype == EVP_PKEY_DSA) {
+        bitlen = check_bitlen_dsa(EVP_PKEY_get0_DSA(pk), ispub, &magic);
+        keyalg = MS_KEYALG_DSS_SIGN;
+    } else if (pktype == EVP_PKEY_RSA) {
+        bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic);
+        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);
+        if (p == NULL)
+            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)
+        write_dsa(&p, EVP_PKEY_get0_DSA(pk), ispub);
+    else
+        write_rsa(&p, EVP_PKEY_get0_RSA(pk), ispub);
+    if (!noinc)
+        *out += outlen;
+    return outlen;
+}
 
 static int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub)
-       {
-       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;
-       }
+{
+    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;
+}
 
 static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic)
-       {
-       int bitlen;
-       bitlen = BN_num_bits(dsa->p);
-       if ((bitlen & 7) || (BN_num_bits(dsa->q) != 160)
-               || (BN_num_bits(dsa->g) > bitlen))
-               goto badkey;
-       if (ispub)
-               {
-               if (BN_num_bits(dsa->pub_key) > bitlen)
-                       goto badkey;
-               *pmagic = MS_DSS1MAGIC;
-               }
-       else
-               {
-               if (BN_num_bits(dsa->priv_key) > 160)
-                       goto badkey;
-               *pmagic = MS_DSS2MAGIC;
-               }
-       
-       return bitlen;
-       badkey:
-       PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
-       return 0;
-       }
+{
+    int bitlen;
+    bitlen = BN_num_bits(dsa->p);
+    if ((bitlen & 7) || (BN_num_bits(dsa->q) != 160)
+        || (BN_num_bits(dsa->g) > bitlen))
+        goto badkey;
+    if (ispub) {
+        if (BN_num_bits(dsa->pub_key) > bitlen)
+            goto badkey;
+        *pmagic = MS_DSS1MAGIC;
+    } else {
+        if (BN_num_bits(dsa->priv_key) > 160)
+            goto badkey;
+        *pmagic = MS_DSS2MAGIC;
+    }
+
+    return bitlen;
+ badkey:
+    PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
+    return 0;
+}
 
 static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
-       {
-       int nbyte, hnbyte, bitlen;
-       if (BN_num_bits(rsa->e) > 32)
-               goto badkey;
-       bitlen = BN_num_bits(rsa->n);
-       nbyte = BN_num_bytes(rsa->n);
-       hnbyte = (BN_num_bits(rsa->n) + 15) >> 4;
-       if (ispub)
-               {
-               *pmagic = MS_RSA1MAGIC;
-               return bitlen;
-               }
-       else
-       {
-               *pmagic = MS_RSA2MAGIC;
-               /* For private key each component must fit within nbyte or
-                * hnbyte.
-                */
-               if (BN_num_bytes(rsa->d) > nbyte)
-                       goto badkey;
-               if ((BN_num_bytes(rsa->iqmp) > hnbyte)
-                       || (BN_num_bytes(rsa->p) > hnbyte)
-                       || (BN_num_bytes(rsa->q) > hnbyte)
-                       || (BN_num_bytes(rsa->dmp1) > hnbyte)
-                       || (BN_num_bytes(rsa->dmq1) > hnbyte))
-                       goto badkey;
-       }
-       return bitlen;
-       badkey:
-       PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
-       return 0;
-       }
-
+{
+    int nbyte, hnbyte, bitlen;
+    if (BN_num_bits(rsa->e) > 32)
+        goto badkey;
+    bitlen = BN_num_bits(rsa->n);
+    nbyte = BN_num_bytes(rsa->n);
+    hnbyte = (BN_num_bits(rsa->n) + 15) >> 4;
+    if (ispub) {
+        *pmagic = MS_RSA1MAGIC;
+        return bitlen;
+    } else {
+        *pmagic = MS_RSA2MAGIC;
+        /*
+         * For private key each component must fit within nbyte or hnbyte.
+         */
+        if (BN_num_bytes(rsa->d) > nbyte)
+            goto badkey;
+        if ((BN_num_bytes(rsa->iqmp) > hnbyte)
+            || (BN_num_bytes(rsa->p) > hnbyte)
+            || (BN_num_bytes(rsa->q) > hnbyte)
+            || (BN_num_bytes(rsa->dmp1) > hnbyte)
+            || (BN_num_bytes(rsa->dmq1) > hnbyte))
+            goto badkey;
+    }
+    return bitlen;
+ badkey:
+    PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
+    return 0;
+}
 
 static void write_rsa(unsigned char **out, RSA *rsa, int ispub)
-       {
-       int nbyte, hnbyte;
-       nbyte = BN_num_bytes(rsa->n);
-       hnbyte = (BN_num_bits(rsa->n) + 15) >> 4;
-       write_lebn(out, rsa->e, 4);
-       write_lebn(out, rsa->n, -1);
-       if (ispub)
-               return;
-       write_lebn(out, rsa->p, hnbyte);
-       write_lebn(out, rsa->q, hnbyte);
-       write_lebn(out, rsa->dmp1, hnbyte);
-       write_lebn(out, rsa->dmq1, hnbyte);
-       write_lebn(out, rsa->iqmp, hnbyte);
-       write_lebn(out, rsa->d, nbyte);
-       }
-
-       
+{
+    int nbyte, hnbyte;
+    nbyte = BN_num_bytes(rsa->n);
+    hnbyte = (BN_num_bits(rsa->n) + 15) >> 4;
+    write_lebn(out, rsa->e, 4);
+    write_lebn(out, rsa->n, -1);
+    if (ispub)
+        return;
+    write_lebn(out, rsa->p, hnbyte);
+    write_lebn(out, rsa->q, hnbyte);
+    write_lebn(out, rsa->dmp1, hnbyte);
+    write_lebn(out, rsa->dmq1, hnbyte);
+    write_lebn(out, rsa->iqmp, hnbyte);
+    write_lebn(out, rsa->d, nbyte);
+}
+
 static void write_dsa(unsigned char **out, DSA *dsa, int ispub)
-       {
-       int nbyte;
-       nbyte = BN_num_bytes(dsa->p);
-       write_lebn(out, dsa->p, nbyte);
-       write_lebn(out, dsa->q, 20);
-       write_lebn(out, dsa->g, nbyte);
-       if (ispub)
-               write_lebn(out, dsa->pub_key, nbyte);
-       else
-               write_lebn(out, dsa->priv_key, 20);
-       /* Set "invalid" for seed structure values */
-       memset(*out, 0xff, 24);
-       *out += 24;
-       return;
-       }
-       
+{
+    int nbyte;
+    nbyte = BN_num_bytes(dsa->p);
+    write_lebn(out, dsa->p, nbyte);
+    write_lebn(out, dsa->q, 20);
+    write_lebn(out, dsa->g, nbyte);
+    if (ispub)
+        write_lebn(out, dsa->pub_key, nbyte);
+    else
+        write_lebn(out, dsa->priv_key, 20);
+    /* Set "invalid" for seed structure values */
+    memset(*out, 0xff, 24);
+    *out += 24;
+    return;
+}
 
 int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk)
-       {
-       return do_i2b_bio(out, pk, 0);
-       }
+{
+    return do_i2b_bio(out, pk, 0);
+}
 
 int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk)
-       {
-       return do_i2b_bio(out, pk, 1);
-       }
+{
+    return do_i2b_bio(out, pk, 1);
+}
+
+# ifndef OPENSSL_NO_RC4
 
 static int do_PVK_header(const unsigned char **in, unsigned int length,
-               int skip_magic,
-               unsigned int *psaltlen, unsigned int *pkeylen)
-               
-       {
-       const unsigned char *p = *in;
-       unsigned int pvk_magic, keytype, is_encrypted;
-       if (skip_magic)
-               {
-               if (length < 20)
-                       {
-                       PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
-                       return 0;
-                       }
-               length -= 20;
-               }
-       else
-               {
-               if (length < 24)
-                       {
-                       PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
-                       return 0;
-                       }
-               length -= 24;
-               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);
-
-       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)
-       {
-       EVP_MD_CTX mctx;
-       EVP_MD_CTX_init(&mctx);
-       EVP_DigestInit_ex(&mctx, EVP_sha1(), NULL);
-       EVP_DigestUpdate(&mctx, salt, saltlen);
-       EVP_DigestUpdate(&mctx, pass, passlen);
-       EVP_DigestFinal_ex(&mctx, key, NULL);
-       EVP_MD_CTX_cleanup(&mctx);
-       return 1;
-       }
-       
+                         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);
+
+    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)
+{
+    EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+    int rv = 1;
+    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))
+        rv = 0;
+
+    EVP_MD_CTX_free(mctx);
+    return rv;
+}
 
 static EVP_PKEY *do_PVK_body(const unsigned char **in,
-               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;
-       if (saltlen)
-               {
-               char psbuf[PEM_BUFSIZE];
-               unsigned char keybuf[20];
-               EVP_CIPHER_CTX cctx;
-               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);
-                       return NULL;
-                       }
-               enctmp = OPENSSL_malloc(keylen + 8);
-               if (!enctmp)
-                       {
-                       PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);
-                       return NULL;
-                       }
-               if (!derive_pvk_key(keybuf, p, saltlen,
-                           (unsigned char *)psbuf, inlen))
-                       return NULL;
-               p += saltlen;
-               /* Copy BLOBHEADER across, decrypt rest */
-               memcpy(enctmp, p, 8);
-               p += 8;
-               inlen = keylen - 8;
-               q = enctmp + 8;
-               EVP_CIPHER_CTX_init(&cctx);
-               EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL);
-               EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen);
-               EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen);
-               magic = read_ledword((const unsigned char **)&q);
-               if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC)
-                       {
-                       q = enctmp + 8;
-                       memset(keybuf + 5, 0, 11);
-                       EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf,
-                                                               NULL);
-                       OPENSSL_cleanse(keybuf, 20);
-                       EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen);
-                       EVP_DecryptFinal_ex(&cctx, q + enctmplen,
-                                                               &enctmplen);
-                       magic = read_ledword((const unsigned char **)&q);
-                       if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC)
-                               {
-                               EVP_CIPHER_CTX_cleanup(&cctx);
-                               PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT);
-                               goto err;
-                               }
-                       }
-               else
-                       OPENSSL_cleanse(keybuf, 20);
-               EVP_CIPHER_CTX_cleanup(&cctx);
-               p = enctmp;
-               }
-
-       ret = b2i_PrivateKey(&p, keylen);
-       err:
-       if (enctmp && saltlen)
-               OPENSSL_free(enctmp);
-       return ret;
-       }
-
+                             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;
+
+    EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new();
+    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);
+            goto err;
+        }
+        enctmp = OPENSSL_malloc(keylen + 8);
+        if (enctmp == NULL) {
+            PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        if (!derive_pvk_key(keybuf, p, saltlen,
+                            (unsigned char *)psbuf, inlen))
+            goto err;
+        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);
+            goto err;
+        }
+        inlen = keylen - 8;
+        q = enctmp + 8;
+        if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+            goto err;
+        if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
+            goto err;
+        if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen))
+            goto err;
+        magic = read_ledword((const unsigned char **)&q);
+        if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) {
+            q = enctmp + 8;
+            memset(keybuf + 5, 0, 11);
+            if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+                goto err;
+            OPENSSL_cleanse(keybuf, 20);
+            if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
+                goto err;
+            if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen))
+                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:
+    EVP_CIPHER_CTX_free(cctx);
+    OPENSSL_free(enctmp);
+    return ret;
+}
 
 EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
-       {
-       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);
-       if (!buf)
-               {
-               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:
-       if (buf)
-               {
-               OPENSSL_cleanse(buf, buflen);
-               OPENSSL_free(buf);
-               }
-       return ret;
-       }
-
-       
-       
-static int i2b_PVK(unsigned char **out, EVP_PKEY*pk, int enclevel,
-               pem_password_cb *cb, void *u)
-       {
-       int outlen = 24, noinc, pklen;
-       unsigned char *p, *salt = NULL;
-       if (enclevel)
-               outlen += PVK_SALTLEN;
-       pklen = do_i2b(NULL, pk, 0);
-       if (pklen < 0)
-               return -1;
-       outlen += pklen;
-       if (!out)
-               return outlen;
-       if (*out)
-               {
-               p = *out;
-               noinc = 0;
-               }
-       else
-               {
-               p = OPENSSL_malloc(outlen);
-               if (!p)
-                       {
-                       PEMerr(PEM_F_I2B_PVK,ERR_R_MALLOC_FAILURE);
-                       return -1;
-                       }
-               *out = p;
-               noinc = 1;
-               }
-
-       write_ledword(&p, MS_PVKMAGIC);
-       write_ledword(&p, 0);
-       if (pk->type == EVP_PKEY_DSA)
-               write_ledword(&p, MS_KEYTYPE_SIGN);
-       else
-               write_ledword(&p, MS_KEYTYPE_KEYX);
-       write_ledword(&p, enclevel ? 1 : 0);
-       write_ledword(&p, enclevel ? PVK_SALTLEN: 0);
-       write_ledword(&p, pklen);
-       if (enclevel)
-               {
-               if (RAND_bytes(p, PVK_SALTLEN) <= 0)
-                       goto error;
-               salt = p;
-               p += PVK_SALTLEN;
-               }
-       do_i2b(&p, pk, 0);
-       if (enclevel == 0)
-               return outlen;
-       else
-               {
-               char psbuf[PEM_BUFSIZE];
-               unsigned char keybuf[20];
-               EVP_CIPHER_CTX cctx;
-               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;
-               EVP_CIPHER_CTX_init(&cctx);
-               EVP_EncryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL);
-               OPENSSL_cleanse(keybuf, 20);
-               EVP_DecryptUpdate(&cctx, p, &enctmplen, p, pklen - 8);
-               EVP_DecryptFinal_ex(&cctx, p + enctmplen, &enctmplen);
-               EVP_CIPHER_CTX_cleanup(&cctx);
-               }
-       return outlen;
-
-       error:
-       return -1;
-       }
+{
+    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);
+    if (buf == NULL) {
+        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:
+    OPENSSL_clear_free(buf, buflen);
+    return ret;
+}
+
+static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
+                   pem_password_cb *cb, void *u)
+{
+    int outlen = 24, pklen;
+    unsigned char *p, *salt = NULL;
+    EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new();
+    if (enclevel)
+        outlen += PVK_SALTLEN;
+    pklen = do_i2b(NULL, pk, 0);
+    if (pklen < 0)
+        return -1;
+    outlen += pklen;
+    if (!out)
+        return outlen;
+    if (*out)
+        p = *out;
+    else {
+        p = OPENSSL_malloc(outlen);
+        if (p == NULL) {
+            PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE);
+            return -1;
+        }
+        *out = p;
+    }
+
+    write_ledword(&p, MS_PVKMAGIC);
+    write_ledword(&p, 0);
+    if (EVP_PKEY_id(pk) == EVP_PKEY_DSA)
+        write_ledword(&p, MS_KEYTYPE_SIGN);
+    else
+        write_ledword(&p, MS_KEYTYPE_KEYX);
+    write_ledword(&p, enclevel ? 1 : 0);
+    write_ledword(&p, enclevel ? PVK_SALTLEN : 0);
+    write_ledword(&p, pklen);
+    if (enclevel) {
+        if (RAND_bytes(p, PVK_SALTLEN) <= 0)
+            goto error;
+        salt = p;
+        p += PVK_SALTLEN;
+    }
+    do_i2b(&p, pk, 0);
+    if (enclevel == 0)
+        return outlen;
+    else {
+        char psbuf[PEM_BUFSIZE];
+        unsigned char keybuf[20];
+        int enctmplen, inlen;
+        if (cb)
+            inlen = cb(psbuf, PEM_BUFSIZE, 1, u);
+        else
+            inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 1, u);
+        if (inlen <= 0) {
+            PEMerr(PEM_F_I2B_PVK, PEM_R_BAD_PASSWORD_READ);
+            goto error;
+        }
+        if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN,
+                            (unsigned char *)psbuf, inlen))
+            goto error;
+        if (enclevel == 1)
+            memset(keybuf + 5, 0, 11);
+        p = salt + PVK_SALTLEN + 8;
+        if (!EVP_EncryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+            goto error;
+        OPENSSL_cleanse(keybuf, 20);
+        if (!EVP_DecryptUpdate(cctx, p, &enctmplen, p, pklen - 8))
+            goto error;
+        if (!EVP_DecryptFinal_ex(cctx, p + enctmplen, &enctmplen))
+            goto error;
+    }
+    EVP_CIPHER_CTX_free(cctx);
+    return outlen;
+
+ error:
+    EVP_CIPHER_CTX_free(cctx);
+    return -1;
+}
 
 int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel,
-               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;
-       }
+                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
+
+#endif