You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2020/04/09 16:17:41 UTC

[couchdb] 02/03: Cleanup and condense aegis

This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch davisp-aegis
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit c8045d659779ff3dce4ef39e1c5769d1008faa40
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Thu Apr 9 11:16:51 2020 -0500

    Cleanup and condense aegis
---
 src/aegis/src/aegis.app.src |  33 ++++---
 src/aegis/src/aegis.erl     | 208 ++++++++++++++++----------------------------
 2 files changed, 90 insertions(+), 151 deletions(-)

diff --git a/src/aegis/src/aegis.app.src b/src/aegis/src/aegis.app.src
index eb3018f..e052323 100644
--- a/src/aegis/src/aegis.app.src
+++ b/src/aegis/src/aegis.app.src
@@ -10,20 +10,19 @@
 % License for the specific language governing permissions and limitations under
 % the License.
 
-{application, aegis,
- [{description, "If it's good enough for Zeus, it's good enough for CouchDB"},
-  {vsn, git},
-  {registered, []},
-  {applications,
-   [kernel,
-    stdlib,
-    crypto,
-    erlfdb
-   ]},
-  {env,[]},
-  {modules, []},
-
-  {maintainers, []},
-  {licenses, []},
-  {links, []}
- ]}.
+{application, aegis, [
+    {description, "If it's good enough for Zeus, it's good enough for CouchDB"},
+    {vsn, git},
+    {registered, []},
+    {applications, [
+        kernel,
+        stdlib,
+        crypto,
+        erlfdb
+    ]},
+    {env,[]},
+    {modules, []},
+    {maintainers, []},
+    {licenses, []},
+    {links, []}
+]}.
diff --git a/src/aegis/src/aegis.erl b/src/aegis/src/aegis.erl
index 5937b4c..9b4778d 100644
--- a/src/aegis/src/aegis.erl
+++ b/src/aegis/src/aegis.erl
@@ -12,9 +12,6 @@
 
 -module(aegis).
 
--define(IS_AEGIS_FUTURE, {aegis_future, _}).
-%% encapsulation violation :/
--define(IS_FUTURE, {erlfdb_future, _, _}).
 
 %% Assume old crypto api
 -define(hmac(Key, PlainText), crypto:hmac(sha256, Key, PlainText)).
@@ -27,11 +24,12 @@
 -ifdef(OTP_RELEASE).
 -if(?OTP_RELEASE >= 22).
 -undef(hmac).
--define(hmac(Key, PlainText), crypto:mac(hmac, sha256, Key, PlainText)).
 -undef(aes_gcm_encrypt).
+-undef(aes_gcm_decrypt).
+
+-define(hmac(Key, PlainText), crypto:mac(hmac, sha256, Key, PlainText)).
 -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)).
@@ -39,147 +37,89 @@
 -endif.
 
 -export([
-    fold_range/6,
-    fold_range/7,
-    fold_range_future/5,
-    fold_range_wait/4,
-    get/3,
-    get_range/4,
-    get_range/5,
-    get_range_startswith/3,
-    get_range_startswith/4,
-    set/4,
-    wait/1
+    init/1,
+    encrypt/3,
+    decrypt/3,
+    decrypt/2,
+    wrap_fold/2
 ]).
 
 
-fold_range(EncryptionContext, DbOrTx, StartKey, EndKey, Fun, Acc) ->
-    fold_range(EncryptionContext, DbOrTx, StartKey, EndKey, Fun, Acc, []).
-
-
-fold_range(EncryptionContext, DbOrTx, StartKey, EndKey, Fun, Acc, Options) ->
-    validate_encryption_context(EncryptionContext),
-    erlfdb:fold_range(DbOrTx, StartKey, EndKey, decrypt_fun(EncryptionContext, Fun), Acc, Options).
-
-
-fold_range_future(EncryptionContext, TxOrSs, StartKey, EndKey, Options) ->
-    validate_encryption_context(EncryptionContext),
-    Future = erlfdb:fold_range_future(TxOrSs, StartKey, EndKey, Options),
-    {aegis_fold_future, EncryptionContext, Future}.
-
-
-fold_range_wait(Tx, {aegis_fold_future, EncryptionContext, Future}, Fun, Acc) ->
-    validate_encryption_context(EncryptionContext),
-    erlfdb:fold_range_wait(Tx, Future, decrypt_fun(EncryptionContext, Fun), Acc).
-
-
-get(EncryptionContext, DbOrTx, Key) ->
-    validate_encryption_context(EncryptionContext),
-    Result = erlfdb:get(DbOrTx, Key),
-    decrypt(EncryptionContext, Key, Result).
-
-
-get_range(EncryptionContext, DbOrTx, StartKey, EndKey) ->
-    get_range(EncryptionContext, DbOrTx, StartKey, EndKey, []).
-
-
-get_range(EncryptionContext, DbOrTx, StartKey, EndKey, Options) ->
-    validate_encryption_context(EncryptionContext),
-    Result = erlfdb:get_range(DbOrTx, StartKey, EndKey, Options),
-    decrypt(EncryptionContext, Result).
-
-
-get_range_startswith(EncryptionContext, DbOrTx, Prefix) ->
-    get_range_startswith(EncryptionContext, DbOrTx, Prefix, []).
-
-
-get_range_startswith(EncryptionContext, DbOrTx, Prefix, Options) ->
-    validate_encryption_context(EncryptionContext),
-    Result = erlfdb:get_range_startswith(DbOrTx, Prefix, Options),
-    decrypt(EncryptionContext, Result).
-
-
-set(EncryptionContext, DbOrTx, Key, Value) ->
-    validate_encryption_context(EncryptionContext),
-    erlfdb:set(DbOrTx, Key, encrypt(EncryptionContext, Key, Value)).
-
-
-wait({aegis_future, EncryptionContext, Future}) ->
-    Value = erlfdb:wait(Future),
-    decrypt(EncryptionContext, Value);
-
-wait({aegis_future, EncryptionContext, Key, Future}) ->
-    Value = erlfdb:wait(Future),
-    decrypt(EncryptionContext, Key, Value);
-
-wait(Result) ->
-    Result.
-
-
-%% Private functions
-
-validate_encryption_context(#{uuid := _UUID}) ->
-    ok;
-validate_encryption_context(_) ->
-    error(invalid_encryption_context).
-
-
 -define(DUMMY_KEY, <<1:256>>).
-
-encrypt(#{uuid := UUID}, Key, Value) ->
-    {CipherText, <<CipherTag:128>>} =
-        ?aes_gcm_encrypt(
-           derive(?DUMMY_KEY, Key),
-           <<0:96>>,
-           UUID,
-           Value),
+-define(AEGIS_KEY_DOOHICKIES, 254).
+
+
+create(#{} = Db) ->
+    #{
+        tx = Tx,
+        db_prefix = DbPrefix
+    } = Db,
+    DbKeyThinger = erlfdb_tuple:pack({?AEGIS_KEY_DOOHICKIES}, DbPrefix),
+    MyThingAMaJig = oooh_look_at_my_fancy_math(UUID, MathStuff),
+    ok = erlfdb:set(Tx, DbKeyThinger, MyThingAMaJig),
+    Db#{
+        aegis_ctx = MyThingAMaJig
+    }.
+
+
+open(#{} = Db) ->
+    #{
+        tx = Tx,
+        db_prefix = DbPrefix
+    } = Db,
+    DbKeyThinger = erlfdb_tuple:pack({?AEGIS_KEY_DOOHICKIES}, DbPrefix),
+    MyLookupThing = erlfdb:wait(erlfdb:get(Tx, DbKeyThinger)),
+    Db#{
+        aegis_ctx => MyLookupThing
+    }.
+
+
+encrypt(#{} = Db, Key, Value) ->
+    #{
+        aegis_ctx = Ctx,
+        uuid := UUID
+    } = Db,
+    DerivedKey = derive(?DUMMY_KEY, Key),
+    {CipherText, <<CipherTag:128>>} = ?aes_gcm_encrypt(
+            Derived,
+            <<0:96>>,
+            UUID,
+            Value
+        ),
     <<1:8, CipherTag:128, CipherText/binary>>.
 
 
-decrypt(EncryptionContext, ?IS_FUTURE = Future) ->
-    decrypt_future(EncryptionContext, Future);
+decrypt(#{} = Db, Key, Value) when is_binary(Key), is_binary(Value) ->
+    #{
+        aegis_ctx = Ctx,
+        uuid := UUID
+    } = Db,
+    <<1:8, CipherTag:128, CipherText/binary>> = Value,
+    Derived = derive(?DUMMY_KEY, Key),
+    Decrypted = ?aes_gcm_decrypt(
+            Derived,
+            <<0:96>>,
+            UUID,
+            CipherText,
+            <<CipherTag:128>>
+        ),
+    if Decrypted /= error -> Decrypted; true ->
+        erlang:error(decryption_failed)
+    end.
 
-decrypt(EncryptionContext, {Key, Value})
-  when is_binary(Key), is_binary(Value) ->
-    decrypt(EncryptionContext, Key, Value);
 
-decrypt(EncryptionContext, Rows) when is_list(Rows) ->
-    [{Key, decrypt(EncryptionContext, Row)} || {Key, _} = Row <- Rows].
+decrypt(Db, {Key, Value}) ->
+    {Key, decrypt(Db, Key, Value)};
 
+decrypt(Db, Rows) when is_list(Rows) ->
+    lists:map(fun({Key, Value}) ->
+        decrypt(Db, {Key, Value})
+    end, Rows).
 
-decrypt(EncryptionContext, Key, ?IS_FUTURE = Future) ->
-    decrypt_future(EncryptionContext, Key, Future);
 
-decrypt(#{uuid := UUID}, Key, Value) when is_binary(Value) ->
-    <<1:8, CipherTag:128, CipherText/binary>> = Value,
-    Decrypted =
-        ?aes_gcm_decrypt(
-           derive(?DUMMY_KEY, Key),
-           <<0:96>>,
-           UUID,
-           CipherText,
-           <<CipherTag:128>>),
-    case Decrypted of
-        error ->
-            erlang:error(decryption_failed);
-        Decrypted ->
-            Decrypted
-    end;
-
-decrypt(_EncryptionContext, _Key, Value) when not is_binary(Value) ->
-    Value.
-
-
-decrypt_future(EncryptionContext, ?IS_FUTURE = Future) ->
-    {aegis_future, EncryptionContext, Future}.
-
-decrypt_future(EncryptionContext, Key, ?IS_FUTURE = Future) ->
-    {aegis_future, EncryptionContext, Key, Future}.
-
-decrypt_fun(EncryptionContext, Fun) ->
-    fun(Rows, Acc) ->
-            Fun(decrypt(EncryptionContext, Rows), Acc)
-    end.
+wrap_fold_fun(Db, Fun) when is_function(Fun, 2)->
+    fun({Key, Val}, Acc) -> Fun(decrypt(Db, {Key, Value}), Acc) end.
+
 
 derive(KEK, KeyMaterial) when bit_size(KEK) == 256 ->
     PlainText = <<1:16, "aegis", 0:8, KeyMaterial/binary, 256:16>>,