Botan
1.11.15
|
00001 /* 00002 * GCM Mode 00003 * (C) 2013 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #ifndef BOTAN_AEAD_GCM_H__ 00009 #define BOTAN_AEAD_GCM_H__ 00010 00011 #include <botan/aead.h> 00012 #include <botan/block_cipher.h> 00013 #include <botan/stream_cipher.h> 00014 00015 namespace Botan { 00016 00017 class GHASH; 00018 00019 /** 00020 * GCM Mode 00021 */ 00022 class BOTAN_DLL GCM_Mode : public AEAD_Mode 00023 { 00024 public: 00025 void set_associated_data(const byte ad[], size_t ad_len) override; 00026 00027 std::string name() const override; 00028 00029 size_t update_granularity() const; 00030 00031 Key_Length_Specification key_spec() const override; 00032 00033 // GCM supports arbitrary nonce lengths 00034 bool valid_nonce_length(size_t) const override { return true; } 00035 00036 size_t tag_size() const override { return m_tag_size; } 00037 00038 void clear() override; 00039 protected: 00040 GCM_Mode(BlockCipher* cipher, size_t tag_size); 00041 00042 const size_t BS = 16; 00043 00044 const size_t m_tag_size; 00045 const std::string m_cipher_name; 00046 00047 std::unique_ptr<StreamCipher> m_ctr; 00048 std::unique_ptr<GHASH> m_ghash; 00049 private: 00050 secure_vector<byte> start_raw(const byte nonce[], size_t nonce_len) override; 00051 00052 void key_schedule(const byte key[], size_t length) override; 00053 }; 00054 00055 /** 00056 * GCM Encryption 00057 */ 00058 class BOTAN_DLL GCM_Encryption : public GCM_Mode 00059 { 00060 public: 00061 /** 00062 * @param cipher the 128 bit block cipher to use 00063 * @param tag_size is how big the auth tag will be 00064 */ 00065 GCM_Encryption(BlockCipher* cipher, size_t tag_size = 16) : 00066 GCM_Mode(cipher, tag_size) {} 00067 00068 size_t output_length(size_t input_length) const override 00069 { return input_length + tag_size(); } 00070 00071 size_t minimum_final_size() const override { return 0; } 00072 00073 void update(secure_vector<byte>& blocks, size_t offset = 0) override; 00074 00075 void finish(secure_vector<byte>& final_block, size_t offset = 0) override; 00076 }; 00077 00078 /** 00079 * GCM Decryption 00080 */ 00081 class BOTAN_DLL GCM_Decryption : public GCM_Mode 00082 { 00083 public: 00084 /** 00085 * @param cipher the 128 bit block cipher to use 00086 * @param tag_size is how big the auth tag will be 00087 */ 00088 GCM_Decryption(BlockCipher* cipher, size_t tag_size = 16) : 00089 GCM_Mode(cipher, tag_size) {} 00090 00091 size_t output_length(size_t input_length) const override 00092 { 00093 BOTAN_ASSERT(input_length > tag_size(), "Sufficient input"); 00094 return input_length - tag_size(); 00095 } 00096 00097 size_t minimum_final_size() const override { return tag_size(); } 00098 00099 void update(secure_vector<byte>& blocks, size_t offset = 0) override; 00100 00101 void finish(secure_vector<byte>& final_block, size_t offset = 0) override; 00102 }; 00103 00104 /** 00105 * GCM's GHASH 00106 * Maybe a Transform? 00107 */ 00108 class BOTAN_DLL GHASH : public SymmetricAlgorithm 00109 { 00110 public: 00111 void set_associated_data(const byte ad[], size_t ad_len); 00112 00113 secure_vector<byte> nonce_hash(const byte nonce[], size_t len); 00114 00115 void start(const byte nonce[], size_t len); 00116 00117 /* 00118 * Assumes input len is multiple of 16 00119 */ 00120 void update(const byte in[], size_t len); 00121 00122 secure_vector<byte> final(); 00123 00124 Key_Length_Specification key_spec() const { return Key_Length_Specification(16); } 00125 00126 void clear() override; 00127 00128 std::string name() const { return "GHASH"; } 00129 private: 00130 void key_schedule(const byte key[], size_t key_len) override; 00131 00132 void gcm_multiply(secure_vector<byte>& x) const; 00133 00134 void ghash_update(secure_vector<byte>& x, 00135 const byte input[], size_t input_len); 00136 00137 void add_final_block(secure_vector<byte>& x, 00138 size_t ad_len, size_t pt_len); 00139 00140 secure_vector<byte> m_H; 00141 secure_vector<byte> m_H_ad; 00142 secure_vector<byte> m_nonce; 00143 secure_vector<byte> m_ghash; 00144 size_t m_ad_len = 0, m_text_len = 0; 00145 }; 00146 00147 } 00148 00149 #endif