aboutsummaryrefslogtreecommitdiffstats
path: root/openssl.c
diff options
context:
space:
mode:
authorLibravatarLibravatar William Ahern <william@server.local> 2012-10-08 22:41:26 -0700
committerLibravatarLibravatar William Ahern <william@server.local> 2012-10-08 22:41:26 -0700
commit175b7db5f19623158f74f068f1a6d67f59bbc533 (patch)
treecbfb1da3688ac998f947a593bad8b30895e26198 /openssl.c
parentee4377fd20153de610f77bc2a355bba4834c1097 (diff)
downloadluaossl-175b7db5f19623158f74f068f1a6d67f59bbc533.tar.gz
luaossl-175b7db5f19623158f74f068f1a6d67f59bbc533.tar.bz2
luaossl-175b7db5f19623158f74f068f1a6d67f59bbc533.zip
-n
add some key bindings
Diffstat (limited to 'openssl.c')
-rw-r--r--openssl.c744
1 files changed, 723 insertions, 21 deletions
diff --git a/openssl.c b/openssl.c
index a3103b0..e870b0f 100644
--- a/openssl.c
+++ b/openssl.c
@@ -48,10 +48,12 @@
#include <lauxlib.h>
+#define BIGNUM_CLASS "OpenSSL BN"
+#define PUBKEY_CLASS "OpenSSL PK"
#define X509_NAME_CLASS "OpenSSL X.509 Name"
#define X509_GENS_CLASS "OpenSSL X.509 AltName"
#define X509_CERT_CLASS "OpenSSL X.509 Cert"
-#define BIGNUM_CLASS "OpenSSL BN"
+#define X509_CSR_CLASS "OpenSSL X.509 Request"
#define countof(a) (sizeof (a) / sizeof *(a))
@@ -109,13 +111,32 @@ static void *checksimple(lua_State *L, int index, const char *tname) {
} /* checksimple() */
+static void *testsimple(lua_State *L, int index, const char *tname) {
+ void **p;
+
+ if (tname) {
+ p = luaL_testudata(L, index, tname);
+ } else {
+ luaL_checktype(L, index, LUA_TUSERDATA);
+ p = lua_touserdata(L, index);
+ }
+
+ return *p;
+} /* testsimple() */
+
+
static int throwssl(lua_State *L, const char *fun) {
unsigned long code;
- const char *file;
+ const char *path, *file;
int line;
char txt[256];
- code = ERR_get_error_line(&file, &line);
+ code = ERR_get_error_line(&path, &line);
+ if ((file = strrchr(path, '/')))
+ ++file;
+ else
+ file = path;
+
ERR_clear_error();
ERR_error_string_n(code, txt, sizeof txt);
@@ -167,6 +188,63 @@ static int checkoption(struct lua_State *L, int index, const char *def, const ch
} /* checkoption() */
+static _Bool getfield(lua_State *L, int index, const char *k) {
+ lua_getfield(L, index, k);
+
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+
+ return 0;
+ } else {
+ return 1;
+ }
+} /* getfield() */
+
+
+static _Bool loadfield(lua_State *L, int index, const char *k, int type, void *p) {
+ if (!getfield(L, index, k))
+ return 0;
+
+ switch (type) {
+ case LUA_TSTRING:
+ *(const char **)p = luaL_checkstring(L, -1);
+ break;
+ case LUA_TNUMBER:
+ *(lua_Number *)p = luaL_checknumber(L, -1);
+ break;
+ default:
+ luaL_error(L, "loadfield(type=%d): invalid type", type);
+ break;
+ } /* switch() */
+
+ lua_pop(L, 1); /* table keeps reference */
+
+ return 1;
+} /* loadfield() */
+
+
+const char *pushnid(lua_State *L, int nid) {
+ const char *txt;
+ ASN1_OBJECT *obj;
+ char buf[256];
+ int len;
+
+ if ((txt = OBJ_nid2sn(nid)) || (txt = OBJ_nid2ln(nid))) {
+ lua_pushstring(L, txt);
+ } else {
+ if (!(obj = OBJ_nid2obj(nid)))
+ luaL_error(L, "%d: unknown ASN.1 NID", nid);
+
+ if (-1 == (len = OBJ_obj2txt(buf, sizeof buf, obj, 1)))
+ luaL_error(L, "%d: invalid ASN.1 NID", nid);
+
+ lua_pushlstring(L, buf, len);
+ }
+
+ return lua_tostring(L, -1);
+} /* pushnid() */
+
+
static void initall(lua_State *L);
@@ -369,7 +447,6 @@ static BN_CTX *getctx(lua_State *L) {
lua_pushcfunction(L, &ctx__gc);
lua_pushvalue(L, -2);
lua_settable(L, LUA_REGISTRYINDEX);
-
}
ctx = lua_touserdata(L, -1);
@@ -555,6 +632,454 @@ int luaopen__openssl_bignum(lua_State *L) {
/*
+ * EVP_PKEY - openssl.pubkey
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+static int bio__gc(lua_State *L) {
+ BIO **bio = lua_touserdata(L, 1);
+
+ BIO_free(*bio);
+ *bio = NULL;
+
+ return 0;
+} /* bio__gc() */
+
+static BIO *getbio(lua_State *L) {
+ BIO **bio;
+
+ lua_pushcfunction(L, &bio__gc);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+
+ bio = prepsimple(L, NULL, &bio__gc);
+
+ if (!(*bio = BIO_new(BIO_s_mem())))
+ throwssl(L, "BIO_new");
+
+ lua_pushcfunction(L, &bio__gc);
+ lua_pushvalue(L, -2);
+ lua_settable(L, LUA_REGISTRYINDEX);
+ }
+
+ bio = lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ BIO_reset(*bio);
+
+ return *bio;
+} /* getbio() */
+
+
+static int pk_new(lua_State *L) {
+ EVP_PKEY **ud;
+
+ lua_settop(L, 1);
+
+ ud = prepsimple(L, PUBKEY_CLASS);
+
+ if (lua_istable(L, 1)) {
+ int type = EVP_PKEY_RSA;
+ unsigned bits = 1024;
+ unsigned exp = 65537;
+ int curve = NID_X9_62_prime192v1;
+ const char *id;
+ lua_Number n;
+
+ if (!lua_istable(L, 1))
+ goto creat;
+
+ if (loadfield(L, 1, "type", LUA_TSTRING, &id)) {
+ static const struct { int nid; const char *sn; } types[] = {
+ { EVP_PKEY_RSA, "RSA" },
+ { EVP_PKEY_DSA, "DSA" },
+ { EVP_PKEY_DH, "DH" },
+ { EVP_PKEY_EC, "EC" },
+ };
+ unsigned i;
+
+ type = OBJ_sn2nid(id);
+
+ if (NID_undef == (type = EVP_PKEY_type(OBJ_sn2nid(id)))) {
+ for (i = 0; i < countof(types); i++) {
+ if (strieq(id, types[i].sn)) {
+ type = types[i].nid;
+ break;
+ }
+ }
+ }
+
+ luaL_argcheck(L, type != NID_undef, 1, lua_pushfstring(L, "%s: invalid key type", id));
+ }
+
+ if (loadfield(L, 1, "bits", LUA_TNUMBER, &n)) {
+ luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `bits' invalid", n));
+ bits = (unsigned)n;
+ }
+
+ if (loadfield(L, 1, "exp", LUA_TNUMBER, &n)) {
+ luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `exp' invalid", n));
+ exp = (unsigned)n;
+ }
+
+ if (loadfield(L, 1, "curve", LUA_TSTRING, &id)) {
+ curve = OBJ_sn2nid(id);
+ luaL_argcheck(L, curve != NID_undef, 1, lua_pushfstring(L, "%s: invalid curve", id));
+ }
+
+creat:
+ if (!(*ud = EVP_PKEY_new()))
+ return throwssl(L, "pubkey.new");
+
+ switch (EVP_PKEY_type(type)) {
+ case EVP_PKEY_RSA: {
+ RSA *rsa;
+
+ if (!(rsa = RSA_generate_key(bits, exp, 0, 0)))
+ return throwssl(L, "pubkey.new");
+
+ EVP_PKEY_set1_RSA(*ud, rsa);
+
+ RSA_free(rsa);
+
+ break;
+ }
+ case EVP_PKEY_DSA: {
+ DSA *dsa;
+
+ if (!(dsa = DSA_generate_parameters(bits, 0, 0, 0, 0, 0, 0)))
+ return throwssl(L, "pubkey.new");
+
+ if (!DSA_generate_key(dsa)) {
+ DSA_free(dsa);
+ return throwssl(L, "pubkey.new");
+ }
+
+ EVP_PKEY_set1_DSA(*ud, dsa);
+
+ DSA_free(dsa);
+
+ break;
+ }
+ case EVP_PKEY_DH: {
+ DH *dh;
+
+ if (!(dh = DH_generate_parameters(bits, exp, 0, 0)))
+ return throwssl(L, "pubkey.new");
+
+ if (!DH_generate_key(dh)) {
+ DH_free(dh);
+ return throwssl(L, "pubkey.new");
+ }
+
+ EVP_PKEY_set1_DH(*ud, dh);
+
+ DH_free(dh);
+
+ break;
+ }
+ case EVP_PKEY_EC: {
+ EC_GROUP *grp;
+ EC_KEY *key;
+
+ if (!(grp = EC_GROUP_new_by_curve_name(curve)))
+ return throwssl(L, "pubkey.new");
+
+ EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_NAMED_CURVE);
+
+ /* compressed points patented */
+ EC_GROUP_set_point_conversion_form(grp, POINT_CONVERSION_UNCOMPRESSED);
+
+ if (!(key = EC_KEY_new())) {
+ EC_GROUP_free(grp);
+ return throwssl(L, "pubkey.new");
+ }
+
+ EC_KEY_set_group(key, grp);
+
+ EC_GROUP_free(grp);
+
+ if (!EC_KEY_generate_key(key)) {
+ EC_KEY_free(key);
+ return throwssl(L, "pubkey.new");
+ }
+
+ EVP_PKEY_set1_EC_KEY(*ud, key);
+
+ EC_KEY_free(key);
+
+ break;
+ }
+ default:
+ return luaL_error(L, "%d: unknown EVP base type (%d)", EVP_PKEY_type(type), type);
+ } /* switch() */
+ } else {
+ const char *pem;
+ size_t len;
+ BIO *bio;
+ int ok;
+
+ if (!(*ud = EVP_PKEY_new()))
+ return throwssl(L, "pubkey.new");
+
+ switch (lua_type(L, 1)) {
+ case LUA_TSTRING:
+ pem = luaL_checklstring(L, 1, &len);
+
+ if (!(bio = BIO_new_mem_buf((void *)pem, len)))
+ return throwssl(L, "pubkey.new");
+
+ if (strstr(pem, "PUBLIC KEY")) {
+ ok = !!PEM_read_bio_PUBKEY(bio, ud, 0, 0);
+ } else {
+ ok = !!PEM_read_bio_PrivateKey(bio, ud, 0, 0);
+ }
+
+ BIO_free(bio);
+
+ if (!ok)
+ return throwssl(L, "pubkey.new");
+
+ break;
+ default:
+ return luaL_error(L, "%s: unknown key initializer", lua_typename(L, lua_type(L, 1)));
+ } /* switch() */
+ }
+
+ return 1;
+} /* pk_new() */
+
+
+static int pk_interpose(lua_State *L) {
+ return interpose(L, X509_NAME_CLASS);
+} /* pk_interpose() */
+
+
+static int pk_type(lua_State *L) {
+ EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS);
+ int nid = key->type;
+
+ pushnid(L, nid);
+
+ return 1;
+} /* pk_type() */
+
+
+static int pk_setPublicKey(lua_State *L) {
+ EVP_PKEY **key = luaL_checkudata(L, 1, PUBKEY_CLASS);
+ const char *pem;
+ size_t len;
+ BIO *bio;
+ int ok;
+
+ lua_settop(L, 2);
+
+ pem = luaL_checklstring(L, 2, &len);
+
+ if (!(bio = BIO_new_mem_buf((void *)pem, len)))
+ return throwssl(L, "pubkey.new");
+
+ ok = !!PEM_read_bio_PUBKEY(bio, key, 0, 0);
+
+ BIO_free(bio);
+
+ if (!ok)
+ return throwssl(L, "pubkey.new");
+
+ lua_pushboolean(L, 1);
+
+ return 1;
+} /* pk_setPublicKey() */
+
+
+static int pk_setPrivateKey(lua_State *L) {
+ EVP_PKEY **key = luaL_checkudata(L, 1, PUBKEY_CLASS);
+ const char *pem;
+ size_t len;
+ BIO *bio;
+ int ok;
+
+ lua_settop(L, 2);
+
+ pem = luaL_checklstring(L, 2, &len);
+
+ if (!(bio = BIO_new_mem_buf((void *)pem, len)))
+ return throwssl(L, "pubkey.new");
+
+ ok = !!PEM_read_bio_PrivateKey(bio, key, 0, 0);
+
+ BIO_free(bio);
+
+ if (!ok)
+ return throwssl(L, "pubkey.new");
+
+ lua_pushboolean(L, 1);
+
+ return 1;
+} /* pk_setPrivateKEY() */
+
+
+static int pk_toPEM(lua_State *L) {
+ EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS);
+ int top, i, ok;
+ BIO *bio;
+ char *pem;
+ long len;
+
+ if (1 == (top = lua_gettop(L))) {
+ lua_pushstring(L, "publickey");
+ ++top;
+ }
+
+ bio = getbio(L);
+
+ for (i = 2; i <= top; i++) {
+ static const char *opts[] = {
+ "public", "PublicKey",
+ "private", "PrivateKey",
+// "params", "Parameters",
+ };
+
+ switch (checkoption(L, i, NULL, opts)) {
+ case 0: case 1:
+ if (!PEM_write_bio_PUBKEY(bio, key))
+ return throwssl(L, "pubkey:__tostring");
+
+ len = BIO_get_mem_data(bio, &pem);
+ lua_pushlstring(L, pem, len);
+
+ BIO_reset(bio);
+ break;
+ case 2: case 3:
+ if (!PEM_write_bio_PrivateKey(bio, key, 0, 0, 0, 0, 0))
+ throwssl(L, "pubkey:__tostring");
+
+ len = BIO_get_mem_data(bio, &pem);
+ lua_pushlstring(L, pem, len);
+
+ break;
+ case 4: case 5:
+ /* EVP_PKEY_base_id not in OS X */
+ switch (EVP_PKEY_type(key->type)) {
+ case EVP_PKEY_RSA:
+ break;
+ case EVP_PKEY_DSA: {
+ DSA *dsa = EVP_PKEY_get1_DSA(key);
+
+ ok = !!PEM_write_bio_DSAparams(bio, dsa);
+
+ DSA_free(dsa);
+
+ if (!ok)
+ return throwssl(L, "pubkey:__tostring");
+
+ break;
+ }
+ case EVP_PKEY_DH: {
+ DH *dh = EVP_PKEY_get1_DH(key);
+
+ ok = !!PEM_write_bio_DHparams(bio, dh);
+
+ DH_free(dh);
+
+ if (!ok)
+ return throwssl(L, "pubkey:__tostring");
+
+ break;
+ }
+ case EVP_PKEY_EC: {
+ EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
+ const EC_GROUP *grp = EC_KEY_get0_group(ec);
+
+ ok = !!PEM_write_bio_ECPKParameters(bio, grp);
+
+ EC_KEY_free(ec);
+
+ if (!ok)
+ return throwssl(L, "pubkey:__tostring");
+
+ break;
+ }
+ default:
+ return luaL_error(L, "%d: unknown EVP base type", EVP_PKEY_type(key->type));
+ }
+
+ lua_pushlstring(L, pem, len);
+
+ BIO_reset(bio);
+
+ break;
+ default:
+ lua_pushnil(L);
+
+ break;
+ } /* switch() */
+ } /* for() */
+
+ return lua_gettop(L) - top;
+} /* pk_toPEM() */
+
+
+static int pk__tostring(lua_State *L) {
+ EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS);
+ BIO *bio = getbio(L);
+ char *pem;
+ long len;
+ int ok;
+
+ if (!PEM_write_bio_PUBKEY(bio, key))
+ return throwssl(L, "pubkey:__tostring");
+
+ len = BIO_get_mem_data(bio, &pem);
+ lua_pushlstring(L, pem, len);
+
+ return 1;
+} /* pk__tostring() */
+
+
+static int pk__gc(lua_State *L) {
+ EVP_PKEY **ud = luaL_checkudata(L, 1, PUBKEY_CLASS);
+
+ EVP_PKEY_free(*ud);
+ *ud = NULL;
+
+ return 0;
+} /* pk__gc() */
+
+
+static const luaL_Reg pk_methods[] = {
+ { "type", &pk_type },
+ { "setPublicKey", &pk_setPublicKey },
+ { "setPrivateKey", &pk_setPrivateKey },
+ { "toPEM", &pk_toPEM },
+ { NULL, NULL },
+};
+
+static const luaL_Reg pk_metatable[] = {
+ { "__tostring", &pk__tostring },
+ { "__gc", &pk__gc },
+ { NULL, NULL },
+};
+
+
+static const luaL_Reg pk_globals[] = {
+ { "new", &pk_new },
+ { "interpose", &pk_interpose },
+ { NULL, NULL },
+};
+
+int luaopen__openssl_pubkey(lua_State *L) {
+ initall(L);
+
+ luaL_newlib(L, pk_globals);
+
+ return 1;
+} /* luaopen__openssl_pubkey() */
+
+
+/*
* X509_NAME - openssl.x509.name
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -1365,7 +1890,9 @@ static int xc_getIssuer(lua_State *L) {
if ((name = X509_get_issuer_name(crt)))
xn_dup(L, name);
- return !!name;
+ lua_pushboolean(L, 1);
+
+ return 1;
} /* xc_getIssuer() */
@@ -1376,7 +1903,9 @@ static int xc_setIssuer(lua_State *L) {
if (!X509_set_issuer_name(crt, name))
return throwssl(L, "x509.cert:setIssuer");
- return !!name;
+ lua_pushboolean(L, 1);
+
+ return 1;
} /* xc_setIssuer() */
@@ -1387,7 +1916,9 @@ static int xc_getSubject(lua_State *L) {
if ((name = X509_get_subject_name(crt)))
xn_dup(L, name);
- return !!name;
+ lua_pushboolean(L, 1);
+
+ return 1;
} /* xc_getSubject() */
@@ -1398,7 +1929,9 @@ static int xc_setSubject(lua_State *L) {
if (!X509_set_subject_name(crt, name))
return throwssl(L, "x509.cert:setSubject");
- return !!name;
+ lua_pushboolean(L, 1);
+
+ return 1;
} /* xc_setSubject() */
@@ -1669,30 +2202,44 @@ static int xc_setBasicConstraintsCritical(lua_State *L) {
} /* xc_setBasicConstraintsCritical() */
+static int xc_getPublicKey(lua_State *L) {
+ X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
+ EVP_PKEY **key = prepsimple(L, PUBKEY_CLASS);
+
+ if (!(*key = X509_get_pubkey(crt)))
+ return throwssl(L, "x509.cert:getPublicKey");
+
+ return 1;
+} /* xc_getPublicKey() */
+
+
+static int xc_setPublicKey(lua_State *L) {
+ X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
+ EVP_PKEY *key = checksimple(L, 2, PUBKEY_CLASS);
+
+ if (!X509_set_pubkey(crt, key))
+ return throwssl(L, "x509.cert:setPublicKey");
+
+ lua_pushboolean(L, 1);
+
+ return 1;
+} /* xc_setPublicKey() */
+
+
static int xc__tostring(lua_State *L) {
X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
int fmt = checkoption(L, 2, "pem", (const char *[]){ "pem", 0 });
- BIO *tmp;
+ BIO *bio = getbio(L);
char *pem;
long len;
- if (!(tmp = BIO_new(BIO_s_mem())))
- return throwssl(L, "x509.cert:__tostring");
-
- if (!PEM_write_bio_X509(tmp, crt)) {
- BIO_free(tmp);
-
+ if (!PEM_write_bio_X509(bio, crt))
return throwssl(L, "x509.cert:__tostring");
- }
- len = BIO_get_mem_data(tmp, &pem);
-
- /* FIXME: leaks on panic */
+ len = BIO_get_mem_data(bio, &pem);
lua_pushlstring(L, pem, len);
- BIO_free(tmp);
-
return 1;
} /* xc__tostring() */
@@ -1733,6 +2280,8 @@ static const luaL_Reg xc_methods[] = {
{ "setBasicConstraint", &xc_setBasicConstraint },
{ "getBasicConstraintsCritical", &xc_getBasicConstraintsCritical },
{ "setBasicConstraintsCritical", &xc_setBasicConstraintsCritical },
+ { "getPublicKey", &xc_getPublicKey },
+ { "setPublicKey", &xc_setPublicKey },
{ NULL, NULL },
};
@@ -1758,14 +2307,167 @@ int luaopen__openssl_x509_cert(lua_State *L) {
} /* luaopen__openssl_x509_cert() */
+/*
+ * X509_REQ - openssl.x509.csr
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+static int xr_new(lua_State *L) {
+ const char *pem;
+ size_t len;
+ X509_REQ **ud;
+ X509 *crt;
+
+ lua_settop(L, 1);
+
+ ud = prepsimple(L, X509_CSR_CLASS);
+
+ if ((crt = testsimple(L, 1, X509_CERT_CLASS))) {
+ if (!(*ud = X509_to_X509_REQ(crt, 0, 0)))
+ return throwssl(L, "x509.csr.new");
+ } else if ((pem = luaL_optlstring(L, 1, NULL, &len))) {
+ BIO *tmp;
+ int ok;
+
+ if (!(tmp = BIO_new_mem_buf((char *)pem, len)))
+ return throwssl(L, "x509.csr.new");
+
+ ok = !!PEM_read_bio_X509_REQ(tmp, ud, 0, ""); /* no password */
+
+ BIO_free(tmp);
+
+ if (!ok)
+ return throwssl(L, "x509.csr.new");
+ } else {
+ if (!(*ud = X509_REQ_new()))
+ return throwssl(L, "x509.csr.new");
+ }
+
+ return 1;
+} /* xr_new() */
+
+
+static int xr_interpose(lua_State *L) {
+ return interpose(L, X509_CSR_CLASS);
+} /* xr_interpose() */
+
+
+static int xr_getVersion(lua_State *L) {
+ X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
+
+ lua_pushinteger(L, X509_REQ_get_version(csr) + 1);
+
+ return 1;
+} /* xr_getVersion() */
+
+
+static int xr_setVersion(lua_State *L) {
+ X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
+ int version = luaL_checkint(L, 2);
+
+ if (!X509_REQ_set_version(csr, version - 1))
+ return luaL_error(L, "x509.csr:setVersion: %d: invalid version", version);
+
+ lua_pushboolean(L, 1);
+
+ return 1;
+} /* xr_setVersion() */
+
+
+static int xr_setSubjectName(lua_State *L) {
+ X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
+ X509_NAME *name = checksimple(L, 2, X509_NAME_CLASS);
+
+ if (!X509_REQ_set_subject_name(csr, name))
+ return throwssl(L, "x509.csr:setSubject");
+
+ lua_pushboolean(L, 1);
+
+ return 1;
+} /* xr_setSubjectName() */
+
+
+static int xr_setPublicKey(lua_State *L) {
+ X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
+ EVP_PKEY *key = checksimple(L, 2, PUBKEY_CLASS);
+
+ if (!X509_REQ_set_pubkey(csr, key))
+ return throwssl(L, "x509.csr:setPublicKey");
+
+ lua_pushboolean(L, 1);
+
+ return 1;
+} /* xr_setPublicKey() */
+
+
+static int xr__tostring(lua_State *L) {
+ X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
+ int fmt = checkoption(L, 2, "pem", (const char *[]){ "pem", 0 });
+ BIO *bio = getbio(L);
+ char *pem;
+ long len;
+
+ if (!PEM_write_bio_X509_REQ(bio, csr))
+ return throwssl(L, "x509.csr:__tostring");
+
+ len = BIO_get_mem_data(bio, &pem);
+
+ lua_pushlstring(L, pem, len);
+
+ return 1;
+} /* xr__tostring() */
+
+
+static int xr__gc(lua_State *L) {
+ X509_REQ **ud = luaL_checkudata(L, 1, X509_CSR_CLASS);
+
+ X509_REQ_free(*ud);
+ *ud = NULL;
+
+ return 0;
+} /* xr__gc() */
+
+static const luaL_Reg xr_methods[] = {
+ { "getVersion", &xr_getVersion },
+ { "setVersion", &xr_setVersion },
+ { "setSubjectName", &xr_setSubjectName },
+ { "setPublicKey", &xr_setPublicKey },
+ { NULL, NULL },
+};
+
+static const luaL_Reg xr_metatable[] = {
+ { "__tostring", &xr__tostring },
+ { "__gc", &xr__gc },
+ { NULL, NULL },
+};
+
+
+static const luaL_Reg xr_globals[] = {
+ { "new", &xr_new },
+ { "interpose", &xr_interpose },
+ { NULL, NULL },
+};
+
+int luaopen__openssl_x509_csr(lua_State *L) {
+ initall(L);
+
+ luaL_newlib(L, xr_globals);
+
+ return 1;
+} /* luaopen__openssl_x509_csr() */
+
+
+
static void initall(lua_State *L) {
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
addclass(L, BIGNUM_CLASS, bn_methods, bn_metatable);
+ addclass(L, PUBKEY_CLASS, pk_methods, pk_metatable);
addclass(L, X509_NAME_CLASS, xn_methods, xn_metatable);
addclass(L, X509_GENS_CLASS, gn_methods, gn_metatable);
addclass(L, X509_CERT_CLASS, xc_methods, xc_metatable);
+ addclass(L, X509_CSR_CLASS, xr_methods, xr_metatable);
} /* initall() */