static EVP_PKEY * do_PVK_body(const unsigned char **in, unsigned int saltlen, unsigned int keylen, pem_password_cb *cb, void *u) { EVP_PKEY *ret = NULL; const unsigned char *p = *in; unsigned int magic; unsigned char *enctmp = NULL, *q; EVP_CIPHER_CTX cctx; EVP_CIPHER_CTX_init(&cctx); if (saltlen) { char psbuf[PEM_BUFSIZE]; unsigned char keybuf[20]; int enctmplen, inlen; if (cb) inlen = cb(psbuf, PEM_BUFSIZE, 0, u); else inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); if (inlen <= 0) { PEMerror(PEM_R_BAD_PASSWORD_READ); goto err; } enctmp = malloc(keylen + 8); if (!enctmp) { PEMerror(ERR_R_MALLOC_FAILURE); goto err; } if (!derive_pvk_key(keybuf, p, saltlen, (unsigned char *)psbuf, inlen)) { goto err; } p += saltlen; /* Copy BLOBHEADER across, decrypt rest */ memcpy(enctmp, p, 8); p += 8; if (keylen < 8) { PEMerror(PEM_R_PVK_TOO_SHORT); goto err; } inlen = keylen - 8; q = enctmp + 8; if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL)) goto err; if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen)) goto err; if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen)) goto err; magic = read_ledword((const unsigned char **)&q); if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { q = enctmp + 8; memset(keybuf + 5, 0, 11); if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL)) goto err; explicit_bzero(keybuf, 20); if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen)) goto err; if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen)) goto err; magic = read_ledword((const unsigned char **)&q); if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { PEMerror(PEM_R_BAD_DECRYPT); goto err; } } else explicit_bzero(keybuf, 20); p = enctmp; } ret = b2i_PrivateKey(&p, keylen); err: EVP_CIPHER_CTX_cleanup(&cctx); if (enctmp && saltlen) free(enctmp); return ret; }
static EVP_PKEY *do_PVK_body(const unsigned char **in, unsigned int saltlen, unsigned int keylen, pem_password_cb *cb, void *u) { EVP_PKEY *ret = NULL; const unsigned char *p = *in; unsigned int magic; unsigned char *enctmp = NULL, *q; if (saltlen) { char psbuf[PEM_BUFSIZE]; unsigned char keybuf[20]; EVP_CIPHER_CTX cctx; int enctmplen, inlen; if (cb) inlen=cb(psbuf,PEM_BUFSIZE,0,u); else inlen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u); if (inlen <= 0) { PEMerr(PEM_F_DO_PVK_BODY,PEM_R_BAD_PASSWORD_READ); return NULL; } enctmp = (unsigned char*)OPENSSL_malloc(keylen + 8); if (!enctmp) { PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE); return NULL; } if (!derive_pvk_key(keybuf, p, saltlen, (unsigned char *)psbuf, inlen)) return NULL; p += saltlen; /* Copy BLOBHEADER across, decrypt rest */ TINYCLR_SSL_MEMCPY(enctmp, p, 8); p += 8; inlen = keylen - 8; q = enctmp + 8; EVP_CIPHER_CTX_init(&cctx); EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL); EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen); EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen); magic = read_ledword((const unsigned char **)&q); if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { q = enctmp + 8; TINYCLR_SSL_MEMSET(keybuf + 5, 0, 11); EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL); OPENSSL_cleanse(keybuf, 20); EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen); EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen); magic = read_ledword((const unsigned char **)&q); if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { EVP_CIPHER_CTX_cleanup(&cctx); PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT); goto err; } } else OPENSSL_cleanse(keybuf, 20); EVP_CIPHER_CTX_cleanup(&cctx); p = enctmp; } ret = b2i_PrivateKey(&p, keylen); err: if (enctmp && saltlen) OPENSSL_free(enctmp); return ret; }