diff options
author | Bjoern Schiessle <schiessle@owncloud.com> | 2014-07-21 13:02:28 +0200 |
---|---|---|
committer | Bjoern Schiessle <schiessle@owncloud.com> | 2014-07-23 12:14:01 +0200 |
commit | 4bbdcfbccfe1fef28d3b6feea8a742e156295a63 (patch) | |
tree | 4b920bc9e16ad4d5b4c1b2e2b8fc521ba9e0dd6e /apps/files_encryption/lib/stream.php | |
parent | ddd8eae9320bcd5317f18a6305120c358f72bcdd (diff) | |
download | nextcloud-server-4bbdcfbccfe1fef28d3b6feea8a742e156295a63.tar.gz nextcloud-server-4bbdcfbccfe1fef28d3b6feea8a742e156295a63.zip |
support aes 256
Diffstat (limited to 'apps/files_encryption/lib/stream.php')
-rw-r--r-- | apps/files_encryption/lib/stream.php | 91 |
1 files changed, 77 insertions, 14 deletions
diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 341114214d5..f74812a7253 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -2,9 +2,10 @@ /** * ownCloud * - * @author Robin Appelman - * @copyright 2012 Sam Tuke <samtuke@owncloud.com>, 2011 Robin Appelman - * <icewind1991@gmail.com> + * @author Bjoern Schiessle, Robin Appelman + * @copyright 2014 Bjoern Schiessle <schiessle@owncloud.com> + * 2012 Sam Tuke <samtuke@owncloud.com>, + * 2011 Robin Appelman <icewind1991@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -49,9 +50,11 @@ namespace OCA\Encryption; * encryption proxies are used and keyfiles deleted. */ class Stream { + + const PADDING_CHAR = '-'; + private $plainKey; private $encKeyfiles; - private $rawPath; // The raw path relative to the data dir private $relPath; // rel path to users file dir private $userId; @@ -66,6 +69,9 @@ class Stream { private $newFile; // helper var, we only need to write the keyfile for new files private $isLocalTmpFile = false; // do we operate on a local tmp file private $localTmpFile; // path of local tmp file + private $headerWritten = false; + private $containHeader = false; // the file contain a header + private $cipher; // cipher used for encryption/decryption /** * @var \OC\Files\View @@ -87,6 +93,9 @@ class Stream { */ public function stream_open($path, $mode, $options, &$opened_path) { + // read default cipher from config + $this->cipher = Helper::getCipher(); + // assume that the file already exist before we decide it finally in getKey() $this->newFile = false; @@ -150,6 +159,9 @@ class Stream { } $this->size = $this->rootView->filesize($this->rawPath); + + $this->readHeader(); + } if ($this->isLocalTmpFile) { @@ -178,6 +190,29 @@ class Stream { } + private function readHeader() { + + if ($this->isLocalTmpFile) { + $handle = fopen($this->localTmpFile, 'r'); + } else { + $handle = $this->rootView->fopen($this->rawPath, 'r'); + } + + if (is_resource($handle)) { + $data = fread($handle, Crypt::BLOCKSIZE); + + $header = Crypt::parseHeader($data); + $this->cipher = Crypt::getCipher($header); + + // remeber that we found a header + if (!empty($header)) { + $this->containHeader = true; + } + + fclose($handle); + } + } + /** * Returns the current position of the file pointer * @return int position of the file pointer @@ -195,6 +230,11 @@ class Stream { $this->flush(); + // ignore the header and just overstep it + if ($this->containHeader) { + $offset += Crypt::BLOCKSIZE; + } + // this wrapper needs to return "true" for success. // the fseek call itself returns 0 on succeess return !fseek($this->handle, $offset, $whence); @@ -204,25 +244,25 @@ class Stream { /** * @param int $count * @return bool|string - * @throws \Exception + * @throws \OCA\Encryption\Exceptions\EncryptionException */ public function stream_read($count) { $this->writeCache = ''; - if ($count !== 8192) { - - // $count will always be 8192 https://bugs.php.net/bug.php?id=21641 - // This makes this function a lot simpler, but will break this class if the above 'bug' gets 'fixed' + if ($count !== Crypt::BLOCKSIZE) { \OCP\Util::writeLog('Encryption library', 'PHP "bug" 21641 no longer holds, decryption system requires refactoring', \OCP\Util::FATAL); - - die(); - + throw new \OCA\Encryption\Exceptions\EncryptionException('expected a blog size of 8192 byte', 20); } // Get the data from the file handle $data = fread($this->handle, $count); + // if this block contained the header we move on to the next block + if (Crypt::isHeader($data)) { + $data = fread($this->handle, $count); + } + $result = null; if (strlen($data)) { @@ -236,7 +276,7 @@ class Stream { } else { // Decrypt data - $result = Crypt::symmetricDecryptFileContent($data, $this->plainKey); + $result = Crypt::symmetricDecryptFileContent($data, $this->plainKey, $this->cipher); } } @@ -254,7 +294,7 @@ class Stream { public function preWriteEncrypt($plainData, $key) { // Encrypt data to 'catfile', which includes IV - if ($encrypted = Crypt::symmetricEncryptFileContent($plainData, $key)) { + if ($encrypted = Crypt::symmetricEncryptFileContent($plainData, $key, $this->cipher)) { return $encrypted; @@ -318,6 +358,25 @@ class Stream { } /** + * write header at beginning of encrypted file + * + * @throws Exceptions\EncryptionException + */ + private function writeHeader() { + + $header = Crypt::generateHeader(); + + if (strlen($header) > Crypt::BLOCKSIZE) { + throw new Exceptions\EncryptionException('max header size exceeded', 30); + } + + $paddedHeader = str_pad($header, Crypt::BLOCKSIZE, self::PADDING_CHAR, STR_PAD_RIGHT); + + fwrite($this->handle, $paddedHeader); + $this->headerWritten = true; + } + + /** * Handle plain data from the stream, and write it in 8192 byte blocks * @param string $data data to be written to disk * @note the data will be written to the path stored in the stream handle, set in stream_open() @@ -334,6 +393,10 @@ class Stream { return strlen($data); } + if ($this->headerWritten === false) { + $this->writeHeader(); + } + // Disable the file proxies so that encryption is not // automatically attempted when the file is written to disk - // we are handling that separately here and we don't want to |