The Datapool API supports encrypted storage of data in the datapool. Although this works fine it would be nice to provide a transparent encryption mechanism to the core system that could replace both VolatileVault and the dedicated Datapool encryption.
diff --git a/trunk/perl-modules/core/trunk/OpenXPKI/Server/Context.pm b/trunk/perl-modules/core/trunk/OpenXPKI/Server/Context.pm
index d15ad8a..1999918 100644
--- a/trunk/perl-modules/core/trunk/OpenXPKI/Server/Context.pm
+++ b/trunk/perl-modules/core/trunk/OpenXPKI/Server/Context.pm
@@ -29,6 +29,7 @@ my $context = {
pki_realm => undef,
pki_realm_by_cfg => undef,
volatile_vault => undef,
+ transparent_encryption => undef,
log => undef,
dbi_backend => undef,
dbi_workflow => undef,
@@ -231,6 +232,8 @@ by calling CTX('...') once create() has been called:
=item * volatile_vault
+=item * transparent_encryption
+
=item * log
=item * dbi_backend
diff --git a/trunk/perl-modules/core/trunk/OpenXPKI/Server/Init.pm b/trunk/perl-modules/core/trunk/OpenXPKI/Server/Init.pm
index 3619e57..9425f59 100644
--- a/trunk/perl-modules/core/trunk/OpenXPKI/Server/Init.pm
+++ b/trunk/perl-modules/core/trunk/OpenXPKI/Server/Init.pm
@@ -67,6 +67,7 @@ my @init_tasks = qw(
crypto_layer
pki_realm
volatile_vault
+ transparent_encryption
acl
api
pki_realm_by_cfg
@@ -402,6 +403,214 @@ sub __do_init_volatile_vault {
});
}
+sub __do_init_transparent_encryption {
+ ##! 1: "init transparent encryption"
+
+ # FIXME: get rekeying policy from configuration?
+ my $key_management_policy = 'CERT';
+ my $tenc = OpenXPKI::Crypto::KeyManagement::TransparentEncryption->new(
+ {
+ KEYMANAGEMENT => $key_management_policy,
+ NAMEPACE_KEY_STORAGE => 'sys.datapool.keys',
+ NAMEPACE_KEY_MAPPING => 'sys.datapool.pwsafe',
+ });
+
+ # delegate implementations for accessing the datapool and for asymmetric
+ # encryption
+ $tenc->delegate(
+ {
+ GET_CURRENT_ASYMMETRIC_KEY_ID => {
+ ##! 1: 'start'
+ my $realm = CTX('session')->get_pki_realm();
+ my $cfg_id = CTX('api')->get_current_config_id();
+
+ my @possible_safes = ();
+ my $pki_realm_cfg = CTX('pki_realm_by_cfg')->{$cfg_id}->{$realm}->{'password_safe'}->{'id'};
+ if (! defined $pki_realm_cfg || ref $pki_realm_cfg ne 'HASH') {
+ OpenXPKI::Exception->throw(
+ message => 'I18N_OPENXPKI_SERVER_API_OBJECT_GET_CURRENT_SAFE_ID_MISSING_PKI_REALM_CONFIG',
+ params => {
+ CONFIG_ID => $cfg_id,
+ REALM => $realm,
+ },
+ log => {
+ logger => CTX('log'),
+ priority => 'error',
+ facility => [ 'system', ],
+ },
+ );
+ }
+
+ foreach my $key (keys %{ $pki_realm_cfg }) {
+ ##! 64: 'key: ' . $key
+ push @possible_safes, {
+ 'id' => $key,
+ 'notbefore' => $pki_realm_cfg->{$key}->{notbefore},
+ 'notafter' => $pki_realm_cfg->{$key}->{notafter},
+ };
+ }
+ ##! 16: 'possible safes: ' . Dumper \@possible_safes
+ # sort safes by notbefore date (latest earliest)
+ my @sorted_safes = sort { DateTime->compare($b->{notbefore}, $a->{notbefore}) } @possible_safes;
+ ##! 16: 'sorted safes: ' . Dumper \@sorted_safes
+
+ # find the topmost one that is available /now/
+ my $now = DateTime->now();
+
+ ##! 16: 'now: ' . Dumper $now
+ my $current_safe = first
+ { DateTime->compare($now, $_->{notbefore}) >= 0
+ && DateTime->compare($_->{notafter}, $now) > 0 } @sorted_safes;
+ if (! defined $current_safe) {
+ OpenXPKI::Exception->throw(
+ message => 'I18N_OPENXPKI_SERVER_INIT_CALLBACK_GET_CURRENT_SAFE_ID_NO_SAFE_AVAILABLE',
+ log => {
+ logger => CTX('log'),
+ priority => 'error',
+ facility => [ 'system', ],
+ },
+ );
+ }
+ ##! 16: 'current safe: ' . Dumper $current_safe
+
+ return $current_safe->{id};
+ },
+
+ ENCRYPT_ASYMMETRICALLY => {
+ my $arg_ref = shift;
+
+ my $keyid = $arg_ref->{KEYID};
+ my $data = $arg_ref->{DATA};
+
+ my $cfg_id = CTX('api')->get_current_config_id();
+ my $realm = CTX('session')->get_pki_realm();
+
+ my $cert = CTX('pki_realm_by_cfg')->{$cfg_id}->{$realm}->{password_safe}->{id}->{$keyid}->{certificate};
+
+ ##! 16: 'cert: ' . $cert
+ if (! defined $cert) {
+ OpenXPKI::Exception->throw(
+ message => 'I18N_OPENXPKI_SERVER_INIT_CALLBACK_ENCRYPT_ASYMMETRICALLY_CERT_NOT_AVAILABLE',
+ params => {
+ PKI_REALM => $realm,
+ KEY_ID => $key,
+ CONFIG_ID => $cfg_id,
+ },
+ log => {
+ logger => CTX('log'),
+ priority => 'error',
+ facility => [ 'system', ],
+ },
+ );
+ }
+
+ ##! 16: 'asymmetric encryption via passwordsafe ' . $current_password_safe
+ my $token = CTX('pki_realm_by_cfg')->{$cfg_id}->{$realm}->{crypto}->{default};
+ $value = $token->command(
+ {
+ COMMAND => 'pkcs7_encrypt',
+ CERT => $cert,
+ CONTENT => $data,
+ });
+ return $value;
+ },
+
+ DECRYPT_ASYMMETRICALLY => {
+ my $arg_ref = shift;
+
+ my $keyid = $arg_ref->{KEYID};
+ my $data = $arg_ref->{DATA};
+
+ my $cfg_id = CTX('api')->get_current_config_id();
+ my $realm = CTX('session')->get_pki_realm();
+
+ my $safe_token = CTX('pki_realm_by_cfg')->{$cfg_id}->{$realm}->{password_safe}->{id}->{$keyid}->{crypto};
+ if (! defined $safe_token) {
+ OpenXPKI::Exception->throw(
+ message => 'I18N_OPENXPKI_SERVER_INIT_CALLBACK_DECRYPT_ASYMMETRICALLY_TOKEN_NOT_AVAILABLE',
+ params => {
+ PKI_REALM => $realm,
+ KEY_ID => $keyid,
+ CONFIG_ID => $cfg_id,
+ },
+ log => {
+ logger => CTX('log'),
+ priority => 'error',
+ facility => [ 'system', ],
+ },
+ );
+ }
+ ##! 16: 'asymmetric decryption via passwordsafe ' . $safe_id
+ eval {
+ $value = $safe_token->command(
+ {
+ COMMAND => 'pkcs7_decrypt',
+ PKCS7 => $value,
+ });
+ };
+ if (my $exc = OpenXPKI::Exception->caught()) {
+ if ($exc->message()
+ eq 'I18N_OPENXPKI_TOOLKIT_COMMAND_FAILED') {
+
+ OpenXPKI::Exception->throw(
+ message => 'I18N_OPENXPKI_SERVER_INIT_CALLBACK_DECRYPT_ASYMMETRICALLY_ENCRYPTION_KEY_UNAVAILABLE',
+ params => {
+ PKI_REALM => $realm,
+ KEY_ID => $keyid,
+ CONFIG_ID => $cfg_id,
+ },
+ log => {
+ logger => CTX('log'),
+ priority => 'error',
+ facility => [ 'system', ],
+ },
+ );
+ }
+
+ $exc->rethrow();
+ }
+ return $value;
+ },
+ STORE_TUPLE => {
+ my $arg_ref = shift;
+
+ my $namespace = $arg_ref->{NAMESPACE};
+ my $key = $arg_ref->{KEY};
+ my $data = $arg_ref->{VALUE};
+
+ my $realm = CTX('session')->get_pki_realm();
+ return CTX('api')->set_data_pool_entry(
+ {
+ PKI_REALM => $realm,
+ NAMESPACE => $namespace,
+ KEY => $key,
+ VALUE => $data,
+ });
+ },
+ RETRIEVE_TUPLE => {
+ my $arg_ref = shift;
+
+ my $namespace = $arg_ref->{NAMESPACE};
+ my $key = $arg_ref->{KEY};
+
+ my $realm = CTX('session')->get_pki_realm();
+ my $result = CTX('api')->get_data_pool_entry(
+ {
+ PKI_REALM => $realm,
+ NAMESPACE => $namespace,
+ KEY => $key,
+ });
+ return unless defined $result;
+ return $result->{VALUE};
+ },
+ });
+
+ OpenXPKI::Server::Context::setcontext(
+ {
+ transparent_encryption => $tenc,
+ });
+}
+
sub __do_init_dbi_backend {
### init backend dbi...
my $dbi = get_dbi(