diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compat52.h | 10 | ||||
-rw-r--r-- | src/openssl.c | 218 |
2 files changed, 191 insertions, 37 deletions
diff --git a/src/compat52.h b/src/compat52.h index 0057b3c..163aecb 100644 --- a/src/compat52.h +++ b/src/compat52.h @@ -23,6 +23,14 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. * ========================================================================== */ + + +#if LUA_VERSION_NUM < 503 + +#define lua_getfield(L, i, f) (lua_getfield(L, (i), (f)), lua_type(L, -1)) + +#endif + #if LUA_VERSION_NUM < 502 #define LUA_OK 0 @@ -86,7 +94,7 @@ static void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf lua_setfield(L, -2, modname); lua_pop(L, 2); - + if (glb) { lua_pushvalue(L, -1); lua_setglobal(L, modname); diff --git a/src/openssl.c b/src/openssl.c index e8dbead..e902edf 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -75,9 +75,7 @@ #include <lualib.h> #include <lauxlib.h> -#if LUA_VERSION_NUM < 502 #include "compat52.h" -#endif #define GNUC_2VER(M, m, p) (((M) * 10000) + ((m) * 100) + (p)) #define GNUC_PREREQ(M, m, p) (__GNUC__ > 0 && GNUC_2VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) >= GNUC_2VER((M), (m), (p))) @@ -315,6 +313,10 @@ #define HAVE_SSLV2_SERVER_METHOD (!OPENSSL_PREREQ(1,1,0) && !defined OPENSSL_NO_SSL2) #endif +#ifndef HAVE_X509_GET_SIGNATURE_NID +#define HAVE_X509_GET_SIGNATURE_NID OPENSSL_PREREQ(1,0,2) +#endif + #ifndef HAVE_X509_STORE_REFERENCES #define HAVE_X509_STORE_REFERENCES (!OPENSSL_PREREQ(1,1,0)) #endif @@ -1630,6 +1632,10 @@ static int compat_SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) { #define X509_get0_ext(crt, i) X509_get_ext((crt), (i)) #endif +#if !HAVE_X509_GET_SIGNATURE_NID +#define X509_get_signature_nid(crt) OBJ_obj2nid((crt)->sig_alg->algorithm) +#endif + #if !HAVE_X509_CRL_GET0_EXT #define X509_CRL_get0_ext(crt, i) X509_CRL_get_ext((crt), (i)) #endif @@ -3077,6 +3083,7 @@ static int pk_new(lua_State *L) { unsigned exp = 65537; int curve = NID_X9_62_prime192v1; const char *id; + const char *dhparam = NULL; lua_Number n; if (!lua_istable(L, 1)) @@ -3118,6 +3125,9 @@ static int pk_new(lua_State *L) { luaL_argerror(L, 1, lua_pushfstring(L, "%s: invalid curve", id)); } + /* dhparam field can contain a PEM encoded string. */ + loadfield(L, 1, "dhparam", LUA_TSTRING, &dhparam); + creat: if (!(*ud = EVP_PKEY_new())) return auxL_error(L, auxL_EOPENSSL, "pkey.new"); @@ -3155,9 +3165,23 @@ creat: case EVP_PKEY_DH: { DH *dh; - if (!(dh = DH_generate_parameters(bits, exp, 0, 0))) + /* DH Parameter Generation can take a long time, therefore we look + * at the "dhparam" field, provided by the user. + * The "dhparam" field takes precedence over "bits" + */ + if (dhparam) { + BIO *bio = BIO_new_mem_buf((void*)dhparam, strlen(dhparam)); + if (!bio) + return auxL_error(L, auxL_EOPENSSL, "pkey.new"); + + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (!dh) + return auxL_error(L, auxL_EOPENSSL, "pkey.new"); + } else if (!(dh = DH_generate_parameters(bits, exp, 0, 0))) return auxL_error(L, auxL_EOPENSSL, "pkey.new"); + if (!DH_generate_key(dh)) { DH_free(dh); return auxL_error(L, auxL_EOPENSSL, "pkey.new"); @@ -4973,6 +4997,25 @@ static _Bool xe_new_isder(const char *value, _Bool *crit) { return 0; } /* xs_new_isder() */ +static CONF* loadconf(lua_State *L, int idx) { + CONF *conf; + size_t len; + const char *cdata = luaL_checklstring(L, idx, &len); + BIO *bio = getbio(L); + if (BIO_write(bio, cdata, len) < 0) + return NULL; + + if (!(conf = NCONF_new(NULL))) + return NULL; + + if (!NCONF_load_bio(conf, bio, NULL)) { + NCONF_free(conf); + return NULL; + } + + return conf; +} + static int xe_new(lua_State *L) { const char *name = luaL_checkstring(L, 1); const char *value = luaL_checkstring(L, 2); @@ -4981,42 +5024,87 @@ static int xe_new(lua_State *L) { CONF *conf = NULL; X509V3_CTX cbuf = { 0 }, *ctx = NULL; X509_EXTENSION **ud; + _Bool crit; lua_settop(L, 3); ud = prepsimple(L, X509_EXT_CLASS); - if (!lua_isnil(L, 3)) { + if (xe_new_isder(value, &crit)) { size_t len; - const char *cdata = luaL_checklstring(L, 3, &len); - _Bool crit; + const char *cdata = lua_tolstring(L, 3, &len); + if (!(obj = OBJ_txt2obj(name, 0))) + goto error; + if (!(oct = ASN1_STRING_new())) + goto error; + if (!ASN1_STRING_set(oct, cdata, len)) + goto error; + if (!(*ud = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct))) + goto error; - if (xe_new_isder(value, &crit)) { - if (!(obj = OBJ_txt2obj(name, 0))) - goto error; - if (!(oct = ASN1_STRING_new())) - goto error; - if (!ASN1_STRING_set(oct, cdata, len)) - goto error; - if (!(*ud = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct))) + ASN1_OBJECT_free(obj); + ASN1_STRING_free(oct); + + return 1; + } + + switch (lua_type(L, 3)) { + case LUA_TNONE: + case LUA_TNIL: + break; + case LUA_TSTRING: { + if (!(conf = loadconf(L, 3))) + goto error; + + ctx = &cbuf; + X509V3_set_nconf(ctx, conf); + break; + } + case LUA_TTABLE: { + X509 *issuer = NULL; + X509 *subject = NULL; + X509_REQ *request = NULL; + X509_CRL *crl = NULL; + int flags = 0; + + ctx = &cbuf; + + if (lua_getfield(L, 3, "db") != LUA_TNIL) { + if (!(conf = loadconf(L, -1))) goto error; + X509V3_set_nconf(ctx, conf); + } + lua_pop(L, 1); + + if (lua_getfield(L, 3, "issuer") != LUA_TNIL) { + issuer = checksimple(L, -1, X509_CERT_CLASS); + } + lua_pop(L, 1); - ASN1_OBJECT_free(obj); - ASN1_STRING_free(oct); + if (lua_getfield(L, 3, "subject") != LUA_TNIL) { + subject = checksimple(L, -1, X509_CERT_CLASS); + } + lua_pop(L, 1); - return 1; + if (lua_getfield(L, 3, "request") != LUA_TNIL) { + request = checksimple(L, -1, X509_CSR_CLASS); } + lua_pop(L, 1); - BIO *bio = getbio(L); - if (BIO_puts(bio, cdata) < 0) - goto error; + if (lua_getfield(L, 3, "crl") != LUA_TNIL) { + crl = checksimple(L, -1, X509_CRL_CLASS); + } + lua_pop(L, 1); - if (!(conf = NCONF_new(NULL))) - goto error; - if (!NCONF_load_bio(conf, bio, NULL)) - goto error; + if (lua_getfield(L, 3, "flags") != LUA_TNIL) { + flags = luaL_checkinteger(L, -1); + } + lua_pop(L, 1); - ctx = &cbuf; - X509V3_set_nconf(ctx, conf); + X509V3_set_ctx(ctx, issuer, subject, request, crl, flags); + break; + } + default: + return luaL_argerror(L, 3, "invalid extra parameter (expected string, table or nil)"); } /* @@ -6066,23 +6154,17 @@ static int xc_getPublicKeyDigest(lua_State *L) { } /* xc_getPublicKeyDigest() */ -#if 0 -/* - * TODO: X509_get_signature_type always seems to return NID_undef. Are we - * using it wrong or is it broken? - */ static int xc_getSignatureName(lua_State *L) { X509 *crt = checksimple(L, 1, X509_CERT_CLASS); int nid; - if (NID_undef == (nid = X509_get_signature_type(crt))) + if (NID_undef == (nid = X509_get_signature_nid(crt))) return 0; auxL_pushnid(L, nid); return 1; } /* xc_getSignatureName() */ -#endif static int xc_sign(lua_State *L) { @@ -6230,9 +6312,7 @@ static const auxL_Reg xc_methods[] = { { "getPublicKey", &xc_getPublicKey }, { "setPublicKey", &xc_setPublicKey }, { "getPublicKeyDigest", &xc_getPublicKeyDigest }, -#if 0 { "getSignatureName", &xc_getSignatureName }, -#endif { "sign", &xc_sign }, { "text", &xc_text }, { "tostring", &xc__tostring }, @@ -6680,7 +6760,7 @@ static int xx_getNextUpdate(lua_State *L) { updateby = timeutc(time); if (isfinite(updateby)) - lua_pushnumber(L, 1); + lua_pushnumber(L, updateby); else lua_pushnil(L); @@ -6870,6 +6950,19 @@ static int xx_sign(lua_State *L) { } /* xx_sign() */ +static int xx_verify(lua_State *L) { + X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); + EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS); + + if (!X509_CRL_verify(crl, key)) + return auxL_error(L, auxL_EOPENSSL, "x509.crl:verify"); + + lua_pushboolean(L, 1); + + return 1; +} /* xx_verify() */ + + static int xx_text(lua_State *L) { X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); @@ -6939,6 +7032,7 @@ static const auxL_Reg xx_methods[] = { { "getExtension", &xx_getExtension }, { "getExtensionCount", &xx_getExtensionCount }, { "sign", &xx_sign }, + { "verify", &xx_verify }, { "text", &xx_text }, { "tostring", &xx__tostring }, { NULL, NULL }, @@ -7466,6 +7560,57 @@ static int p12_interpose(lua_State *L) { } /* p12_interpose() */ +static int p12_parse(lua_State *L) { + /* parse a p12 binary string and return the parts */ + PKCS12 *p12; + + /* gather input parameters */ + size_t len; + const char *blob = luaL_checklstring(L, 1, &len); + const char *passphrase = luaL_optstring(L, 2, NULL); + + /* prepare return values */ + EVP_PKEY **ud_pkey = prepsimple(L, PKEY_CLASS); + X509 **ud_cert = prepsimple(L, X509_CERT_CLASS); + STACK_OF(X509) **ud_chain = prepsimple(L, X509_CHAIN_CLASS); + /* Note: *ud_chain must be initialised to NULL, which prepsimple does. */ + + /* read PKCS#12 data into OpenSSL memory buffer */ + BIO *bio = BIO_new_mem_buf((void*)blob, len); + if (!bio) + return auxL_error(L, auxL_EOPENSSL, "pkcs12.parse"); + p12 = d2i_PKCS12_bio(bio, NULL); + BIO_free(bio); + if (!p12) + return auxL_error(L, auxL_EOPENSSL, "pkcs12.parse"); + + /* the p12 pointer holds the data we're interested in */ + int rc = PKCS12_parse(p12, passphrase, ud_pkey, ud_cert, ud_chain); + PKCS12_free(p12); + if (!rc) + auxL_error(L, auxL_EOPENSSL, "pkcs12.parse"); + + /* replace the return values by nil if the ud pointers are NULL */ + if (*ud_pkey == NULL) { + lua_pushnil(L); + lua_replace(L, -4); + } + + if (*ud_cert == NULL) { + lua_pushnil(L); + lua_replace(L, -3); + } + + /* other certificates (a chain, STACK_OF(X509) *) */ + if (*ud_chain == NULL) { + lua_pop(L, 1); + lua_pushnil(L); + } + + return 3; +} /* p12_parse() */ + + static int p12__tostring(lua_State *L) { PKCS12 *p12 = checksimple(L, 1, PKCS12_CLASS); BIO *bio = getbio(L); @@ -7509,6 +7654,7 @@ static const auxL_Reg p12_metatable[] = { static const auxL_Reg p12_globals[] = { { "new", &p12_new }, { "interpose", &p12_interpose }, + { "parse", &p12_parse }, { NULL, NULL }, }; |