1221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * project 2005. 3221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */ 4221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* ==================================================================== 5221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Copyright (c) 2005 The OpenSSL Project. All rights reserved. 6221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 7221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Redistribution and use in source and binary forms, with or without 8221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * modification, are permitted provided that the following conditions 9221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * are met: 10221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 11221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 1. Redistributions of source code must retain the above copyright 12221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * notice, this list of conditions and the following disclaimer. 13221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 14221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 2. Redistributions in binary form must reproduce the above copyright 15221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * notice, this list of conditions and the following disclaimer in 16221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * the documentation and/or other materials provided with the 17221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * distribution. 18221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 19221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 3. All advertising materials mentioning features or use of this 20221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * software must display the following acknowledgment: 21221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * "This product includes software developed by the OpenSSL Project 22221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 23221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 24221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * endorse or promote products derived from this software without 26221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * prior written permission. For written permission, please contact 27221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * licensing@OpenSSL.org. 28221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 29221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 5. Products derived from this software may not be called "OpenSSL" 30221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * nor may "OpenSSL" appear in their names without prior written 31221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * permission of the OpenSSL Project. 32221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 33221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 6. Redistributions of any form whatsoever must retain the following 34221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * acknowledgment: 35221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * "This product includes software developed by the OpenSSL Project 36221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 37221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 38221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * OF THE POSSIBILITY OF SUCH DAMAGE. 50221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ==================================================================== 51221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 52221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * This product includes cryptographic software written by Eric Young 53221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * (eay@cryptsoft.com). This product includes software written by Tim 54221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Hudson (tjh@cryptsoft.com). 55221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 56221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */ 57221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 58221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Support for PVK format keys and related structures (such a PUBLICKEYBLOB 59221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * and PRIVATEKEYBLOB). 60221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */ 61221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 62221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "cryptlib.h" 63221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/pem.h> 64221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/rand.h> 65221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/bn.h> 66221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) 67221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/dsa.h> 68221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/rsa.h> 69221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 70221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Utility function: read a DWORD (4 byte unsigned integer) in little endian 71221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * format 72221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */ 73221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 74221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic unsigned int read_ledword(const unsigned char **in) 75221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 76221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *p = *in; 77221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int ret; 78221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret = *p++; 79221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret |= (*p++ << 8); 80221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret |= (*p++ << 16); 81221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret |= (*p++ << 24); 82221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *in = p; 83221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return ret; 84221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 85221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 86221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Read a BIGNUM in little endian format. The docs say that this should take up 87221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * bitlen/8 bytes. 88221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */ 89221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 90221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r) 91221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 92221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *p; 93221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char *tmpbuf, *q; 94221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int i; 95221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = *in + nbyte - 1; 96221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom tmpbuf = OPENSSL_malloc(nbyte); 97221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!tmpbuf) 98221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 99221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom q = tmpbuf; 100221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom for (i = 0; i < nbyte; i++) 101221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *q++ = *p--; 102221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *r = BN_bin2bn(tmpbuf, nbyte, NULL); 103221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_free(tmpbuf); 104221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (*r) 105221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 106221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *in += nbyte; 107221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 1; 108221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 109221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 110221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 111221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 112221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 113221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 114221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */ 115221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 116221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_PUBLICKEYBLOB 0x6 117221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_PRIVATEKEYBLOB 0x7 118221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_RSA1MAGIC 0x31415352L 119221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_RSA2MAGIC 0x32415352L 120221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_DSS1MAGIC 0x31535344L 121221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_DSS2MAGIC 0x32535344L 122221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 123221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_KEYALG_RSA_KEYX 0xa400 124221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_KEYALG_DSS_SIGN 0x2200 125221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 126221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_KEYTYPE_KEYX 0x1 127221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_KEYTYPE_SIGN 0x2 128221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 129221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */ 130221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_PVKMAGIC 0xb0b5f11eL 131221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Salt length for PVK files */ 132221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define PVK_SALTLEN 0x10 133221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 134221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length, 135221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int bitlen, int ispub); 136221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length, 137221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int bitlen, int ispub); 138221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 139221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int do_blob_header(const unsigned char **in, unsigned int length, 140221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int *pmagic, unsigned int *pbitlen, 141221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int *pisdss, int *pispub) 142221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 143221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *p = *in; 144221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (length < 16) 145221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 146221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* bType */ 147221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (*p == MS_PUBLICKEYBLOB) 148221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 149221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (*pispub == 0) 150221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 151221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_BLOB_HEADER, 152221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEM_R_EXPECTING_PRIVATE_KEY_BLOB); 153221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 154221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 155221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pispub = 1; 156221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 157221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else if (*p == MS_PRIVATEKEYBLOB) 158221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 159221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (*pispub == 1) 160221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 161221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_BLOB_HEADER, 162221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEM_R_EXPECTING_PUBLIC_KEY_BLOB); 163221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 164221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 165221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pispub = 0; 166221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 167221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 168221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 169221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p++; 170221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Version */ 171221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (*p++ != 0x2) 172221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 173221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_VERSION_NUMBER); 174221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 175221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 176221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Ignore reserved, aiKeyAlg */ 177221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p+= 6; 178221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pmagic = read_ledword(&p); 179221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pbitlen = read_ledword(&p); 180221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pisdss = 0; 181221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom switch (*pmagic) 182221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 183221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 184221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom case MS_DSS1MAGIC: 185221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pisdss = 1; 186221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom case MS_RSA1MAGIC: 187221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (*pispub == 0) 188221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 189221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_BLOB_HEADER, 190221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEM_R_EXPECTING_PRIVATE_KEY_BLOB); 191221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 192221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 193221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom break; 194221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 195221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom case MS_DSS2MAGIC: 196221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pisdss = 1; 197221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom case MS_RSA2MAGIC: 198221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (*pispub == 1) 199221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 200221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_BLOB_HEADER, 201221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEM_R_EXPECTING_PUBLIC_KEY_BLOB); 202221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 203221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 204221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom break; 205221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 206221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom default: 207221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_MAGIC_NUMBER); 208221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 209221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 210221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *in = p; 211221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 1; 212221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 213221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 214221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic unsigned int blob_length(unsigned bitlen, int isdss, int ispub) 215221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 216221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int nbyte, hnbyte; 217221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom nbyte = (bitlen + 7) >> 3; 218221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom hnbyte = (bitlen + 15) >> 4; 219221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (isdss) 220221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 221221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 222221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Expected length: 20 for q + 3 components bitlen each + 24 223221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * for seed structure. 224221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */ 225221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ispub) 226221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 44 + 3 * nbyte; 227221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Expected length: 20 for q, priv, 2 bitlen components + 24 228221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * for seed structure. 229221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */ 230221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 231221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 64 + 2 * nbyte; 232221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 233221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 234221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 235221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Expected length: 4 for 'e' + 'n' */ 236221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ispub) 237221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 4 + nbyte; 238221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 239221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Expected length: 4 for 'e' and 7 other components. 240221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 2 components are bitlen size, 5 are bitlen/2 241221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */ 242221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 4 + 2*nbyte + 5*hnbyte; 243221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 244221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 245221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 246221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 247221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length, 248221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int ispub) 249221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 250221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *p = *in; 251221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int bitlen, magic; 252221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int isdss; 253221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0) 254221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 255221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_HEADER_PARSE_ERROR); 256221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return NULL; 257221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 258221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom length -= 16; 259221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (length < blob_length(bitlen, isdss, ispub)) 260221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 261221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_TOO_SHORT); 262221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return NULL; 263221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 264221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (isdss) 265221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return b2i_dss(&p, length, bitlen, ispub); 266221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 267221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return b2i_rsa(&p, length, bitlen, ispub); 268221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 269221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 270221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *do_b2i_bio(BIO *in, int ispub) 271221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 272221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *p; 273221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char hdr_buf[16], *buf = NULL; 274221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int bitlen, magic, length; 275221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int isdss; 276221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_PKEY *ret = NULL; 277221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (BIO_read(in, hdr_buf, 16) != 16) 278221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 279221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT); 280221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return NULL; 281221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 282221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = hdr_buf; 283221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0) 284221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return NULL; 285221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 286221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom length = blob_length(bitlen, isdss, ispub); 287221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom buf = OPENSSL_malloc(length); 288221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!buf) 289221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 290221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE); 291221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto err; 292221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 293221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = buf; 294221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (BIO_read(in, buf, length) != (int)length) 295221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 296221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT); 297221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto err; 298221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 299221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 300221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (isdss) 301221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret = b2i_dss(&p, length, bitlen, ispub); 302221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 303221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret = b2i_rsa(&p, length, bitlen, ispub); 304221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 305221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom err: 306221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (buf) 307221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_free(buf); 308221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return ret; 309221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 310221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 311221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length, 312221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int bitlen, int ispub) 313221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 314221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *p = *in; 315221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_PKEY *ret = NULL; 316221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom DSA *dsa = NULL; 317221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom BN_CTX *ctx = NULL; 318221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int nbyte; 319221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom nbyte = (bitlen + 7) >> 3; 320221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 321221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom dsa = DSA_new(); 322221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret = EVP_PKEY_new(); 323221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!dsa || !ret) 324221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 325221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, nbyte, &dsa->p)) 326221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 327221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, 20, &dsa->q)) 328221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 329221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, nbyte, &dsa->g)) 330221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 331221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ispub) 332221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 333221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, nbyte, &dsa->pub_key)) 334221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 335221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 336221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 337221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 338221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, 20, &dsa->priv_key)) 339221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 340221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Calculate public key */ 341221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!(dsa->pub_key = BN_new())) 342221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 343221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!(ctx = BN_CTX_new())) 344221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 345221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 346221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!BN_mod_exp(dsa->pub_key, dsa->g, 347221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom dsa->priv_key, dsa->p, ctx)) 348221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 349221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 350221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom BN_CTX_free(ctx); 351221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 352221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 353221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_PKEY_set1_DSA(ret, dsa); 354221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom DSA_free(dsa); 355221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *in = p; 356221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return ret; 357221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 358221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom memerr: 359221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE); 360221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (dsa) 361221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom DSA_free(dsa); 362221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ret) 363221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_PKEY_free(ret); 364221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ctx) 365221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom BN_CTX_free(ctx); 366221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return NULL; 367221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 368221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 369221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length, 370221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int bitlen, int ispub) 371221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 372221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 373221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *p = *in; 374221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_PKEY *ret = NULL; 375221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom RSA *rsa = NULL; 376221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int nbyte, hnbyte; 377221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom nbyte = (bitlen + 7) >> 3; 378221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom hnbyte = (bitlen + 15) >> 4; 379221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom rsa = RSA_new(); 380221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret = EVP_PKEY_new(); 381221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!rsa || !ret) 382221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 383221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom rsa->e = BN_new(); 384221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!rsa->e) 385221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 386221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!BN_set_word(rsa->e, read_ledword(&p))) 387221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 388221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, nbyte, &rsa->n)) 389221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 390221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!ispub) 391221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 392221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, hnbyte, &rsa->p)) 393221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 394221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, hnbyte, &rsa->q)) 395221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 396221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, hnbyte, &rsa->dmp1)) 397221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 398221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, hnbyte, &rsa->dmq1)) 399221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 400221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, hnbyte, &rsa->iqmp)) 401221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 402221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!read_lebn(&p, nbyte, &rsa->d)) 403221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto memerr; 404221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 405221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 406221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_PKEY_set1_RSA(ret, rsa); 407221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom RSA_free(rsa); 408221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *in = p; 409221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return ret; 410221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom memerr: 411221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE); 412221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (rsa) 413221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom RSA_free(rsa); 414221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ret) 415221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_PKEY_free(ret); 416221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return NULL; 417221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 418221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 419221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromEVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length) 420221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 421221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return do_b2i(in, length, 0); 422221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 423221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 424221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromEVP_PKEY *b2i_PublicKey(const unsigned char **in, long length) 425221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 426221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return do_b2i(in, length, 1); 427221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 428221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 429221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 430221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromEVP_PKEY *b2i_PrivateKey_bio(BIO *in) 431221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 432221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return do_b2i_bio(in, 0); 433221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 434221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 435221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromEVP_PKEY *b2i_PublicKey_bio(BIO *in) 436221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 437221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return do_b2i_bio(in, 1); 438221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 439221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 440221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_ledword(unsigned char **out, unsigned int dw) 441221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 442221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char *p = *out; 443221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *p++ = dw & 0xff; 444221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *p++ = (dw>>8) & 0xff; 445221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *p++ = (dw>>16) & 0xff; 446221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *p++ = (dw>>24) & 0xff; 447221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *out = p; 448221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 449221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 450221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_lebn(unsigned char **out, const BIGNUM *bn, int len) 451221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 452221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int nb, i; 453221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char *p = *out, *q, c; 454221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom nb = BN_num_bytes(bn); 455221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom BN_bn2bin(bn, p); 456221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom q = p + nb - 1; 457221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* In place byte order reversal */ 458221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom for (i = 0; i < nb/2; i++) 459221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 460221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom c = *p; 461221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *p++ = *q; 462221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *q-- = c; 463221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 464221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *out += nb; 465221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Pad with zeroes if we have to */ 466221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (len > 0) 467221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 468221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom len -= nb; 469221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (len > 0) 470221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 471221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom memset(*out, 0, len); 472221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *out += len; 473221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 474221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 475221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 476221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 477221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 478221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *magic); 479221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *magic); 480221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 481221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_rsa(unsigned char **out, RSA *rsa, int ispub); 482221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_dsa(unsigned char **out, DSA *dsa, int ispub); 483221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 484221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub) 485221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 486221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char *p; 487221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int bitlen, magic = 0, keyalg; 488221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int outlen, noinc = 0; 489221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (pk->type == EVP_PKEY_DSA) 490221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 491221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom bitlen = check_bitlen_dsa(pk->pkey.dsa, ispub, &magic); 492221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom keyalg = MS_KEYALG_DSS_SIGN; 493221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 494221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else if (pk->type == EVP_PKEY_RSA) 495221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 496221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom bitlen = check_bitlen_rsa(pk->pkey.rsa, ispub, &magic); 497221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom keyalg = MS_KEYALG_RSA_KEYX; 498221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 499221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 500221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 501221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (bitlen == 0) 502221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 503221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom outlen = 16 + blob_length(bitlen, 504221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub); 505221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (out == NULL) 506221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return outlen; 507221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (*out) 508221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = *out; 509221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 510221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 511221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = OPENSSL_malloc(outlen); 512221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!p) 513221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 514221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *out = p; 515221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom noinc = 1; 516221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 517221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ispub) 518221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *p++ = MS_PUBLICKEYBLOB; 519221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 520221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *p++ = MS_PRIVATEKEYBLOB; 521221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *p++ = 0x2; 522221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *p++ = 0; 523221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *p++ = 0; 524221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_ledword(&p, keyalg); 525221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_ledword(&p, magic); 526221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_ledword(&p, bitlen); 527221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (keyalg == MS_KEYALG_DSS_SIGN) 528221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_dsa(&p, pk->pkey.dsa, ispub); 529221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 530221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_rsa(&p, pk->pkey.rsa, ispub); 531221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!noinc) 532221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *out += outlen; 533221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return outlen; 534221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 535221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 536221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub) 537221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 538221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char *tmp = NULL; 539221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int outlen, wrlen; 540221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom outlen = do_i2b(&tmp, pk, ispub); 541221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (outlen < 0) 542221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 543221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom wrlen = BIO_write(out, tmp, outlen); 544221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_free(tmp); 545221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (wrlen == outlen) 546221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return outlen; 547221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 548221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 549221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 550221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic) 551221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 552221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int bitlen; 553221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom bitlen = BN_num_bits(dsa->p); 554221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if ((bitlen & 7) || (BN_num_bits(dsa->q) != 160) 555221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom || (BN_num_bits(dsa->g) > bitlen)) 556221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto badkey; 557221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ispub) 558221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 559221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (BN_num_bits(dsa->pub_key) > bitlen) 560221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto badkey; 561221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pmagic = MS_DSS1MAGIC; 562221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 563221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 564221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 565221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (BN_num_bits(dsa->priv_key) > 160) 566221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto badkey; 567221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pmagic = MS_DSS2MAGIC; 568221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 569221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 570221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return bitlen; 571221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom badkey: 572221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS); 573221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 574221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 575221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 576221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic) 577221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 578221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int nbyte, hnbyte, bitlen; 579221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (BN_num_bits(rsa->e) > 32) 580221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto badkey; 581221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom bitlen = BN_num_bits(rsa->n); 582221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom nbyte = BN_num_bytes(rsa->n); 583221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom hnbyte = (BN_num_bits(rsa->n) + 15) >> 4; 584221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ispub) 585221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 586221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pmagic = MS_RSA1MAGIC; 587221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return bitlen; 588221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 589221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 590221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 591221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pmagic = MS_RSA2MAGIC; 592221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* For private key each component must fit within nbyte or 593221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * hnbyte. 594221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */ 595221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (BN_num_bytes(rsa->d) > nbyte) 596221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto badkey; 597221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if ((BN_num_bytes(rsa->iqmp) > hnbyte) 598221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom || (BN_num_bytes(rsa->p) > hnbyte) 599221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom || (BN_num_bytes(rsa->q) > hnbyte) 600221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom || (BN_num_bytes(rsa->dmp1) > hnbyte) 601221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom || (BN_num_bytes(rsa->dmq1) > hnbyte)) 602221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto badkey; 603221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 604221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return bitlen; 605221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom badkey: 606221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS); 607221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 608221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 609221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 610221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 611221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_rsa(unsigned char **out, RSA *rsa, int ispub) 612221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 613221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int nbyte, hnbyte; 614221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom nbyte = BN_num_bytes(rsa->n); 615221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom hnbyte = (BN_num_bits(rsa->n) + 15) >> 4; 616221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, rsa->e, 4); 617221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, rsa->n, -1); 618221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ispub) 619221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return; 620221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, rsa->p, hnbyte); 621221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, rsa->q, hnbyte); 622221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, rsa->dmp1, hnbyte); 623221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, rsa->dmq1, hnbyte); 624221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, rsa->iqmp, hnbyte); 625221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, rsa->d, nbyte); 626221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 627221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 628221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 629221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_dsa(unsigned char **out, DSA *dsa, int ispub) 630221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 631221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int nbyte; 632221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom nbyte = BN_num_bytes(dsa->p); 633221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, dsa->p, nbyte); 634221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, dsa->q, 20); 635221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, dsa->g, nbyte); 636221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (ispub) 637221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, dsa->pub_key, nbyte); 638221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 639221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_lebn(out, dsa->priv_key, 20); 640221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Set "invalid" for seed structure values */ 641221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom memset(*out, 0xff, 24); 642221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *out += 24; 643221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return; 644221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 645221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 646221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 647221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk) 648221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 649221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return do_i2b_bio(out, pk, 0); 650221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 651221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 652221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk) 653221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 654221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return do_i2b_bio(out, pk, 1); 655221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 656221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 6573d3a1b8fcf46ca3bdb3d8f09acd6ef604624a30dBrian Carlstrom#ifndef OPENSSL_NO_RC4 6583d3a1b8fcf46ca3bdb3d8f09acd6ef604624a30dBrian Carlstrom 659221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int do_PVK_header(const unsigned char **in, unsigned int length, 660221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int skip_magic, 661221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int *psaltlen, unsigned int *pkeylen) 662221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 663221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 664221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *p = *in; 665221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int pvk_magic, keytype, is_encrypted; 666221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (skip_magic) 667221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 668221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (length < 20) 669221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 670221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT); 671221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 672221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 673221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom length -= 20; 674221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 675221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 676221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 677221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (length < 24) 678221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 679221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT); 680221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 681221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 682221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom length -= 24; 683221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom pvk_magic = read_ledword(&p); 684221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (pvk_magic != MS_PVKMAGIC) 685221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 686221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER); 687221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 688221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 689221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 690221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Skip reserved */ 691221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p += 4; 692221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom keytype = read_ledword(&p); 693221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom is_encrypted = read_ledword(&p); 694221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *psaltlen = read_ledword(&p); 695221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *pkeylen = read_ledword(&p); 696221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 697221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (is_encrypted && !*psaltlen) 698221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 699221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER); 700221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 701221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 702221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 703221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *in = p; 704221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 1; 705221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 706221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 707221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int derive_pvk_key(unsigned char *key, 708221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *salt, unsigned int saltlen, 709221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *pass, int passlen) 710221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 711221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_MD_CTX mctx; 712221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_MD_CTX_init(&mctx); 713221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DigestInit_ex(&mctx, EVP_sha1(), NULL); 714221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DigestUpdate(&mctx, salt, saltlen); 715221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DigestUpdate(&mctx, pass, passlen); 716221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DigestFinal_ex(&mctx, key, NULL); 717221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_MD_CTX_cleanup(&mctx); 718221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 1; 719221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 720221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 721221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 722221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *do_PVK_body(const unsigned char **in, 723221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int saltlen, unsigned int keylen, 724221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom pem_password_cb *cb, void *u) 725221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 726221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_PKEY *ret = NULL; 727221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *p = *in; 728221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int magic; 729221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char *enctmp = NULL, *q; 730221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (saltlen) 731221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 732221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom char psbuf[PEM_BUFSIZE]; 733221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char keybuf[20]; 734221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_CIPHER_CTX cctx; 735221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int enctmplen, inlen; 736221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (cb) 737221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom inlen=cb(psbuf,PEM_BUFSIZE,0,u); 738221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 739221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom inlen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u); 740221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (inlen <= 0) 741221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 742221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_PVK_BODY,PEM_R_BAD_PASSWORD_READ); 743221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return NULL; 744221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 745221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom enctmp = OPENSSL_malloc(keylen + 8); 746221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!enctmp) 747221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 748221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE); 749221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return NULL; 750221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 751221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!derive_pvk_key(keybuf, p, saltlen, 752221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom (unsigned char *)psbuf, inlen)) 753221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return NULL; 754221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p += saltlen; 755221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Copy BLOBHEADER across, decrypt rest */ 756221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom memcpy(enctmp, p, 8); 757221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p += 8; 758221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom inlen = keylen - 8; 759221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom q = enctmp + 8; 760221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_CIPHER_CTX_init(&cctx); 761221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL); 762221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen); 763221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen); 764221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom magic = read_ledword((const unsigned char **)&q); 765221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) 766221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 767221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom q = enctmp + 8; 768221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom memset(keybuf + 5, 0, 11); 769221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, 770221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom NULL); 771221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_cleanse(keybuf, 20); 772221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen); 773221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DecryptFinal_ex(&cctx, q + enctmplen, 774221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom &enctmplen); 775221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom magic = read_ledword((const unsigned char **)&q); 776221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) 777221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 778221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_CIPHER_CTX_cleanup(&cctx); 779221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT); 780221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto err; 781221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 782221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 783221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 784221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_cleanse(keybuf, 20); 785221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_CIPHER_CTX_cleanup(&cctx); 786221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = enctmp; 787221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 788221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 789221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret = b2i_PrivateKey(&p, keylen); 790221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom err: 791221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (enctmp && saltlen) 792221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_free(enctmp); 793221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return ret; 794221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 795221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 796221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 797221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromEVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u) 798221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 799221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char pvk_hdr[24], *buf = NULL; 800221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const unsigned char *p; 801221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int buflen; 802221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_PKEY *ret = NULL; 803221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned int saltlen, keylen; 804221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (BIO_read(in, pvk_hdr, 24) != 24) 805221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 806221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT); 807221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return NULL; 808221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 809221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = pvk_hdr; 810221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 811221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!do_PVK_header(&p, 24, 0, &saltlen, &keylen)) 812221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 813221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom buflen = (int) keylen + saltlen; 814221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom buf = OPENSSL_malloc(buflen); 815221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!buf) 816221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 817221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_B2I_PVK_BIO, ERR_R_MALLOC_FAILURE); 818221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 819221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 820221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = buf; 821221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (BIO_read(in, buf, buflen) != buflen) 822221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 823221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT); 824221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto err; 825221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 826221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret = do_PVK_body(&p, saltlen, keylen, cb, u); 827221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 828221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom err: 829221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (buf) 830221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 831221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_cleanse(buf, buflen); 832221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_free(buf); 833221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 834221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return ret; 835221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 836221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 837221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 838221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 839221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int i2b_PVK(unsigned char **out, EVP_PKEY*pk, int enclevel, 840221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom pem_password_cb *cb, void *u) 841221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 842221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int outlen = 24, noinc, pklen; 843221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char *p, *salt = NULL; 844221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (enclevel) 845221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom outlen += PVK_SALTLEN; 846221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom pklen = do_i2b(NULL, pk, 0); 847221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (pklen < 0) 848221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 849221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom outlen += pklen; 850221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!out) 851221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return outlen; 852221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (*out) 853221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 854221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = *out; 855221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom noinc = 0; 856221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 857221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 858221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 859221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = OPENSSL_malloc(outlen); 860221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!p) 861221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 862221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_I2B_PVK,ERR_R_MALLOC_FAILURE); 863221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 864221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 865221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *out = p; 866221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom noinc = 1; 867221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 868221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 869221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_ledword(&p, MS_PVKMAGIC); 870221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_ledword(&p, 0); 871221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (pk->type == EVP_PKEY_DSA) 872221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_ledword(&p, MS_KEYTYPE_SIGN); 873221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 874221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_ledword(&p, MS_KEYTYPE_KEYX); 875221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_ledword(&p, enclevel ? 1 : 0); 876221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_ledword(&p, enclevel ? PVK_SALTLEN: 0); 877221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom write_ledword(&p, pklen); 878221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (enclevel) 879221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 880221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (RAND_bytes(p, PVK_SALTLEN) <= 0) 881221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto error; 882221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom salt = p; 883221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p += PVK_SALTLEN; 884221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 885221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom do_i2b(&p, pk, 0); 886221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (enclevel == 0) 887221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return outlen; 888221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 889221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 890221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom char psbuf[PEM_BUFSIZE]; 891221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char keybuf[20]; 892221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_CIPHER_CTX cctx; 893221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int enctmplen, inlen; 894221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (cb) 895221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom inlen=cb(psbuf,PEM_BUFSIZE,1,u); 896221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 897221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom inlen=PEM_def_callback(psbuf,PEM_BUFSIZE,1,u); 898221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (inlen <= 0) 899221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 900221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_I2B_PVK,PEM_R_BAD_PASSWORD_READ); 901221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto error; 902221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 903221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN, 904221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom (unsigned char *)psbuf, inlen)) 905221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto error; 906221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (enclevel == 1) 907221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom memset(keybuf + 5, 0, 11); 908221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom p = salt + PVK_SALTLEN + 8; 909221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_CIPHER_CTX_init(&cctx); 910221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_EncryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL); 911221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_cleanse(keybuf, 20); 912221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DecryptUpdate(&cctx, p, &enctmplen, p, pklen - 8); 913221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_DecryptFinal_ex(&cctx, p + enctmplen, &enctmplen); 914221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom EVP_CIPHER_CTX_cleanup(&cctx); 915221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 916221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return outlen; 917221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 918221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom error: 919221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 920221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 921221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 922221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, 923221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom pem_password_cb *cb, void *u) 924221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 925221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom unsigned char *tmp = NULL; 926221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int outlen, wrlen; 927221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom outlen = i2b_PVK(&tmp, pk, enclevel, cb, u); 928221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (outlen < 0) 929221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 930221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom wrlen = BIO_write(out, tmp, outlen); 931221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_free(tmp); 932221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (wrlen == outlen) 933221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 934221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE); 935221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return outlen; 936221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 937221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return -1; 938221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 9393d3a1b8fcf46ca3bdb3d8f09acd6ef604624a30dBrian Carlstrom 9403d3a1b8fcf46ca3bdb3d8f09acd6ef604624a30dBrian Carlstrom#endif 9413d3a1b8fcf46ca3bdb3d8f09acd6ef604624a30dBrian Carlstrom 942221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif 943