@@ -58,6 +58,7 @@ const EVP_CIPHER *EVP_aes_256_cfb1(void);
5858const EVP_CIPHER *EVP_aes_256_cfb8 (void );
5959const EVP_CIPHER *EVP_aes_256_cfb128 (void );
6060const EVP_CIPHER *EVP_aes_256_ofb (void );
61+ const EVP_CIPHER *EVP_aes_256_ctr (void );
6162const EVP_CIPHER *EVP_aes_128_gcm (void );
6263const EVP_CIPHER *EVP_aes_192_gcm (void );
6364const EVP_CIPHER *EVP_aes_256_gcm (void );
@@ -103,11 +104,14 @@ hash = {
103104_M .hash = hash
104105
105106local EVP_MAX_BLOCK_LENGTH = 32
107+ local shared_out_len_ptr = ffi_new (" int[1]" )
108+ local shared_tmp_len_ptr = ffi_new (" int[1]" )
109+ local shared_tag_buf_ptr = ffi_new (" unsigned char[?]" , 16 )
106110
107111local cipher
108112cipher = function (size , _cipher )
109113 local _size = size or 128
110- local _cipher = _cipher or " cbc"
114+ _cipher = _cipher or " cbc"
111115 local func = " EVP_aes_" .. _size .. " _" .. _cipher
112116 if C [func ] then
113117 return { size = _size , cipher = _cipher , method = C [func ]()}
@@ -132,12 +136,12 @@ function _M.new(self, key, salt, _cipher, _hash, hash_rounds, iv_len, enable_pad
132136
133137 ffi_gc (decrypt_ctx , C .EVP_CIPHER_CTX_free )
134138
135- local _cipher = _cipher or cipher ()
136- local _hash = _hash or hash .md5
137- local hash_rounds = hash_rounds or 1
139+ _cipher = _cipher or cipher ()
140+ _hash = _hash or hash .md5
141+ hash_rounds = hash_rounds or 1
138142 local _cipherLength = _cipher .size / 8
139- local gen_key = ffi_new (" unsigned char[?]" ,_cipherLength )
140- local gen_iv = ffi_new (" unsigned char[?]" ,_cipherLength )
143+ local gen_key = ffi_new (" unsigned char[?]" , _cipherLength )
144+ local gen_iv = ffi_new (" unsigned char[?]" , _cipherLength )
141145 iv_len = iv_len or _cipherLength
142146 -- enable padding by default
143147 local padding = (enable_padding == nil or enable_padding ) and 1 or 0
@@ -223,6 +227,21 @@ function _M.new(self, key, salt, _cipher, _hash, hash_rounds, iv_len, enable_pad
223227 }, mt )
224228end
225229
230+ local function alloc_buf (max_len )
231+ local buf = ffi_new (" unsigned char[?]" , max_len )
232+ return buf , max_len
233+ end
234+
235+ do
236+ local ok , str_buf_mod = pcall (require , " string.buffer" )
237+ if ok then
238+ local str_buf = str_buf_mod .new (4096 )
239+ function alloc_buf (max_len )
240+ local buf , sz = str_buf :reset ():reserve (max_len )
241+ return buf , sz
242+ end
243+ end
244+ end
226245
227246function _M .encrypt (self , s , aad )
228247 local typ = type (self )
@@ -231,10 +250,9 @@ function _M.encrypt(self, s, aad)
231250 end
232251
233252 local s_len = # s
234- local max_len = s_len + 2 * EVP_MAX_BLOCK_LENGTH
235- local buf = ffi_new (" unsigned char[?]" , max_len )
236- local out_len = ffi_new (" int[1]" )
237- local tmp_len = ffi_new (" int[1]" )
253+ local buf = alloc_buf (s_len + 2 * EVP_MAX_BLOCK_LENGTH )
254+ local out_len = shared_out_len_ptr
255+ local tmp_len = shared_tmp_len_ptr
238256 local ctx = self ._encrypt_ctx
239257
240258 if C .EVP_EncryptInit_ex (ctx , nil , nil , self ._key , self ._iv ) == 0 then
@@ -254,7 +272,7 @@ function _M.encrypt(self, s, aad)
254272 if self ._cipher == " gcm" then
255273 local encrypt_data = ffi_str (buf , out_len [0 ])
256274 if C .EVP_EncryptFinal_ex (ctx , buf , out_len ) == 0 then
257- return nil , " EVP_DecryptFinal_ex failed"
275+ return nil , " EVP_EncryptFinal_ex failed"
258276 end
259277
260278 -- FIXME: For OCB mode the taglen must either be 16
@@ -280,14 +298,13 @@ function _M.decrypt(self, s, tag, aad)
280298 end
281299
282300 local s_len = # s
283- local max_len = s_len + 2 * EVP_MAX_BLOCK_LENGTH
284- local buf = ffi_new (" unsigned char[?]" , max_len )
285- local out_len = ffi_new (" int[1]" )
286- local tmp_len = ffi_new (" int[1]" )
301+ local buf = alloc_buf (s_len + 2 * EVP_MAX_BLOCK_LENGTH )
302+ local out_len = shared_out_len_ptr
303+ local tmp_len = shared_tmp_len_ptr
287304 local ctx = self ._decrypt_ctx
288305
289306 if C .EVP_DecryptInit_ex (ctx , nil , nil , self ._key , self ._iv ) == 0 then
290- return nil , " EVP_DecryptInit_ex failed"
307+ return nil , " EVP_DecryptInit_ex failed"
291308 end
292309
293310 if self ._cipher == " gcm" and aad ~= nil then
@@ -297,14 +314,14 @@ function _M.decrypt(self, s, tag, aad)
297314 end
298315
299316 if C .EVP_DecryptUpdate (ctx , buf , out_len , s , s_len ) == 0 then
300- return nil , " EVP_DecryptUpdate failed"
317+ return nil , " EVP_DecryptUpdate failed"
301318 end
302319
303320 if self ._cipher == " gcm" then
304321 local plain_txt = ffi_str (buf , out_len [0 ])
305322 if tag ~= nil then
306- local tag_buf = ffi_new ( " unsigned char[?] " , 16 )
307- ffi . copy (tag_buf , tag , 16 )
323+ local tag_buf = shared_tag_buf_ptr
324+ ffi_copy (tag_buf , tag , 16 )
308325 C .EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_TAG , 16 , tag_buf );
309326 end
310327
0 commit comments