Mercurial > dovecot > core-2.2
changeset 20570:fe9af2fb0dae
lib-dcrypt: change v2 key field separator to ':'
author | Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi> |
---|---|
date | Wed, 03 Aug 2016 17:55:15 +0300 |
parents | 8b9bbc3948b5 |
children | af359811edb4 |
files | src/lib-dcrypt/dcrypt-openssl.c src/lib-dcrypt/test-crypto.c |
diffstat | 2 files changed, 110 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-dcrypt/dcrypt-openssl.c Thu Aug 04 15:57:22 2016 +0300 +++ b/src/lib-dcrypt/dcrypt-openssl.c Wed Aug 03 17:55:15 2016 +0300 @@ -1213,8 +1213,21 @@ const char *data, const char *password, struct dcrypt_private_key *key, const char **error_r) { + /* FIXME: duplicated from info */ + if (strncmp(data, "1:", 2) == 0) { + if (error_r != NULL) + *error_r = "Dovecot v1 key format " + "uses tab to separate fields"; + return FALSE; + } else if (strncmp(data, "2\t", 2) == 0) { + if (error_r != NULL) + *error_r = "Dovecot v2 key format uses " + "colon to separate fields"; + return FALSE; + } + bool ret; - const char **input = t_strsplit_tab(data); + const char **input = t_strsplit(data, ":\t"); size_t len = str_array_length(input); if (len < 4) { @@ -1344,9 +1357,21 @@ bool dcrypt_openssl_load_public_key_dovecot(struct dcrypt_public_key **key_r, const char *data, const char **error_r) { - int ec = 0; + /* FIXME: duplicated from info */ + if (strncmp(data, "1:", 2) == 0) { + if (error_r != NULL) + *error_r = "Dovecot v1 key format " + "uses tab to separate fields"; + return FALSE; + } else if (strncmp(data, "2\t", 2) == 0) { + if (error_r != NULL) + *error_r = "Dovecot v2 key format uses " + "colon to separate fields"; + return FALSE; + } - const char **input = t_strsplit_tab(data); + int ec = 0; + const char **input = t_strsplit(data, ":\t"); size_t len = str_array_length(input); if (len < 2) ec = -1; @@ -1378,14 +1403,14 @@ cipher = t_str_lcase(cipher); str_append(destination, cipher); - str_append_c(destination, '\t'); + str_append_c(destination, ':'); random_fill(salt, sizeof(salt)); binary_to_hex_append(destination, salt, sizeof(salt)); buffer_t saltbuf; buffer_create_from_const_data(&saltbuf, salt, sizeof(salt)); /* so we don't have to make new version if we ever upgrade these */ - str_append(destination, t_strdup_printf("\t%s\t%d\t", + str_append(destination, t_strdup_printf(":%s:%d:", DCRYPT_DOVECOT_KEY_ENCRYPT_HASH, DCRYPT_DOVECOT_KEY_ENCRYPT_ROUNDS)); @@ -1422,11 +1447,11 @@ /* some additional fields or private key version */ if (enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_PK) { - str_append_c(destination, '\t'); + str_append_c(destination, ':'); /* for RSA, this is the actual encrypted secret */ binary_to_hex_append(destination, peer_key->data, peer_key->used); - str_append_c(destination, '\t'); + str_append_c(destination, ':'); buffer_set_used_size(peer_key, 0); if (!dcrypt_openssl_public_key_id(enc_key, "sha256", peer_key, error_r)) @@ -1500,7 +1525,7 @@ } /* put in OID and encryption type */ - str_append(destination, t_strdup_printf("2\t%s\t%d\t", + str_append(destination, t_strdup_printf("2:%s:%d:", objtxt, enctype)); /* perform encryption if desired */ @@ -1514,7 +1539,7 @@ } /* append public key id */ - str_append_c(destination, '\t'); + str_append_c(destination, ':'); buffer_set_used_size(buf, 0); bool res = dcrypt_openssl_private_key_id(key, "sha256", buf, error_r); binary_to_hex_append(destination, buf->data, buf->used); @@ -1541,12 +1566,12 @@ /* then store it */ str_append_c(destination, '2'); - str_append_c(destination, '\t'); + str_append_c(destination, ':'); binary_to_hex_append(destination, tmp, rv); OPENSSL_free(tmp); /* append public key ID */ - str_append_c(destination, '\t'); + str_append_c(destination, ':'); buffer_t *buf = buffer_create_dynamic(pool_datastack_create(), 32); bool res = dcrypt_openssl_public_key_id(key, "sha256", buf, error_r); @@ -1805,7 +1830,18 @@ return FALSE; } } else { - const char **fields = t_strsplit_tab(key_data); + if (strncmp(key_data, "1:", 2) == 0) { + if (error_r != NULL) + *error_r = "Dovecot v1 key format " + "uses tab to separate fields"; + return FALSE; + } else if (strncmp(key_data, "2\t", 2) == 0) { + if (error_r != NULL) + *error_r = "Dovecot v2 key format uses " + "colon to separate fields"; + return FALSE; + } + const char **fields = t_strsplit(key_data, ":\t"); int nfields = str_array_length(fields); if (nfields < 2) {
--- a/src/lib-dcrypt/test-crypto.c Thu Aug 04 15:57:22 2016 +0300 +++ b/src/lib-dcrypt/test-crypto.c Wed Aug 03 17:55:15 2016 +0300 @@ -374,9 +374,9 @@ "yLJV2ui8A/CUyqyEMrezvwgMO6EkAyIAAybRUR3MsH0+0PQcDwkrXOJ9aePwzTQV\n" \ "DN51+n1JCxbI\n" \ "-----END PRIVATE KEY-----\n", - "2\t1.2.840.10045.3.1.7\t0\t0000002100b6e40903eb9ba19595c201dc0dc8b255dae8bc03f094caac8432b7b3bf080c3b\tab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd", - "2\t1.2.840.10045.3.1.7\t2\taes-256-ctr\t2b19763d4bbf7754\tsha256\t2048\tc36fa194669a1aec400eae32fbadaa7c58b14f53c464cfbb0a4b61fbe24ab7750637c4025d\tab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd", - "2\t1.2.840.10045.3.1.7\t1\taes-256-ctr\t7c7f1d12a7c011de\tsha256\t2048\tf5d1de11d58a81b141cf038012a618623e9d7b18062deeb3a4e35872c62ca0837db8688370\t021abfbc5bc4f6cf49c40b9fc388c4616ea079941675f477ee4557df1919626d35\tab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd\tab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd" + "2:1.2.840.10045.3.1.7:0:0000002100b6e40903eb9ba19595c201dc0dc8b255dae8bc03f094caac8432b7b3bf080c3b:ab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd", + "2:1.2.840.10045.3.1.7:2:aes-256-ctr:2b19763d4bbf7754:sha256:2048:c36fa194669a1aec400eae32fbadaa7c58b14f53c464cfbb0a4b61fbe24ab7750637c4025d:ab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd", + "2:1.2.840.10045.3.1.7:1:aes-256-ctr:7c7f1d12a7c011de:sha256:2048:f5d1de11d58a81b141cf038012a618623e9d7b18062deeb3a4e35872c62ca0837db8688370:021abfbc5bc4f6cf49c40b9fc388c4616ea079941675f477ee4557df1919626d35:ab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd:ab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd" }; test_begin("test_load_v2_key"); @@ -424,7 +424,7 @@ const char *error; test_begin("test_load_v2_public_key"); - const char *key = "2\t3058301006072a8648ce3d020106052b810400230344000301c50954e734dd8b410a607764a7057065a45510da52f2c6e28e0cb353b9c389fa8cb786943ae991fce9befed78fb162fbbc615415f06af06c8cc80c37f4e94ff6c7\t185a7212542782e239111f9c19d126ad55b18ddaf4883d66afe8d9627c3607d8"; + const char *key = "2:3058301006072a8648ce3d020106052b810400230344000301c50954e734dd8b410a607764a7057065a45510da52f2c6e28e0cb353b9c389fa8cb786943ae991fce9befed78fb162fbbc615415f06af06c8cc80c37f4e94ff6c7:185a7212542782e239111f9c19d126ad55b18ddaf4883d66afe8d9627c3607d8"; test_assert(dcrypt_key_load_public(&pub, DCRYPT_FORMAT_DOVECOT, key, &error)); @@ -444,7 +444,7 @@ void test_get_info_v2_key(void) { test_begin("test_get_info_v2_key"); - const char *key = "2\t305e301006072a8648ce3d020106052b81040026034a000203fcc90034fa03d6fb79a0fc8b3b43c3398f68e76029307360cdcb9e27bb7e84b3c19dfb7244763bc4d442d216f09b7b7945ed9d182f3156550e9ee30b237a0217dbf79d28975f31\t86706b69d1f640011a65d26a42f2ba20a619173644e1cc7475eb1d90966e84dc"; + const char *key = "2:305e301006072a8648ce3d020106052b81040026034a000203fcc90034fa03d6fb79a0fc8b3b43c3398f68e76029307360cdcb9e27bb7e84b3c19dfb7244763bc4d442d216f09b7b7945ed9d182f3156550e9ee30b237a0217dbf79d28975f31:86706b69d1f640011a65d26a42f2ba20a619173644e1cc7475eb1d90966e84dc"; enum dcrypt_key_format format; enum dcrypt_key_version version = DCRYPT_KEY_VERSION_NA; enum dcrypt_key_kind kind; @@ -563,6 +563,61 @@ test_end(); } +static +void test_get_info_invalid_keys(void) { + test_begin("test_get_info_invalid_keys"); + + const char *key = "1:716:030131D8A5FD5167947A0AE9CB112ADED6526654635AA5887051EE2364414B60FF32EBA8FA0BBE9485DBDE8794BBBCB44BBFC0D662A4287A848BA570D4E5E45A11FE0F:d0cfaca5d335f9edc41c84bb47465184cb0e2ec3931bebfcea4dd433615e77a0"; + const char *error = NULL; + + test_assert(dcrypt_key_string_get_info(key, NULL, NULL, + NULL, NULL, NULL, NULL, &error) == FALSE); + test_assert(error != NULL); + test_assert(strstr(error, "tab") != NULL); + + key = "2\t305e301006072a8648ce3d020106052b81040026034a000203fcc90034fa03d6fb79a0fc8b3b43c3398f68e76029307360cdcb9e27bb7e84b3c19dfb7244763bc4d442d216f09b7b7945ed9d182f3156550e9ee30b237a0217dbf79d28975f31\t86706b69d1f640011a65d26a42f2ba20a619173644e1cc7475eb1d90966e84dc"; + error = NULL; + + test_assert(dcrypt_key_string_get_info(key, NULL, NULL, + NULL, NULL, NULL, NULL, &error) == FALSE); + test_assert(error != NULL); + test_assert(strstr(error, "colon") != NULL); + + key = "2"; + error = NULL; + + test_assert(dcrypt_key_string_get_info(key, NULL, NULL, + NULL, NULL, NULL, NULL, &error) == FALSE); + test_assert(error != NULL); + test_assert(strstr(error, "Unknown") != NULL); + + test_end(); +} + +static +void test_load_invalid_keys(void) { + test_begin("test_load_invalid_keys"); + + const char *error = NULL; + const char *key = "1:716:0301EB00973C4EFC8FCECA4EA33E941F50B561199A5159BCB6C2EED9DD1D62D65E38A254979D89E28F0C28883E71EE2AD264CD16B863FA094A8F6F69A56B62E8918040:7c9a1039ea2e4fed73e81dd3ffc3fa22ea4a28352939adde7bf8ea858b00fa4f"; + struct dcrypt_public_key *pub_key = NULL; + + bool ret = dcrypt_key_load_public(&pub_key, DCRYPT_FORMAT_DOVECOT, + key, &error); + test_assert(ret == FALSE); + test_assert(error != NULL); + + error = NULL; + key = "2:305e301006072a8648ce3d020106052b81040026034a000203fcc90034fa03d6fb79a0fc8b3b43c3398f68e76029307360cdcb9e27bb7e84b3c19dfb7244763bc4d442d216f09b7b7945ed9d182f3156550e9ee30b237a0217dbf79d28975f31:86706b69d1f640011a65d26a42f2ba20a619173644e1cc7475eb1d90966e84dc"; + struct dcrypt_private_key *priv_key = NULL; + + ret = dcrypt_key_load_private(&priv_key, DCRYPT_FORMAT_DOVECOT, key, NULL, NULL, &error); + test_assert(ret == FALSE); + test_assert(error != NULL); + + test_end(); +} + int main(void) { random_init(); dcrypt_initialize("openssl", NULL, NULL); @@ -579,6 +634,8 @@ test_get_info_v2_key, test_gen_and_get_info_rsa_pem, test_get_info_rsa_private_key, + test_get_info_invalid_keys, + test_load_invalid_keys, NULL };