(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:
Love Hörnquist Åstrand
2006-10-11 20:28:49 +00:00
parent 7c19b50856
commit 1a196d0776

View File

@@ -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)