Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/luaossl.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1485,6 +1485,14 @@ \section{Modules}

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:get\_tag}]{\fn{cipher:get\_tag($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:set\_tag}]{\fn{cipher:set\_tag($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}


Expand Down
43 changes: 43 additions & 0 deletions src/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -11975,6 +11975,47 @@ static int cipher_final(lua_State *L) {
} /* cipher_final() */


static int cipher_get_tag(lua_State *L) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be cipher_gcm_get_tag or similar to follow the naming of the option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly. It's actually not unique to GCM, but to the family of AEAD modes - in OpenSSL this includes CCM. In 1.1.x there is now therefore an alias for EVP_CTRL_AEAD_GET_TAG but this constant is not defined in 1.0.x. The current code should work with both GCM and CCM.

If we change the name, we could call it e.g. :get_aead_tag(), but I don't know whether this level of disambiguation is necessary.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be sensible to use EVP_CIPHER_type to get the type of the cipher and then use the relevant constant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. As I mentioned, modern versions of OpenSSL have both CCM_GET_TAG and GCM_GET_TAG aliased to AEAD_GET_TAG. The latter was added in 1.1, but before this the CCM variant was an alias of GCM_GET_TAG anyway.

In summary: in old versions, GCM_GET_TAG and CCM_GET_TAG are interchangeable identifiers for the same operation. In newer versions (1.1+) AEAD_GET_TAG was added as a generic identifier for this operation.

References:

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment saying as much?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 4a8b770

EVP_CIPHER_CTX *ctx = checksimple(L, 1, CIPHER_CLASS);
luaL_Buffer tag;
size_t tag_size = luaL_checkinteger(L, 2);

luaL_buffinit(L, &tag);

if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_size, (void*)luaL_prepbuffsize(&tag, tag_size))) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When was EVP_CIPHER_CTX_ctrl introduced? luaossl still tries to be compatible with old openssl versions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's been around a "long time". I don't know if it was in 0.9.8 (I can dig if really necessary), but it's certainly in 1.0.2. It's due to be retired post-3.0.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's due to be retired post-3.0.

What is it going to be replaced with?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new OSSL_PARAM API they've introduced. I haven't looked too much into it so far, as I haven't been working on any code that can be 3.0.x-only just yet.

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_get_tag() */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} /* cipher_get_tag() */
} /* cipher_set_tag() */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0dad2b3


static int cipher__gc(lua_State *L) {
EVP_CIPHER_CTX **ctx = luaL_checkudata(L, 1, CIPHER_CLASS);

Expand All @@ -11990,6 +12031,8 @@ static const auxL_Reg cipher_methods[] = {
{ "decrypt", &cipher_decrypt },
{ "update", &cipher_update },
{ "final", &cipher_final },
{ "get_tag", &cipher_get_tag },
{ "set_tag", &cipher_set_tag },
{ NULL, NULL },
};

Expand Down