1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CRYPTO_ENCRYPTOR_H_
6#define CRYPTO_ENCRYPTOR_H_
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/strings/string_piece.h"
13#include "build/build_config.h"
14#include "crypto/crypto_export.h"
15
16#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
17#include "crypto/scoped_nss_types.h"
18#endif
19
20namespace crypto {
21
22class SymmetricKey;
23
24class CRYPTO_EXPORT Encryptor {
25 public:
26  enum Mode {
27    CBC,
28    CTR,
29  };
30
31  // This class implements a 128-bits counter to be used in AES-CTR encryption.
32  // Only 128-bits counter is supported in this class.
33  class CRYPTO_EXPORT Counter {
34   public:
35    explicit Counter(const base::StringPiece& counter);
36    ~Counter();
37
38    // Increment the counter value.
39    bool Increment();
40
41    // Write the content of the counter to |buf|. |buf| should have enough
42    // space for |GetLengthInBytes()|.
43    void Write(void* buf);
44
45    // Return the length of this counter.
46    size_t GetLengthInBytes() const;
47
48   private:
49    union {
50      uint32 components32[4];
51      uint64 components64[2];
52    } counter_;
53  };
54
55  Encryptor();
56  virtual ~Encryptor();
57
58  // Initializes the encryptor using |key| and |iv|. Returns false if either the
59  // key or the initialization vector cannot be used.
60  //
61  // If |mode| is CBC, |iv| must not be empty; if it is CTR, then |iv| must be
62  // empty.
63  bool Init(SymmetricKey* key, Mode mode, const base::StringPiece& iv);
64
65  // Encrypts |plaintext| into |ciphertext|.  |plaintext| may only be empty if
66  // the mode is CBC.
67  bool Encrypt(const base::StringPiece& plaintext, std::string* ciphertext);
68
69  // Decrypts |ciphertext| into |plaintext|.  |ciphertext| must not be empty.
70  //
71  // WARNING: In CBC mode, Decrypt() returns false if it detects the padding
72  // in the decrypted plaintext is wrong. Padding errors can result from
73  // tampered ciphertext or a wrong decryption key. But successful decryption
74  // does not imply the authenticity of the data. The caller of Decrypt()
75  // must either authenticate the ciphertext before decrypting it, or take
76  // care to not report decryption failure. Otherwise it could inadvertently
77  // be used as a padding oracle to attack the cryptosystem.
78  bool Decrypt(const base::StringPiece& ciphertext, std::string* plaintext);
79
80  // Sets the counter value when in CTR mode. Currently only 128-bits
81  // counter value is supported.
82  //
83  // Returns true only if update was successful.
84  bool SetCounter(const base::StringPiece& counter);
85
86  // TODO(albertb): Support streaming encryption.
87
88 private:
89  // Generates a mask using |counter_| to be used for encryption in CTR mode.
90  // Resulting mask will be written to |mask| with |mask_len| bytes.
91  //
92  // Make sure there's enough space in mask when calling this method.
93  // Reserve at least |plaintext_len| + 16 bytes for |mask|.
94  //
95  // The generated mask will always have at least |plaintext_len| bytes and
96  // will be a multiple of the counter length.
97  //
98  // This method is used only in CTR mode.
99  //
100  // Returns false if this call failed.
101  bool GenerateCounterMask(size_t plaintext_len,
102                           uint8* mask,
103                           size_t* mask_len);
104
105  // Mask the |plaintext| message using |mask|. The output will be written to
106  // |ciphertext|. |ciphertext| must have at least |plaintext_len| bytes.
107  void MaskMessage(const void* plaintext,
108                   size_t plaintext_len,
109                   const void* mask,
110                   void* ciphertext) const;
111
112  SymmetricKey* key_;
113  Mode mode_;
114  scoped_ptr<Counter> counter_;
115
116#if defined(USE_OPENSSL)
117  bool Crypt(bool do_encrypt,  // Pass true to encrypt, false to decrypt.
118             const base::StringPiece& input,
119             std::string* output);
120  bool CryptCTR(bool do_encrypt,
121                const base::StringPiece& input,
122                std::string* output);
123  std::string iv_;
124#elif defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
125  bool Crypt(PK11Context* context,
126             const base::StringPiece& input,
127             std::string* output);
128  bool CryptCTR(PK11Context* context,
129                const base::StringPiece& input,
130                std::string* output);
131  ScopedSECItem param_;
132#endif
133};
134
135}  // namespace crypto
136
137#endif  // CRYPTO_ENCRYPTOR_H_
138