Skip to content

Commit 595f066

Browse files
authored
feature: add AES-256-CTR binding and reuse buffers.
1 parent 046c2c5 commit 595f066

1 file changed

Lines changed: 36 additions & 19 deletions

File tree

lib/resty/aes.lua

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const EVP_CIPHER *EVP_aes_256_cfb1(void);
5858
const EVP_CIPHER *EVP_aes_256_cfb8(void);
5959
const EVP_CIPHER *EVP_aes_256_cfb128(void);
6060
const EVP_CIPHER *EVP_aes_256_ofb(void);
61+
const EVP_CIPHER *EVP_aes_256_ctr(void);
6162
const EVP_CIPHER *EVP_aes_128_gcm(void);
6263
const EVP_CIPHER *EVP_aes_192_gcm(void);
6364
const EVP_CIPHER *EVP_aes_256_gcm(void);
@@ -103,11 +104,14 @@ hash = {
103104
_M.hash = hash
104105

105106
local 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

107111
local cipher
108112
cipher = 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)
224228
end
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

227246
function _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

Comments
 (0)