1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* 11e1051a39Sopenharmony_ci * Support for PVK format keys and related structures (such a PUBLICKEYBLOB 12e1051a39Sopenharmony_ci * and PRIVATEKEYBLOB). 13e1051a39Sopenharmony_ci */ 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_ci/* 16e1051a39Sopenharmony_ci * RSA and DSA low level APIs are deprecated for public use, but still ok for 17e1051a39Sopenharmony_ci * internal use. 18e1051a39Sopenharmony_ci */ 19e1051a39Sopenharmony_ci#include "internal/deprecated.h" 20e1051a39Sopenharmony_ci 21e1051a39Sopenharmony_ci#include <openssl/pem.h> 22e1051a39Sopenharmony_ci#include <openssl/rand.h> 23e1051a39Sopenharmony_ci#include <openssl/bn.h> 24e1051a39Sopenharmony_ci#include <openssl/dsa.h> 25e1051a39Sopenharmony_ci#include <openssl/rsa.h> 26e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 27e1051a39Sopenharmony_ci#include "crypto/pem.h" 28e1051a39Sopenharmony_ci#include "crypto/evp.h" 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ci/* 31e1051a39Sopenharmony_ci * Utility function: read a DWORD (4 byte unsigned integer) in little endian 32e1051a39Sopenharmony_ci * format 33e1051a39Sopenharmony_ci */ 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_cistatic unsigned int read_ledword(const unsigned char **in) 36e1051a39Sopenharmony_ci{ 37e1051a39Sopenharmony_ci const unsigned char *p = *in; 38e1051a39Sopenharmony_ci unsigned int ret; 39e1051a39Sopenharmony_ci 40e1051a39Sopenharmony_ci ret = (unsigned int)*p++; 41e1051a39Sopenharmony_ci ret |= (unsigned int)*p++ << 8; 42e1051a39Sopenharmony_ci ret |= (unsigned int)*p++ << 16; 43e1051a39Sopenharmony_ci ret |= (unsigned int)*p++ << 24; 44e1051a39Sopenharmony_ci *in = p; 45e1051a39Sopenharmony_ci return ret; 46e1051a39Sopenharmony_ci} 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci/* 49e1051a39Sopenharmony_ci * Read a BIGNUM in little endian format. The docs say that this should take 50e1051a39Sopenharmony_ci * up bitlen/8 bytes. 51e1051a39Sopenharmony_ci */ 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_cistatic int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r) 54e1051a39Sopenharmony_ci{ 55e1051a39Sopenharmony_ci *r = BN_lebin2bn(*in, nbyte, NULL); 56e1051a39Sopenharmony_ci if (*r == NULL) 57e1051a39Sopenharmony_ci return 0; 58e1051a39Sopenharmony_ci *in += nbyte; 59e1051a39Sopenharmony_ci return 1; 60e1051a39Sopenharmony_ci} 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci/* 63e1051a39Sopenharmony_ci * Create an EVP_PKEY from a type specific key. 64e1051a39Sopenharmony_ci * This takes ownership of |key|, as long as the |evp_type| is acceptable 65e1051a39Sopenharmony_ci * (EVP_PKEY_RSA or EVP_PKEY_DSA), even if the resulting EVP_PKEY wasn't 66e1051a39Sopenharmony_ci * created. 67e1051a39Sopenharmony_ci */ 68e1051a39Sopenharmony_ci#define isdss_to_evp_type(isdss) \ 69e1051a39Sopenharmony_ci (isdss == 0 ? EVP_PKEY_RSA : isdss == 1 ? EVP_PKEY_DSA : EVP_PKEY_NONE) 70e1051a39Sopenharmony_cistatic EVP_PKEY *evp_pkey_new0_key(void *key, int evp_type) 71e1051a39Sopenharmony_ci{ 72e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ci /* 75e1051a39Sopenharmony_ci * It's assumed that if |key| is NULL, something went wrong elsewhere 76e1051a39Sopenharmony_ci * and suitable errors are already reported. 77e1051a39Sopenharmony_ci */ 78e1051a39Sopenharmony_ci if (key == NULL) 79e1051a39Sopenharmony_ci return NULL; 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci if (!ossl_assert(evp_type == EVP_PKEY_RSA || evp_type == EVP_PKEY_DSA)) { 82e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_INTERNAL_ERROR); 83e1051a39Sopenharmony_ci return NULL; 84e1051a39Sopenharmony_ci } 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci if ((pkey = EVP_PKEY_new()) != NULL) { 87e1051a39Sopenharmony_ci switch (evp_type) { 88e1051a39Sopenharmony_ci case EVP_PKEY_RSA: 89e1051a39Sopenharmony_ci if (EVP_PKEY_set1_RSA(pkey, key)) 90e1051a39Sopenharmony_ci break; 91e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 92e1051a39Sopenharmony_ci pkey = NULL; 93e1051a39Sopenharmony_ci break; 94e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 95e1051a39Sopenharmony_ci case EVP_PKEY_DSA: 96e1051a39Sopenharmony_ci if (EVP_PKEY_set1_DSA(pkey, key)) 97e1051a39Sopenharmony_ci break; 98e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 99e1051a39Sopenharmony_ci pkey = NULL; 100e1051a39Sopenharmony_ci break; 101e1051a39Sopenharmony_ci#endif 102e1051a39Sopenharmony_ci } 103e1051a39Sopenharmony_ci } 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_ci switch (evp_type) { 106e1051a39Sopenharmony_ci case EVP_PKEY_RSA: 107e1051a39Sopenharmony_ci RSA_free(key); 108e1051a39Sopenharmony_ci break; 109e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 110e1051a39Sopenharmony_ci case EVP_PKEY_DSA: 111e1051a39Sopenharmony_ci DSA_free(key); 112e1051a39Sopenharmony_ci break; 113e1051a39Sopenharmony_ci#endif 114e1051a39Sopenharmony_ci } 115e1051a39Sopenharmony_ci 116e1051a39Sopenharmony_ci if (pkey == NULL) 117e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 118e1051a39Sopenharmony_ci return pkey; 119e1051a39Sopenharmony_ci} 120e1051a39Sopenharmony_ci 121e1051a39Sopenharmony_ci/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */ 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci# define MS_PUBLICKEYBLOB 0x6 124e1051a39Sopenharmony_ci# define MS_PRIVATEKEYBLOB 0x7 125e1051a39Sopenharmony_ci# define MS_RSA1MAGIC 0x31415352L 126e1051a39Sopenharmony_ci# define MS_RSA2MAGIC 0x32415352L 127e1051a39Sopenharmony_ci# define MS_DSS1MAGIC 0x31535344L 128e1051a39Sopenharmony_ci# define MS_DSS2MAGIC 0x32535344L 129e1051a39Sopenharmony_ci 130e1051a39Sopenharmony_ci# define MS_KEYALG_RSA_KEYX 0xa400 131e1051a39Sopenharmony_ci# define MS_KEYALG_DSS_SIGN 0x2200 132e1051a39Sopenharmony_ci 133e1051a39Sopenharmony_ci# define MS_KEYTYPE_KEYX 0x1 134e1051a39Sopenharmony_ci# define MS_KEYTYPE_SIGN 0x2 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */ 137e1051a39Sopenharmony_ci# define MS_PVKMAGIC 0xb0b5f11eL 138e1051a39Sopenharmony_ci/* Salt length for PVK files */ 139e1051a39Sopenharmony_ci# define PVK_SALTLEN 0x10 140e1051a39Sopenharmony_ci/* Maximum length in PVK header */ 141e1051a39Sopenharmony_ci# define PVK_MAX_KEYLEN 102400 142e1051a39Sopenharmony_ci/* Maximum salt length */ 143e1051a39Sopenharmony_ci# define PVK_MAX_SALTLEN 10240 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci/* 146e1051a39Sopenharmony_ci * Read the MSBLOB header and get relevant data from it. 147e1051a39Sopenharmony_ci * 148e1051a39Sopenharmony_ci * |pisdss| and |pispub| have a double role, as they can be used for 149e1051a39Sopenharmony_ci * discovery as well as to check the the blob meets expectations. 150e1051a39Sopenharmony_ci * |*pisdss| is the indicator for whether the key is a DSA key or not. 151e1051a39Sopenharmony_ci * |*pispub| is the indicator for whether the key is public or not. 152e1051a39Sopenharmony_ci * In both cases, the following input values apply: 153e1051a39Sopenharmony_ci * 154e1051a39Sopenharmony_ci * 0 Expected to not be what the variable indicates. 155e1051a39Sopenharmony_ci * 1 Expected to be what the variable indicates. 156e1051a39Sopenharmony_ci * -1 No expectations, this function will assign 0 or 1 depending on 157e1051a39Sopenharmony_ci * header data. 158e1051a39Sopenharmony_ci */ 159e1051a39Sopenharmony_ciint ossl_do_blob_header(const unsigned char **in, unsigned int length, 160e1051a39Sopenharmony_ci unsigned int *pmagic, unsigned int *pbitlen, 161e1051a39Sopenharmony_ci int *pisdss, int *pispub) 162e1051a39Sopenharmony_ci{ 163e1051a39Sopenharmony_ci const unsigned char *p = *in; 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_ci if (length < 16) 166e1051a39Sopenharmony_ci return 0; 167e1051a39Sopenharmony_ci /* bType */ 168e1051a39Sopenharmony_ci switch (*p) { 169e1051a39Sopenharmony_ci case MS_PUBLICKEYBLOB: 170e1051a39Sopenharmony_ci if (*pispub == 0) { 171e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_PRIVATE_KEY_BLOB); 172e1051a39Sopenharmony_ci return 0; 173e1051a39Sopenharmony_ci } 174e1051a39Sopenharmony_ci *pispub = 1; 175e1051a39Sopenharmony_ci break; 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_ci case MS_PRIVATEKEYBLOB: 178e1051a39Sopenharmony_ci if (*pispub == 1) { 179e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_PUBLIC_KEY_BLOB); 180e1051a39Sopenharmony_ci return 0; 181e1051a39Sopenharmony_ci } 182e1051a39Sopenharmony_ci *pispub = 0; 183e1051a39Sopenharmony_ci break; 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ci default: 186e1051a39Sopenharmony_ci return 0; 187e1051a39Sopenharmony_ci } 188e1051a39Sopenharmony_ci p++; 189e1051a39Sopenharmony_ci /* Version */ 190e1051a39Sopenharmony_ci if (*p++ != 0x2) { 191e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_BAD_VERSION_NUMBER); 192e1051a39Sopenharmony_ci return 0; 193e1051a39Sopenharmony_ci } 194e1051a39Sopenharmony_ci /* Ignore reserved, aiKeyAlg */ 195e1051a39Sopenharmony_ci p += 6; 196e1051a39Sopenharmony_ci *pmagic = read_ledword(&p); 197e1051a39Sopenharmony_ci *pbitlen = read_ledword(&p); 198e1051a39Sopenharmony_ci 199e1051a39Sopenharmony_ci /* Consistency check for private vs public */ 200e1051a39Sopenharmony_ci switch (*pmagic) { 201e1051a39Sopenharmony_ci case MS_DSS1MAGIC: 202e1051a39Sopenharmony_ci case MS_RSA1MAGIC: 203e1051a39Sopenharmony_ci if (*pispub == 0) { 204e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_PRIVATE_KEY_BLOB); 205e1051a39Sopenharmony_ci return 0; 206e1051a39Sopenharmony_ci } 207e1051a39Sopenharmony_ci break; 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_ci case MS_DSS2MAGIC: 210e1051a39Sopenharmony_ci case MS_RSA2MAGIC: 211e1051a39Sopenharmony_ci if (*pispub == 1) { 212e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_PUBLIC_KEY_BLOB); 213e1051a39Sopenharmony_ci return 0; 214e1051a39Sopenharmony_ci } 215e1051a39Sopenharmony_ci break; 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ci default: 218e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_BAD_MAGIC_NUMBER); 219e1051a39Sopenharmony_ci return -1; 220e1051a39Sopenharmony_ci } 221e1051a39Sopenharmony_ci 222e1051a39Sopenharmony_ci /* Check that we got the expected type */ 223e1051a39Sopenharmony_ci switch (*pmagic) { 224e1051a39Sopenharmony_ci case MS_DSS1MAGIC: 225e1051a39Sopenharmony_ci case MS_DSS2MAGIC: 226e1051a39Sopenharmony_ci if (*pisdss == 0) { 227e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_DSS_KEY_BLOB); 228e1051a39Sopenharmony_ci return 0; 229e1051a39Sopenharmony_ci } 230e1051a39Sopenharmony_ci *pisdss = 1; 231e1051a39Sopenharmony_ci break; 232e1051a39Sopenharmony_ci case MS_RSA1MAGIC: 233e1051a39Sopenharmony_ci case MS_RSA2MAGIC: 234e1051a39Sopenharmony_ci if (*pisdss == 1) { 235e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_RSA_KEY_BLOB); 236e1051a39Sopenharmony_ci return 0; 237e1051a39Sopenharmony_ci } 238e1051a39Sopenharmony_ci *pisdss = 0; 239e1051a39Sopenharmony_ci break; 240e1051a39Sopenharmony_ci 241e1051a39Sopenharmony_ci default: 242e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_BAD_MAGIC_NUMBER); 243e1051a39Sopenharmony_ci return -1; 244e1051a39Sopenharmony_ci } 245e1051a39Sopenharmony_ci *in = p; 246e1051a39Sopenharmony_ci return 1; 247e1051a39Sopenharmony_ci} 248e1051a39Sopenharmony_ci 249e1051a39Sopenharmony_ciunsigned int ossl_blob_length(unsigned bitlen, int isdss, int ispub) 250e1051a39Sopenharmony_ci{ 251e1051a39Sopenharmony_ci unsigned int nbyte = (bitlen + 7) >> 3; 252e1051a39Sopenharmony_ci unsigned int hnbyte = (bitlen + 15) >> 4; 253e1051a39Sopenharmony_ci 254e1051a39Sopenharmony_ci if (isdss) { 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci /* 257e1051a39Sopenharmony_ci * Expected length: 20 for q + 3 components bitlen each + 24 for seed 258e1051a39Sopenharmony_ci * structure. 259e1051a39Sopenharmony_ci */ 260e1051a39Sopenharmony_ci if (ispub) 261e1051a39Sopenharmony_ci return 44 + 3 * nbyte; 262e1051a39Sopenharmony_ci /* 263e1051a39Sopenharmony_ci * Expected length: 20 for q, priv, 2 bitlen components + 24 for seed 264e1051a39Sopenharmony_ci * structure. 265e1051a39Sopenharmony_ci */ 266e1051a39Sopenharmony_ci else 267e1051a39Sopenharmony_ci return 64 + 2 * nbyte; 268e1051a39Sopenharmony_ci } else { 269e1051a39Sopenharmony_ci /* Expected length: 4 for 'e' + 'n' */ 270e1051a39Sopenharmony_ci if (ispub) 271e1051a39Sopenharmony_ci return 4 + nbyte; 272e1051a39Sopenharmony_ci else 273e1051a39Sopenharmony_ci /* 274e1051a39Sopenharmony_ci * Expected length: 4 for 'e' and 7 other components. 2 275e1051a39Sopenharmony_ci * components are bitlen size, 5 are bitlen/2 276e1051a39Sopenharmony_ci */ 277e1051a39Sopenharmony_ci return 4 + 2 * nbyte + 5 * hnbyte; 278e1051a39Sopenharmony_ci } 279e1051a39Sopenharmony_ci 280e1051a39Sopenharmony_ci} 281e1051a39Sopenharmony_ci 282e1051a39Sopenharmony_cistatic void *do_b2i_key(const unsigned char **in, unsigned int length, 283e1051a39Sopenharmony_ci int *isdss, int *ispub) 284e1051a39Sopenharmony_ci{ 285e1051a39Sopenharmony_ci const unsigned char *p = *in; 286e1051a39Sopenharmony_ci unsigned int bitlen, magic; 287e1051a39Sopenharmony_ci void *key = NULL; 288e1051a39Sopenharmony_ci 289e1051a39Sopenharmony_ci if (ossl_do_blob_header(&p, length, &magic, &bitlen, isdss, ispub) <= 0) { 290e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_HEADER_PARSE_ERROR); 291e1051a39Sopenharmony_ci return NULL; 292e1051a39Sopenharmony_ci } 293e1051a39Sopenharmony_ci length -= 16; 294e1051a39Sopenharmony_ci if (length < ossl_blob_length(bitlen, *isdss, *ispub)) { 295e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT); 296e1051a39Sopenharmony_ci return NULL; 297e1051a39Sopenharmony_ci } 298e1051a39Sopenharmony_ci if (!*isdss) 299e1051a39Sopenharmony_ci key = ossl_b2i_RSA_after_header(&p, bitlen, *ispub); 300e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 301e1051a39Sopenharmony_ci else 302e1051a39Sopenharmony_ci key = ossl_b2i_DSA_after_header(&p, bitlen, *ispub); 303e1051a39Sopenharmony_ci#endif 304e1051a39Sopenharmony_ci 305e1051a39Sopenharmony_ci if (key == NULL) { 306e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE); 307e1051a39Sopenharmony_ci return NULL; 308e1051a39Sopenharmony_ci } 309e1051a39Sopenharmony_ci 310e1051a39Sopenharmony_ci return key; 311e1051a39Sopenharmony_ci} 312e1051a39Sopenharmony_ci 313e1051a39Sopenharmony_ciEVP_PKEY *ossl_b2i(const unsigned char **in, unsigned int length, int *ispub) 314e1051a39Sopenharmony_ci{ 315e1051a39Sopenharmony_ci int isdss = -1; 316e1051a39Sopenharmony_ci void *key = do_b2i_key(in, length, &isdss, ispub); 317e1051a39Sopenharmony_ci 318e1051a39Sopenharmony_ci return evp_pkey_new0_key(key, isdss_to_evp_type(isdss)); 319e1051a39Sopenharmony_ci} 320e1051a39Sopenharmony_ci 321e1051a39Sopenharmony_ciEVP_PKEY *ossl_b2i_bio(BIO *in, int *ispub) 322e1051a39Sopenharmony_ci{ 323e1051a39Sopenharmony_ci const unsigned char *p; 324e1051a39Sopenharmony_ci unsigned char hdr_buf[16], *buf = NULL; 325e1051a39Sopenharmony_ci unsigned int bitlen, magic, length; 326e1051a39Sopenharmony_ci int isdss = -1; 327e1051a39Sopenharmony_ci void *key = NULL; 328e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 329e1051a39Sopenharmony_ci 330e1051a39Sopenharmony_ci if (BIO_read(in, hdr_buf, 16) != 16) { 331e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT); 332e1051a39Sopenharmony_ci return NULL; 333e1051a39Sopenharmony_ci } 334e1051a39Sopenharmony_ci p = hdr_buf; 335e1051a39Sopenharmony_ci if (ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, ispub) <= 0) 336e1051a39Sopenharmony_ci return NULL; 337e1051a39Sopenharmony_ci 338e1051a39Sopenharmony_ci length = ossl_blob_length(bitlen, isdss, *ispub); 339e1051a39Sopenharmony_ci if (length > BLOB_MAX_LENGTH) { 340e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG); 341e1051a39Sopenharmony_ci return NULL; 342e1051a39Sopenharmony_ci } 343e1051a39Sopenharmony_ci buf = OPENSSL_malloc(length); 344e1051a39Sopenharmony_ci if (buf == NULL) { 345e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 346e1051a39Sopenharmony_ci goto err; 347e1051a39Sopenharmony_ci } 348e1051a39Sopenharmony_ci p = buf; 349e1051a39Sopenharmony_ci if (BIO_read(in, buf, length) != (int)length) { 350e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT); 351e1051a39Sopenharmony_ci goto err; 352e1051a39Sopenharmony_ci } 353e1051a39Sopenharmony_ci 354e1051a39Sopenharmony_ci if (!isdss) 355e1051a39Sopenharmony_ci key = ossl_b2i_RSA_after_header(&p, bitlen, *ispub); 356e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 357e1051a39Sopenharmony_ci else 358e1051a39Sopenharmony_ci key = ossl_b2i_DSA_after_header(&p, bitlen, *ispub); 359e1051a39Sopenharmony_ci#endif 360e1051a39Sopenharmony_ci 361e1051a39Sopenharmony_ci if (key == NULL) { 362e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE); 363e1051a39Sopenharmony_ci goto err; 364e1051a39Sopenharmony_ci } 365e1051a39Sopenharmony_ci 366e1051a39Sopenharmony_ci pkey = evp_pkey_new0_key(key, isdss_to_evp_type(isdss)); 367e1051a39Sopenharmony_ci err: 368e1051a39Sopenharmony_ci OPENSSL_free(buf); 369e1051a39Sopenharmony_ci return pkey; 370e1051a39Sopenharmony_ci} 371e1051a39Sopenharmony_ci 372e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 373e1051a39Sopenharmony_ciDSA *ossl_b2i_DSA_after_header(const unsigned char **in, unsigned int bitlen, 374e1051a39Sopenharmony_ci int ispub) 375e1051a39Sopenharmony_ci{ 376e1051a39Sopenharmony_ci const unsigned char *p = *in; 377e1051a39Sopenharmony_ci DSA *dsa = NULL; 378e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 379e1051a39Sopenharmony_ci BIGNUM *pbn = NULL, *qbn = NULL, *gbn = NULL, *priv_key = NULL; 380e1051a39Sopenharmony_ci BIGNUM *pub_key = NULL; 381e1051a39Sopenharmony_ci unsigned int nbyte = (bitlen + 7) >> 3; 382e1051a39Sopenharmony_ci 383e1051a39Sopenharmony_ci dsa = DSA_new(); 384e1051a39Sopenharmony_ci if (dsa == NULL) 385e1051a39Sopenharmony_ci goto memerr; 386e1051a39Sopenharmony_ci if (!read_lebn(&p, nbyte, &pbn)) 387e1051a39Sopenharmony_ci goto memerr; 388e1051a39Sopenharmony_ci 389e1051a39Sopenharmony_ci if (!read_lebn(&p, 20, &qbn)) 390e1051a39Sopenharmony_ci goto memerr; 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_ci if (!read_lebn(&p, nbyte, &gbn)) 393e1051a39Sopenharmony_ci goto memerr; 394e1051a39Sopenharmony_ci 395e1051a39Sopenharmony_ci if (ispub) { 396e1051a39Sopenharmony_ci if (!read_lebn(&p, nbyte, &pub_key)) 397e1051a39Sopenharmony_ci goto memerr; 398e1051a39Sopenharmony_ci } else { 399e1051a39Sopenharmony_ci if (!read_lebn(&p, 20, &priv_key)) 400e1051a39Sopenharmony_ci goto memerr; 401e1051a39Sopenharmony_ci 402e1051a39Sopenharmony_ci /* Set constant time flag before public key calculation */ 403e1051a39Sopenharmony_ci BN_set_flags(priv_key, BN_FLG_CONSTTIME); 404e1051a39Sopenharmony_ci 405e1051a39Sopenharmony_ci /* Calculate public key */ 406e1051a39Sopenharmony_ci pub_key = BN_new(); 407e1051a39Sopenharmony_ci if (pub_key == NULL) 408e1051a39Sopenharmony_ci goto memerr; 409e1051a39Sopenharmony_ci if ((ctx = BN_CTX_new()) == NULL) 410e1051a39Sopenharmony_ci goto memerr; 411e1051a39Sopenharmony_ci 412e1051a39Sopenharmony_ci if (!BN_mod_exp(pub_key, gbn, priv_key, pbn, ctx)) 413e1051a39Sopenharmony_ci goto memerr; 414e1051a39Sopenharmony_ci 415e1051a39Sopenharmony_ci BN_CTX_free(ctx); 416e1051a39Sopenharmony_ci ctx = NULL; 417e1051a39Sopenharmony_ci } 418e1051a39Sopenharmony_ci if (!DSA_set0_pqg(dsa, pbn, qbn, gbn)) 419e1051a39Sopenharmony_ci goto memerr; 420e1051a39Sopenharmony_ci pbn = qbn = gbn = NULL; 421e1051a39Sopenharmony_ci if (!DSA_set0_key(dsa, pub_key, priv_key)) 422e1051a39Sopenharmony_ci goto memerr; 423e1051a39Sopenharmony_ci pub_key = priv_key = NULL; 424e1051a39Sopenharmony_ci 425e1051a39Sopenharmony_ci *in = p; 426e1051a39Sopenharmony_ci return dsa; 427e1051a39Sopenharmony_ci 428e1051a39Sopenharmony_ci memerr: 429e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 430e1051a39Sopenharmony_ci DSA_free(dsa); 431e1051a39Sopenharmony_ci BN_free(pbn); 432e1051a39Sopenharmony_ci BN_free(qbn); 433e1051a39Sopenharmony_ci BN_free(gbn); 434e1051a39Sopenharmony_ci BN_free(pub_key); 435e1051a39Sopenharmony_ci BN_free(priv_key); 436e1051a39Sopenharmony_ci BN_CTX_free(ctx); 437e1051a39Sopenharmony_ci return NULL; 438e1051a39Sopenharmony_ci} 439e1051a39Sopenharmony_ci#endif 440e1051a39Sopenharmony_ci 441e1051a39Sopenharmony_ciRSA *ossl_b2i_RSA_after_header(const unsigned char **in, unsigned int bitlen, 442e1051a39Sopenharmony_ci int ispub) 443e1051a39Sopenharmony_ci{ 444e1051a39Sopenharmony_ci const unsigned char *pin = *in; 445e1051a39Sopenharmony_ci BIGNUM *e = NULL, *n = NULL, *d = NULL; 446e1051a39Sopenharmony_ci BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; 447e1051a39Sopenharmony_ci RSA *rsa = NULL; 448e1051a39Sopenharmony_ci unsigned int nbyte = (bitlen + 7) >> 3; 449e1051a39Sopenharmony_ci unsigned int hnbyte = (bitlen + 15) >> 4; 450e1051a39Sopenharmony_ci 451e1051a39Sopenharmony_ci rsa = RSA_new(); 452e1051a39Sopenharmony_ci if (rsa == NULL) 453e1051a39Sopenharmony_ci goto memerr; 454e1051a39Sopenharmony_ci e = BN_new(); 455e1051a39Sopenharmony_ci if (e == NULL) 456e1051a39Sopenharmony_ci goto memerr; 457e1051a39Sopenharmony_ci if (!BN_set_word(e, read_ledword(&pin))) 458e1051a39Sopenharmony_ci goto memerr; 459e1051a39Sopenharmony_ci if (!read_lebn(&pin, nbyte, &n)) 460e1051a39Sopenharmony_ci goto memerr; 461e1051a39Sopenharmony_ci if (!ispub) { 462e1051a39Sopenharmony_ci if (!read_lebn(&pin, hnbyte, &p)) 463e1051a39Sopenharmony_ci goto memerr; 464e1051a39Sopenharmony_ci if (!read_lebn(&pin, hnbyte, &q)) 465e1051a39Sopenharmony_ci goto memerr; 466e1051a39Sopenharmony_ci if (!read_lebn(&pin, hnbyte, &dmp1)) 467e1051a39Sopenharmony_ci goto memerr; 468e1051a39Sopenharmony_ci if (!read_lebn(&pin, hnbyte, &dmq1)) 469e1051a39Sopenharmony_ci goto memerr; 470e1051a39Sopenharmony_ci if (!read_lebn(&pin, hnbyte, &iqmp)) 471e1051a39Sopenharmony_ci goto memerr; 472e1051a39Sopenharmony_ci if (!read_lebn(&pin, nbyte, &d)) 473e1051a39Sopenharmony_ci goto memerr; 474e1051a39Sopenharmony_ci if (!RSA_set0_factors(rsa, p, q)) 475e1051a39Sopenharmony_ci goto memerr; 476e1051a39Sopenharmony_ci p = q = NULL; 477e1051a39Sopenharmony_ci if (!RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp)) 478e1051a39Sopenharmony_ci goto memerr; 479e1051a39Sopenharmony_ci dmp1 = dmq1 = iqmp = NULL; 480e1051a39Sopenharmony_ci } 481e1051a39Sopenharmony_ci if (!RSA_set0_key(rsa, n, e, d)) 482e1051a39Sopenharmony_ci goto memerr; 483e1051a39Sopenharmony_ci n = e = d = NULL; 484e1051a39Sopenharmony_ci 485e1051a39Sopenharmony_ci *in = pin; 486e1051a39Sopenharmony_ci return rsa; 487e1051a39Sopenharmony_ci memerr: 488e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 489e1051a39Sopenharmony_ci BN_free(e); 490e1051a39Sopenharmony_ci BN_free(n); 491e1051a39Sopenharmony_ci BN_free(p); 492e1051a39Sopenharmony_ci BN_free(q); 493e1051a39Sopenharmony_ci BN_free(dmp1); 494e1051a39Sopenharmony_ci BN_free(dmq1); 495e1051a39Sopenharmony_ci BN_free(iqmp); 496e1051a39Sopenharmony_ci BN_free(d); 497e1051a39Sopenharmony_ci RSA_free(rsa); 498e1051a39Sopenharmony_ci return NULL; 499e1051a39Sopenharmony_ci} 500e1051a39Sopenharmony_ci 501e1051a39Sopenharmony_ciEVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length) 502e1051a39Sopenharmony_ci{ 503e1051a39Sopenharmony_ci int ispub = 0; 504e1051a39Sopenharmony_ci 505e1051a39Sopenharmony_ci return ossl_b2i(in, length, &ispub); 506e1051a39Sopenharmony_ci} 507e1051a39Sopenharmony_ci 508e1051a39Sopenharmony_ciEVP_PKEY *b2i_PublicKey(const unsigned char **in, long length) 509e1051a39Sopenharmony_ci{ 510e1051a39Sopenharmony_ci int ispub = 1; 511e1051a39Sopenharmony_ci 512e1051a39Sopenharmony_ci return ossl_b2i(in, length, &ispub); 513e1051a39Sopenharmony_ci} 514e1051a39Sopenharmony_ci 515e1051a39Sopenharmony_ciEVP_PKEY *b2i_PrivateKey_bio(BIO *in) 516e1051a39Sopenharmony_ci{ 517e1051a39Sopenharmony_ci int ispub = 0; 518e1051a39Sopenharmony_ci 519e1051a39Sopenharmony_ci return ossl_b2i_bio(in, &ispub); 520e1051a39Sopenharmony_ci} 521e1051a39Sopenharmony_ci 522e1051a39Sopenharmony_ciEVP_PKEY *b2i_PublicKey_bio(BIO *in) 523e1051a39Sopenharmony_ci{ 524e1051a39Sopenharmony_ci int ispub = 1; 525e1051a39Sopenharmony_ci 526e1051a39Sopenharmony_ci return ossl_b2i_bio(in, &ispub); 527e1051a39Sopenharmony_ci} 528e1051a39Sopenharmony_ci 529e1051a39Sopenharmony_cistatic void write_ledword(unsigned char **out, unsigned int dw) 530e1051a39Sopenharmony_ci{ 531e1051a39Sopenharmony_ci unsigned char *p = *out; 532e1051a39Sopenharmony_ci 533e1051a39Sopenharmony_ci *p++ = dw & 0xff; 534e1051a39Sopenharmony_ci *p++ = (dw >> 8) & 0xff; 535e1051a39Sopenharmony_ci *p++ = (dw >> 16) & 0xff; 536e1051a39Sopenharmony_ci *p++ = (dw >> 24) & 0xff; 537e1051a39Sopenharmony_ci *out = p; 538e1051a39Sopenharmony_ci} 539e1051a39Sopenharmony_ci 540e1051a39Sopenharmony_cistatic void write_lebn(unsigned char **out, const BIGNUM *bn, int len) 541e1051a39Sopenharmony_ci{ 542e1051a39Sopenharmony_ci BN_bn2lebinpad(bn, *out, len); 543e1051a39Sopenharmony_ci *out += len; 544e1051a39Sopenharmony_ci} 545e1051a39Sopenharmony_ci 546e1051a39Sopenharmony_cistatic int check_bitlen_rsa(const RSA *rsa, int ispub, unsigned int *magic); 547e1051a39Sopenharmony_cistatic void write_rsa(unsigned char **out, const RSA *rsa, int ispub); 548e1051a39Sopenharmony_ci 549e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 550e1051a39Sopenharmony_cistatic int check_bitlen_dsa(const DSA *dsa, int ispub, unsigned int *magic); 551e1051a39Sopenharmony_cistatic void write_dsa(unsigned char **out, const DSA *dsa, int ispub); 552e1051a39Sopenharmony_ci#endif 553e1051a39Sopenharmony_ci 554e1051a39Sopenharmony_cistatic int do_i2b(unsigned char **out, const EVP_PKEY *pk, int ispub) 555e1051a39Sopenharmony_ci{ 556e1051a39Sopenharmony_ci unsigned char *p; 557e1051a39Sopenharmony_ci unsigned int bitlen = 0, magic = 0, keyalg = 0; 558e1051a39Sopenharmony_ci int outlen = -1, noinc = 0; 559e1051a39Sopenharmony_ci 560e1051a39Sopenharmony_ci if (EVP_PKEY_is_a(pk, "RSA")) { 561e1051a39Sopenharmony_ci bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic); 562e1051a39Sopenharmony_ci keyalg = MS_KEYALG_RSA_KEYX; 563e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 564e1051a39Sopenharmony_ci } else if (EVP_PKEY_is_a(pk, "DSA")) { 565e1051a39Sopenharmony_ci bitlen = check_bitlen_dsa(EVP_PKEY_get0_DSA(pk), ispub, &magic); 566e1051a39Sopenharmony_ci keyalg = MS_KEYALG_DSS_SIGN; 567e1051a39Sopenharmony_ci#endif 568e1051a39Sopenharmony_ci } 569e1051a39Sopenharmony_ci if (bitlen == 0) { 570e1051a39Sopenharmony_ci goto end; 571e1051a39Sopenharmony_ci } 572e1051a39Sopenharmony_ci outlen = 16 573e1051a39Sopenharmony_ci + ossl_blob_length(bitlen, keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub); 574e1051a39Sopenharmony_ci if (out == NULL) 575e1051a39Sopenharmony_ci goto end; 576e1051a39Sopenharmony_ci if (*out) 577e1051a39Sopenharmony_ci p = *out; 578e1051a39Sopenharmony_ci else { 579e1051a39Sopenharmony_ci if ((p = OPENSSL_malloc(outlen)) == NULL) { 580e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 581e1051a39Sopenharmony_ci outlen = -1; 582e1051a39Sopenharmony_ci goto end; 583e1051a39Sopenharmony_ci } 584e1051a39Sopenharmony_ci *out = p; 585e1051a39Sopenharmony_ci noinc = 1; 586e1051a39Sopenharmony_ci } 587e1051a39Sopenharmony_ci if (ispub) 588e1051a39Sopenharmony_ci *p++ = MS_PUBLICKEYBLOB; 589e1051a39Sopenharmony_ci else 590e1051a39Sopenharmony_ci *p++ = MS_PRIVATEKEYBLOB; 591e1051a39Sopenharmony_ci *p++ = 0x2; 592e1051a39Sopenharmony_ci *p++ = 0; 593e1051a39Sopenharmony_ci *p++ = 0; 594e1051a39Sopenharmony_ci write_ledword(&p, keyalg); 595e1051a39Sopenharmony_ci write_ledword(&p, magic); 596e1051a39Sopenharmony_ci write_ledword(&p, bitlen); 597e1051a39Sopenharmony_ci if (keyalg == MS_KEYALG_RSA_KEYX) 598e1051a39Sopenharmony_ci write_rsa(&p, EVP_PKEY_get0_RSA(pk), ispub); 599e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 600e1051a39Sopenharmony_ci else 601e1051a39Sopenharmony_ci write_dsa(&p, EVP_PKEY_get0_DSA(pk), ispub); 602e1051a39Sopenharmony_ci#endif 603e1051a39Sopenharmony_ci if (!noinc) 604e1051a39Sopenharmony_ci *out += outlen; 605e1051a39Sopenharmony_ci end: 606e1051a39Sopenharmony_ci return outlen; 607e1051a39Sopenharmony_ci} 608e1051a39Sopenharmony_ci 609e1051a39Sopenharmony_cistatic int do_i2b_bio(BIO *out, const EVP_PKEY *pk, int ispub) 610e1051a39Sopenharmony_ci{ 611e1051a39Sopenharmony_ci unsigned char *tmp = NULL; 612e1051a39Sopenharmony_ci int outlen, wrlen; 613e1051a39Sopenharmony_ci 614e1051a39Sopenharmony_ci outlen = do_i2b(&tmp, pk, ispub); 615e1051a39Sopenharmony_ci if (outlen < 0) 616e1051a39Sopenharmony_ci return -1; 617e1051a39Sopenharmony_ci wrlen = BIO_write(out, tmp, outlen); 618e1051a39Sopenharmony_ci OPENSSL_free(tmp); 619e1051a39Sopenharmony_ci if (wrlen == outlen) 620e1051a39Sopenharmony_ci return outlen; 621e1051a39Sopenharmony_ci return -1; 622e1051a39Sopenharmony_ci} 623e1051a39Sopenharmony_ci 624e1051a39Sopenharmony_cistatic int check_bitlen_rsa(const RSA *rsa, int ispub, unsigned int *pmagic) 625e1051a39Sopenharmony_ci{ 626e1051a39Sopenharmony_ci int nbyte, hnbyte, bitlen; 627e1051a39Sopenharmony_ci const BIGNUM *e; 628e1051a39Sopenharmony_ci 629e1051a39Sopenharmony_ci RSA_get0_key(rsa, NULL, &e, NULL); 630e1051a39Sopenharmony_ci if (BN_num_bits(e) > 32) 631e1051a39Sopenharmony_ci goto badkey; 632e1051a39Sopenharmony_ci bitlen = RSA_bits(rsa); 633e1051a39Sopenharmony_ci nbyte = RSA_size(rsa); 634e1051a39Sopenharmony_ci hnbyte = (bitlen + 15) >> 4; 635e1051a39Sopenharmony_ci if (ispub) { 636e1051a39Sopenharmony_ci *pmagic = MS_RSA1MAGIC; 637e1051a39Sopenharmony_ci return bitlen; 638e1051a39Sopenharmony_ci } else { 639e1051a39Sopenharmony_ci const BIGNUM *d, *p, *q, *iqmp, *dmp1, *dmq1; 640e1051a39Sopenharmony_ci 641e1051a39Sopenharmony_ci *pmagic = MS_RSA2MAGIC; 642e1051a39Sopenharmony_ci 643e1051a39Sopenharmony_ci /* 644e1051a39Sopenharmony_ci * For private key each component must fit within nbyte or hnbyte. 645e1051a39Sopenharmony_ci */ 646e1051a39Sopenharmony_ci RSA_get0_key(rsa, NULL, NULL, &d); 647e1051a39Sopenharmony_ci if (BN_num_bytes(d) > nbyte) 648e1051a39Sopenharmony_ci goto badkey; 649e1051a39Sopenharmony_ci RSA_get0_factors(rsa, &p, &q); 650e1051a39Sopenharmony_ci RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); 651e1051a39Sopenharmony_ci if ((BN_num_bytes(iqmp) > hnbyte) 652e1051a39Sopenharmony_ci || (BN_num_bytes(p) > hnbyte) 653e1051a39Sopenharmony_ci || (BN_num_bytes(q) > hnbyte) 654e1051a39Sopenharmony_ci || (BN_num_bytes(dmp1) > hnbyte) 655e1051a39Sopenharmony_ci || (BN_num_bytes(dmq1) > hnbyte)) 656e1051a39Sopenharmony_ci goto badkey; 657e1051a39Sopenharmony_ci } 658e1051a39Sopenharmony_ci return bitlen; 659e1051a39Sopenharmony_ci badkey: 660e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS); 661e1051a39Sopenharmony_ci return 0; 662e1051a39Sopenharmony_ci} 663e1051a39Sopenharmony_ci 664e1051a39Sopenharmony_cistatic void write_rsa(unsigned char **out, const RSA *rsa, int ispub) 665e1051a39Sopenharmony_ci{ 666e1051a39Sopenharmony_ci int nbyte, hnbyte; 667e1051a39Sopenharmony_ci const BIGNUM *n, *d, *e, *p, *q, *iqmp, *dmp1, *dmq1; 668e1051a39Sopenharmony_ci 669e1051a39Sopenharmony_ci nbyte = RSA_size(rsa); 670e1051a39Sopenharmony_ci hnbyte = (RSA_bits(rsa) + 15) >> 4; 671e1051a39Sopenharmony_ci RSA_get0_key(rsa, &n, &e, &d); 672e1051a39Sopenharmony_ci write_lebn(out, e, 4); 673e1051a39Sopenharmony_ci write_lebn(out, n, nbyte); 674e1051a39Sopenharmony_ci if (ispub) 675e1051a39Sopenharmony_ci return; 676e1051a39Sopenharmony_ci RSA_get0_factors(rsa, &p, &q); 677e1051a39Sopenharmony_ci RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); 678e1051a39Sopenharmony_ci write_lebn(out, p, hnbyte); 679e1051a39Sopenharmony_ci write_lebn(out, q, hnbyte); 680e1051a39Sopenharmony_ci write_lebn(out, dmp1, hnbyte); 681e1051a39Sopenharmony_ci write_lebn(out, dmq1, hnbyte); 682e1051a39Sopenharmony_ci write_lebn(out, iqmp, hnbyte); 683e1051a39Sopenharmony_ci write_lebn(out, d, nbyte); 684e1051a39Sopenharmony_ci} 685e1051a39Sopenharmony_ci 686e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 687e1051a39Sopenharmony_cistatic int check_bitlen_dsa(const DSA *dsa, int ispub, unsigned int *pmagic) 688e1051a39Sopenharmony_ci{ 689e1051a39Sopenharmony_ci int bitlen; 690e1051a39Sopenharmony_ci const BIGNUM *p = NULL, *q = NULL, *g = NULL; 691e1051a39Sopenharmony_ci const BIGNUM *pub_key = NULL, *priv_key = NULL; 692e1051a39Sopenharmony_ci 693e1051a39Sopenharmony_ci DSA_get0_pqg(dsa, &p, &q, &g); 694e1051a39Sopenharmony_ci DSA_get0_key(dsa, &pub_key, &priv_key); 695e1051a39Sopenharmony_ci bitlen = BN_num_bits(p); 696e1051a39Sopenharmony_ci if ((bitlen & 7) || (BN_num_bits(q) != 160) 697e1051a39Sopenharmony_ci || (BN_num_bits(g) > bitlen)) 698e1051a39Sopenharmony_ci goto badkey; 699e1051a39Sopenharmony_ci if (ispub) { 700e1051a39Sopenharmony_ci if (BN_num_bits(pub_key) > bitlen) 701e1051a39Sopenharmony_ci goto badkey; 702e1051a39Sopenharmony_ci *pmagic = MS_DSS1MAGIC; 703e1051a39Sopenharmony_ci } else { 704e1051a39Sopenharmony_ci if (BN_num_bits(priv_key) > 160) 705e1051a39Sopenharmony_ci goto badkey; 706e1051a39Sopenharmony_ci *pmagic = MS_DSS2MAGIC; 707e1051a39Sopenharmony_ci } 708e1051a39Sopenharmony_ci 709e1051a39Sopenharmony_ci return bitlen; 710e1051a39Sopenharmony_ci badkey: 711e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS); 712e1051a39Sopenharmony_ci return 0; 713e1051a39Sopenharmony_ci} 714e1051a39Sopenharmony_ci 715e1051a39Sopenharmony_cistatic void write_dsa(unsigned char **out, const DSA *dsa, int ispub) 716e1051a39Sopenharmony_ci{ 717e1051a39Sopenharmony_ci int nbyte; 718e1051a39Sopenharmony_ci const BIGNUM *p = NULL, *q = NULL, *g = NULL; 719e1051a39Sopenharmony_ci const BIGNUM *pub_key = NULL, *priv_key = NULL; 720e1051a39Sopenharmony_ci 721e1051a39Sopenharmony_ci DSA_get0_pqg(dsa, &p, &q, &g); 722e1051a39Sopenharmony_ci DSA_get0_key(dsa, &pub_key, &priv_key); 723e1051a39Sopenharmony_ci nbyte = BN_num_bytes(p); 724e1051a39Sopenharmony_ci write_lebn(out, p, nbyte); 725e1051a39Sopenharmony_ci write_lebn(out, q, 20); 726e1051a39Sopenharmony_ci write_lebn(out, g, nbyte); 727e1051a39Sopenharmony_ci if (ispub) 728e1051a39Sopenharmony_ci write_lebn(out, pub_key, nbyte); 729e1051a39Sopenharmony_ci else 730e1051a39Sopenharmony_ci write_lebn(out, priv_key, 20); 731e1051a39Sopenharmony_ci /* Set "invalid" for seed structure values */ 732e1051a39Sopenharmony_ci memset(*out, 0xff, 24); 733e1051a39Sopenharmony_ci *out += 24; 734e1051a39Sopenharmony_ci return; 735e1051a39Sopenharmony_ci} 736e1051a39Sopenharmony_ci#endif 737e1051a39Sopenharmony_ci 738e1051a39Sopenharmony_ciint i2b_PrivateKey_bio(BIO *out, const EVP_PKEY *pk) 739e1051a39Sopenharmony_ci{ 740e1051a39Sopenharmony_ci return do_i2b_bio(out, pk, 0); 741e1051a39Sopenharmony_ci} 742e1051a39Sopenharmony_ci 743e1051a39Sopenharmony_ciint i2b_PublicKey_bio(BIO *out, const EVP_PKEY *pk) 744e1051a39Sopenharmony_ci{ 745e1051a39Sopenharmony_ci return do_i2b_bio(out, pk, 1); 746e1051a39Sopenharmony_ci} 747e1051a39Sopenharmony_ci 748e1051a39Sopenharmony_ciint ossl_do_PVK_header(const unsigned char **in, unsigned int length, 749e1051a39Sopenharmony_ci int skip_magic, 750e1051a39Sopenharmony_ci unsigned int *psaltlen, unsigned int *pkeylen) 751e1051a39Sopenharmony_ci{ 752e1051a39Sopenharmony_ci const unsigned char *p = *in; 753e1051a39Sopenharmony_ci unsigned int pvk_magic, is_encrypted; 754e1051a39Sopenharmony_ci 755e1051a39Sopenharmony_ci if (skip_magic) { 756e1051a39Sopenharmony_ci if (length < 20) { 757e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT); 758e1051a39Sopenharmony_ci return 0; 759e1051a39Sopenharmony_ci } 760e1051a39Sopenharmony_ci } else { 761e1051a39Sopenharmony_ci if (length < 24) { 762e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT); 763e1051a39Sopenharmony_ci return 0; 764e1051a39Sopenharmony_ci } 765e1051a39Sopenharmony_ci pvk_magic = read_ledword(&p); 766e1051a39Sopenharmony_ci if (pvk_magic != MS_PVKMAGIC) { 767e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_BAD_MAGIC_NUMBER); 768e1051a39Sopenharmony_ci return 0; 769e1051a39Sopenharmony_ci } 770e1051a39Sopenharmony_ci } 771e1051a39Sopenharmony_ci /* Skip reserved */ 772e1051a39Sopenharmony_ci p += 4; 773e1051a39Sopenharmony_ci /* 774e1051a39Sopenharmony_ci * keytype = 775e1051a39Sopenharmony_ci */ read_ledword(&p); 776e1051a39Sopenharmony_ci is_encrypted = read_ledword(&p); 777e1051a39Sopenharmony_ci *psaltlen = read_ledword(&p); 778e1051a39Sopenharmony_ci *pkeylen = read_ledword(&p); 779e1051a39Sopenharmony_ci 780e1051a39Sopenharmony_ci if (*pkeylen > PVK_MAX_KEYLEN || *psaltlen > PVK_MAX_SALTLEN) 781e1051a39Sopenharmony_ci return 0; 782e1051a39Sopenharmony_ci 783e1051a39Sopenharmony_ci if (is_encrypted && *psaltlen == 0) { 784e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_INCONSISTENT_HEADER); 785e1051a39Sopenharmony_ci return 0; 786e1051a39Sopenharmony_ci } 787e1051a39Sopenharmony_ci 788e1051a39Sopenharmony_ci *in = p; 789e1051a39Sopenharmony_ci return 1; 790e1051a39Sopenharmony_ci} 791e1051a39Sopenharmony_ci 792e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RC4 793e1051a39Sopenharmony_cistatic int derive_pvk_key(unsigned char *key, 794e1051a39Sopenharmony_ci const unsigned char *salt, unsigned int saltlen, 795e1051a39Sopenharmony_ci const unsigned char *pass, int passlen, 796e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 797e1051a39Sopenharmony_ci{ 798e1051a39Sopenharmony_ci EVP_MD_CTX *mctx = EVP_MD_CTX_new(); 799e1051a39Sopenharmony_ci int rv = 0; 800e1051a39Sopenharmony_ci EVP_MD *sha1 = NULL; 801e1051a39Sopenharmony_ci 802e1051a39Sopenharmony_ci if ((sha1 = EVP_MD_fetch(libctx, SN_sha1, propq)) == NULL) 803e1051a39Sopenharmony_ci goto err; 804e1051a39Sopenharmony_ci 805e1051a39Sopenharmony_ci if (mctx == NULL 806e1051a39Sopenharmony_ci || !EVP_DigestInit_ex(mctx, sha1, NULL) 807e1051a39Sopenharmony_ci || !EVP_DigestUpdate(mctx, salt, saltlen) 808e1051a39Sopenharmony_ci || !EVP_DigestUpdate(mctx, pass, passlen) 809e1051a39Sopenharmony_ci || !EVP_DigestFinal_ex(mctx, key, NULL)) 810e1051a39Sopenharmony_ci goto err; 811e1051a39Sopenharmony_ci 812e1051a39Sopenharmony_ci rv = 1; 813e1051a39Sopenharmony_cierr: 814e1051a39Sopenharmony_ci EVP_MD_CTX_free(mctx); 815e1051a39Sopenharmony_ci EVP_MD_free(sha1); 816e1051a39Sopenharmony_ci return rv; 817e1051a39Sopenharmony_ci} 818e1051a39Sopenharmony_ci#endif 819e1051a39Sopenharmony_ci 820e1051a39Sopenharmony_cistatic void *do_PVK_body_key(const unsigned char **in, 821e1051a39Sopenharmony_ci unsigned int saltlen, unsigned int keylen, 822e1051a39Sopenharmony_ci pem_password_cb *cb, void *u, 823e1051a39Sopenharmony_ci int *isdss, int *ispub, 824e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 825e1051a39Sopenharmony_ci{ 826e1051a39Sopenharmony_ci const unsigned char *p = *in; 827e1051a39Sopenharmony_ci unsigned char *enctmp = NULL; 828e1051a39Sopenharmony_ci unsigned char keybuf[20]; 829e1051a39Sopenharmony_ci void *key = NULL; 830e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RC4 831e1051a39Sopenharmony_ci EVP_CIPHER *rc4 = NULL; 832e1051a39Sopenharmony_ci#endif 833e1051a39Sopenharmony_ci EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new(); 834e1051a39Sopenharmony_ci 835e1051a39Sopenharmony_ci if (cctx == NULL) { 836e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 837e1051a39Sopenharmony_ci goto err; 838e1051a39Sopenharmony_ci } 839e1051a39Sopenharmony_ci 840e1051a39Sopenharmony_ci if (saltlen) { 841e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RC4 842e1051a39Sopenharmony_ci unsigned int magic; 843e1051a39Sopenharmony_ci char psbuf[PEM_BUFSIZE]; 844e1051a39Sopenharmony_ci int enctmplen, inlen; 845e1051a39Sopenharmony_ci unsigned char *q; 846e1051a39Sopenharmony_ci 847e1051a39Sopenharmony_ci if (cb) 848e1051a39Sopenharmony_ci inlen = cb(psbuf, PEM_BUFSIZE, 0, u); 849e1051a39Sopenharmony_ci else 850e1051a39Sopenharmony_ci inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); 851e1051a39Sopenharmony_ci if (inlen < 0) { 852e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ); 853e1051a39Sopenharmony_ci goto err; 854e1051a39Sopenharmony_ci } 855e1051a39Sopenharmony_ci enctmp = OPENSSL_malloc(keylen + 8); 856e1051a39Sopenharmony_ci if (enctmp == NULL) { 857e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 858e1051a39Sopenharmony_ci goto err; 859e1051a39Sopenharmony_ci } 860e1051a39Sopenharmony_ci if (!derive_pvk_key(keybuf, p, saltlen, 861e1051a39Sopenharmony_ci (unsigned char *)psbuf, inlen, libctx, propq)) 862e1051a39Sopenharmony_ci goto err; 863e1051a39Sopenharmony_ci p += saltlen; 864e1051a39Sopenharmony_ci /* Copy BLOBHEADER across, decrypt rest */ 865e1051a39Sopenharmony_ci memcpy(enctmp, p, 8); 866e1051a39Sopenharmony_ci p += 8; 867e1051a39Sopenharmony_ci if (keylen < 8) { 868e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT); 869e1051a39Sopenharmony_ci goto err; 870e1051a39Sopenharmony_ci } 871e1051a39Sopenharmony_ci inlen = keylen - 8; 872e1051a39Sopenharmony_ci q = enctmp + 8; 873e1051a39Sopenharmony_ci if ((rc4 = EVP_CIPHER_fetch(libctx, "RC4", propq)) == NULL) 874e1051a39Sopenharmony_ci goto err; 875e1051a39Sopenharmony_ci if (!EVP_DecryptInit_ex(cctx, rc4, NULL, keybuf, NULL)) 876e1051a39Sopenharmony_ci goto err; 877e1051a39Sopenharmony_ci if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen)) 878e1051a39Sopenharmony_ci goto err; 879e1051a39Sopenharmony_ci if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen)) 880e1051a39Sopenharmony_ci goto err; 881e1051a39Sopenharmony_ci magic = read_ledword((const unsigned char **)&q); 882e1051a39Sopenharmony_ci if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { 883e1051a39Sopenharmony_ci q = enctmp + 8; 884e1051a39Sopenharmony_ci memset(keybuf + 5, 0, 11); 885e1051a39Sopenharmony_ci if (!EVP_DecryptInit_ex(cctx, rc4, NULL, keybuf, NULL)) 886e1051a39Sopenharmony_ci goto err; 887e1051a39Sopenharmony_ci if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen)) 888e1051a39Sopenharmony_ci goto err; 889e1051a39Sopenharmony_ci if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen)) 890e1051a39Sopenharmony_ci goto err; 891e1051a39Sopenharmony_ci magic = read_ledword((const unsigned char **)&q); 892e1051a39Sopenharmony_ci if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { 893e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_BAD_DECRYPT); 894e1051a39Sopenharmony_ci goto err; 895e1051a39Sopenharmony_ci } 896e1051a39Sopenharmony_ci } 897e1051a39Sopenharmony_ci p = enctmp; 898e1051a39Sopenharmony_ci#else 899e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER); 900e1051a39Sopenharmony_ci goto err; 901e1051a39Sopenharmony_ci#endif 902e1051a39Sopenharmony_ci } 903e1051a39Sopenharmony_ci 904e1051a39Sopenharmony_ci key = do_b2i_key(&p, keylen, isdss, ispub); 905e1051a39Sopenharmony_ci err: 906e1051a39Sopenharmony_ci EVP_CIPHER_CTX_free(cctx); 907e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RC4 908e1051a39Sopenharmony_ci EVP_CIPHER_free(rc4); 909e1051a39Sopenharmony_ci#endif 910e1051a39Sopenharmony_ci if (enctmp != NULL) { 911e1051a39Sopenharmony_ci OPENSSL_cleanse(keybuf, sizeof(keybuf)); 912e1051a39Sopenharmony_ci OPENSSL_free(enctmp); 913e1051a39Sopenharmony_ci } 914e1051a39Sopenharmony_ci return key; 915e1051a39Sopenharmony_ci} 916e1051a39Sopenharmony_ci 917e1051a39Sopenharmony_cistatic void *do_PVK_key_bio(BIO *in, pem_password_cb *cb, void *u, 918e1051a39Sopenharmony_ci int *isdss, int *ispub, 919e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 920e1051a39Sopenharmony_ci{ 921e1051a39Sopenharmony_ci unsigned char pvk_hdr[24], *buf = NULL; 922e1051a39Sopenharmony_ci const unsigned char *p; 923e1051a39Sopenharmony_ci int buflen; 924e1051a39Sopenharmony_ci void *key = NULL; 925e1051a39Sopenharmony_ci unsigned int saltlen, keylen; 926e1051a39Sopenharmony_ci 927e1051a39Sopenharmony_ci if (BIO_read(in, pvk_hdr, 24) != 24) { 928e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT); 929e1051a39Sopenharmony_ci return NULL; 930e1051a39Sopenharmony_ci } 931e1051a39Sopenharmony_ci p = pvk_hdr; 932e1051a39Sopenharmony_ci 933e1051a39Sopenharmony_ci if (!ossl_do_PVK_header(&p, 24, 0, &saltlen, &keylen)) 934e1051a39Sopenharmony_ci return 0; 935e1051a39Sopenharmony_ci buflen = (int)keylen + saltlen; 936e1051a39Sopenharmony_ci buf = OPENSSL_malloc(buflen); 937e1051a39Sopenharmony_ci if (buf == NULL) { 938e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 939e1051a39Sopenharmony_ci return 0; 940e1051a39Sopenharmony_ci } 941e1051a39Sopenharmony_ci p = buf; 942e1051a39Sopenharmony_ci if (BIO_read(in, buf, buflen) != buflen) { 943e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT); 944e1051a39Sopenharmony_ci goto err; 945e1051a39Sopenharmony_ci } 946e1051a39Sopenharmony_ci key = do_PVK_body_key(&p, saltlen, keylen, cb, u, isdss, ispub, libctx, propq); 947e1051a39Sopenharmony_ci 948e1051a39Sopenharmony_ci err: 949e1051a39Sopenharmony_ci OPENSSL_clear_free(buf, buflen); 950e1051a39Sopenharmony_ci return key; 951e1051a39Sopenharmony_ci} 952e1051a39Sopenharmony_ci 953e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 954e1051a39Sopenharmony_ciDSA *b2i_DSA_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u, 955e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 956e1051a39Sopenharmony_ci{ 957e1051a39Sopenharmony_ci int isdss = 1; 958e1051a39Sopenharmony_ci int ispub = 0; /* PVK keys are always private */ 959e1051a39Sopenharmony_ci 960e1051a39Sopenharmony_ci return do_PVK_key_bio(in, cb, u, &isdss, &ispub, libctx, propq); 961e1051a39Sopenharmony_ci} 962e1051a39Sopenharmony_ci 963e1051a39Sopenharmony_ciDSA *b2i_DSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u) 964e1051a39Sopenharmony_ci{ 965e1051a39Sopenharmony_ci return b2i_DSA_PVK_bio_ex(in, cb, u, NULL, NULL); 966e1051a39Sopenharmony_ci} 967e1051a39Sopenharmony_ci#endif 968e1051a39Sopenharmony_ci 969e1051a39Sopenharmony_ciRSA *b2i_RSA_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u, 970e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 971e1051a39Sopenharmony_ci{ 972e1051a39Sopenharmony_ci int isdss = 0; 973e1051a39Sopenharmony_ci int ispub = 0; /* PVK keys are always private */ 974e1051a39Sopenharmony_ci 975e1051a39Sopenharmony_ci return do_PVK_key_bio(in, cb, u, &isdss, &ispub, libctx, propq); 976e1051a39Sopenharmony_ci} 977e1051a39Sopenharmony_ci 978e1051a39Sopenharmony_ciRSA *b2i_RSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u) 979e1051a39Sopenharmony_ci{ 980e1051a39Sopenharmony_ci return b2i_RSA_PVK_bio_ex(in, cb, u, NULL, NULL); 981e1051a39Sopenharmony_ci} 982e1051a39Sopenharmony_ci 983e1051a39Sopenharmony_ciEVP_PKEY *b2i_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u, 984e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 985e1051a39Sopenharmony_ci{ 986e1051a39Sopenharmony_ci int isdss = -1; 987e1051a39Sopenharmony_ci int ispub = -1; 988e1051a39Sopenharmony_ci void *key = do_PVK_key_bio(in, cb, u, &isdss, &ispub, NULL, NULL); 989e1051a39Sopenharmony_ci 990e1051a39Sopenharmony_ci return evp_pkey_new0_key(key, isdss_to_evp_type(isdss)); 991e1051a39Sopenharmony_ci} 992e1051a39Sopenharmony_ci 993e1051a39Sopenharmony_ciEVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u) 994e1051a39Sopenharmony_ci{ 995e1051a39Sopenharmony_ci return b2i_PVK_bio_ex(in, cb, u, NULL, NULL); 996e1051a39Sopenharmony_ci} 997e1051a39Sopenharmony_ci 998e1051a39Sopenharmony_cistatic int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel, 999e1051a39Sopenharmony_ci pem_password_cb *cb, void *u, OSSL_LIB_CTX *libctx, 1000e1051a39Sopenharmony_ci const char *propq) 1001e1051a39Sopenharmony_ci{ 1002e1051a39Sopenharmony_ci int ret = -1; 1003e1051a39Sopenharmony_ci int outlen = 24, pklen; 1004e1051a39Sopenharmony_ci unsigned char *p = NULL, *start = NULL; 1005e1051a39Sopenharmony_ci EVP_CIPHER_CTX *cctx = NULL; 1006e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RC4 1007e1051a39Sopenharmony_ci unsigned char *salt = NULL; 1008e1051a39Sopenharmony_ci EVP_CIPHER *rc4 = NULL; 1009e1051a39Sopenharmony_ci#endif 1010e1051a39Sopenharmony_ci 1011e1051a39Sopenharmony_ci if (enclevel) 1012e1051a39Sopenharmony_ci outlen += PVK_SALTLEN; 1013e1051a39Sopenharmony_ci pklen = do_i2b(NULL, pk, 0); 1014e1051a39Sopenharmony_ci if (pklen < 0) 1015e1051a39Sopenharmony_ci return -1; 1016e1051a39Sopenharmony_ci outlen += pklen; 1017e1051a39Sopenharmony_ci if (out == NULL) 1018e1051a39Sopenharmony_ci return outlen; 1019e1051a39Sopenharmony_ci if (*out != NULL) { 1020e1051a39Sopenharmony_ci p = *out; 1021e1051a39Sopenharmony_ci } else { 1022e1051a39Sopenharmony_ci start = p = OPENSSL_malloc(outlen); 1023e1051a39Sopenharmony_ci if (p == NULL) { 1024e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 1025e1051a39Sopenharmony_ci return -1; 1026e1051a39Sopenharmony_ci } 1027e1051a39Sopenharmony_ci } 1028e1051a39Sopenharmony_ci 1029e1051a39Sopenharmony_ci cctx = EVP_CIPHER_CTX_new(); 1030e1051a39Sopenharmony_ci if (cctx == NULL) 1031e1051a39Sopenharmony_ci goto error; 1032e1051a39Sopenharmony_ci 1033e1051a39Sopenharmony_ci write_ledword(&p, MS_PVKMAGIC); 1034e1051a39Sopenharmony_ci write_ledword(&p, 0); 1035e1051a39Sopenharmony_ci if (EVP_PKEY_get_id(pk) == EVP_PKEY_RSA) 1036e1051a39Sopenharmony_ci write_ledword(&p, MS_KEYTYPE_KEYX); 1037e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 1038e1051a39Sopenharmony_ci else 1039e1051a39Sopenharmony_ci write_ledword(&p, MS_KEYTYPE_SIGN); 1040e1051a39Sopenharmony_ci#endif 1041e1051a39Sopenharmony_ci write_ledword(&p, enclevel ? 1 : 0); 1042e1051a39Sopenharmony_ci write_ledword(&p, enclevel ? PVK_SALTLEN : 0); 1043e1051a39Sopenharmony_ci write_ledword(&p, pklen); 1044e1051a39Sopenharmony_ci if (enclevel) { 1045e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RC4 1046e1051a39Sopenharmony_ci if (RAND_bytes_ex(libctx, p, PVK_SALTLEN, 0) <= 0) 1047e1051a39Sopenharmony_ci goto error; 1048e1051a39Sopenharmony_ci salt = p; 1049e1051a39Sopenharmony_ci p += PVK_SALTLEN; 1050e1051a39Sopenharmony_ci#endif 1051e1051a39Sopenharmony_ci } 1052e1051a39Sopenharmony_ci do_i2b(&p, pk, 0); 1053e1051a39Sopenharmony_ci if (enclevel != 0) { 1054e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RC4 1055e1051a39Sopenharmony_ci char psbuf[PEM_BUFSIZE]; 1056e1051a39Sopenharmony_ci unsigned char keybuf[20]; 1057e1051a39Sopenharmony_ci int enctmplen, inlen; 1058e1051a39Sopenharmony_ci if (cb) 1059e1051a39Sopenharmony_ci inlen = cb(psbuf, PEM_BUFSIZE, 1, u); 1060e1051a39Sopenharmony_ci else 1061e1051a39Sopenharmony_ci inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 1, u); 1062e1051a39Sopenharmony_ci if (inlen <= 0) { 1063e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ); 1064e1051a39Sopenharmony_ci goto error; 1065e1051a39Sopenharmony_ci } 1066e1051a39Sopenharmony_ci if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN, 1067e1051a39Sopenharmony_ci (unsigned char *)psbuf, inlen, libctx, propq)) 1068e1051a39Sopenharmony_ci goto error; 1069e1051a39Sopenharmony_ci if ((rc4 = EVP_CIPHER_fetch(libctx, "RC4", propq)) == NULL) 1070e1051a39Sopenharmony_ci goto error; 1071e1051a39Sopenharmony_ci if (enclevel == 1) 1072e1051a39Sopenharmony_ci memset(keybuf + 5, 0, 11); 1073e1051a39Sopenharmony_ci p = salt + PVK_SALTLEN + 8; 1074e1051a39Sopenharmony_ci if (!EVP_EncryptInit_ex(cctx, rc4, NULL, keybuf, NULL)) 1075e1051a39Sopenharmony_ci goto error; 1076e1051a39Sopenharmony_ci OPENSSL_cleanse(keybuf, 20); 1077e1051a39Sopenharmony_ci if (!EVP_EncryptUpdate(cctx, p, &enctmplen, p, pklen - 8)) 1078e1051a39Sopenharmony_ci goto error; 1079e1051a39Sopenharmony_ci if (!EVP_EncryptFinal_ex(cctx, p + enctmplen, &enctmplen)) 1080e1051a39Sopenharmony_ci goto error; 1081e1051a39Sopenharmony_ci#else 1082e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER); 1083e1051a39Sopenharmony_ci goto error; 1084e1051a39Sopenharmony_ci#endif 1085e1051a39Sopenharmony_ci } 1086e1051a39Sopenharmony_ci 1087e1051a39Sopenharmony_ci if (*out == NULL) 1088e1051a39Sopenharmony_ci *out = start; 1089e1051a39Sopenharmony_ci ret = outlen; 1090e1051a39Sopenharmony_ci error: 1091e1051a39Sopenharmony_ci EVP_CIPHER_CTX_free(cctx); 1092e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RC4 1093e1051a39Sopenharmony_ci EVP_CIPHER_free(rc4); 1094e1051a39Sopenharmony_ci#endif 1095e1051a39Sopenharmony_ci if (*out == NULL) 1096e1051a39Sopenharmony_ci OPENSSL_free(start); 1097e1051a39Sopenharmony_ci 1098e1051a39Sopenharmony_ci return ret; 1099e1051a39Sopenharmony_ci} 1100e1051a39Sopenharmony_ci 1101e1051a39Sopenharmony_ciint i2b_PVK_bio_ex(BIO *out, const EVP_PKEY *pk, int enclevel, 1102e1051a39Sopenharmony_ci pem_password_cb *cb, void *u, OSSL_LIB_CTX *libctx, 1103e1051a39Sopenharmony_ci const char *propq) 1104e1051a39Sopenharmony_ci{ 1105e1051a39Sopenharmony_ci unsigned char *tmp = NULL; 1106e1051a39Sopenharmony_ci int outlen, wrlen; 1107e1051a39Sopenharmony_ci 1108e1051a39Sopenharmony_ci outlen = i2b_PVK(&tmp, pk, enclevel, cb, u, libctx, propq); 1109e1051a39Sopenharmony_ci if (outlen < 0) 1110e1051a39Sopenharmony_ci return -1; 1111e1051a39Sopenharmony_ci wrlen = BIO_write(out, tmp, outlen); 1112e1051a39Sopenharmony_ci OPENSSL_free(tmp); 1113e1051a39Sopenharmony_ci if (wrlen == outlen) { 1114e1051a39Sopenharmony_ci return outlen; 1115e1051a39Sopenharmony_ci } 1116e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_BIO_WRITE_FAILURE); 1117e1051a39Sopenharmony_ci return -1; 1118e1051a39Sopenharmony_ci} 1119e1051a39Sopenharmony_ci 1120e1051a39Sopenharmony_ciint i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel, 1121e1051a39Sopenharmony_ci pem_password_cb *cb, void *u) 1122e1051a39Sopenharmony_ci{ 1123e1051a39Sopenharmony_ci return i2b_PVK_bio_ex(out, pk, enclevel, cb, u, NULL, NULL); 1124e1051a39Sopenharmony_ci} 1125e1051a39Sopenharmony_ci 1126