Skip to content
Draft
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
aa72b5e
Infrastructure for returning additional fields in crypto:supports/0, /1
kvakvs Oct 14, 2025
fa19b83
Documentation for enable_fips_mode where we discourage its manual inv…
kvakvs Nov 5, 2025
44fe090
Lazy pubkey algorithms init
kvakvs Nov 5, 2025
69805e9
Cipher and MAC algorithms init edits
kvakvs Nov 6, 2025
d5d08e3
New store module for algorithms
kvakvs Nov 6, 2025
06b59d4
Functioning storage for curves and pkeys
kvakvs Nov 6, 2025
d3196a0
Minor changes
kvakvs Nov 7, 2025
dc92bac
Pubkey collections implementation
kvakvs Nov 8, 2025
72a5b56
Digest collection looks good
kvakvs Nov 9, 2025
91b4f05
WIP curve algorithms; auto resource helpers
kvakvs Nov 9, 2025
466634f
Trying with SSL API 3.0 and FIPS
kvakvs Nov 11, 2025
7b7ffb2
Syntax and warnings fixes
kvakvs Nov 12, 2025
c1f436e
KEM algorithms storage and probes
kvakvs Nov 12, 2025
9e88a40
RSA opts and fix errors/warnings accessing C api for digests
kvakvs Nov 12, 2025
4d2feb7
rsa opts and macs added, ciphers placeholder added
kvakvs Nov 12, 2025
1733798
Switch to FIPS 3.5.4 and test with it (WIP)
kvakvs Nov 14, 2025
7ab9908
Some fixes for 3.5.4 non-fips
kvakvs Nov 14, 2025
00c34b5
Fix stopper logic in the probes iteration
kvakvs Nov 14, 2025
b5603f6
Finished probe data for ciphers, probe code still WIP
kvakvs Nov 15, 2025
01da622
Cipher collection finished. Tested in 3.5.4 no-fips
kvakvs Nov 15, 2025
493e0b8
Reverting some formatting. Review notes addressed
kvakvs Nov 18, 2025
1f7793c
Return type is not bool
kvakvs Nov 18, 2025
b4a5f8a
Formatting; Testing under OpenSSL 1.1.1w
kvakvs Nov 20, 2025
f92e679
Fixes for 1.1.1w non FIPS
kvakvs Nov 25, 2025
c74d1bb
Correct use of v1 name for Erlang atoms; Typo in exported rsaopts_as_…
kvakvs Nov 25, 2025
8354508
Fixes for 0.9.8zh and for 3.5.4 FIPS
kvakvs Nov 25, 2025
43063a2
Fixes for 3.5.4 FIPS
kvakvs Nov 26, 2025
3c6b0e4
Documentation updated with OpenSSL 0.x and 1.1.0 out of support
kvakvs Nov 26, 2025
fe0ccf4
Testing with 1.0.1u
kvakvs Nov 27, 2025
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
22 changes: 18 additions & 4 deletions lib/crypto/c_src/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ CC = @DED_CC@
LD = @DED_LD@
SHELL = /bin/sh
LIBS = @DED_LIBS@
LDFLAGS += @DED_LDFLAGS@
LDFLAGS += @DED_LDFLAGS@ -lstdc++
CFLAGS = @DED_CFLAGS@ @SSL_FLAGS@ @DEFS@

# From configure
Expand Down Expand Up @@ -91,14 +91,22 @@ CRYPTO_OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o \
$(OBJDIR)/aead$(TYPEMARKER).o \
$(OBJDIR)/aes$(TYPEMARKER).o \
$(OBJDIR)/algorithms$(TYPEMARKER).o \
$(OBJDIR)/algorithms_collection$(TYPEMARKER).cpp.o \
$(OBJDIR)/algorithms_digest$(TYPEMARKER).cpp.o \
$(OBJDIR)/algorithms_pubkey$(TYPEMARKER).cpp.o \
$(OBJDIR)/algorithms_curve$(TYPEMARKER).cpp.o \
$(OBJDIR)/algorithms_kem$(TYPEMARKER).cpp.o \
$(OBJDIR)/algorithms_rsaopt$(TYPEMARKER).cpp.o \
$(OBJDIR)/algorithms_mac$(TYPEMARKER).cpp.o \
$(OBJDIR)/algorithms_cipher$(TYPEMARKER).cpp.o \
$(OBJDIR)/auto_openssl_resource$(TYPEMARKER).cpp.o \
$(OBJDIR)/api_ng$(TYPEMARKER).o \
$(OBJDIR)/atoms$(TYPEMARKER).o \
$(OBJDIR)/bn$(TYPEMARKER).o \
$(OBJDIR)/cipher$(TYPEMARKER).o \
$(OBJDIR)/cmac$(TYPEMARKER).o \
$(OBJDIR)/common$(TYPEMARKER).o \
$(OBJDIR)/dh$(TYPEMARKER).o \
$(OBJDIR)/digest$(TYPEMARKER).o \
$(OBJDIR)/dss$(TYPEMARKER).o \
$(OBJDIR)/ec$(TYPEMARKER).o \
$(OBJDIR)/ecdh$(TYPEMARKER).o \
Expand All @@ -119,7 +127,8 @@ CRYPTO_OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o \
$(OBJDIR)/pbkdf2_hmac$(TYPEMARKER).o

CALLBACK_OBJS = $(OBJDIR)/crypto_callback$(TYPEMARKER).o
CRYPTO_STATIC_OBJS = $(patsubst $(OBJDIR)/%$(TYPEMARKER).o,$(OBJDIR)/%_static$(TYPEMARKER).o,$(CRYPTO_OBJS) $(CALLBACK_OBJS))
CRYPTO_STATIC_OBJS = $(patsubst $(OBJDIR)/%$(TYPEMARKER).o,$(OBJDIR)/%_static$(TYPEMARKER).o,$(CRYPTO_OBJS) $(CALLBACK_OBJS)) \
$(patsubst $(OBJDIR)/%$(TYPEMARKER).cpp.o,$(OBJDIR)/%_static$(TYPEMARKER).cpp.o,$(CRYPTO_OBJS) $(CALLBACK_OBJS))

NIF_ARCHIVE = $(LIBDIR)/crypto$(TYPEMARKER).a

Expand Down Expand Up @@ -179,7 +188,8 @@ endif

CONFIGURE_ARGS = -DDISABLE_EVP_DH=@DISABLE_EVP_DH@ -DDISABLE_EVP_HMAC=@DISABLE_EVP_HMAC@

ALL_CFLAGS = $(TYPE_FLAGS) $(EXTRA_FLAGS) $(CONFIGURE_ARGS) $(INCLUDES)
ALL_CFLAGS = $(TYPE_FLAGS) $(EXTRA_FLAGS) $(CONFIGURE_ARGS) $(INCLUDES) -std=gnu99
ALL_CXXFLAGS = $(TYPE_FLAGS) $(EXTRA_FLAGS) $(CONFIGURE_ARGS) $(INCLUDES) -std=c++14
ALL_STATIC_CFLAGS = @DED_STATIC_CFLAGS@ $(TYPE_EXTRA_CFLAGS) $(CONFIGURE_ARGS) $(INCLUDES)

# ----------------------------------------------------
Expand Down Expand Up @@ -222,6 +232,10 @@ $(OBJDIR)/pkey$(TYPEMARKER).o: pkey.c

# ---- End of Hard-coded removal of deprecated warning for ENGINE function calls

$(OBJDIR)/%$(TYPEMARKER).cpp.o: %.cpp
$(V_at)$(INSTALL_DIR) $(OBJDIR)
$(V_CXX) -MMD -c -o $@ $(ALL_CXXFLAGS) $<

$(OBJDIR)/%$(TYPEMARKER).o: %.c
$(V_at)$(INSTALL_DIR) $(OBJDIR)
$(V_CC) -MMD -c -o $@ $(ALL_CFLAGS) $<
Expand Down
114 changes: 74 additions & 40 deletions lib/crypto/c_src/aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
#include "aes.h"
#include "cipher.h"
#include "info.h"

#include "algorithms_cipher.h"

ErlNifResourceType* aead_cipher_ctx_rtype;

struct aead_cipher_ctx {
const struct cipher_type_t *cipherp;
const cipher_type_C *cipherp;
EVP_CIPHER_CTX *ctx;

ERL_NIF_TERM key;
Expand Down Expand Up @@ -106,27 +106,42 @@ ERL_NIF_TERM aead_cipher_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
{ret = EXCP_BADARG_N(env, 1, "key or tag too long"); goto done;}

if ((ctx_res->cipherp = get_cipher_type(type, key.size)) == NULL)
{ret = EXCP_BADARG_N(env, 0, "Unknown cipher or invalid key size"); goto done;}
if (ctx_res->cipherp->flags & NON_EVP_CIPHER)
{ret = EXCP_BADARG_N(env, 0, "Bad cipher"); goto done;}
if (! (ctx_res->cipherp->flags & AEAD_CIPHER) )
{ret = EXCP_BADARG_N(env, 0, "Not aead cipher"); goto done;}
if (CIPHER_FORBIDDEN_IN_FIPS(ctx_res->cipherp))
{ret = EXCP_NOTSUP_N(env, 0, "Forbidden in FIPS"); goto done;}
{ret = EXCP_BADARG_N(env, 0, "Unknown cipher or invalid key size"); goto done;
}

const struct cipher_type_flags_t flags = cipher_type_flags(ctx_res->cipherp);
if (flags.non_evp_cipher) {
ret = EXCP_BADARG_N(env, 0, "Bad cipher");
goto done;
}
if (!flags.aead_cipher) {
ret = EXCP_BADARG_N(env, 0, "Not aead cipher");
goto done;
}
if (is_cipher_forbidden_in_fips(ctx_res->cipherp)) {
ret = EXCP_NOTSUP_N(env, 0, "Forbidden in FIPS");
goto done;
}

#if defined(HAVE_GCM_EVP_DECRYPT_BUG)
if ( !ctx_res->encflg && (ctx_res->cipherp->flags & GCM_MODE)) {
{ret = EXCP_NOTSUP_N(env, 0, "HAVE_GCM_EVP_DECRYPT_BUG with init aead not supported, update ssl version"); goto done;}
}
#endif

if (ctx_res->cipherp->cipher.p == NULL)
{ret = EXCP_NOTSUP_N(env, 0, "The cipher is not supported in this libcrypto version"); goto done;}

if ((ctx_res->ctx = EVP_CIPHER_CTX_new()) == NULL)
{ret = EXCP_ERROR(env, "Can't allocate ctx"); goto done;}
if (EVP_CipherInit_ex(ctx_res->ctx, ctx_res->cipherp->cipher.p, NULL, NULL, NULL, ctx_res->encflg) != 1)
{ret = EXCP_ERROR(env, "CipherInit failed"); goto done;}
if (cipher_type_resource(ctx_res->cipherp) == NULL) {
ret = EXCP_NOTSUP_N(env, 0, "The cipher is not supported in this libcrypto version");
goto done;
}
if ((ctx_res->ctx = EVP_CIPHER_CTX_new()) == NULL) {
ret = EXCP_ERROR(env, "Can't allocate ctx");
goto done;
}
if (EVP_CipherInit_ex(ctx_res->ctx, cipher_type_resource(ctx_res->cipherp),
NULL, NULL, NULL, ctx_res->encflg) != 1) {
ret = EXCP_ERROR(env, "CipherInit failed");
goto done;
}

ret = enif_make_resource(env, ctx_res);

Expand Down Expand Up @@ -202,29 +217,45 @@ ERL_NIF_TERM aead_cipher_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
|| iv.size > INT_MAX
|| in.size > INT_MAX
|| aad.size > INT_MAX)
{ret = EXCP_BADARG_N(env, 5, "binary too long"); goto done;}
{ret = EXCP_BADARG_N(env, 5, "binary too long"); goto done;
}

if ((cipherp = get_cipher_type(type, key.size)) == NULL)
{ret = EXCP_BADARG_N(env, 0, "Unknown cipher or invalid key size"); goto done;}
if (cipherp->flags & NON_EVP_CIPHER)
{ret = EXCP_BADARG_N(env, 0, "Bad cipher"); goto done;}
if (! (cipherp->flags & AEAD_CIPHER) )
{ret = EXCP_BADARG_N(env, 0, "Not aead cipher"); goto done;}
if (CIPHER_FORBIDDEN_IN_FIPS(cipherp))
{ret = EXCP_NOTSUP_N(env, 0, "Forbidden in FIPS"); goto done;}
if ((cipherp = get_cipher_type(type, key.size)) == NULL) {
ret = EXCP_BADARG_N(env, 0, "Unknown cipher or invalid key size");
goto done;
}

const struct cipher_type_flags_t flags = cipher_type_flags(cipherp);
if (flags.non_evp_cipher) {
ret = EXCP_BADARG_N(env, 0, "Bad cipher");
goto done;
}
if (!flags.aead_cipher) {
ret = EXCP_BADARG_N(env, 0, "Not aead cipher");
goto done;
}
if (is_cipher_forbidden_in_fips(cipherp)) {
ret = EXCP_NOTSUP_N(env, 0, "Forbidden in FIPS");
goto done;
}

#if defined(HAVE_GCM_EVP_DECRYPT_BUG)
if ( !encflg && (cipherp->flags & GCM_MODE)) {
return aes_gcm_decrypt_NO_EVP(env, argc, argv);
}
#endif
if ((cipher = cipherp->cipher.p) == NULL)
{ret = EXCP_NOTSUP_N(env, 0, "The cipher is not supported in this libcrypto version"); goto done;}

if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
{ret = EXCP_ERROR(env, "Can't allocate ctx"); goto done;}
if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, encflg) != 1)
{ret = EXCP_ERROR(env, "CipherInit failed"); goto done;}
if ((cipher = cipher_type_resource(cipherp)) == NULL) {
ret = EXCP_NOTSUP_N(env, 0, "The cipher is not supported in this libcrypto version");
goto done;
}
if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
ret = EXCP_ERROR(env, "Can't allocate ctx");
goto done;
}
if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, encflg) != 1) {
ret = EXCP_ERROR(env, "CipherInit failed");
goto done;
}

} else {
/* argc = 4 {state, IV, InData, AAD } */
Expand Down Expand Up @@ -258,17 +289,20 @@ ERL_NIF_TERM aead_cipher_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
}

cipherp = ctx_res->cipherp;
cipher = cipherp->cipher.p;
cipher = cipher_type_resource(cipherp);
ctx = ctx_res->ctx;
}
/* Init done */

if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1)
struct cipher_type_aead_t aead = cipher_type_aead(cipherp);
struct cipher_type_flags_t flags = cipher_type_flags(cipherp);

if (EVP_CIPHER_CTX_ctrl(ctx, aead.ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1)
{ret = EXCP_BADARG_N(env, 2, "Bad IV length"); goto done;}

#if defined(HAVE_CCM)
if (cipherp->flags & CCM_MODE) {
if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_set_tag, (int)tag_len, tag_data) != 1)
if (flags.ccm_mode) {
if (EVP_CIPHER_CTX_ctrl(ctx, aead.ctx_ctrl_set_tag, (int)tag_len, tag_data) != 1)
{ret = EXCP_BADARG_N(env, 5, "Can't set tag"); goto done;}
if (EVP_CipherInit_ex(ctx, NULL, NULL, key.data, iv.data, -1) != 1)
{ret = EXCP_ERROR(env, "Can't set key or iv"); goto done;}
Expand Down Expand Up @@ -314,7 +348,7 @@ ERL_NIF_TERM aead_cipher_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
/* Get the tag */
if ((tagp = enif_make_new_binary(env, tag_len, &out_tag)) == NULL)
{ret = EXCP_ERROR(env, "Can't make 'Out' binary"); goto done;}
if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_get_tag, (int)tag_len, tagp) != 1)
if (EVP_CIPHER_CTX_ctrl(ctx, aead.ctx_ctrl_get_tag, (int)tag_len, tagp) != 1)
{ret = EXCP_ERROR(env, "Can't get Tag"); goto done;}

/* Make the return value (the tuple with binary crypto text and the tag) */
Expand All @@ -324,7 +358,7 @@ ERL_NIF_TERM aead_cipher_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
{ret = EXCP_ERROR(env, "Encrypt error"); goto done;}
/* Add tag to output end */
tagp = outp + in_len;
if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_get_tag, (int)tag_len, tagp) != 1)
if (EVP_CIPHER_CTX_ctrl(ctx, aead.ctx_ctrl_get_tag, (int)tag_len, tagp) != 1)
{ret = EXCP_ERROR(env, "Can't get Tag"); goto done;}
ret = out;
}
Expand All @@ -333,8 +367,8 @@ ERL_NIF_TERM aead_cipher_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
{
#if defined(HAVE_GCM) || defined(HAVE_CHACHA20_POLY1305)
/* Check the Tag before returning. CCM_MODE does this previously. */
if (!(cipherp->flags & CCM_MODE)) { /* That is, CHACHA20_POLY1305 or GCM_MODE */
if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_set_tag, (int)tag_len, tag_data) != 1)
if (!flags.ccm_mode) { /* That is, CHACHA20_POLY1305 or GCM_MODE */
if (EVP_CIPHER_CTX_ctrl(ctx, aead.ctx_ctrl_set_tag, (int)tag_len, tag_data) != 1)
/* Decrypt error */
{ret = atom_error; goto done;}
/* CCM dislikes EVP_DecryptFinal_ex on decrypting for pre 1.1.1, so we do it only here */
Expand Down
Loading
Loading