PageRenderTime 122ms CodeModel.GetById 60ms app.highlight 6ms RepoModel.GetById 54ms app.codeStats 0ms

/mordor/streams/crypto.h

http://github.com/mozy/mordor
C Header | 82 lines | 51 code | 13 blank | 18 comment | 2 complexity | cb0c3e3bdcd65e6a404e9002f3806788 MD5 | raw file
 1#ifndef __MORDOR_CRYPTO_STREAM__
 2#define __MORDOR_CRYPTO_STREAM__
 3// Copyright (c) 2011 - Mozy, Inc.
 4
 5#include <openssl/evp.h>
 6#include "filter.h"
 7#include "buffer.h"
 8
 9namespace Mordor {
10
11// encryption/decryption stream using OpenSSL EVP API
12// supports all four permutations of (encrypt, decrypt) and (read, write),
13// although only one per instance
14
15// NOTE: if WRITE, close() must be called when finish!!!
16
17class CryptoStream : public MutatingFilterStream
18{
19public:
20    typedef boost::shared_ptr<CryptoStream> ptr;
21    static const std::string RANDOM_IV;
22
23    enum Direction {
24        INFER,  // check whether parent supportsRead() or supportsWrite();
25                // exactly one of these must be true
26        READ,
27        WRITE
28    };
29    enum Operation {
30        AUTO,   // encrypt on WRITE; decrypt on READ
31        DECRYPT,
32        ENCRYPT
33    };
34
35    // cipher is e.g. EVP_aes_256_cbc() (see openssl/evp.h for all options)
36    // key and iv are *binary* and must be the correct length for the cipher
37    // if iv is required and not supplied (or set to RANDOM_IV),
38    // then the initialization vector will:
39    //  * on encrypt, generated randomly and prepended to the ciphertext
40    //  * on decrypt, extracted from the beginning of the ciphertext
41    // WARNING: due to older versions of OpenSSL reporting a nonzero IV size
42    //   for ECB cipher contexts, you should explicitly supply an empty IV
43    //   instead of RANDOM_IV when operating in ECB mode
44    // WARNING: using RANDOM_IV will cause the generated cipher data incompatible
45    //   with openssl tool implementation, hence no 3rdparty tool can decrypt the
46    //   cipher data directly except Mordor::CryptoStream itself
47    CryptoStream(Stream::ptr parent, const EVP_CIPHER *cipher, const std::string &key,
48        const std::string &iv = RANDOM_IV, Direction = INFER, Operation = AUTO,
49        bool own = true);
50    ~CryptoStream();
51
52    bool supportsRead() { return m_dir == READ; }
53    bool supportsWrite() { return m_dir == WRITE; }
54    bool supportsSeek() { return false; }
55    bool supportsSize() { return false; }
56
57    void close(CloseType type = BOTH);
58    using MutatingFilterStream::read;
59    size_t read(Buffer &buffer, size_t len);
60    using MutatingFilterStream::write;
61    size_t write(const Buffer &buffer, size_t len);
62
63private:
64    size_t cipher(const Buffer &src, Buffer &dst, size_t len, size_t skip = 0);    // ciphers len bytes from src
65    size_t final(Buffer &dst);  // finalizes the cipher and writes the last few bytes to dst
66    void write_buffer(Buffer &buffer);    // writes and consumes entire buffer
67    void init_iv();
68    void finalize();
69
70    std::string m_iv;
71    Direction m_dir;
72    Operation m_op;
73    Buffer m_buf, m_tmp;
74    EVP_CIPHER_CTX m_ctx;
75    int m_blocksize;
76    bool m_eof;
77    size_t m_iv_to_extract;
78};
79
80}
81
82#endif