From 3eb66b869582bcd791cf89dd552abc4bb9e7c627 Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Tue, 8 Nov 2016 15:34:44 +1100
Subject: openssl.pkey: Add pkey:encrypt() method

---
 src/openssl.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/src/openssl.c b/src/openssl.c
index 4564061..87938e5 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -3181,6 +3181,61 @@ static int pk_setPrivateKey(lua_State *L) {
 } /* pk_setPrivateKey() */
 
 
+static int pk_encrypt(lua_State *L) {
+	size_t outlen, inlen;
+	EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS);
+	EVP_PKEY_CTX *ctx;
+	const char *str = luaL_checklstring(L, 2, &inlen);
+	BIO *bio;
+	BUF_MEM *buf;
+	int rsaPadding = RSA_PKCS1_PADDING; /* default for `openssl rsautl` */
+	int base_type = EVP_PKEY_base_id(key);
+
+	if (lua_istable(L, 3)) {
+		if (base_type == EVP_PKEY_RSA) {
+			lua_getfield(L, 3, "rsaPadding");
+			rsaPadding = luaL_optint(L, -1, rsaPadding);
+			lua_pop(L, 1);
+		}
+	}
+
+	bio = getbio(L);
+	BIO_get_mem_ptr(bio, &buf);
+
+	if (!(ctx = EVP_PKEY_CTX_new(key, NULL)))
+		goto sslerr;
+
+	if (EVP_PKEY_encrypt_init(ctx) <= 0)
+		goto sslerr;
+
+	if (base_type == EVP_PKEY_RSA && !EVP_PKEY_CTX_set_rsa_padding(ctx, rsaPadding))
+		goto sslerr;
+
+	if (EVP_PKEY_encrypt(ctx, NULL, &outlen, str, inlen) <= 0)
+		goto sslerr;
+
+	if (!BUF_MEM_grow_clean(buf, outlen))
+		goto sslerr;
+
+	if (EVP_PKEY_encrypt(ctx, buf->data, &outlen, str, inlen) <= 0)
+		goto sslerr;
+
+	EVP_PKEY_CTX_free(ctx);
+	ctx = NULL;
+
+	lua_pushlstring(L, buf->data, outlen);
+
+	return 1;
+sslerr:
+	if (ctx) {
+		EVP_PKEY_CTX_free(ctx);
+		ctx = NULL;
+	}
+
+	return auxL_error(L, auxL_EOPENSSL, "pkey:encrypt");
+} /* pk_encrypt() */
+
+
 static int pk_sign(lua_State *L) {
 	EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS);
 	EVP_MD_CTX *md = checksimple(L, 2, DIGEST_CLASS);
@@ -3907,6 +3962,7 @@ static const auxL_Reg pk_methods[] = {
 	{ "type",          &pk_type },
 	{ "setPublicKey",  &pk_setPublicKey },
 	{ "setPrivateKey", &pk_setPrivateKey },
+	{ "encrypt",       &pk_encrypt },
 	{ "sign",          &pk_sign },
 	{ "verify",        &pk_verify },
 	{ "getDefaultDigestName", &pk_getDefaultDigestName },
-- 
cgit v1.2.3-55-g6feb