support of encrypted private key files
This commit is contained in:
parent
833a7cbc50
commit
490d267ac3
|
@ -89,38 +89,47 @@ static bool find_boundary(const char* tag, chunk_t *line)
|
|||
/*
|
||||
* decrypts a DES-EDE-CBC encrypted data block
|
||||
*/
|
||||
static err_t pem_decrypt(chunk_t *blob, chunk_t *iv, char *passphrase)
|
||||
static err_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, size_t key_size,
|
||||
chunk_t *iv, chunk_t *passphrase)
|
||||
{
|
||||
hasher_t *hasher;
|
||||
crypter_t *crypter;
|
||||
chunk_t hash;
|
||||
chunk_t decrypted;
|
||||
chunk_t pass = {(char*)passphrase, strlen(passphrase)};
|
||||
chunk_t key = {alloca(24), 24};
|
||||
chunk_t key = {alloca(key_size), key_size};
|
||||
u_int8_t padding, *last_padding_pos, *first_padding_pos;
|
||||
|
||||
if (passphrase == NULL || passphrase->len == 0)
|
||||
return "missing passphrase";
|
||||
|
||||
/* build key from passphrase and IV */
|
||||
hasher = hasher_create(HASH_MD5);
|
||||
hash.len = hasher->get_hash_size(hasher);
|
||||
hash.ptr = alloca(hash.len);
|
||||
hasher->get_hash(hasher, pass, NULL);
|
||||
hasher->get_hash(hasher, *passphrase, NULL);
|
||||
hasher->get_hash(hasher, *iv, hash.ptr);
|
||||
|
||||
memcpy(key.ptr, hash.ptr, hash.len);
|
||||
|
||||
hasher->get_hash(hasher, hash, NULL);
|
||||
hasher->get_hash(hasher, pass, NULL);
|
||||
hasher->get_hash(hasher, *iv, hash.ptr);
|
||||
|
||||
memcpy(key.ptr + hash.len, hash.ptr, key.len - hash.len);
|
||||
|
||||
|
||||
printf("hash.len: %d, key.len: %d, iv.len: %d\n", hash.len, key.len, iv->len);
|
||||
if (key.len > hash.len)
|
||||
{
|
||||
hasher->get_hash(hasher, hash, NULL);
|
||||
hasher->get_hash(hasher, *passphrase, NULL);
|
||||
hasher->get_hash(hasher, *iv, hash.ptr);
|
||||
memcpy(key.ptr + hash.len, hash.ptr, key.len - hash.len);
|
||||
}
|
||||
hasher->destroy(hasher);
|
||||
|
||||
/* decrypt blob */
|
||||
crypter = crypter_create(ENCR_3DES, 0);
|
||||
crypter = crypter_create(alg, key_size);
|
||||
crypter->set_key(crypter, key);
|
||||
crypter->decrypt(crypter, *blob, *iv, &decrypted);
|
||||
logger->log_chunk(logger, CONTROL, " cipher text:", *blob);
|
||||
if (crypter->decrypt(crypter, *blob, *iv, &decrypted) != SUCCESS)
|
||||
{
|
||||
return "data size is not multiple of block size";
|
||||
}
|
||||
memcpy(blob->ptr, decrypted.ptr, blob->len);
|
||||
logger->log_chunk(logger, CONTROL, " plain text:", *blob);
|
||||
chunk_free(&decrypted);
|
||||
|
||||
/* determine amount of padding */
|
||||
|
@ -144,7 +153,7 @@ static err_t pem_decrypt(chunk_t *blob, chunk_t *iv, char *passphrase)
|
|||
* RFC 1421 Privacy Enhancement for Electronic Mail, February 1993
|
||||
* RFC 934 Message Encapsulation, January 1985
|
||||
*/
|
||||
err_t pem_to_bin(chunk_t *blob, char *passphrase, bool *pgp)
|
||||
err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
|
||||
{
|
||||
typedef enum {
|
||||
PEM_PRE = 0,
|
||||
|
@ -155,6 +164,9 @@ err_t pem_to_bin(chunk_t *blob, char *passphrase, bool *pgp)
|
|||
PEM_ABORT = 5
|
||||
} state_t;
|
||||
|
||||
encryption_algorithm_t alg = ENCR_UNDEFINED;
|
||||
size_t key_size;
|
||||
|
||||
bool encrypted = FALSE;
|
||||
|
||||
state_t state = PEM_PRE;
|
||||
|
@ -198,6 +210,7 @@ err_t pem_to_bin(chunk_t *blob, char *passphrase, bool *pgp)
|
|||
}
|
||||
if (state == PEM_HEADER)
|
||||
{
|
||||
err_t ugh = NULL;
|
||||
chunk_t name = CHUNK_INITIALIZER;
|
||||
chunk_t value = CHUNK_INITIALIZER;
|
||||
|
||||
|
@ -210,14 +223,14 @@ err_t pem_to_bin(chunk_t *blob, char *passphrase, bool *pgp)
|
|||
|
||||
/* we are looking for a parameter: value pair */
|
||||
logger->log(logger, CONTROL|LEVEL2, " %.*s", (int)line.len, line.ptr);
|
||||
if (!extract_parameter_value(&name, &value, &line))
|
||||
ugh = extract_parameter_value(&name, &value, &line);
|
||||
if (ugh != NULL)
|
||||
continue;
|
||||
|
||||
if (match("Proc-Type", &name) && *value.ptr == '4')
|
||||
encrypted = TRUE;
|
||||
else if (match("DEK-Info", &name))
|
||||
{
|
||||
const char *ugh = NULL;
|
||||
size_t len = 0;
|
||||
chunk_t dek;
|
||||
|
||||
|
@ -225,8 +238,25 @@ err_t pem_to_bin(chunk_t *blob, char *passphrase, bool *pgp)
|
|||
dek = value;
|
||||
|
||||
/* we support DES-EDE3-CBC encrypted files, only */
|
||||
if (!match("DES-EDE3-CBC", &dek))
|
||||
if (match("DES-EDE3-CBC", &dek))
|
||||
{
|
||||
alg = ENCR_3DES;
|
||||
key_size = 24;
|
||||
}
|
||||
else if (match("AES-128-CBC", &dek))
|
||||
{
|
||||
alg = ENCR_AES_CBC;
|
||||
key_size = 16;
|
||||
}
|
||||
else if (match("AES-256-CBC", &dek))
|
||||
{
|
||||
alg = ENCR_AES_CBC;
|
||||
key_size = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "encryption algorithm not supported";
|
||||
}
|
||||
|
||||
eat_whitespace(&value);
|
||||
ugh = ttodata(value.ptr, value.len, 16, iv.ptr, 16, &len);
|
||||
|
@ -279,13 +309,13 @@ err_t pem_to_bin(chunk_t *blob, char *passphrase, bool *pgp)
|
|||
if (state != PEM_POST)
|
||||
return "file coded in unknown format, discarded";
|
||||
|
||||
return (encrypted)? pem_decrypt(blob, &iv, passphrase) : NULL;
|
||||
return (encrypted)? pem_decrypt(blob, alg, key_size, &iv, passphrase) : NULL;
|
||||
}
|
||||
|
||||
/* load a coded key or certificate file with autodetection
|
||||
* of binary DER or base64 PEM ASN.1 formats and armored PGP format
|
||||
*/
|
||||
bool pem_asn1_load_file(const char *filename, char *passphrase,
|
||||
bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
|
||||
const char *type, chunk_t *blob, bool *pgp)
|
||||
{
|
||||
err_t ugh = NULL;
|
||||
|
@ -314,6 +344,9 @@ bool pem_asn1_load_file(const char *filename, char *passphrase,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
if (passphrase != NULL)
|
||||
logger->log_bytes(logger, PRIVATE, " passphrase:", passphrase->ptr, passphrase->len);
|
||||
|
||||
/* try PEM format */
|
||||
ugh = pem_to_bin(blob, passphrase, pgp);
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
|
||||
#include <types.h>
|
||||
|
||||
err_t pem_to_bin(chunk_t *blob, char *passphrase, bool *pgp);
|
||||
err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp);
|
||||
|
||||
bool pem_asn1_load_file(const char *filename, char *passphrase,
|
||||
bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
|
||||
const char *type, chunk_t *blob, bool *pgp);
|
||||
|
||||
#endif /*PEM_H_*/
|
||||
|
|
|
@ -518,7 +518,7 @@ crl_t *crl_create_from_file(const char *filename)
|
|||
chunk_t chunk = CHUNK_INITIALIZER;
|
||||
crl_t *crl = NULL;
|
||||
|
||||
if (!pem_asn1_load_file(filename, "", "crl", &chunk, &pgp))
|
||||
if (!pem_asn1_load_file(filename, NULL, "crl", &chunk, &pgp))
|
||||
return NULL;
|
||||
|
||||
crl = crl_create_from_chunk(chunk);
|
||||
|
|
|
@ -759,7 +759,7 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob)
|
|||
/*
|
||||
* see header
|
||||
*/
|
||||
rsa_private_key_t *rsa_private_key_create_from_file(char *filename, char *passphrase)
|
||||
rsa_private_key_t *rsa_private_key_create_from_file(char *filename, chunk_t *passphrase)
|
||||
{
|
||||
bool pgp = FALSE;
|
||||
chunk_t chunk = CHUNK_INITIALIZER;
|
||||
|
|
|
@ -173,7 +173,7 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk);
|
|||
* passphrase is used to decrypt an ecrypted key.
|
||||
*
|
||||
* @param filename filename which holds the key
|
||||
* @param passphrase optional passphase for decryption
|
||||
* @param passphrase optional passphase for decryption, can be NULL
|
||||
* @return loaded rsa_private_key_t, or NULL
|
||||
*
|
||||
* @todo Implement PEM file loading
|
||||
|
@ -181,6 +181,6 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk);
|
|||
*
|
||||
* @ingroup rsa
|
||||
*/
|
||||
rsa_private_key_t *rsa_private_key_create_from_file(char *filename, char *passphrase);
|
||||
rsa_private_key_t *rsa_private_key_create_from_file(char *filename, chunk_t *passphrase);
|
||||
|
||||
#endif /*RSA_PRIVATE_KEY_H_*/
|
||||
|
|
|
@ -488,7 +488,7 @@ rsa_public_key_t *rsa_public_key_create_from_file(char *filename)
|
|||
chunk_t chunk = CHUNK_INITIALIZER;
|
||||
rsa_public_key_t *pubkey = NULL;
|
||||
|
||||
if (!pem_asn1_load_file(filename, "", "public key", &chunk, &pgp))
|
||||
if (!pem_asn1_load_file(filename, NULL, "public key", &chunk, &pgp))
|
||||
return NULL;
|
||||
|
||||
pubkey = rsa_public_key_create_from_chunk(chunk);
|
||||
|
|
|
@ -1268,7 +1268,7 @@ x509_t *x509_create_from_file(const char *filename, const char *label)
|
|||
chunk_t chunk = CHUNK_INITIALIZER;
|
||||
x509_t *cert = NULL;
|
||||
|
||||
if (!pem_asn1_load_file(filename, "", label, &chunk, &pgp))
|
||||
if (!pem_asn1_load_file(filename, NULL, label, &chunk, &pgp))
|
||||
return NULL;
|
||||
|
||||
cert = x509_create_from_chunk(chunk);
|
||||
|
|
Loading…
Reference in New Issue