(parse_rsa_private_key): try all password and prompter.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@18404 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -123,12 +123,74 @@ parse_certificate(hx509_context context, struct hx509_collector *c,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
try_decrypt(hx509_context context,
|
||||||
|
struct hx509_collector *collector,
|
||||||
|
const EVP_CIPHER *c,
|
||||||
|
const void *ivdata,
|
||||||
|
const void *password,
|
||||||
|
size_t passwordlen,
|
||||||
|
const void *cipher,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
heim_octet_string clear;
|
||||||
|
size_t keylen;
|
||||||
|
void *key;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
keylen = EVP_CIPHER_key_length(c);
|
||||||
|
|
||||||
|
key = malloc(keylen);
|
||||||
|
if (key == NULL) {
|
||||||
|
hx509_clear_error_string(context);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = EVP_BytesToKey(c, EVP_md5(), ivdata,
|
||||||
|
password, passwordlen,
|
||||||
|
1, key, NULL);
|
||||||
|
if (ret <= 0) {
|
||||||
|
hx509_set_error_string(context, 0, EINVAL,
|
||||||
|
"Failed to do string2key for private key");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear.data = malloc(len);
|
||||||
|
if (clear.data == NULL) {
|
||||||
|
hx509_set_error_string(context, 0, ENOMEM,
|
||||||
|
"Out of memory to decrypt for private key");
|
||||||
|
ret = ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
clear.length = len;
|
||||||
|
|
||||||
|
{
|
||||||
|
EVP_CIPHER_CTX ctx;
|
||||||
|
EVP_CIPHER_CTX_init(&ctx);
|
||||||
|
EVP_CipherInit_ex(&ctx, c, NULL, key, ivdata, 0);
|
||||||
|
EVP_Cipher(&ctx, clear.data, cipher, len);
|
||||||
|
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _hx509_collector_private_key_add(collector,
|
||||||
|
hx509_signature_rsa(),
|
||||||
|
NULL,
|
||||||
|
&clear,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
memset(clear.data, 0, clear.length);
|
||||||
|
free(clear.data);
|
||||||
|
out:
|
||||||
|
memset(key, 0, keylen);
|
||||||
|
free(key);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_rsa_private_key(hx509_context context, struct hx509_collector *c,
|
parse_rsa_private_key(hx509_context context, struct hx509_collector *c,
|
||||||
const struct header *headers,
|
const struct header *headers,
|
||||||
const void *data, size_t len)
|
const void *data, size_t len)
|
||||||
{
|
{
|
||||||
heim_octet_string keydata;
|
|
||||||
int ret;
|
int ret;
|
||||||
const char *enc;
|
const char *enc;
|
||||||
|
|
||||||
@@ -139,11 +201,9 @@ parse_rsa_private_key(hx509_context context, struct hx509_collector *c,
|
|||||||
ssize_t ssize, size;
|
ssize_t ssize, size;
|
||||||
void *ivdata;
|
void *ivdata;
|
||||||
const EVP_CIPHER *cipher;
|
const EVP_CIPHER *cipher;
|
||||||
const void *password;
|
|
||||||
size_t passwordlen;
|
|
||||||
void *key;
|
|
||||||
const struct _hx509_password *pw;
|
const struct _hx509_password *pw;
|
||||||
hx509_lock lock;
|
hx509_lock lock;
|
||||||
|
int i, decrypted = 0;
|
||||||
|
|
||||||
lock = _hx509_collector_get_lock(c);
|
lock = _hx509_collector_get_lock(c);
|
||||||
if (lock == NULL) {
|
if (lock == NULL) {
|
||||||
@@ -152,16 +212,6 @@ parse_rsa_private_key(hx509_context context, struct hx509_collector *c,
|
|||||||
"password protected file");
|
"password protected file");
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
pw = _hx509_lock_get_passwords(lock);
|
|
||||||
if (pw == NULL || pw->len < 1) {
|
|
||||||
hx509_set_error_string(context, 0, EINVAL,
|
|
||||||
"No passwords when decoding a "
|
|
||||||
"password protected file");
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
password = pw->val[0];
|
|
||||||
passwordlen = strlen(password);
|
|
||||||
|
|
||||||
if (strcmp(enc, "4,ENCRYPTED") != 0) {
|
if (strcmp(enc, "4,ENCRYPTED") != 0) {
|
||||||
hx509_set_error_string(context, 0, EINVAL,
|
hx509_set_error_string(context, 0, EINVAL,
|
||||||
@@ -216,53 +266,60 @@ parse_rsa_private_key(hx509_context context, struct hx509_collector *c,
|
|||||||
|
|
||||||
if (ssize < 0 || ssize < PKCS5_SALT_LEN || ssize < EVP_CIPHER_iv_length(cipher)) {
|
if (ssize < 0 || ssize < PKCS5_SALT_LEN || ssize < EVP_CIPHER_iv_length(cipher)) {
|
||||||
free(ivdata);
|
free(ivdata);
|
||||||
hx509_clear_error_string(context);
|
hx509_set_error_string(context, 0, EINVAL,
|
||||||
|
"Salt have wrong length in RSA key file");
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = malloc(EVP_CIPHER_key_length(cipher));
|
pw = _hx509_lock_get_passwords(lock);
|
||||||
if (key == NULL) {
|
if (pw != NULL) {
|
||||||
free(ivdata);
|
const void *password;
|
||||||
hx509_clear_error_string(context);
|
size_t passwordlen;
|
||||||
return ENOMEM;
|
|
||||||
|
for (i = 0; i < pw->len; i++) {
|
||||||
|
password = pw->val[i];
|
||||||
|
passwordlen = strlen(password);
|
||||||
|
|
||||||
|
ret = try_decrypt(context, c, cipher,
|
||||||
|
ivdata, password, passwordlen,
|
||||||
|
data, len);
|
||||||
|
if (ret == 0) {
|
||||||
|
decrypted = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (!decrypted) {
|
||||||
|
hx509_prompt prompt;
|
||||||
|
char password[128];
|
||||||
|
|
||||||
ret = EVP_BytesToKey(cipher, EVP_md5(), ivdata,
|
memset(&prompt, 0, sizeof(prompt));
|
||||||
password, passwordlen,
|
|
||||||
1, key, NULL);
|
prompt.prompt = "Password for keyfile: ";
|
||||||
if (ret <= 0) {
|
prompt.type = HX509_PROMPT_TYPE_PASSWORD;
|
||||||
free(key);
|
prompt.reply.data = password;
|
||||||
free(ivdata);
|
prompt.reply.length = sizeof(password);
|
||||||
hx509_set_error_string(context, 0, EINVAL,
|
|
||||||
"Failed to do string2key for RSA key");
|
ret = hx509_lock_prompt(lock, &prompt);
|
||||||
return EINVAL;
|
if (ret == 0)
|
||||||
|
ret = try_decrypt(context, c, cipher,
|
||||||
|
ivdata, password, strlen(password),
|
||||||
|
data, len);
|
||||||
|
/* XXX add password to lock password collection ? */
|
||||||
|
memset(password, 0, sizeof(password));
|
||||||
}
|
}
|
||||||
|
|
||||||
keydata.data = malloc(len);
|
|
||||||
keydata.length = len;
|
|
||||||
|
|
||||||
{
|
|
||||||
EVP_CIPHER_CTX ctx;
|
|
||||||
EVP_CIPHER_CTX_init(&ctx);
|
|
||||||
EVP_CipherInit_ex(&ctx, cipher, NULL, key, ivdata, 0);
|
|
||||||
EVP_Cipher(&ctx, keydata.data, data, len);
|
|
||||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
|
||||||
}
|
|
||||||
free(ivdata);
|
|
||||||
free(key);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
heim_octet_string keydata;
|
||||||
|
|
||||||
keydata.data = rk_UNCONST(data);
|
keydata.data = rk_UNCONST(data);
|
||||||
keydata.length = len;
|
keydata.length = len;
|
||||||
}
|
|
||||||
|
|
||||||
ret = _hx509_collector_private_key_add(c,
|
ret = _hx509_collector_private_key_add(c,
|
||||||
hx509_signature_rsa(),
|
hx509_signature_rsa(),
|
||||||
NULL,
|
NULL,
|
||||||
&keydata,
|
&keydata,
|
||||||
NULL);
|
NULL);
|
||||||
if (keydata.data != data)
|
}
|
||||||
free(keydata.data);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -406,8 +463,11 @@ parse_pem_file(hx509_context context,
|
|||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
if (where != BEFORE)
|
if (where != BEFORE) {
|
||||||
|
hx509_set_error_string(context, 0, EINVAL,
|
||||||
|
"File ends before end of PEM end tag");
|
||||||
ret = EINVAL;
|
ret = EINVAL;
|
||||||
|
}
|
||||||
if (data)
|
if (data)
|
||||||
free(data);
|
free(data);
|
||||||
if (type)
|
if (type)
|
||||||
|
Reference in New Issue
Block a user