CDS-94: Fix old keyring compatibility (#9)

* CDS-94: Fix old keyring compatibility

* CDS-94: Hide error from logs
This commit is contained in:
ndiezel0 2019-07-26 17:59:31 +03:00 committed by GitHub
parent bbbf99db96
commit c022cceb1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 17 deletions

View File

@ -58,8 +58,8 @@ encrypt(Key, Plain) ->
try
{Cipher, Tag} = crypto:block_encrypt(?CIPHER_TYPE, Key, IV, {AAD, Plain}),
marshall_cedf(#cedf{iv = IV, aad = AAD, cipher = Cipher, tag = Tag})
catch Class:Reason ->
_ = logger:error("encryption failed with ~p ~p", [Class, Reason]),
catch Class:_Reason:Stacktrace ->
_ = logger:error("encryption failed with ~p ST: ~p", [Class, Stacktrace]),
throw(encryption_failed)
end.
@ -88,8 +88,8 @@ decrypt(Key, MarshalledCEDF) ->
throw(decryption_failed);
Plain ->
Plain
catch Type:Error ->
_ = logger:error("decryption failed with ~p ~p", [Type, Error]),
catch Type:_Error:Stacktrace ->
_ = logger:error("decryption failed with ~p ST: ~p", [Type, Stacktrace]),
throw(decryption_failed)
end.

View File

@ -114,20 +114,26 @@ encrypt(MasterKey, #{data := KeyringData, meta := KeyringMeta}) ->
-spec decrypt(key(), encrypted_keyring()) -> {ok, keyring()} | {error, decryption_failed}.
decrypt(MasterKey, #{data := EncryptedKeyringData, meta := KeyringMeta}) ->
try unmarshall(kds_crypto:decrypt(MasterKey, base64:decode(EncryptedKeyringData))) of
KeyringData ->
case KeyringMeta of
undefined ->
case KeyringMeta of
undefined ->
try unmarshall(kds_crypto:decrypt(MasterKey, EncryptedKeyringData)) of
KeyringData ->
{ok, #{
data => KeyringData,
meta => kds_keyring_meta:get_default_keyring_meta(KeyringData)
}};
_ ->
}}
catch
decryption_failed ->
{error, decryption_failed}
end;
_ ->
try unmarshall(kds_crypto:decrypt(MasterKey, base64:decode(EncryptedKeyringData))) of
KeyringData ->
{ok, #{data => KeyringData, meta => KeyringMeta}}
catch
decryption_failed ->
{error, decryption_failed}
end
catch
decryption_failed ->
{error, decryption_failed}
end.
-spec marshall(keyring_data()) -> binary().
@ -140,7 +146,7 @@ marshall(#{keys := Keys}) ->
-spec unmarshall(binary()) -> keyring_data().
unmarshall(<<MaxKeyId, Keys/binary>> = MarshalledKeyring) ->
KeysSize = erlang:byte_size(Keys),
case (KeysSize div 33 =:= MaxKeyId) and (KeysSize rem 33 =:= 0) of
case (KeysSize div 33 =:= (MaxKeyId + 1)) and (KeysSize rem 33 =:= 0) of
true ->
#{keys => unmarshall_keys(Keys, #{})};
false ->

View File

@ -47,11 +47,23 @@
-type encoded_keyring_meta_diff() :: #'cds_KeyringMetaDiff'{}.
-type encoded_security_parameters() :: #'cds_SecurityParameters'{}.
-define(DEFAULT_SEC_PARAMS, #{
deduplication_hash_opts => #{
n => 16384,
r => 8,
p => 1
}
}).
-define(DEFAULT_KEY_META, #{
retired => false,
security_parameters => application:get_env(kds, new_key_security_parameters, ?DEFAULT_SEC_PARAMS)
}).
-spec get_default_keyring_meta(kds_keyring:keyring_data()) -> keyring_meta().
get_default_keyring_meta(KeyringData) ->
Keys = maps:get(keys, KeyringData),
CurrentKeyId = lists:max(maps:keys(Keys)),
KeysMeta = maps:map(fun(_KeyId, _Key) -> #{retired => false} end, Keys),
KeysMeta = maps:map(fun(_KeyId, _Key) -> ?DEFAULT_KEY_META end, Keys),
#{current_key_id => CurrentKeyId, version => 1, keys => KeysMeta}.
-spec update_meta(keyring_meta(), keyring_meta_diff()) -> keyring_meta().

View File

@ -1,5 +1,7 @@
-module(kds_ct_keyring).
-include_lib("shamir/include/shamir.hrl").
-export([init/1]).
-export([rekey/1]).
-export([lock/1]).
@ -7,9 +9,12 @@
-export([rotate/1]).
-export([decrypt_and_sign_masterkeys/3]).
-export([decrypt_and_reconstruct/3]).
-export([validate_init/2]).
-export([validate_rekey/2]).
-export([marshall_old_format/1]).
%%
%% Internal types
%%
@ -41,6 +46,29 @@ decrypt_and_sign_masterkeys(EncryptedMasterKeyShares, EncPrivateKeys, SigPrivate
end,
EncryptedMasterKeyShares).
-spec decrypt_and_reconstruct(kds_keysharing:encrypted_master_key_shares(), map(), integer()) ->
kds_keysharing:masterkey().
decrypt_and_reconstruct(EncryptedMasterKeyShares, EncPrivateKeys, Threshold) ->
{ThresholdEncryptedMasterKeyShares, _} = lists:split(Threshold, EncryptedMasterKeyShares),
Shares = lists:foldl(
fun (#{id := Id, encrypted_share := EncryptedShare}, Acc) ->
EncPrivateKey = maps:get(Id, EncPrivateKeys),
DecryptedShare = kds_crypto:private_decrypt(EncPrivateKey, EncryptedShare),
[DecryptedShare | Acc]
end,
[],
ThresholdEncryptedMasterKeyShares
),
case kds_keysharing:recover(Shares) of
{ok, MasterKey} ->
MasterKey;
{error, failed_to_recover} ->
_ = logger:error("failed to recover Shares: ~p~nEncryptedMasterKeyShares: ~p",
[Shares, EncryptedMasterKeyShares]),
throw(recover_error)
end.
-spec validate_init([{kds_shareholder:shareholder_id(), kds_keysharing:masterkey_share()}], config()) -> ok.
validate_init([{Id, DecryptedMasterKeyShare} | []], C) ->
@ -97,6 +125,14 @@ rotate(C) ->
{more_keys_needed, 1} = kds_keyring_client:confirm_rotate(Id1, MasterKey1, root_url(C)),
ok = kds_keyring_client:confirm_rotate(Id2, MasterKey2, root_url(C)).
-spec marshall_old_format(term()) -> binary().
marshall_old_format(#{current_key := CurrentKey, keys := Keys}) ->
<<CurrentKey, (maps:fold(fun marshall_keys/3, <<>>, Keys))/binary>>.
-spec marshall_keys(byte(), binary(), binary()) -> binary().
marshall_keys(KeyId, Key, Acc) ->
<<Acc/binary, KeyId, Key:32/binary>>.
config(Key, Config) ->
config(Key, Config, undefined).

View File

@ -14,6 +14,7 @@
-export([init_with_cancel/1]).
-export([lock/1]).
-export([unlock/1]).
-export([unlock_old_keyring/1]).
-export([unlock_with_timeout/1]).
-export([rekey/1]).
-export([rekey_with_timeout/1]).
@ -64,6 +65,8 @@ groups() ->
{basic_lifecycle, [sequence], [
init,
lock,
unlock_old_keyring,
lock,
unlock,
rekey,
rekey_with_timeout,
@ -142,7 +145,8 @@ end_per_group(_, C) ->
-spec init(config()) -> _.
init(C) ->
EncryptedMasterKeyShares = kds_keyring_client:start_init(2, root_url(C)),
Threshold = 2,
EncryptedMasterKeyShares = kds_keyring_client:start_init(Threshold, root_url(C)),
Shareholders = kds_shareholder:get_all(),
_ = ?assertEqual(length(EncryptedMasterKeyShares), length(Shareholders)),
EncPrivateKeys = enc_private_keys(C),
@ -173,7 +177,9 @@ init(C) ->
},
kds_keyring_client:get_state(root_url(C))
),
kds_ct_utils:store(master_keys, DecryptedMasterKeyShares, C).
MasterKey = kds_ct_keyring:decrypt_and_reconstruct(EncryptedMasterKeyShares, EncPrivateKeys, Threshold),
ok = kds_ct_utils:store(master_keys, DecryptedMasterKeyShares, C),
kds_ct_utils:store(master_key, MasterKey, C).
-spec init_with_timeout(config()) -> _.
@ -280,6 +286,17 @@ unlock(C) ->
),
_ = ?assertEqual(ok, kds_keyring_client:confirm_unlock(Id2, MasterKey2, root_url(C))).
-spec unlock_old_keyring(config()) -> _.
unlock_old_keyring(C) ->
MasterKey = kds_ct_utils:lookup(master_key, C),
KeyringStorageOpts = application:get_env(kds, keyring_storage_opts, #{}),
KeyringPath = maps:get(keyring_path, KeyringStorageOpts, filename:join(config(priv_dir, C), "keyring")),
MarshalledKeyring = kds_ct_keyring:marshall_old_format(#{current_key => 0, keys => #{0 => kds_crypto:key()}}),
EncodedOldKeyring = kds_crypto:encrypt(MasterKey, MarshalledKeyring),
ok = file:write_file(KeyringPath, EncodedOldKeyring),
_ = unlock(C).
-spec unlock_with_timeout(config()) -> _.
unlock_with_timeout(C) ->