diff --git a/src/openssl.c b/src/openssl.c index db64d03..34839b7 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -4662,6 +4662,53 @@ static int pk_encrypt(lua_State *L) { return auxL_error(L, auxL_EOPENSSL, "pkey:encrypt"); } /* pk_encrypt() */ + +static int pk_derive(lua_State *L) { + size_t outlen; + EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS); + EVP_PKEY *peer = checksimple(L, 2, PKEY_CLASS); + EVP_PKEY_CTX *ctx; + BIO *bio; + BUF_MEM *buf; + + bio = getbio(L); + BIO_get_mem_ptr(bio, &buf); + + if (!(ctx = EVP_PKEY_CTX_new(key, NULL))) + goto sslerr; + + if (EVP_PKEY_derive_init(ctx) <= 0) + goto sslerr; + + if (EVP_PKEY_derive_set_peer(ctx, peer) <= 0) + goto sslerr; + + if (EVP_PKEY_derive(ctx, NULL, &outlen) <= 0) + goto sslerr; + + if (!BUF_MEM_grow_clean(buf, outlen)) + goto sslerr; + + if (EVP_PKEY_derive(ctx, (unsigned char*)buf->data, &outlen) <= 0) + goto sslerr; + + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + + lua_pushlstring(L, buf->data, outlen); + + BIO_reset(bio); + + return 1; +sslerr: + if (ctx) { + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + } + BIO_reset(bio); + + return auxL_error(L, auxL_EOPENSSL, "pkey:encrypt"); +} /* pk_derive() */ #endif static int pk_sign(lua_State *L) { @@ -5393,6 +5440,7 @@ static const auxL_Reg pk_methods[] = { { "toPEM", &pk_toPEM }, { "tostring", &pk__tostring }, { "verify", &pk_verify }, + { "derive", &pk_derive }, { NULL, NULL }, };