Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable10] Backport of Integrate HSM changes to encryption #34527

Merged
merged 1 commit into from
Feb 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/encryption/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<command>OCA\Encryption\Command\SelectEncryptionType</command>
<command>OCA\Encryption\Command\RecreateMasterKey</command>
<command>OCA\Encryption\Command\MigrateKeys</command>
<command>OCA\Encryption\Command\HSMDaemon</command>
</commands>
<settings>
<admin>OCA\Encryption\Panels\Admin</admin>
Expand Down
43 changes: 25 additions & 18 deletions apps/encryption/lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
*/
namespace OCA\Encryption\AppInfo;


use OC\Files\View;
use OC\Helper\EnvironmentHelper;
use OCA\Encryption\Controller\RecoveryController;
Expand All @@ -39,13 +38,12 @@
use OCA\Encryption\Session;
use OCA\Encryption\Users\Setup;
use OCA\Encryption\Util;
use OCP\App;
use OCA\Encryption\Crypto\CryptHSM;
use OCP\AppFramework\IAppContainer;
use OCP\Encryption\IManager;
use OCP\IConfig;
use Symfony\Component\Console\Helper\QuestionHelper;


class Application extends \OCP\AppFramework\App {

/** @var IManager */
Expand All @@ -62,7 +60,7 @@ public function __construct($urlParams = [], $encryptionSystemReady = true) {
$this->encryptionManager = \OC::$server->getEncryptionManager();
$this->config = \OC::$server->getConfig();
$this->registerServices();
if($encryptionSystemReady === false) {
if ($encryptionSystemReady === false) {
/** @var Session $session */
$session = $this->getContainer()->query('Session');
$session->setStatus(Session::RUN_MIGRATION);
Expand All @@ -80,7 +78,6 @@ public function __construct($urlParams = [], $encryptionSystemReady = true) {

public function registerHooks() {
if (!$this->config->getSystemValue('maintenance', false)) {

$container = $this->getContainer();
$server = $container->getServer();
// Register our hooks and fire them.
Expand All @@ -99,7 +96,6 @@ public function registerHooks() {
]);

$hookManager->fireHooks();

} else {
// Logout user if we are in maintenance to force re-login
$this->getContainer()->getServer()->getUserSession()->logout();
Expand All @@ -109,13 +105,11 @@ public function registerHooks() {
public function registerEncryptionModule() {
$container = $this->getContainer();


$this->encryptionManager->registerEncryptionModule(
Encryption::ID,
Encryption::DISPLAY_NAME,
function() use ($container) {

return new Encryption(
function () use ($container) {
return new Encryption(
$container->query('Crypt'),
$container->query('KeyManager'),
$container->query('Util'),
Expand All @@ -125,8 +119,7 @@ function() use ($container) {
$container->getServer()->getLogger(),
$container->getServer()->getL10N($container->getAppName())
);
});

});
}

public function registerServices() {
Expand All @@ -135,10 +128,25 @@ public function registerServices() {
$container->registerService('Crypt',
function (IAppContainer $c) {
$server = $c->getServer();
return new Crypt($server->getLogger(),
$server->getUserSession(),
$server->getConfig(),
$server->getL10N($c->getAppName()));

if ($this->config->getAppValue('encryption', 'hsm.url', '') !== '') {
$this->config->setAppValue('crypto.engine', 'internal', 'hsm');
}

if ($this->config->getAppValue('crypto.engine', 'internal', '') === 'hsm') {
return new CryptHSM($server->getLogger(),
$server->getUserSession(),
$server->getConfig(),
$server->getL10N($c->getAppName()),
$server->getHTTPClientService(),
$server->getRequest(),
$server->getTimeFactory());
} else {
return new Crypt($server->getLogger(),
$server->getUserSession(),
$server->getConfig(),
$server->getL10N($c->getAppName()));
}
});

$container->registerService('Session',
Expand Down Expand Up @@ -266,9 +274,8 @@ function (IAppContainer $c) {
);
}
);
$container->registerService('OCP\Encryption\Keys\IStorage', function(IAppContainer $c) {
$container->registerService('OCP\Encryption\Keys\IStorage', function (IAppContainer $c) {
return $c->getServer()->getEncryptionKeyStorage();
});
}

}
119 changes: 119 additions & 0 deletions apps/encryption/lib/Command/HSMDaemon.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php
/**
* @author Jörn Friedrich Dreyer <[email protected]>
*
* @copyright Copyright (c) 2017, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OCA\Encryption\Command;

use OCA\Encryption\AppInfo\Application;
use OCA\Encryption\JWT;
use OCA\Encryption\KeyManager;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Encryption\IEncryptionModule;
use OCP\Http\Client\IClient;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\ILogger;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class HSMDaemon extends Command {

/** @var IClient */
private $httpClient;
/** @var IConfig */
private $config;
/** @var ILogger */
private $logger;
/** @var ITimeFactory */
private $timeFactory;

/**
* @param IEncryptionModule $encryption
* @param IClient $httpClient
* @param IConfig $config
* @param ILogger $logger
*/
public function __construct(IClientService $httpClient,
IConfig $config,
ILogger $logger,
ITimeFactory $timeFactory) {
$this->httpClient = $httpClient->newClient();
$this->config = $config;
$this->logger = $logger;
$this->timeFactory = $timeFactory;
parent::__construct();
}

// TODO add route for hsmdaemon to post current secret
// TODO add encrypt masterkey command / as option
// TODO add decrypt option
protected function configure() {
$this
->setName('encryption:hsmdaemon')
->setDescription('hsmdaemon tool');
$this->addOption(
'export-masterkey',
null,
InputOption::VALUE_NONE,
'export the private master key in base64'
);
$this->addOption(
'import-masterkey',
null,
InputOption::VALUE_REQUIRED,
'import a base64 encoded private masterkey'
);
$this->addOption(
'decrypt',
null,
InputOption::VALUE_REQUIRED,
'decrypt a base64 encoded value with the hsm'
);
}

protected function execute(InputInterface $input, OutputInterface $output) {
$hsmUrl = $this->config->getAppValue('encryption', 'hsm.url');
if (\is_string($hsmUrl) && $hsmUrl !== '') {
$decrypt = $input->getOption('decrypt');
if ($decrypt) {
$response = $this->httpClient->post($hsmUrl, [
'headers' => [
'Authorization' => 'Bearer ' . JWT::token([
'exp' => $this->timeFactory->getTime() + 120 // 2min for clock skew
], 'secret')
],
'body' => \base64_decode($decrypt)
]);

$output->writeln("received: '".$response->getBody()."'");
} elseif ($input->getOption('export-masterkey')) {
$manager = \OC::$server->getEncryptionKeyStorage();
$keyId = $this->config->getAppValue('encryption', 'masterKeyId').'.privateKey';
$key = $manager->getSystemUserKey($keyId, \OC::$server->getEncryptionManager()->getDefaultEncryptionModuleId());
// FIXME key might be too long to encrypt in one piece
$output->writeln("current masterkey (base64 encoded): '".\base64_encode($key)."'");
}
} else {
$output->writeln("<error>hsm.url not set</error>");
}
}
}
Loading