static void test_load_v1_public_key(void) { test_begin("test_load_v1_public_key"); const char* data1 = "1\t716\t030131D8A5FD5167947A0AE9CB112ADED6526654635AA5887051EE2364414B60FF32EBA8FA0BBE9485DBDE8794BBBCB44BBFC0D662A4287A848BA570D4E5E45A11FE0F\td0cfaca5d335f9edc41c84bb47465184cb0e2ec3931bebfcea4dd433615e77a0"; const char* error = NULL; const char* key_hash = NULL; const char* encryption_key_hash = NULL; enum dcrypt_key_format format; enum dcrypt_key_version version; enum dcrypt_key_kind kind; enum dcrypt_key_encryption_type encryption_type; bool ret = dcrypt_key_string_get_info(data1, &format, &version, &kind, &encryption_type, &encryption_key_hash, &key_hash, &error); test_assert(ret == TRUE); test_assert(error == NULL); test_assert(format == DCRYPT_FORMAT_DOVECOT); test_assert(version == DCRYPT_KEY_VERSION_1); test_assert(kind == DCRYPT_KEY_KIND_PUBLIC); test_assert(encryption_type == DCRYPT_KEY_ENCRYPTION_TYPE_NONE); test_assert(key_hash != NULL && strcmp(key_hash, "d0cfaca5d335f9edc41c84bb47465184cb0e2ec3931bebfcea4dd433615e77a0") == 0); test_assert(encryption_key_hash == NULL); struct dcrypt_public_key *pub_key = NULL; ret = dcrypt_key_load_public(&pub_key, format, data1, &error); test_assert(ret == TRUE); test_assert(error == NULL); test_assert(dcrypt_key_type_public(pub_key) == DCRYPT_KEY_EC); dcrypt_key_free_public(&pub_key); test_assert(pub_key == NULL); test_end(); }
static int o_stream_encrypt_key_for_pubkey_v2(struct encrypt_ostream *stream, const char *malg, const unsigned char *key, size_t key_len, struct dcrypt_public_key *pubkey, buffer_t *res) { enum dcrypt_key_type ktype; const char *error; buffer_t *encrypted_key, *ephemeral_key, *temp_key; ephemeral_key = buffer_create_dynamic(pool_datastack_create(), 256); encrypted_key = buffer_create_dynamic(pool_datastack_create(), 256); temp_key = buffer_create_dynamic(pool_datastack_create(), 48); ktype = dcrypt_key_type_public(pubkey); if (ktype == DCRYPT_KEY_RSA) { /* encrypt key as R (as we don't need DH with RSA)*/ if (!dcrypt_rsa_encrypt(pubkey, key, key_len, encrypted_key, &error)) { io_stream_set_error(&stream->ostream.iostream, "Cannot encrypt key data: %s", error); return -1; } } else if (ktype == DCRYPT_KEY_EC) { /* R = our ephemeral public key */ buffer_t *secret = buffer_create_dynamic(pool_datastack_create(), 256); /* derive ephemeral key and shared secret */ if (!dcrypt_ecdh_derive_secret_peer(pubkey, ephemeral_key, secret, &error)) { io_stream_set_error(&stream->ostream.iostream, "Cannot perform ECDH: %s", error); return -1; } /* use shared secret and ephemeral key to generate encryption key/iv */ if (!dcrypt_pbkdf2(secret->data, secret->used, ephemeral_key->data, ephemeral_key->used, malg, IO_STREAM_ENCRYPT_ROUNDS, temp_key, 48, &error)) { safe_memset(buffer_get_modifiable_data(secret, 0), 0, secret->used); io_stream_set_error(&stream->ostream.iostream, "Cannot perform key encryption: %s", error); } safe_memset(buffer_get_modifiable_data(secret, 0), 0, secret->used); /* encrypt key with shared secret */ struct dcrypt_context_symmetric *dctx; if (!dcrypt_ctx_sym_create("AES-256-CBC", DCRYPT_MODE_ENCRYPT, &dctx, &error)) { safe_memset(buffer_get_modifiable_data(temp_key, 0), 0, temp_key->used); io_stream_set_error(&stream->ostream.iostream, "Cannot perform key encryption: %s", error); return -1; } const unsigned char *ptr = temp_key->data; i_assert(temp_key->used == 48); dcrypt_ctx_sym_set_key(dctx, ptr, 32); dcrypt_ctx_sym_set_iv(dctx, ptr+32, 16); safe_memset(buffer_get_modifiable_data(temp_key, 0), 0, temp_key->used); int ec = 0; if (!dcrypt_ctx_sym_init(dctx, &error) || !dcrypt_ctx_sym_update(dctx, key, key_len, encrypted_key, &error) || !dcrypt_ctx_sym_final(dctx, encrypted_key, &error)) { io_stream_set_error(&stream->ostream.iostream, "Cannot perform key encryption: %s", error); ec = -1; } dcrypt_ctx_sym_destroy(&dctx); if (ec != 0) return ec; } else { io_stream_set_error(&stream->ostream.iostream, "Unsupported key type"); return -1; } /* store key type */ char kt = ktype; buffer_append(res, &kt, 1); /* store hash of public key as ID */ dcrypt_key_id_public(stream->pub, "sha256", res, NULL); /* store ephemeral key (if present) */ unsigned int val = htonl(ephemeral_key->used); buffer_append(res, &val, 4); buffer_append_buf(res, ephemeral_key, 0, (size_t)-1); /* store encrypted key */ val = htonl(encrypted_key->used); buffer_append(res, &val, 4); buffer_append_buf(res, encrypted_key, 0, (size_t)-1); return 0; }