aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatarLibravatar daurnimator <quae@daurnimator.com> 2022-07-03 22:54:31 +1000
committerLibravatarLibravatar daurnimator <quae@daurnimator.com> 2022-07-03 22:56:07 +1000
commitbed73b66dee1dde0bfa5a658cf109457c3f70b46 (patch)
tree932f7b82052832b459f607323a92dad8929014dc
parentb9212f4029be6d51d12ac0414b06eb9fe450a0e3 (diff)
parent2922f436c562cf4dc716fc24816784b71da27403 (diff)
downloadluaossl-bed73b66dee1dde0bfa5a658cf109457c3f70b46.tar.gz
luaossl-bed73b66dee1dde0bfa5a658cf109457c3f70b46.tar.bz2
luaossl-bed73b66dee1dde0bfa5a658cf109457c3f70b46.zip
Merge remote-tracking branch 'origin/refs/pull/201/head'
-rw-r--r--doc/luaossl.pdfbin182982 -> 333327 bytes
-rw-r--r--doc/luaossl.tex8
-rw-r--r--regress/115-test-aead.lua39
-rw-r--r--src/openssl.c49
4 files changed, 96 insertions, 0 deletions
diff --git a/doc/luaossl.pdf b/doc/luaossl.pdf
index b7a09dc..b8a0e27 100644
--- a/doc/luaossl.pdf
+++ b/doc/luaossl.pdf
Binary files differ
diff --git a/doc/luaossl.tex b/doc/luaossl.tex
index efc6422..df5626a 100644
--- a/doc/luaossl.tex
+++ b/doc/luaossl.tex
@@ -1485,6 +1485,14 @@ Update the cipher instance with the specified string(s). Returns a string on suc
Update the cipher with the specified string(s). Returns the final output string on success, or nil and an error message on failure. The returned string may be empty if all blocks have already been flushed in prior \fn{:update} calls.
+\subsubsection[\fn{cipher:getTag}]{\fn{cipher:getTag($len$)}}
+
+Returns the authentication tag for the ciphertext (GCM ciphers only) as a binary string. This method can only be called when encrypting data, and must be called after all data has been processed (i.e. after calling \fn{:final()}).
+
+\subsubsection[\fn{cipher:setTag}]{\fn{cipher:setTag($tag$)}}
+
+Sets the provided binary string as the expected authentication tag for the forthcoming ciphertext (GCM ciphers only). This method can only be called when decrypting data, and must be called before \fn{:final()} to ensure the ciphertext integrity can be verified successfully.
+
\end{Module}
diff --git a/regress/115-test-aead.lua b/regress/115-test-aead.lua
new file mode 100644
index 0000000..ed0f7f8
--- /dev/null
+++ b/regress/115-test-aead.lua
@@ -0,0 +1,39 @@
+local regress = require "regress";
+local openssl = require "openssl";
+local cipher = require "openssl.cipher"
+
+
+-- Test AES-256-GCM
+local key = "abcdefghijklmnopabcdefghijklmnop"
+local iv = "123456123456"
+local message = "My secret message"
+
+function test_aead(params)
+ local c = cipher.new(params.cipher):encrypt(key, iv)
+
+ local encrypted = c:update(message)
+ regress.check(encrypted)
+ regress.check(c:final(), "fail final encrypt")
+
+ local tag = assert(c:getTag(params.tag_length))
+ regress.check(tag and #tag == params.tag_length)
+
+
+ -- Now for the decryption
+ local d = cipher.new(params.cipher):decrypt(key, iv)
+ d:setTag(tag);
+
+ local decrypted = d:update(encrypted)
+ regress.check(decrypted == message, "decrypted message doesn't match")
+ regress.check(d:final(), "fail final decrypt")
+end
+
+test_aead {
+ cipher = "aes-256-gcm";
+ tag_length = 16;
+}
+
+test_aead {
+ cipher = "aes-256-ccm";
+ tag_length = 12;
+}
diff --git a/src/openssl.c b/src/openssl.c
index 198e6a6..3506089 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -12020,6 +12020,53 @@ sslerr:
} /* cipher_final() */
+static int cipher_get_tag(lua_State *L) {
+ EVP_CIPHER_CTX *ctx = checksimple(L, 1, CIPHER_CLASS);
+ luaL_Buffer tag;
+ size_t tag_size = luaL_checkinteger(L, 2);
+
+ luaL_buffinit(L, &tag);
+
+ /* EVP_CTRL_GCM_GET_TAG is works for both GCM and CCM and across all
+ * supported OpenSSL versions. We can switch to the unified identifier
+ * 'EVP_CTRL_AEAD_GET_TAG' in OpenSSL 1.1+.
+ */
+ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_size, (void*)luaL_prepbuffsize(&tag, tag_size))) {
+ goto sslerr;
+ }
+
+ luaL_pushresultsize(&tag, tag_size);
+
+ return 1;
+
+sslerr:
+ lua_pushnil(L);
+ auxL_pusherror(L, auxL_EOPENSSL, NULL);
+
+ return 2;
+} /* cipher_get_tag() */
+
+
+static int cipher_set_tag(lua_State *L) {
+ EVP_CIPHER_CTX *ctx = checksimple(L, 1, CIPHER_CLASS);
+ size_t tag_size;
+ const char* tag = luaL_checklstring(L, 2, &tag_size);
+ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag_size, (void*)tag)) {
+ goto sslerr;
+ }
+
+ lua_pushlstring(L, tag, tag_size);
+
+ return 1;
+
+sslerr:
+ lua_pushnil(L);
+ auxL_pusherror(L, auxL_EOPENSSL, NULL);
+
+ return 2;
+} /* cipher_set_tag() */
+
+
static int cipher__gc(lua_State *L) {
EVP_CIPHER_CTX **ctx = luaL_checkudata(L, 1, CIPHER_CLASS);
@@ -12035,6 +12082,8 @@ static const auxL_Reg cipher_methods[] = {
{ "decrypt", &cipher_decrypt },
{ "update", &cipher_update },
{ "final", &cipher_final },
+ { "getTag", &cipher_get_tag },
+ { "setTag", &cipher_set_tag },
{ NULL, NULL },
};