This is an automated email from the ASF dual-hosted git repository. eiri pushed a commit to branch prototype/fdb-encryption in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 9629fdaaebabd5392d66e3fd9514d8ef62ede1dd Author: Eric Avdey <[email protected]> AuthorDate: Wed Mar 4 18:28:54 2020 -0400 Don't block encryption server on encode/decode operations --- src/fabric/src/fabric2_encryption.erl | 97 +++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/src/fabric/src/fabric2_encryption.erl b/src/fabric/src/fabric2_encryption.erl index 5d8d389..6f8a488 100644 --- a/src/fabric/src/fabric2_encryption.erl +++ b/src/fabric/src/fabric2_encryption.erl @@ -32,6 +32,12 @@ ]). +-export([ + do_encode/5, + do_decode/5 +]). + + -define(INIT_TIMEOUT, 60000). -define(LABEL, "couchdb-aes256-gcm-encryption-key"). @@ -74,29 +80,51 @@ terminate(_, _St) -> ok. -handle_call({encode, DbName, DocId, DocRev, DocBody}, _From, St) -> - #{iid := InstanceId} = St, - {ok, AAD} = get_aad(InstanceId, DbName), - {ok, DEK} = get_dek(DbName, DocId, DocRev), - {CipherText, CipherTag} = crypto:crypto_one_time_aead( - aes_256_gcm, DEK, <<0:96>>, DocBody, AAD, 16, true), - Encoded = <<CipherTag/binary, CipherText/binary>>, - {reply, {ok, Encoded}, St}; +handle_call({encode, DbName, DocId, DocRev, DocBody}, From, St) -> + #{ + iid := InstanceId, + waiters := Waiters + } = St, + + {Pid, _Ref} = erlang:spawn_monitor(?MODULE, + do_encode, [InstanceId, DbName, DocId, DocRev, DocBody]), + + NewSt = St#{ + waiters := dict:store(Pid, From, Waiters) + }, + {noreply, NewSt}; + +handle_call({decode, DbName, DocId, DocRev, Encoded}, From, St) -> + #{ + iid := InstanceId, + waiters := Waiters + } = St, -handle_call({decode, DbName, DocId, DocRev, Encoded}, _From, St) -> - #{iid := InstanceId} = St, - {ok, AAD} = get_aad(InstanceId, DbName), - {ok, DEK} = get_dek(DbName, DocId, DocRev), - <<CipherTag:16/binary, CipherText/binary>> = Encoded, - DocBody = crypto:crypto_one_time_aead( - aes_256_gcm, DEK, <<0:96>>, CipherText, AAD, CipherTag, false), - {reply, {ok, DocBody}, St}. + {Pid, _Ref} = erlang:spawn_monitor(?MODULE, + do_decode, [InstanceId, DbName, DocId, DocRev, Encoded]), + + NewSt = St#{ + waiters := dict:store(Pid, From, Waiters) + }, + {noreply, NewSt}. handle_cast(Msg, St) -> {stop, {bad_cast, Msg}, St}. +handle_info({'DOWN', _, _, Pid, Resp}, #{waiters := Waiters} = St) -> + case dict:take(Pid, Waiters) of + {From, Waiters1} -> + gen_server:reply(From, Resp), + NewSt = St#{ + waiters := Waiters1 + }, + {noreply, NewSt}; + error -> + {noreply, St} + end; + handle_info(timeout, St) -> {stop, normal, St}. @@ -108,7 +136,42 @@ code_change(_OldVsn, St, _Extra) -> init_st() -> FdbDirs = fabric2_server:fdb_directory(), - {ok, #{iid => iolist_to_binary(FdbDirs)}}. + {ok, #{ + iid => iolist_to_binary(FdbDirs), + waiters => dict:new() + }}. + + +do_encode(InstanceId, DbName, DocId, DocRev, DocBody) -> + try + {ok, AAD} = get_aad(InstanceId, DbName), + {ok, DEK} = get_dek(DbName, DocId, DocRev), + {CipherText, CipherTag} = crypto:crypto_one_time_aead( + aes_256_gcm, DEK, <<0:96>>, DocBody, AAD, 16, true), + <<CipherTag/binary, CipherText/binary>> + of + Resp -> + exit({ok, Resp}) + catch + _:Error -> + exit({error, Error}) + end. + + +do_decode(InstanceId, DbName, DocId, DocRev, Encoded) -> + try + <<CipherTag:16/binary, CipherText/binary>> = Encoded, + {ok, AAD} = get_aad(InstanceId, DbName), + {ok, DEK} = get_dek(DbName, DocId, DocRev), + crypto:crypto_one_time_aead( + aes_256_gcm, DEK, <<0:96>>, CipherText, AAD, CipherTag, false) + of + Resp -> + exit({ok, Resp}) + catch + _:Error -> + exit({error, Error}) + end. get_aad(InstanceId, DbName) when is_binary(InstanceId), is_binary(DbName) ->
