changeset 20871:536d185e3794

lib-dcrypt: enc_key and pw must be NULL on storing unencrypted private key Add tests for password and key encryption, and get_info on them. Also give examples of valid cipher values for password and key encryption in dcrypt.h comment.
author Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi>
date Thu, 13 Oct 2016 23:38:36 +0300
parents f254622a8c2c
children 4c571ff37f8f
files src/lib-dcrypt/dcrypt-openssl.c src/lib-dcrypt/dcrypt.h src/lib-dcrypt/test-crypto.c
diffstat 3 files changed, 86 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-dcrypt/dcrypt-openssl.c	Wed Oct 12 21:29:51 2016 +0300
+++ b/src/lib-dcrypt/dcrypt-openssl.c	Thu Oct 13 23:38:36 2016 +0300
@@ -1456,7 +1456,7 @@
 		obj = OBJ_nid2obj(EVP_PKEY_id(pkey));
 	}
 
-	int enctype = 0;
+	int enctype = DCRYPT_KEY_ENCRYPTION_TYPE_NONE;
 	int ln = OBJ_obj2txt(objtxt, sizeof(objtxt), obj, 1);
 	if (ln < 1)
 		return dcrypt_openssl_error(error_r);
@@ -1500,6 +1500,8 @@
 		i_assert(password != NULL);
 		enctype = DCRYPT_DOVECOT_KEY_ENCRYPT_PASSWORD;
 		cipher2 = cipher;
+	} else if (enctype == DCRYPT_KEY_ENCRYPTION_TYPE_NONE) {
+		i_assert(enc_key == NULL && password == NULL);
 	}
 
 	/* put in OID and encryption type */
@@ -1507,7 +1509,7 @@
 		objtxt, enctype));
 
 	/* perform encryption if desired */
-	if (enctype > 0) {
+	if (enctype != DCRYPT_KEY_ENCRYPTION_TYPE_NONE) {
 		if (!dcrypt_openssl_encrypt_private_key_dovecot(buf, enctype, cipher2, password, enc_key, destination, error_r)) {
 			buffer_set_used_size(destination, dest_used);
 			return FALSE;
--- a/src/lib-dcrypt/dcrypt.h	Wed Oct 12 21:29:51 2016 +0300
+++ b/src/lib-dcrypt/dcrypt.h	Thu Oct 13 23:38:36 2016 +0300
@@ -178,6 +178,11 @@
 bool dcrypt_key_load_public(struct dcrypt_public_key **key_r, const char *data,
 	const char **error_r);
 
+/**
+ * When encrypting with public key, the cipher parameter here must begin with
+ * ecdh-, for example ecdh-aes-256-ctr. An example of a valid cipher for
+ * encrypting with password would be aes-256-ctr.
+ */
 bool dcrypt_key_store_private(struct dcrypt_private_key *key, enum dcrypt_key_format format, const char *cipher, 
 	buffer_t *destination, const char *password, struct dcrypt_public_key *enc_key, const char **error_r);
 
--- a/src/lib-dcrypt/test-crypto.c	Wed Oct 12 21:29:51 2016 +0300
+++ b/src/lib-dcrypt/test-crypto.c	Thu Oct 13 23:38:36 2016 +0300
@@ -592,6 +592,81 @@
 }
 
 static
+void test_get_info_key_encrypted(void) {
+	test_begin("test_get_info_key_encrypted");
+
+	struct dcrypt_keypair p1, p2;
+	const char *error = NULL;
+	bool ret = dcrypt_keypair_generate(&p1, DCRYPT_KEY_EC, 0, "sect571k1", &error);
+	test_assert(ret == TRUE);
+	ret = dcrypt_keypair_generate(&p2, DCRYPT_KEY_EC, 0, "sect571k1", &error);
+	test_assert(ret == TRUE);
+
+	string_t* buf = str_new(default_pool, 4096);
+
+	buffer_set_used_size(buf, 0);
+	ret = dcrypt_key_store_private(p1.priv, DCRYPT_FORMAT_DOVECOT, "ecdh-aes-256-ctr", buf, NULL, p2.pub, &error);
+	test_assert(ret == TRUE);
+
+	enum dcrypt_key_format format;
+	enum dcrypt_key_version version;
+	enum dcrypt_key_kind kind;
+	enum dcrypt_key_encryption_type enc_type;
+	const char *enc_hash;
+	const char *key_hash;
+
+	ret = dcrypt_key_string_get_info(str_c(buf), &format, &version,
+			&kind, &enc_type, &enc_hash, &key_hash, &error);
+	test_assert(ret == TRUE);
+	test_assert(format == DCRYPT_FORMAT_DOVECOT);
+	test_assert(version == DCRYPT_KEY_VERSION_2);
+	test_assert(kind == DCRYPT_KEY_KIND_PRIVATE);
+	test_assert(enc_type == DCRYPT_KEY_ENCRYPTION_TYPE_KEY);
+	test_assert(enc_hash != NULL);
+	test_assert(key_hash != NULL);
+
+	dcrypt_keypair_unref(&p1);
+	dcrypt_keypair_unref(&p2);
+
+	test_end();
+}
+
+static
+void test_get_info_pw_encrypted(void) {
+	test_begin("test_get_info_pw_encrypted");
+
+	struct dcrypt_keypair p1;
+	const char *error;
+	bool ret = dcrypt_keypair_generate(&p1, DCRYPT_KEY_EC, 0, "sect571k1", &error);
+	test_assert(ret == TRUE);
+
+	string_t* buf = str_new(default_pool, 4096);
+	ret = dcrypt_key_store_private(p1.priv, DCRYPT_FORMAT_DOVECOT, "aes-256-ctr", buf, "pw", NULL, &error);
+	test_assert(ret == TRUE);
+
+	enum dcrypt_key_format format;
+	enum dcrypt_key_version version;
+	enum dcrypt_key_kind kind;
+	enum dcrypt_key_encryption_type enc_type;
+	const char *enc_hash;
+	const char *key_hash;
+
+	ret = dcrypt_key_string_get_info(str_c(buf), &format, &version,
+			&kind, &enc_type, &enc_hash, &key_hash, &error);
+	test_assert(ret == TRUE);
+	test_assert(format == DCRYPT_FORMAT_DOVECOT);
+	test_assert(version == DCRYPT_KEY_VERSION_2);
+	test_assert(kind == DCRYPT_KEY_KIND_PRIVATE);
+	test_assert(enc_type == DCRYPT_KEY_ENCRYPTION_TYPE_PASSWORD);
+	test_assert(enc_hash == NULL);
+	test_assert(key_hash != NULL);
+
+	dcrypt_keypair_unref(&p1);
+
+	test_end();
+}
+
+static
 void test_load_invalid_keys(void) {
 	test_begin("test_load_invalid_keys");
 
@@ -634,6 +709,8 @@
 		test_gen_and_get_info_rsa_pem,
 		test_get_info_rsa_private_key,
 		test_get_info_invalid_keys,
+		test_get_info_key_encrypted,
+		test_get_info_pw_encrypted,
 		test_load_invalid_keys,
 		NULL
 	};