support of encrypted private key files
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 20 Sep 2006 05:48:54 +0000 (05:48 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 20 Sep 2006 05:48:54 +0000 (05:48 -0000)
src/libstrongswan/asn1/pem.c
src/libstrongswan/asn1/pem.h
src/libstrongswan/crypto/crl.c
src/libstrongswan/crypto/rsa/rsa_private_key.c
src/libstrongswan/crypto/rsa/rsa_private_key.h
src/libstrongswan/crypto/rsa/rsa_public_key.c
src/libstrongswan/crypto/x509.c

index 3a41c5a..6de340a 100755 (executable)
@@ -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);
 
index 9edb3dc..2c0b457 100755 (executable)
@@ -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_*/
index 43f616f..513dfc8 100755 (executable)
@@ -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);
index 13e593b..244c78c 100644 (file)
@@ -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;
index b2fff8c..da5cb43 100644 (file)
@@ -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_*/
index 469f9ea..4aa529d 100644 (file)
@@ -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);
index 60d2a6e..07745ba 100755 (executable)
@@ -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);