Skip to content

Commit

Permalink
feat(*) initial support for OpenSSL 3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
fffonion committed May 14, 2020
1 parent 3ab9747 commit be5dc10
Show file tree
Hide file tree
Showing 30 changed files with 158 additions and 113 deletions.
10 changes: 6 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
sudo: required
dist: trusty
dist: bionic

os: linux

Expand Down Expand Up @@ -33,6 +33,8 @@ env:
- NGINX_VERSION=1.15.8 OPENSSL_VER=1.0.2u
- NGINX_VERSION=1.15.8 OPENSSL_VER=1.1.0l
- NGINX_VERSION=1.15.8 OPENSSL_VER=1.1.1g
# add -Wno-error to fix deprecation warnings from openssl
- NGINX_VERSION=1.15.8 OPENSSL_HASH=90ad284f4e76254f8d67686ae3a5d6c576037091 NGINX_CC_OPTS=-Wno-error

install:
- export NGX_BUILD_CC=$CC
Expand All @@ -53,8 +55,8 @@ install:
- git clone https://github.com/openresty/lua-resty-string ../lua-resty-string
# openssl
# openssl 1.0.2 config doesn't work correctly on a cached directory
- wget https://www.openssl.org/source/openssl-$OPENSSL_VER.tar.gz -O - | tar zxf -
- pushd openssl-$OPENSSL_VER/
- if [ "X$OPENSSL_HASH" != "X" ]; then wget https://github.com/openssl/openssl/archive/$OPENSSL_HASH.tar.gz -O - | tar zxf - ; pushd openssl-$OPENSSL_HASH/; fi
- if [ "X$OPENSSL_HASH" = "X" ] ; then wget https://www.openssl.org/source/openssl-$OPENSSL_VER.tar.gz -O - | tar zxf -; pushd openssl-$OPENSSL_VER/; fi
- if [ ! -e $OPENSSL_PREFIX/include ]; then ./config shared --prefix=$OPENSSL_PREFIX -DPURIFY > build.log 2>&1 || (cat build.log && exit 1); fi
- if [ ! -e $OPENSSL_PREFIX/include ]; then make -j$JOBS > build.log 2>&1 || (cat build.log && exit 1); fi
- if [ ! -e $OPENSSL_PREFIX/include ]; then sudo make PATH=$PATH install_sw > build.log 2>&1 || (cat build.log && exit 1); fi
Expand All @@ -71,7 +73,7 @@ install:
- if [ ! -e lua-cjson ]; then git clone https://github.com/openresty/lua-cjson.git ./lua-cjson; fi
- pushd ./lua-cjson && make && sudo PATH=$PATH make install && popd
# nginx
- if [ ! -e work ]; then ngx-build $NGINX_VERSION --add-module=../ndk-nginx-module --add-module=../lua-nginx-module --with-http_ssl_module --with-cc-opt="-I$OPENSSL_INC" --with-ld-opt="-L$OPENSSL_LIB -Wl,-rpath,$OPENSSL_LIB" --with-debug > build.log 2>&1 || (cat build.log && exit 1); fi
- if [ ! -e work ]; then ngx-build $NGINX_VERSION --add-module=../ndk-nginx-module --add-module=../lua-nginx-module --with-http_ssl_module --with-cc-opt="-I$OPENSSL_INC $NGINX_CC_OPTS" --with-ld-opt="-L$OPENSSL_LIB -Wl,-rpath,$OPENSSL_LIB" --with-debug > build.log 2>&1 || (cat build.log && exit 1); fi
- nginx -V
- ldd `which nginx`|grep -E 'luajit|ssl|pcre'
- popd
Expand Down
23 changes: 8 additions & 15 deletions examples/aes-gcm-aead.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
local function new_cipher()
return assert(require("resty.openssl.cipher").new("aes-256-gcm"))
end

local key = string.rep("0", 32)
local iv = string.rep("0", 12)

Expand All @@ -10,10 +6,9 @@ local to_be_encrypted = "secret"
local aad = "aead aad"

-- using one shot interface
local cipher = new_cipher()
local cipher = assert(require("resty.openssl.cipher").new("aes-256-gcm"))
local encrypted = assert(cipher:encrypt(key, iv, to_be_encrypted, false, aad))
-- OR using streaming interface
local cipher = new_cipher()
assert(cipher:init(key, iv, {
is_encrypt = true,
}))
Expand All @@ -26,27 +21,25 @@ local tag = assert(cipher:get_aead_tag())

ngx.say("tag is: ", ngx.encode_base64(tag))

local ok, _ = new_cipher():decrypt(key, iv, encrypted, false, nil, tag)
local ok, _ = cipher:decrypt(key, iv, encrypted, false, nil, tag)
if not ok then
ngx.say("no AAD, decryption failed")
end

local ok, _ = new_cipher():decrypt(key, iv, encrypted, false, aad, nil)
local ok, _ = cipher:decrypt(key, iv, encrypted, false, aad, nil)
if not ok then
ngx.say("no tag, decryption failed")
end

-- using one shot interface
local cipher2 = new_cipher()
local decrypted = assert(cipher2:decrypt(key, iv, encrypted, false, aad, tag))
local decrypted = assert(cipher:decrypt(key, iv, encrypted, false, aad, tag))
-- OR using streaming interface
local cipher2 = new_cipher()
assert(cipher2:init(key, iv, {
assert(cipher:init(key, iv, {
is_encrypt = false,
}))
assert(cipher2:update_aead_aad(aad))
assert(cipher2:set_aead_tag(tag))
decrypted = assert(cipher2:final(encrypted))
assert(cipher:update_aead_aad(aad))
assert(cipher:set_aead_tag(tag))
decrypted = assert(cipher:final(encrypted))

ngx.say("decryption result: ", decrypted)

7 changes: 6 additions & 1 deletion lib/resty/openssl/aux/jwk.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ local ec_lib = require "resty.openssl.ec"
local ecx_lib = require "resty.openssl.ecx"
local bn_lib = require "resty.openssl.bn"
local digest_lib = require "resty.openssl.digest"
local OPENSSL_30 = require("resty.openssl.version").OPENSSL_30

local _M = {}

Expand Down Expand Up @@ -174,7 +175,11 @@ function _M.load_jwk(txt)
end
key, err = load_jwk_okp(key_type, tbl)
if key ~= nil then
return key
if OPENSSL_30 then
return { key, key_type }
else
return key
end
end
else
return nil, "not yet supported jwk type \"" .. (tbl["kty"] or "nil") .. "\""
Expand Down
12 changes: 8 additions & 4 deletions lib/resty/openssl/cipher.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ local evp_macro = require "resty.openssl.include.evp"
local ctypes = require "resty.openssl.aux.ctypes"
local format_error = require("resty.openssl.err").format_error
local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
local OPENSSL_11 = require("resty.openssl.version").OPENSSL_11
local OPENSSL_11_OR_LATER = require("resty.openssl.version").OPENSSL_11_OR_LATER

local uchar_array = ctypes.uchar_array
local void_ptr = ctypes.void_ptr
Expand All @@ -26,7 +26,7 @@ function _M.new(typ)
end

local ctx
if OPENSSL_11 then
if OPENSSL_11_OR_LATER then
ctx = C.EVP_CIPHER_CTX_new()
ffi_gc(ctx, C.EVP_CIPHER_CTX_free)
elseif OPENSSL_10 then
Expand All @@ -50,6 +50,7 @@ function _M.new(typ)

return setmetatable({
ctx = ctx,
cipher_type = dtyp,
initialized = false,
block_size = tonumber(C.EVP_CIPHER_CTX_block_size(ctx)),
key_size = tonumber(C.EVP_CIPHER_CTX_key_length(ctx)),
Expand All @@ -70,8 +71,11 @@ function _M:init(key, iv, opts)
return false, string.format("cipher:init: incorrect iv size, expect %d", self.iv_size)
end

if C.EVP_CipherInit_ex(self.ctx, nil, nil, key, iv, opts.is_encrypt and 1 or 0) == 0 then
return false, format_error("cipher:init")
-- always passed in the `EVP_CIPHER` parameter to reinitialized the cipher
-- it will have a same effect as EVP_CIPHER_CTX_cleanup/EVP_CIPHER_CTX_reset then Init_ex with
-- empty cipher_type
if C.EVP_CipherInit_ex(self.ctx, self.cipher_type, nil, key, iv, opts.is_encrypt and 1 or 0) == 0 then
return false, format_error("cipher:init EVP_CipherInit_ex")
end

if opts.no_padding then
Expand Down
4 changes: 2 additions & 2 deletions lib/resty/openssl/digest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ local ffi_str = ffi.string
require "resty.openssl.include.evp"
local format_error = require("resty.openssl.err").format_error
local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
local OPENSSL_11 = require("resty.openssl.version").OPENSSL_11
local OPENSSL_11_OR_LATER = require("resty.openssl.version").OPENSSL_11_OR_LATER

local _M = {}
local mt = {__index = _M}
Expand All @@ -16,7 +16,7 @@ local md_ctx_ptr_ct = ffi.typeof('EVP_MD_CTX*')

function _M.new(typ)
local ctx
if OPENSSL_11 then
if OPENSSL_11_OR_LATER then
ctx = C.EVP_MD_CTX_new()
ffi_gc(ctx, C.EVP_MD_CTX_free)
elseif OPENSSL_10 then
Expand Down
16 changes: 8 additions & 8 deletions lib/resty/openssl/ecx.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ local ffi_str = ffi.string

require "resty.openssl.include.ec"
require "resty.openssl.include.evp"
local ctypes = require "resty.openssl.aux.ctypes"
local format_error = require("resty.openssl.err").format_error

local _M = {}
Expand All @@ -17,23 +18,22 @@ local MAX_ECX_KEY_SIZE = 114 -- ed448 uses 114 bytes
function _M.get_parameters(evp_pkey_st)
return setmetatable(empty_table, {
__index = function(_, k)
local buf = ffi_new('unsigned char[?]', MAX_ECX_KEY_SIZE)
local size_t_ptr = ffi_new("size_t[1]")
size_t_ptr[0] = MAX_ECX_KEY_SIZE
local buf = ffi_new(ctypes.uchar_array, MAX_ECX_KEY_SIZE)
local length = ffi_new(ctypes.ptr_of_size_t)
length[0] = MAX_ECX_KEY_SIZE

if k == 'public' or k == "pub_key" then
if C.EVP_PKEY_get_raw_public_key(evp_pkey_st, buf, size_t_ptr) ~= 1 then
return nil, format_error("ecx.get_parameters: EVP_PKEY_get_raw_private_key")
if C.EVP_PKEY_get_raw_public_key(evp_pkey_st, buf, length) ~= 1 then
error(format_error("ecx.get_parameters: EVP_PKEY_get_raw_private_key"))
end
elseif k == 'private' or k == "priv ~=_key" then
if C.EVP_PKEY_get_raw_private_key(evp_pkey_st, buf, size_t_ptr) ~= 1 then
if C.EVP_PKEY_get_raw_private_key(evp_pkey_st, buf, length) ~= 1 then
return nil, format_error("ecx.get_parameters: EVP_PKEY_get_raw_private_key")
end
else
return nil, "ecx.get_parameters: unknown parameter \"" .. k .. "\" for EC key"
end

return ffi_str(buf, size_t_ptr[0])
return ffi_str(buf, length[0])
end
}), nil
end
Expand Down
8 changes: 5 additions & 3 deletions lib/resty/openssl/hmac.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ local ffi_new = ffi.new
local ffi_str = ffi.string

require "resty.openssl.include.hmac"
local evp_macro = require "resty.openssl.include.evp"
local format_error = require("resty.openssl.err").format_error
local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
local OPENSSL_11 = require("resty.openssl.version").OPENSSL_11
local OPENSSL_11_OR_LATER = require("resty.openssl.version").OPENSSL_11_OR_LATER

local _M = {}
local mt = {__index = _M}

local hmac_ctx_ptr_ct = ffi.typeof('HMAC_CTX*')

-- Note: https://www.openssl.org/docs/manmaster/man3/HMAC_Init.html
-- Replace with EVP_MAC_* functions for OpenSSL 3.0

function _M.new(key, typ)
local ctx
if OPENSSL_11 then
if OPENSSL_11_OR_LATER then
ctx = C.HMAC_CTX_new()
ffi_gc(ctx, C.HMAC_CTX_free)
elseif OPENSSL_10 then
Expand Down
4 changes: 2 additions & 2 deletions lib/resty/openssl/include/asn1.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ declare_asn1_functions("ASN1_OBJECT")
declare_asn1_functions("ASN1_STRING")

local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
local OPENSSL_11 = require("resty.openssl.version").OPENSSL_11
local OPENSSL_11_OR_LATER = require("resty.openssl.version").OPENSSL_11_OR_LATER

local ASN1_STRING_get0_data
if OPENSSL_11 then
if OPENSSL_11_OR_LATER then
ffi.cdef[[
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
]]
Expand Down
4 changes: 2 additions & 2 deletions lib/resty/openssl/include/crypto.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ local ffi = require "ffi"
local C = ffi.C

local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
local OPENSSL_11 = require("resty.openssl.version").OPENSSL_11
local OPENSSL_11_OR_LATER = require("resty.openssl.version").OPENSSL_11_OR_LATER

local OPENSSL_free
if OPENSSL_10 then
ffi.cdef [[
void CRYPTO_free(void *ptr);
]]
OPENSSL_free = C.CRYPTO_free
elseif OPENSSL_11 then
elseif OPENSSL_11_OR_LATER then
ffi.cdef [[
void CRYPTO_free(void *ptr, const char *file, int line);
]]
Expand Down
18 changes: 15 additions & 3 deletions lib/resty/openssl/include/evp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ local bit = require("bit")
require "resty.openssl.include.ossl_typ"
require "resty.openssl.include.objects"
local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
local OPENSSL_11 = require("resty.openssl.version").OPENSSL_11
local OPENSSL_11_OR_LATER = require("resty.openssl.version").OPENSSL_11_OR_LATER
local OPENSSL_30 = require("resty.openssl.version").OPENSSL_30

ffi.cdef [[
EVP_PKEY *EVP_PKEY_new(void);
Expand Down Expand Up @@ -82,6 +83,11 @@ ffi.cdef [[
/*__owur*/ int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm,
int *outl);

// openssl 1.0.2
int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
// openssl >= 1.1.0
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx);

int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
Expand Down Expand Up @@ -118,7 +124,13 @@ ffi.cdef [[
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
]]

if OPENSSL_11 then
if OPENSSL_30 then
ffi.cdef [[
int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad_mode);
]]
end

if OPENSSL_11_OR_LATER then
ffi.cdef [[
EVP_MD_CTX *EVP_MD_CTX_new(void);
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
Expand Down Expand Up @@ -215,7 +227,7 @@ local _M = {
EVP_PKEY_X448 = ffi.C.OBJ_txt2nid("X448"),
EVP_PKEY_ED448 = ffi.C.OBJ_txt2nid("ED448"),

EVP_PKEY_OP_DERIVE = bit.lshift(1, 10),
EVP_PKEY_OP_DERIVE = OPENSSL_30 and bit.lshift(1, 12) or bit.lshift(1, 10),

EVP_PKEY_ALG_CTRL = 0x1000,
EVP_PKEY_CTRL_RSA_PADDING = 0x1000 + 1,
Expand Down
4 changes: 2 additions & 2 deletions lib/resty/openssl/include/hmac.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ local ffi = require "ffi"
require "resty.openssl.include.ossl_typ"
require "resty.openssl.include.evp"
local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
local OPENSSL_11 = require("resty.openssl.version").OPENSSL_11
local OPENSSL_11_OR_LATER = require("resty.openssl.version").OPENSSL_11_OR_LATER

ffi.cdef [[
/*__owur*/ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
Expand All @@ -14,7 +14,7 @@ ffi.cdef [[
unsigned int *len);
]]

if OPENSSL_11 then
if OPENSSL_11_OR_LATER then
ffi.cdef [[
HMAC_CTX *HMAC_CTX_new(void);
void HMAC_CTX_free(HMAC_CTX *ctx);
Expand Down
4 changes: 2 additions & 2 deletions lib/resty/openssl/include/rsa.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ local ffi = require "ffi"

require "resty.openssl.include.ossl_typ"
local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
local OPENSSL_11 = require("resty.openssl.version").OPENSSL_11
local OPENSSL_11_OR_LATER = require("resty.openssl.version").OPENSSL_11_OR_LATER

ffi.cdef [[
RSA *RSA_new(void);
void RSA_free(RSA *r);
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
]]

if OPENSSL_11 then
if OPENSSL_11_OR_LATER then
ffi.cdef [[
void RSA_get0_key(const RSA *r,
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
Expand Down
4 changes: 2 additions & 2 deletions lib/resty/openssl/include/stack.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ local C = ffi.C

require "resty.openssl.include.ossl_typ"
local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
local OPENSSL_11 = require("resty.openssl.version").OPENSSL_11
local OPENSSL_11_OR_LATER = require("resty.openssl.version").OPENSSL_11_OR_LATER

local _M = {}

ffi.cdef [[
typedef char *OPENSSL_STRING;
]]

if OPENSSL_11 then
if OPENSSL_11_OR_LATER then
ffi.cdef [[
typedef struct stack_st OPENSSL_STACK;

Expand Down
4 changes: 2 additions & 2 deletions lib/resty/openssl/include/x509/crl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require "resty.openssl.include.stack"
local asn1_macro = require "resty.openssl.include.asn1"

local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
local OPENSSL_11 = require("resty.openssl.version").OPENSSL_11
local OPENSSL_11_OR_LATER = require("resty.openssl.version").OPENSSL_11_OR_LATER

asn1_macro.declare_asn1_functions("X509_CRL")

Expand All @@ -30,7 +30,7 @@ ffi.cdef [[
X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl);
]]

if OPENSSL_11 then
if OPENSSL_11_OR_LATER then
ffi.cdef [[
int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm);
int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm);
Expand Down
Loading

0 comments on commit be5dc10

Please sign in to comment.