This is an automated email from the ASF dual-hosted git repository.
rnewson pushed a commit to branch database_encryption
in repository https://gitbox.apache.org/repos/asf/couchdb.git
The following commit(s) were added to refs/heads/database_encryption by this
push:
new 27ede6952 simplify
27ede6952 is described below
commit 27ede6952ffc6a6a949129670f345ab5877df792
Author: Robert Newson <[email protected]>
AuthorDate: Mon Jun 13 22:07:26 2022 +0100
simplify
---
rebar.config.script | 1 -
rel/reltool.config | 2 -
src/aegis/rebar.config.script | 42 -----
src/aegis/src/aegis.app.src | 28 ----
src/aegis/src/aegis.erl | 60 -------
src/aegis/src/aegis_cmac.erl | 79 ----------
src/aegis/src/aegis_compat.hrl | 42 -----
src/aegis/src/aegis_key_manager.erl | 36 -----
src/aegis/src/aegis_key_manager_config.erl | 64 --------
src/aegis/src/aegis_s2v.erl | 53 -------
src/aegis/src/aegis_siv.erl | 136 ----------------
src/aegis/src/aegis_util.erl | 90 -----------
src/couch/src/couch_bt_engine.erl | 3 +-
src/couch/src/couch_bt_engine_compactor.erl | 17 +-
src/couch/src/couch_db_updater.erl | 6 +-
.../src/couch_encryption_manager.erl} | 21 +--
src/couch/src/couch_file.erl | 173 +++++++++++++--------
src/couch_mrview/src/couch_mrview_compactor.erl | 6 +-
src/couch_mrview/src/couch_mrview_index.erl | 6 +-
src/couch_mrview/src/couch_mrview_util.erl | 8 +-
20 files changed, 153 insertions(+), 720 deletions(-)
diff --git a/rebar.config.script b/rebar.config.script
index 0e6af11d3..44c4d61b1 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -113,7 +113,6 @@ os:putenv("COUCHDB_APPS_CONFIG_DIR",
filename:join([COUCHDB_ROOT, "rel/apps"])).
SubDirs = [
%% must be compiled first as it has a custom behavior
"src/couch_epi",
- "src/aegis",
"src/couch_log",
"src/chttpd",
"src/couch",
diff --git a/rel/reltool.config b/rel/reltool.config
index a7ab87c5f..ab26fb2ed 100644
--- a/rel/reltool.config
+++ b/rel/reltool.config
@@ -26,7 +26,6 @@
syntax_tools,
xmerl,
%% couchdb
- aegis,
b64url,
bear,
chttpd,
@@ -91,7 +90,6 @@
{app, xmerl, [{incl_cond, include}]},
%% couchdb
- {app, aegis, [{incl_cond, include}]},
{app, b64url, [{incl_cond, include}]},
{app, bear, [{incl_cond, include}]},
{app, chttpd, [{incl_cond, include}]},
diff --git a/src/aegis/rebar.config.script b/src/aegis/rebar.config.script
deleted file mode 100644
index cb334032b..000000000
--- a/src/aegis/rebar.config.script
+++ /dev/null
@@ -1,42 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
-
-CoverProps = [
- {cover_enabled, true},
- {cover_print_enabled, true}
-],
-
-CouchConfig = case filelib:is_file(os:getenv("COUCHDB_CONFIG")) of
- true ->
- {ok, Result} = file:consult(os:getenv("COUCHDB_CONFIG")),
- Result;
- false ->
- []
-end.
-
-AegisKeyManager = case lists:keyfind(aegis_key_manager, 1, CouchConfig) of
- {aegis_key_manager, Module} when Module /= "" ->
- list_to_atom(Module);
- _ ->
- aegis_key_manager_noop
-end,
-
-CurrentOpts = case lists:keyfind(erl_opts, 1, CONFIG) of
- {erl_opts, Opts} -> Opts;
- false -> []
-end,
-
-Config = CoverProps ++ CONFIG,
-
-AegisOpts = {d, 'AEGIS_KEY_MANAGER', AegisKeyManager},
-lists:keystore(erl_opts, 1, Config, {erl_opts, [AegisOpts | CurrentOpts]}).
\ No newline at end of file
diff --git a/src/aegis/src/aegis.app.src b/src/aegis/src/aegis.app.src
deleted file mode 100644
index 9088ec46c..000000000
--- a/src/aegis/src/aegis.app.src
+++ /dev/null
@@ -1,28 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
-{application, aegis,
- [{description, "An OTP application"},
- {vsn, git},
- {registered, []},
- {applications,
- [kernel,
- stdlib,
- crypto
- ]},
- {env,[]},
- {modules, []},
-
- {maintainers, []},
- {licenses, []},
- {links, []}
- ]}.
diff --git a/src/aegis/src/aegis.erl b/src/aegis/src/aegis.erl
deleted file mode 100644
index ac7b49b6d..000000000
--- a/src/aegis/src/aegis.erl
+++ /dev/null
@@ -1,60 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(aegis).
-
--export([wrap_key/3, unwrap_key/3]).
-
-wrap_key(KEK, AAD, DEK) when is_binary(KEK), is_list(AAD), is_binary(DEK) ->
- ExpandedKey = aegis_util:expand(KEK),
- {CipherText, CipherTag} =
- aegis_siv:block_encrypt(
- ExpandedKey,
- AAD,
- DEK
- ),
- <<CipherTag/binary, CipherText/binary>>.
-
-unwrap_key(KEK, AAD, <<CipherTag:16/binary, CipherText/binary>>) when
- is_binary(KEK), is_list(AAD)
-->
- ExpandedKey = aegis_util:expand(KEK),
- aegis_siv:block_decrypt(
- ExpandedKey,
- AAD,
- {CipherText, CipherTag}
- ).
-
--ifdef(TEST).
--include_lib("eunit/include/eunit.hrl").
-
-aegis_test_() ->
- [
- ?_assertEqual(
- <<91, 78, 2, 43, 95, 157, 34, 252, 93, 35, 150, 141, 155, 139,
247, 136, 154, 203, 16,
- 143, 196, 78, 93, 9, 189, 119, 22, 27, 60, 47, 186, 114, 70,
231, 113, 189, 36, 236,
- 139, 153, 85, 58, 207, 165, 169, 70, 67, 61>>,
- wrap_key(<<0:256>>, [], <<1:256>>)
- ),
- ?_assertEqual(
- <<1:256>>,
- unwrap_key(
- <<0:256>>,
- [],
- <<91, 78, 2, 43, 95, 157, 34, 252, 93, 35, 150, 141, 155, 139,
247, 136, 154, 203,
- 16, 143, 196, 78, 93, 9, 189, 119, 22, 27, 60, 47, 186,
114, 70, 231, 113, 189,
- 36, 236, 139, 153, 85, 58, 207, 165, 169, 70, 67, 61>>
- )
- )
- ].
-
--endif.
diff --git a/src/aegis/src/aegis_cmac.erl b/src/aegis/src/aegis_cmac.erl
deleted file mode 100644
index 1ba73415e..000000000
--- a/src/aegis/src/aegis_cmac.erl
+++ /dev/null
@@ -1,79 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(aegis_cmac).
-
--export([cmac/2]).
-
--include("aegis_compat.hrl").
-
-cmac(Key, Message) ->
- cmac(Key, <<0:128>>, Message).
-
-cmac(Key, X, <<Last:16/binary>>) ->
- {K1, _K2} = generate_subkeys(Key),
- ?block_encrypt(?ecb(Key), Key, crypto:exor(X, crypto:exor(Last, K1)));
-cmac(Key, X, <<Block:16/binary, Rest/binary>>) ->
- cmac(Key, ?block_encrypt(?ecb(Key), Key, crypto:exor(X, Block)), Rest);
-cmac(Key, X, Last) ->
- {_K1, K2} = generate_subkeys(Key),
- ?block_encrypt(
- ?ecb(Key),
- Key,
- crypto:exor(X, crypto:exor(aegis_util:pad(Last), K2))
- ).
-
-generate_subkeys(Key) ->
- L = ?block_encrypt(?ecb(Key), Key, <<0:128>>),
- K1 = aegis_util:double(L),
- K2 = aegis_util:double(K1),
- {K1, K2}.
-
--ifdef(TEST).
--include_lib("eunit/include/eunit.hrl").
-
-cmac_test_() ->
- [
- ?_assertEqual(
- <<16#bb1d6929e95937287fa37d129b756746:128>>,
- cmac(
- <<16#2b7e151628aed2a6abf7158809cf4f3c:128>>,
- <<>>
- )
- ),
-
- ?_assertEqual(
- <<16#070a16b46b4d4144f79bdd9dd04a287c:128>>,
- cmac(
- <<16#2b7e151628aed2a6abf7158809cf4f3c:128>>,
- <<16#6bc1bee22e409f96e93d7e117393172a:128>>
- )
- ),
-
- ?_assertEqual(
- <<16#028962f61b7bf89efc6b551f4667d983:128>>,
- cmac(
-
<<16#603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4:256>>,
- <<>>
- )
- ),
-
- ?_assertEqual(
- <<16#28a7023f452e8f82bd4bf28d8c37c35c:128>>,
- cmac(
-
<<16#603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4:256>>,
- <<16#6bc1bee22e409f96e93d7e117393172a:128>>
- )
- )
- ].
-
--endif.
diff --git a/src/aegis/src/aegis_compat.hrl b/src/aegis/src/aegis_compat.hrl
deleted file mode 100644
index 9de05eb27..000000000
--- a/src/aegis/src/aegis_compat.hrl
+++ /dev/null
@@ -1,42 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
-%% Assume old crypto api
-
--define(block_encrypt(Cipher, Key, Data), crypto:block_encrypt(Cipher, Key,
Data)).
-
--define(stream_encrypt(Cipher, Key, IVec, Data), element(2,
crypto:stream_encrypt(crypto:stream_init(Cipher, Key, IVec), Data))).
-
--define(ecb(Key), aes_ecb).
-
--define(ctr(Key), aes_ctr).
-
-%% Replace macros if new crypto api is available
--ifdef(OTP_RELEASE).
--if(?OTP_RELEASE >= 22).
-
--undef(block_encrypt).
--define(block_encrypt(Cipher, Key, Data), crypto:crypto_one_time(Cipher, Key,
Data, true)).
-
--undef(stream_encrypt).
--define(stream_encrypt(Cipher, Key, IVec, Data),
crypto:crypto_one_time(Cipher, Key, IVec, Data, true)).
-
--undef(ecb).
--define(ecb(Key), case bit_size(Key) of
- 128 -> aes_128_ecb; 192 -> aes_192_ecb; 256 -> aes_256_ecb end).
-
--undef(ctr).
--define(ctr(Key), case bit_size(Key) of
- 128 -> aes_128_ctr; 192 -> aes_192_ctr; 256 -> aes_256_ctr end).
-
--endif.
--endif.
\ No newline at end of file
diff --git a/src/aegis/src/aegis_key_manager.erl
b/src/aegis/src/aegis_key_manager.erl
deleted file mode 100644
index de7bf3808..000000000
--- a/src/aegis/src/aegis_key_manager.erl
+++ /dev/null
@@ -1,36 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(aegis_key_manager).
-
--export([
- wrap_key/2,
- unwrap_key/2
-]).
-
--type dek() :: binary().
--type wek() :: binary().
-
--callback wrap_key(Filepath :: binary(), DataEncryptionKey :: dek()) ->
- {ok, WrappedKey :: wek()}
- | dont_encrypt
- | {error, Reason :: term()}.
-
--callback unwrap_key(Filepath :: binary(), WrappedKey :: wek()) ->
- {ok, DataEncryptionKey :: dek()}
- | {error, Reason :: term()}.
-
-wrap_key(Filepath, DataEncryptionKey) ->
- ?AEGIS_KEY_MANAGER:wrap_key(Filepath, DataEncryptionKey).
-
-unwrap_key(Filepath, WrappedKey) ->
- ?AEGIS_KEY_MANAGER:unwrap_key(Filepath, WrappedKey).
diff --git a/src/aegis/src/aegis_key_manager_config.erl
b/src/aegis/src/aegis_key_manager_config.erl
deleted file mode 100644
index a1c8cefbf..000000000
--- a/src/aegis/src/aegis_key_manager_config.erl
+++ /dev/null
@@ -1,64 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(aegis_key_manager_config).
--behaviour(aegis_key_manager).
-
--export([
- wrap_key/2,
- unwrap_key/2
-]).
-
-wrap_key(_Filepath, DataEncryptionKey) when is_binary(DataEncryptionKey) ->
- {ok, WrappingKeyId, WrappingKey} = current_wrapping_key(),
- WrappedKey = aegis:wrap_key(WrappingKey, [WrappingKeyId],
DataEncryptionKey),
- {ok, <<(byte_size(WrappingKeyId)):8, WrappingKeyId/binary,
WrappedKey/binary>>}.
-
-unwrap_key(
- _Filepath, <<WrappingKeyIdLen:8, WrappingKeyId:WrappingKeyIdLen/binary,
WrappedKey/binary>>
-) ->
- case wrapping_key(WrappingKeyId) of
- {ok, WrappingKeyId, WrappingKey} ->
- case aegis:unwrap_key(WrappingKey, [WrappingKeyId], WrappedKey) of
- fail ->
- {error, unwrap_failed};
- Key when is_binary(Key) ->
- {ok, Key}
- end;
- {error, Reason} ->
- {error, Reason}
- end;
-unwrap_key(_, _) ->
- {error, invalid_key}.
-
-current_wrapping_key() ->
- wrapping_key(config:get("encryption", "wrapping_key_id")).
-
-wrapping_key(KeyId) when is_binary(KeyId) ->
- wrapping_key(binary_to_list(KeyId));
-wrapping_key(KeyId) when is_list(KeyId), length(KeyId) == 16 ->
- case get_config_binary("encryption_keys", KeyId, undefined) of
- Hex when is_binary(Hex), byte_size(Hex) == 64 ->
- {ok, list_to_binary(KeyId), couch_util:from_hex(Hex)};
- undefined ->
- {error, no_key};
- _ ->
- {error, invalid_key}
- end.
-
-get_config_binary(Section, Key, Default) ->
- case config:get(Section, Key) of
- undefined ->
- Default;
- Value ->
- list_to_binary(Value)
- end.
diff --git a/src/aegis/src/aegis_s2v.erl b/src/aegis/src/aegis_s2v.erl
deleted file mode 100644
index 0bc6f49cd..000000000
--- a/src/aegis/src/aegis_s2v.erl
+++ /dev/null
@@ -1,53 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(aegis_s2v).
-
--export([s2v/3]).
-
-s2v(Key, [], <<>>) ->
- aegis_cmac:cmac(Key, <<1:128>>);
-s2v(Key, AAD, PlainText) when length(AAD) < 127 ->
- s2v(Key, AAD, PlainText, aegis_cmac:cmac(Key, <<0:128>>)).
-
-s2v(Key, [], PlainText, Acc) when bit_size(PlainText) >= 128 ->
- aegis_cmac:cmac(Key, aegis_util:xorend(PlainText, Acc));
-s2v(Key, [], PlainText, Acc) ->
- aegis_cmac:cmac(
- Key,
- crypto:exor(aegis_util:double(Acc), aegis_util:pad(PlainText))
- );
-s2v(Key, [H | T], PlainText, Acc0) ->
- Acc1 = crypto:exor(aegis_util:double(Acc0), aegis_cmac:cmac(Key, H)),
- s2v(Key, T, PlainText, Acc1).
-
--ifdef(TEST).
--include_lib("eunit/include/eunit.hrl").
-
-s2v_0_test() ->
- ?assertEqual(
- <<16#85632d07c6e8f37f950acd320a2ecc93:128>>,
- s2v(
- <<16#fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0:128>>,
- [<<16#101112131415161718191a1b1c1d1e1f2021222324252627:192>>],
- <<16#112233445566778899aabbccddee:112>>
- )
- ).
-
-%% for test coverage only. this value does not come from a test vector.
-s2v_1_test() ->
- ?assertEqual(
- <<106, 56, 130, 35, 180, 192, 121, 7, 97, 30, 181, 248, 111, 114, 85,
151>>,
- s2v(<<0:128>>, [], <<>>)
- ).
-
--endif.
diff --git a/src/aegis/src/aegis_siv.erl b/src/aegis/src/aegis_siv.erl
deleted file mode 100644
index 83d3b69ea..000000000
--- a/src/aegis/src/aegis_siv.erl
+++ /dev/null
@@ -1,136 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(aegis_siv).
-
--export([block_encrypt/3, block_decrypt/3]).
-
--include("aegis_compat.hrl").
-
--spec block_encrypt(binary(), list(), binary()) -> {binary(), binary()}.
-block_encrypt(Key, AAD, PlainText) when
- bit_size(Key) == 256; bit_size(Key) == 512
-->
- {K1, K2} = split(Key),
- <<V:128>> = aegis_s2v:s2v(K1, AAD, PlainText),
- Q = V band 16#ffffffffffffffff7fffffff7fffffff,
- CipherText = aes_ctr(K2, <<Q:128>>, PlainText),
- {CipherText, <<V:128>>}.
-
-block_decrypt(Key, AAD, {CipherText, <<V:128>>}) when
- bit_size(Key) == 256; bit_size(Key) == 512
-->
- {K1, K2} = split(Key),
- Q = V band 16#ffffffffffffffff7fffffff7fffffff,
- PlainText = aes_ctr(K2, <<Q:128>>, CipherText),
- <<T:128>> = aegis_s2v:s2v(K1, AAD, PlainText),
- case V == T of
- true ->
- PlainText;
- false ->
- fail
- end.
-
-split(Key) ->
- Half = byte_size(Key) div 2,
- <<K1:Half/binary, K2:Half/binary>> = Key,
- {K1, K2}.
-
-aes_ctr(Key, IV, Data) ->
- ?stream_encrypt(?ctr(Key), Key, IV, Data).
-
--ifdef(TEST).
--include_lib("eunit/include/eunit.hrl").
-
-encrypt_test_() ->
- [
- ?_assertEqual(
- {<<16#40c02b9690c4dc04daef7f6afe5c:112>>,
<<16#85632d07c6e8f37f950acd320a2ecc93:128>>},
- block_encrypt(
-
<<16#fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:256>>,
- [<<16#101112131415161718191a1b1c1d1e1f2021222324252627:192>>],
- <<16#112233445566778899aabbccddee:112>>
- )
- ),
-
- ?_assertEqual(
- {
- <<
-
16#cb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829ea64ad544a272e9c485b62a3fd5c0d:376
- >>,
- <<16#7bdb6e3b432667eb06f4d14bff2fbd0f:128>>
- },
- block_encrypt(
-
<<16#7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f:256>>,
- [
- <<
-
16#00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa99887766554433221100:320
- >>,
- <<16#102030405060708090a0:80>>,
- <<16#09f911029d74e35bd84156c5635688c0:128>>
- ],
- <<
-
16#7468697320697320736f6d6520706c61696e7465787420746f20656e6372797074207573696e67205349562d414553:376
- >>
- )
- )
- ].
-
-decrypt_test_() ->
- [
- ?_assertEqual(
- <<16#112233445566778899aabbccddee:112>>,
- block_decrypt(
-
<<16#fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:256>>,
- [<<16#101112131415161718191a1b1c1d1e1f2021222324252627:192>>],
- {<<16#40c02b9690c4dc04daef7f6afe5c:112>>, <<
- 16#85632d07c6e8f37f950acd320a2ecc93:128
- >>}
- )
- ),
-
- ?_assertEqual(
- fail,
- block_decrypt(
-
<<16#fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:256>>,
- [<<16#101112131415161718191a1b1c1d1e1f2021222324252627:192>>],
- {<<16#40c02b9690c4dc04daef7f6afe5c:112>>, <<
- 16#85632d07c6e8f37f950acd320a2ecc94:128
- >>}
- )
- ),
-
- ?_assertEqual(
- <<
-
16#7468697320697320736f6d6520706c61696e7465787420746f20656e6372797074207573696e67205349562d414553:376
- >>,
-
- block_decrypt(
-
<<16#7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f:256>>,
- [
- <<
-
16#00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa99887766554433221100:320
- >>,
- <<16#102030405060708090a0:80>>,
- <<16#09f911029d74e35bd84156c5635688c0:128>>
- ],
- {
- <<
-
16#cb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829ea64ad544a272e9c485b62a3fd5c0d:376
- >>,
- <<16#7bdb6e3b432667eb06f4d14bff2fbd0f:128>>
- }
- )
- )
- ].
-
--endif.
diff --git a/src/aegis/src/aegis_util.erl b/src/aegis/src/aegis_util.erl
deleted file mode 100644
index 7303b67e4..000000000
--- a/src/aegis/src/aegis_util.erl
+++ /dev/null
@@ -1,90 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(aegis_util).
-
--export([
- double/1,
- expand/1,
- pad/1,
- xorend/2
-]).
-
--include("aegis_compat.hrl").
-
-%% @doc double
-%% is the multiplication of S and 0...010 in the finite field
-%% represented using the primitive polynomial
-%% x<sup>128</sup> + x<sup>7</sup> + x<sup>2</sup> + x + 1.
-%% @end
--spec double(Val :: binary()) -> binary().
-double(<<0:1, Lo:127>>) ->
- <<(Lo bsl 1):128>>;
-double(<<1:1, Lo:127>>) ->
- crypto:exor(<<(Lo bsl 1):128>>, <<16#87:128>>).
-
-%% because SIV only uses half the bits of the input key
-%% to encrypt and the other half for the authentication/IV
-%% we expand our keys to 512 to ensure an overall security
-%% threshold of 256.
-expand(Key) when bit_size(Key) == 256 ->
- %% expansion technique from Bjoern Tackmann - IBM Zurich
- K0 = ?block_encrypt(?ecb(Key), Key, <<0:128>>),
- K1 = ?block_encrypt(?ecb(Key), Key, <<1:128>>),
- K2 = ?block_encrypt(?ecb(Key), Key, <<2:128>>),
- K3 = ?block_encrypt(?ecb(Key), Key, <<3:128>>),
- <<K0/binary, K1/binary, K2/binary, K3/binary>>.
-
-%% @doc pad
-%% indicates padding of string X, len(X) < 128, out to 128 bits by
-%% the concatenation of a single bit of 1 followed by as many 0 bits
-%% as are necessary.
-%% @end
--spec pad(binary()) -> binary().
-pad(Val) when bit_size(Val) =< 128 ->
- Pad = 128 - bit_size(Val) - 1,
- <<Val/binary, 1:1, 0:Pad>>.
-
-%% @doc xorend
-%% where len(A) >= len(B), means xoring a string B onto the end of
-%% string A -- i.e., leftmost(A, len(A)-len(B)) || (rightmost(A,
-%% len(B)) xor B).
-%% @end
--spec xorend(binary(), binary()) -> binary().
-xorend(A, B) when byte_size(A) >= byte_size(B) ->
- Diff = byte_size(A) - byte_size(B),
- <<Left:Diff/binary, Right/binary>> = A,
- Xor = crypto:exor(Right, B),
- <<Left/binary, Xor/binary>>.
-
--ifdef(TEST).
--include_lib("eunit/include/eunit.hrl").
-
-double_0_test() ->
- ?assertEqual(
- <<16#1c09bf5f83df7e080280b050b37e0e74:128>>,
- double(<<16#0e04dfafc1efbf040140582859bf073a:128>>)
- ).
-
-double_1_test() ->
- ?assertEqual(
- <<16#dbe13bd0ed8c85dc9af179c99ddbf819:128>>,
- double(<<16#edf09de876c642ee4d78bce4ceedfc4f:128>>)
- ).
-
-pad_test() ->
- ?assertEqual(
- <<16#112233445566778899aabbccddee8000:128>>,
- pad(<<16#112233445566778899aabbccddee:112>>)
- ).
-
--endif.
diff --git a/src/couch/src/couch_bt_engine.erl
b/src/couch/src/couch_bt_engine.erl
index 486ed7cb0..d270f8071 100644
--- a/src/couch/src/couch_bt_engine.erl
+++ b/src/couch/src/couch_bt_engine.erl
@@ -834,7 +834,8 @@ open_db_file(FilePath, Options) ->
{error, enoent} ->
% Couldn't find file. is there a compact version? This ca
% happen (rarely) if we crashed during the file switch.
- case couch_file:open(FilePath ++ ".compact", [nologifmissing]) of
+ Options2 = couch_encryption_manager:encryption_options(Options),
+ case couch_file:open(FilePath ++ ".compact", [nologifmissing |
Options2]) of
{ok, Fd} ->
Fmt = "Recovering from compaction file: ~s~s",
couch_log:info(Fmt, [FilePath, ".compact"]),
diff --git a/src/couch/src/couch_bt_engine_compactor.erl
b/src/couch/src/couch_bt_engine_compactor.erl
index 8ed55b5c3..e39ab76c1 100644
--- a/src/couch/src/couch_bt_engine_compactor.erl
+++ b/src/couch/src/couch_bt_engine_compactor.erl
@@ -54,7 +54,11 @@ start(#st{} = St, DbName, Options, Parent) ->
couch_db_engine:trigger_on_compact(DbName),
?COMP_EVENT(init),
- {ok, InitCompSt} = open_compaction_files(DbName, St, Options),
+ EncryptionOptions = case couch_encryption_manager:get_key(DbName) of
+ false -> [];
+ KEK -> [{kek, KEK}]
+ end,
+ {ok, InitCompSt} = open_compaction_files(DbName, St, Options ++
EncryptionOptions),
?COMP_EVENT(files_opened),
Stages = [
@@ -94,8 +98,9 @@ open_compaction_files(DbName, OldSt, Options) ->
} = OldSt,
DataFile = DbFilePath ++ ".compact.data",
MetaFile = DbFilePath ++ ".compact.meta",
- {ok, DataFd, DataHdr} = open_compaction_file(DataFile),
- {ok, MetaFd, MetaHdr} = open_compaction_file(MetaFile),
+ EncryptionOptions = couch_encryption_manager:encryption_options(Options),
+ {ok, DataFd, DataHdr} = open_compaction_file(DataFile, EncryptionOptions),
+ {ok, MetaFd, MetaHdr} = open_compaction_file(MetaFile, EncryptionOptions),
DataHdrIsDbHdr = couch_bt_engine_header:is_header(DataHdr),
CompSt =
case {DataHdr, MetaHdr} of
@@ -623,15 +628,15 @@ compact_final_sync(#comp_st{new_st = St0} = CompSt) ->
new_st = St1
}.
-open_compaction_file(FilePath) ->
- case couch_file:open(FilePath, [nologifmissing]) of
+open_compaction_file(FilePath, FileOpenOptions) ->
+ case couch_file:open(FilePath, [nologifmissing | FileOpenOptions]) of
{ok, Fd} ->
case couch_file:read_header(Fd) of
{ok, Header} -> {ok, Fd, Header};
no_valid_header -> {ok, Fd, nil}
end;
{error, enoent} ->
- {ok, Fd} = couch_file:open(FilePath, [create]),
+ {ok, Fd} = couch_file:open(FilePath, [create | FileOpenOptions]),
{ok, Fd, nil}
end.
diff --git a/src/couch/src/couch_db_updater.erl
b/src/couch/src/couch_db_updater.erl
index 17a1e9160..eca81c7f0 100644
--- a/src/couch/src/couch_db_updater.erl
+++ b/src/couch/src/couch_db_updater.erl
@@ -37,7 +37,11 @@ init({Engine, DbName, FilePath, Options0}) ->
erlang:put(io_priority, {db_update, DbName}),
update_idle_limit_from_config(),
DefaultSecObj = default_security_object(DbName),
- Options = [{default_security_object, DefaultSecObj} | Options0],
+ Options = [{default_security_object, DefaultSecObj} | Options0] ++
+ case couch_encryption_manager:get_key(DbName) of
+ false -> [];
+ KEK -> [{kek, KEK}]
+ end,
try
{ok, EngineState} = couch_db_engine:init(Engine, FilePath, Options),
Db = init_db(DbName, FilePath, EngineState, Options),
diff --git a/src/aegis/src/aegis_key_manager_noop.erl
b/src/couch/src/couch_encryption_manager.erl
similarity index 58%
rename from src/aegis/src/aegis_key_manager_noop.erl
rename to src/couch/src/couch_encryption_manager.erl
index 8e1a3f540..ca736324e 100644
--- a/src/aegis/src/aegis_key_manager_noop.erl
+++ b/src/couch/src/couch_encryption_manager.erl
@@ -10,16 +10,17 @@
% License for the specific language governing permissions and limitations under
% the License.
--module(aegis_key_manager_noop).
--behaviour(aegis_key_manager).
+-module(couch_encryption_manager).
--export([
- wrap_key/2,
- unwrap_key/2
-]).
+-export([get_key/1, encryption_options/1]).
-wrap_key(_Filepath, _DataEncryptionKey) ->
- dont_encrypt.
+-spec get_key(DbName :: binary()) -> KEK :: binary() | false.
+get_key(_DbName) ->
+ <<0:256>>.
-unwrap_key(_Filepath, _DataEncryptionKey) ->
- {error, encryption_not_supported}.
+%% Extract just the encryption related options from an options list.
+encryption_options(Options) ->
+ case lists:keyfind(kek, 1, Options) of
+ false -> [];
+ {kek, KEK} -> [{kek, KEK}]
+ end.
\ No newline at end of file
diff --git a/src/couch/src/couch_file.erl b/src/couch/src/couch_file.erl
index 153dbd422..879070016 100644
--- a/src/couch/src/couch_file.erl
+++ b/src/couch/src/couch_file.erl
@@ -29,7 +29,7 @@
%% If, at couch_file creation time, encryption is enabled, couch_file
%% generates a random 256-bit AES key and a random 128 bit
-%% initialisation vector. The currently configured aegis key manager
+%% initialisation vector. The currently configured key manager
%% module is asked to wrap the key and return it as a
%% binary. couch_file stores the IV and the wrapped key in a special
%% header block, always block 0, in the first 4 KiB of the file. All
@@ -48,20 +48,49 @@
db_monitor,
pread_limit = 0,
iv,
- key
+ dek,
+ wek
}).
--define(encrypt(File, Pos, Data), encrypt_20(File, Pos, Data)).
--define(decrypt(File, Pos, Data), decrypt_20(File, Pos, Data)).
+-define(encrypt_ctr(File, Pos, Data),
+ crypto:stream_encrypt(
+ crypto:stream_init(aes_ctr, File#file.dek, aes_ctr(File#file.iv,
Pos)), Data
+ )
+).
+-define(decrypt_ctr(File, Pos, Data),
+ crypto:stream_decrypt(
+ crypto:stream_init(aes_ctr, File#file.dek, aes_ctr(File#file.iv,
Pos)), Data
+ )
+).
+
+-define(aes_gcm_encrypt(Key, IV, AAD, Data),
+ crypto:block_encrypt(aes_gcm, Key, IV, {AAD, Data, 16})),
+
+-define(aes_gcm_decrypt(Key, IV, AAD, CipherText, CipherTag),
+ crypto:block_decrypt(aes_gcm, Key, IV, {AAD, CipherText, CipherTag})).
-ifdef(OTP_RELEASE).
-if(?OTP_RELEASE >= 22).
--undef(encrypt).
--define(encrypt(File, Pos, Data), encrypt_22(File, Pos, Data)).
+-undef(encrypt_ctr).
+-define(encrypt_ctr(File, Pos, Data),
+ crypto:crypto_one_time(aes_256_ctr, File#file.dek, aes_ctr(File#file.iv,
Pos), Data, true)
+).
+
+-undef(decrypt_ctr).
+-define(decrypt_ctr(File, Pos, Data),
+ crypto:crypto_one_time(aes_256_ctr, File#file.dek, aes_ctr(File#file.iv,
Pos), Data, false)
+).
--undef(decrypt).
--define(decrypt(File, Pos, Data), decrypt_22(File, Pos, Data)).
+-undef(aes_gcm_encrypt).
+-define(aes_gcm_encrypt(Key, IV, AAD, Data),
+ crypto:crypto_one_time_aead(aes_256_gcm, Key, IV, Data, AAD, 16, true)
+).
+
+-undef(aes_gcm_decrypt).
+-define(aes_gcm_decrypt(Key, IV, AAD, CipherText, CipherTag),
+ crypto:crypto_one_time_aead(aes_256_gcm, Key, IV, CipherText, AAD,
CipherTag, false)
+).
-endif.
-endif.
@@ -469,9 +498,12 @@ init({Filepath, Options, ReturnPid, Ref}) ->
ok = file:sync(Fd),
maybe_track_open_os_files(Options),
erlang:send_after(?INITIAL_WAIT, self(),
maybe_close),
- init_crypto(Filepath, #file{
- fd = Fd, is_sys = IsSys, pread_limit =
Limit
- });
+ init_crypto(
+ #file{
+ fd = Fd, is_sys = IsSys,
pread_limit = Limit
+ },
+ Options
+ );
false ->
ok = file:close(Fd),
init_status_error(ReturnPid, Ref, {error,
eexist})
@@ -479,9 +511,12 @@ init({Filepath, Options, ReturnPid, Ref}) ->
false ->
maybe_track_open_os_files(Options),
erlang:send_after(?INITIAL_WAIT, self(),
maybe_close),
- init_crypto(Filepath, #file{
- fd = Fd, is_sys = IsSys, pread_limit = Limit
- })
+ init_crypto(
+ #file{
+ fd = Fd, is_sys = IsSys, pread_limit =
Limit
+ },
+ Options
+ )
end;
Error ->
init_status_error(ReturnPid, Ref, Error)
@@ -498,9 +533,12 @@ init({Filepath, Options, ReturnPid, Ref}) ->
maybe_track_open_os_files(Options),
{ok, Eof} = file:position(Fd, eof),
erlang:send_after(?INITIAL_WAIT, self(),
maybe_close),
- init_crypto(Filepath, #file{
- fd = Fd, eof = Eof, is_sys = IsSys,
pread_limit = Limit
- });
+ init_crypto(
+ #file{
+ fd = Fd, eof = Eof, is_sys = IsSys,
pread_limit = Limit
+ },
+ Options
+ );
Error ->
init_status_error(ReturnPid, Ref, Error)
end;
@@ -603,8 +641,7 @@ handle_call({truncate, Pos}, _From, #file{fd = Fd} = File)
->
{ok, Pos} = file:position(Fd, Pos),
case file:truncate(Fd) of
ok ->
- {_Fd, Filepath} = get(couch_file_fd),
- case init_crypto(Filepath, File#file{eof = Pos}) of
+ case init_crypto(File#file{eof = Pos}, []) of
{ok, File1} ->
{reply, ok, File1};
{error, Reason} ->
@@ -947,33 +984,49 @@ reset_eof(#file{} = File) ->
{ok, Eof} = file:position(File#file.fd, eof),
File#file{eof = Eof}.
-%% new file or we've wiped all the data, including the wrapped key, so we need
a new one.
-init_crypto(Filepath, #file{eof = 0} = File0) ->
- DataEncryptionKey = crypto:strong_rand_bytes(32),
- IV = crypto:strong_rand_bytes(16),
- case aegis_key_manager:wrap_key(Filepath, DataEncryptionKey) of
- {ok, WrappedKey} ->
- case write_encryption_header(File0, WrappedKey, IV) of
+%% new file.
+init_crypto(#file{eof = 0, dek = undefined, wek = undefined} = File0, Options)
->
+ case lists:keyfind(kek, 1, Options) of
+ {kek, KEK} ->
+ DEK = crypto:strong_rand_bytes(32),
+ WEK = wrap_key(KEK, DEK),
+ IV = crypto:strong_rand_bytes(16),
+ case write_encryption_header(File0, WEK, IV) of
{ok, File1} ->
ok = file:sync(File1#file.fd),
- {ok, init_crypto(File1, DataEncryptionKey, IV)};
+ {ok, init_crypto(File1, WEK, DEK, IV)};
{error, Reason} ->
{error, Reason}
end;
- dont_encrypt ->
- {ok, File0};
+ false ->
+ {ok, File0}
+ end;
+%% truncated file.
+init_crypto(#file{eof = Pos, dek = DEK, wek = WEK} = File0, _Options) when
+ Pos < ?SIZE_BLOCK, is_binary(DEK), is_binary(WEK)
+->
+ IV = crypto:strong_rand_bytes(16),
+ case write_encryption_header(File0, WEK, IV) of
+ {ok, File1} ->
+ ok = file:sync(File1#file.fd),
+ {ok, init_crypto(File1, WEK, DEK, IV)};
{error, Reason} ->
{error, Reason}
end;
%% we're opening an existing file and need to unwrap the key if file is
encrypted.
-init_crypto(Filepath, #file{eof = Pos, key = undefined} = File) when Pos > 0 ->
+init_crypto(#file{eof = Pos, dek = undefined} = File, Options) when Pos >=
?SIZE_BLOCK ->
case read_encryption_header(File) of
- {ok, WrappedKey, IV} ->
- case aegis_key_manager:unwrap_key(Filepath, WrappedKey) of
- {ok, DataEncryptionKey} ->
- {ok, init_crypto(File, DataEncryptionKey, IV)};
- {error, Reason} ->
- {error, Reason}
+ {ok, WEK, IV} ->
+ case lists:keyfind(kek, 1, Options) of
+ {kek, KEK} ->
+ case unwrap_key(KEK, WEK) of
+ error ->
+ {error, <<"failed to unwrap encryption key">>};
+ DEK when is_binary(DEK) ->
+ {ok, init_crypto(File, WEK, DEK, IV)}
+ end;
+ false ->
+ {error, <<"required encryption key not supplied">>}
end;
not_encrypted ->
{ok, File};
@@ -981,19 +1034,27 @@ init_crypto(Filepath, #file{eof = Pos, key = undefined}
= File) when Pos > 0 ->
{error, Reason}
end.
-init_crypto(#file{} = File, DataEncryptionKey, IV) when
- is_binary(DataEncryptionKey), is_binary(IV)
-->
- File#file{iv = crypto:bytes_to_integer(IV), key = DataEncryptionKey}.
+init_crypto(#file{} = File, WEK, DEK, IV) when is_binary(WEK), is_binary(DEK),
is_binary(IV) ->
+ File#file{iv = crypto:bytes_to_integer(IV), wek = WEK, dek = DEK}.
+
+wrap_key(KEK, DEK) when is_binary(KEK), is_binary(DEK) ->
+ IV = crypto:strong_rand_bytes(16),
+ {<<_:32/binary>> = CipherText, <<_:16/binary>> = CipherTag} =
?aes_gcm_encrypt(
+ KEK, IV, <<>>, DEK
+ ),
+ <<IV:16/binary, CipherText/binary, CipherTag/binary>>.
+
+unwrap_key(KEK, <<IV:16/binary, CipherText:32/binary, CipherTag:16/binary>>)
when is_binary(KEK) ->
+ ?aes_gcm_decrypt(KEK, IV, <<>>, CipherText, CipherTag).
-write_encryption_header(#file{eof = 0} = File, WrappedKey, IV) when
- byte_size(WrappedKey) < 1024, bit_size(IV) == 128
+write_encryption_header(#file{eof = Pos} = File, WrappedKey, IV) when
+ Pos < ?SIZE_BLOCK, byte_size(WrappedKey) < 1024, bit_size(IV) == 128
->
Header = [<<?ENCRYPTED_HEADER>>, IV, <<(byte_size(WrappedKey)):16>>,
WrappedKey],
PaddedHeader = [Header, <<0:((?SIZE_BLOCK - iolist_size(Header) - 32) *
8)>>],
DigestHeader = [PaddedHeader, crypto:hash(sha256, PaddedHeader)],
?SIZE_BLOCK = iolist_size(DigestHeader),
- case file:write(File#file.fd, DigestHeader) of
+ case file:pwrite(File#file.fd, 0, DigestHeader) of
ok ->
{ok, File#file{eof = ?SIZE_BLOCK}};
{error, Reason} ->
@@ -1021,13 +1082,13 @@ read_encryption_header(#file{} = File) ->
%% We can encrypt any section of the file but we must make
%% sure we align with the key stream.
-encrypted_write(#file{key = undefined} = File, Data) ->
+encrypted_write(#file{dek = undefined} = File, Data) ->
file:write(File#file.fd, Data);
encrypted_write(#file{} = File, Data) ->
- CipherText = ?encrypt(File, File#file.eof, pad(File#file.eof, Data)),
+ CipherText = ?encrypt_ctr(File, File#file.eof, pad(File#file.eof, Data)),
file:write(File#file.fd, unpad(File#file.eof, CipherText)).
-encrypted_pread(#file{key = undefined} = File, LocNums) ->
+encrypted_pread(#file{dek = undefined} = File, LocNums) ->
file:pread(File#file.fd, LocNums);
encrypted_pread(#file{} = File, LocNums) ->
case file:pread(File#file.fd, LocNums) of
@@ -1035,7 +1096,7 @@ encrypted_pread(#file{} = File, LocNums) ->
{ok,
lists:zipwith(
fun({Pos, _Len}, CipherText) ->
- PlainText = ?decrypt(File, Pos, pad(Pos, CipherText)),
+ PlainText = ?decrypt_ctr(File, Pos, pad(Pos,
CipherText)),
unpad(Pos, PlainText)
end,
LocNums,
@@ -1045,31 +1106,17 @@ encrypted_pread(#file{} = File, LocNums) ->
Else
end.
-encrypted_pread(#file{key = undefined} = File, Pos, Len) ->
+encrypted_pread(#file{dek = undefined} = File, Pos, Len) ->
file:pread(File#file.fd, Pos, Len);
encrypted_pread(#file{} = File, Pos, Len) ->
case file:pread(File#file.fd, Pos, Len) of
{ok, CipherText} ->
- PlainText = ?decrypt(File, Pos, pad(Pos, CipherText)),
+ PlainText = ?decrypt_ctr(File, Pos, pad(Pos, CipherText)),
{ok, unpad(Pos, PlainText)};
Else ->
Else
end.
-encrypt_20(#file{key = Key, iv = IV}, Pos, Data) ->
- State = crypto:stream_init(aes_ctr, Key, aes_ctr(IV, Pos)),
- crypto:stream_encrypt(State, Data).
-
-decrypt_20(#file{key = Key, iv = IV}, Pos, Data) ->
- State = crypto:stream_init(aes_ctr, Key, aes_ctr(IV, Pos)),
- crypto:stream_decrypt(State, Data).
-
-encrypt_22(#file{key = Key, iv = IV}, Pos, Data) ->
- crypto:crypto_one_time(aes_256_ctr, Key, aes_ctr(IV, Pos), Data, true).
-
-decrypt_22(#file{key = Key, iv = IV}, Pos, Data) ->
- crypto:crypto_one_time(aes_256_ctr, Key, aes_ctr(IV, Pos), Data, false).
-
aes_ctr(IV, Pos) ->
<<(IV + (Pos div 16)):128>>.
diff --git a/src/couch_mrview/src/couch_mrview_compactor.erl
b/src/couch_mrview/src/couch_mrview_compactor.erl
index 28e5a9b3d..be67adbcb 100644
--- a/src/couch_mrview/src/couch_mrview_compactor.erl
+++ b/src/couch_mrview/src/couch_mrview_compactor.erl
@@ -47,7 +47,11 @@ compact(State) ->
{EmptyState, NumDocIds} = couch_util:with_db(DbName, fun(Db) ->
CompactFName = couch_mrview_util:compaction_file(DbName, Sig),
- {ok, Fd} = couch_mrview_util:open_file(CompactFName),
+ Options = case couch_encryption_manager:get_key(DbName) of
+ false -> [];
+ KEK -> [{kek, KEK}]
+ end,
+ {ok, Fd} = couch_mrview_util:open_file(CompactFName, Options),
ESt = couch_mrview_util:reset_index(Db, Fd, State),
{ok, Count} = couch_db:get_doc_count(Db),
diff --git a/src/couch_mrview/src/couch_mrview_index.erl
b/src/couch_mrview/src/couch_mrview_index.erl
index 1bfdb2818..bcbb19ce5 100644
--- a/src/couch_mrview/src/couch_mrview_index.erl
+++ b/src/couch_mrview/src/couch_mrview_index.erl
@@ -120,7 +120,11 @@ open(Db, State0) ->
OldSig = couch_mrview_util:maybe_update_index_file(State),
- case couch_mrview_util:open_file(IndexFName) of
+ Options = case couch_encryption_manager:get_key(DbName) of
+ false -> [];
+ KEK -> [{kek, KEK}]
+ end,
+ case couch_mrview_util:open_file(IndexFName, Options) of
{ok, Fd} ->
case couch_file:read_header(Fd) of
% upgrade code for <= 2.x
diff --git a/src/couch_mrview/src/couch_mrview_util.erl
b/src/couch_mrview/src/couch_mrview_util.erl
index 9e3d292ed..f9c533376 100644
--- a/src/couch_mrview/src/couch_mrview_util.erl
+++ b/src/couch_mrview/src/couch_mrview_util.erl
@@ -17,7 +17,7 @@
-export([verify_view_filename/1, get_signature_from_filename/1]).
-export([ddoc_to_mrst/2, init_state/4, reset_index/3]).
-export([make_header/1]).
--export([index_file/2, compaction_file/2, open_file/1]).
+-export([index_file/2, compaction_file/2, open_file/2]).
-export([delete_files/2, delete_index_file/2, delete_compaction_file/2]).
-export([get_row_count/1, all_docs_reduce_to_count/1, reduce_to_count/1]).
-export([all_docs_key_opts/1, all_docs_key_opts/2, key_opts/1, key_opts/2]).
@@ -791,10 +791,10 @@ compaction_file(DbName, Sig) ->
FileName = couch_index_util:hexsig(Sig) ++ ".compact.view",
couch_index_util:index_file(mrview, DbName, FileName).
-open_file(FName) ->
- case couch_file:open(FName, [nologifmissing]) of
+open_file(FName, Options) ->
+ case couch_file:open(FName, [nologifmissing | Options]) of
{ok, Fd} -> {ok, Fd};
- {error, enoent} -> couch_file:open(FName, [create]);
+ {error, enoent} -> couch_file:open(FName, [create | Options]);
Error -> Error
end.