Skip to content
Snippets Groups Projects
Commit e9db303e authored by Georgy Kirichenko's avatar Georgy Kirichenko
Browse files

Properly handle openssl errors. Fixed #1383

parent f9601599
No related merge requests found
......@@ -4,6 +4,12 @@ local ffi = require 'ffi'
local buffer = require('buffer')
ffi.cdef[[
/* from openssl/err.h */
unsigned long ERR_get_error(void);
char *ERR_error_string(unsigned long e, char *buf);
void ERR_load_ERR_strings(void);
void ERR_load_crypto_strings(void);
/* from openssl/evp.h */
void OpenSSL_add_all_digests();
void OpenSSL_add_all_ciphers();
......@@ -50,11 +56,16 @@ if ssl == nil then
if ssl ~= nil then
ssl.OpenSSL_add_all_digests()
ssl.OpenSSL_add_all_ciphers()
ssl.ERR_load_crypto_strings()
break
end
end
end
local function openssl_err_str()
return ffi.string(ssl.ERR_error_string(ssl.ERR_get_error(), nil))
end
local digests = {}
if ssl then
for class, name in pairs({
......@@ -62,7 +73,10 @@ if ssl then
sha = 'SHA', sha1 = 'SHA1', sha224 = 'SHA224',
sha256 = 'SHA256', sha384 = 'SHA384', sha512 = 'SHA512',
dss = 'DSS', dss1 = 'DSS1', mdc2 = 'MDC2', ripemd160 = 'RIPEMD160'}) do
digests[class] = ssl.EVP_get_digestbyname(class)
local digest = ssl.EVP_get_digestbyname(class)
if digest ~= nil then
digests[class] = digest
end
end
end
......@@ -75,7 +89,7 @@ end
local function digest_new(digest)
local ctx = ssl.EVP_MD_CTX_create()
if ctx == nil then
return error('Can\'t create digest ctx')
return error('Can\'t create digest ctx: ' .. openssl_err_str())
end
ffi.gc(ctx, digest_gc)
local self = setmetatable({
......@@ -94,7 +108,7 @@ local function digest_init(self)
return error('Digest context isn\'t usable')
end
if ssl.EVP_DigestInit_ex(self.ctx, self.digest, nil) ~= 1 then
return error('Can\'t init digest')
return error('Can\'t init digest: ' .. openssl_err_str())
end
self.initialized = true
end
......@@ -104,7 +118,7 @@ local function digest_update(self, input)
return error('Digest not initialized')
end
if ssl.EVP_DigestUpdate(self.ctx, input, input:len()) ~= 1 then
return error('Can\'t update digest')
return error('Can\'t update digest: ' .. openssl_err_str())
end
end
......@@ -114,7 +128,7 @@ local function digest_final(self)
end
self.initialized = false
if ssl.EVP_DigestFinal_ex(self.ctx, self.buf.wpos, self.outl) ~= 1 then
return error('Can\'t finalize digest')
return error('Can\'t finalize digest: ' .. openssl_err_str())
end
return ffi.string(self.buf.wpos, self.outl[0])
end
......@@ -142,8 +156,11 @@ if ssl then
local algo_api = {}
for mode, mode_name in pairs({cfb = 'CFB', ofb = 'OFB',
cbc = 'CBC', ecb = 'ECB'}) do
algo_api[mode] =
local cipher =
ssl.EVP_get_cipherbyname(algo_name .. '-' .. mode_name)
if cipher ~= nil then
algo_api[mode] = cipher
end
end
if algo_api ~= {} then
ciphers[algo] = algo_api
......@@ -158,15 +175,24 @@ local function cipher_gc(ctx)
end
local function cipher_new(cipher, key, iv, direction)
local block_size = ssl.EVP_CIPHER_block_size(cipher)
if key == nil or key:len() < block_size then
return error('Key length should be equal cipher block size ('
.. tostring(block_size) .. ')')
end
if iv == nil or iv:len() < block_size then
return error('Initial vector length should be equal cipher block size ('
.. tostring(block_size) .. ')')
end
local ctx = ssl.EVP_CIPHER_CTX_new()
if ctx == nil then
return error('Can\'t create cipher ctx')
return error('Can\'t create cipher ctx: ' .. openssl_err_str())
end
ffi.gc(ctx, cipher_gc)
local self = setmetatable({
ctx = ctx,
cipher = cipher,
block_size = ssl.EVP_CIPHER_block_size(cipher),
block_size = block_size,
direction = direction,
buf = buffer.ibuf(),
initialized = false,
......@@ -180,9 +206,9 @@ local function cipher_init(self, key, iv)
if self.ctx == nil then
return error('Cipher context isn\'t usable')
end
if ssl.EVP_CipherInit_ex(self.ctx, self.cipher, nil,
if ssl.EVP_CipherInit_ex(self.ctx, self.cipher, nil,
key, iv, self.direction) ~= 1 then
return error('Can\'t init cipher')
return error('Can\'t init cipher:' .. openssl_err_str())
end
self.initialized = true
end
......@@ -191,9 +217,13 @@ local function cipher_update(self, input)
if not self.initialized then
return error('Cipher not initialized')
end
if input == nil then
return ''
end
input = tostring(input)
local wpos = self.buf:reserve(input:len() + self.block_size - 1)
if ssl.EVP_CipherUpdate(self.ctx, wpos, self.outl, input, input:len()) ~= 1 then
return error('Can\'t update cipher')
return error('Can\'t update cipher:' .. openssl_err_str())
end
return ffi.string(wpos, self.outl[0])
end
......@@ -205,7 +235,7 @@ local function cipher_final(self)
self.initialized = false
local wpos = self.buf:reserve(self.block_size - 1)
if ssl.EVP_CipherFinal_ex(self.ctx, wpos, self.outl) ~= 1 then
return error('Can\'t finalize cipher')
return error('Can\'t finalize cipher:' .. openssl_err_str())
end
self.initialized = false
return ffi.string(wpos, self.outl[0])
......@@ -254,7 +284,7 @@ digest_api = setmetatable(digest_api,
' is not supported or SSL library not found') end })
local function cipher_mode_error(self, mode)
error('Cipher mode' .. mode .. ' is not supported')
error('Cipher mode ' .. mode .. ' is not supported')
end
local cipher_api = {}
......
crypto = require('crypto')
---
...
type(crypto)
---
- table
...
ciph = crypto.cipher.aes128.cbc
---
...
pass = '12345678876543211234567887654321'
---
...
iv = 'abcdefghijklmnopqrstuvwxyz123456'
---
...
enc = ciph.encrypt('test', pass, iv)
---
...
enc
---
- !!binary WpJJu6l6oziZcyvND8KueA==
...
ciph.decrypt(enc, pass, iv)
---
- test
...
--Failing scenaries
crypto.cipher.aes128.cbc.encrypt('a')
---
- error: 'builtin/crypto.lua:302: Key length should be equal cipher block size (16)'
...
crypto.cipher.aes128.cbc.encrypt('a', '123456', '435')
---
- error: 'builtin/crypto.lua:302: Key length should be equal cipher block size (16)'
...
crypto.cipher.aes128.cbc.encrypt('a', '1234567887654321')
---
- error: 'builtin/crypto.lua:302: Initial vector length should be equal cipher block
size (16)'
...
crypto.cipher.aes128.cbc.encrypt('a', '1234567887654321', '12')
---
- error: 'builtin/crypto.lua:302: Initial vector length should be equal cipher block
size (16)'
...
crypto.cipher.aes256.cbc.decrypt('a')
---
- error: 'builtin/crypto.lua:302: Key length should be equal cipher block size (16)'
...
crypto.cipher.aes256.cbc.decrypt('a', '123456', '435')
---
- error: 'builtin/crypto.lua:302: Key length should be equal cipher block size (16)'
...
crypto.cipher.aes256.cbc.decrypt('a', '12345678876543211234567887654321')
---
- error: 'builtin/crypto.lua:302: Initial vector length should be equal cipher block
size (16)'
...
crypto.cipher.aes256.cbc.decrypt('12', '12345678876543211234567887654321', '12')
---
- error: 'builtin/crypto.lua:302: Initial vector length should be equal cipher block
size (16)'
...
crypto.cipher.aes192.cbc.encrypt.new()
---
- error: Key length should be equal cipher block size (16)
...
crypto.cipher.aes192.cbc.encrypt.new('123321')
---
- error: Key length should be equal cipher block size (16)
...
crypto.cipher.aes192.cbc.decrypt.new('123456788765432112345678')
---
- error: Initial vector length should be equal cipher block size (16)
...
crypto.cipher.aes192.cbc.decrypt.new('123456788765432112345678', '12345')
---
- error: Initial vector length should be equal cipher block size (16)
...
crypto.cipher.aes100.efb
---
- error: 'builtin/crypto.lua:318: Cipher method aes100 is not supported or SSL library
not found'
...
crypto.cipher.aes256.nomode
---
- error: 'builtin/crypto.lua:287: Cipher mode nomode is not supported'
...
crypto.digest.nodigest
---
- error: 'builtin/crypto.lua:283: Digest method nodigest is not supported or SSL library
not found'
...
bad_pass = '87654321123456788765432112345678'
---
...
bad_iv = '123456abcdefghijklmnopqrstuvwxyz'
---
...
ciph.decrypt(enc, bad_pass, iv)
---
- error: 'builtin/crypto.lua:304: Can''t finalize cipher:error:06065064:digital envelope
routines:EVP_DecryptFinal_ex:bad decrypt'
...
ciph.decrypt(enc, pass, bad_iv)
---
- error: 'builtin/crypto.lua:304: Can''t finalize cipher:error:06065064:digital envelope
routines:EVP_DecryptFinal_ex:bad decrypt'
...
crypto = require('crypto')
type(crypto)
ciph = crypto.cipher.aes128.cbc
pass = '12345678876543211234567887654321'
iv = 'abcdefghijklmnopqrstuvwxyz123456'
enc = ciph.encrypt('test', pass, iv)
enc
ciph.decrypt(enc, pass, iv)
--Failing scenaries
crypto.cipher.aes128.cbc.encrypt('a')
crypto.cipher.aes128.cbc.encrypt('a', '123456', '435')
crypto.cipher.aes128.cbc.encrypt('a', '1234567887654321')
crypto.cipher.aes128.cbc.encrypt('a', '1234567887654321', '12')
crypto.cipher.aes256.cbc.decrypt('a')
crypto.cipher.aes256.cbc.decrypt('a', '123456', '435')
crypto.cipher.aes256.cbc.decrypt('a', '12345678876543211234567887654321')
crypto.cipher.aes256.cbc.decrypt('12', '12345678876543211234567887654321', '12')
crypto.cipher.aes192.cbc.encrypt.new()
crypto.cipher.aes192.cbc.encrypt.new('123321')
crypto.cipher.aes192.cbc.decrypt.new('123456788765432112345678')
crypto.cipher.aes192.cbc.decrypt.new('123456788765432112345678', '12345')
crypto.cipher.aes100.efb
crypto.cipher.aes256.nomode
crypto.digest.nodigest
bad_pass = '87654321123456788765432112345678'
bad_iv = '123456abcdefghijklmnopqrstuvwxyz'
ciph.decrypt(enc, bad_pass, iv)
ciph.decrypt(enc, pass, bad_iv)
......@@ -326,7 +326,8 @@ digest.aes256cbc.decrypt(digest.aes256cbc.encrypt('test123', 'passpasspasspasspa
...
digest.aes256cbc.decrypt(digest.aes256cbc.encrypt('test123', 'passpasspasspasspasspasspasspass', 'iv12tras8712cvbhuytrghjklmnbdr34'), 'nosspasspasspasspasspasspasspass', 'iv12tras8712cvbhuytrghjklmnbdr34')
---
- error: 'builtin/crypto.lua:274: Can''t finalize cipher'
- error: 'builtin/crypto.lua:304: Can''t finalize cipher:error:06065064:digital envelope
routines:EVP_DecryptFinal_ex:bad decrypt'
...
digest = nil
---
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment