Skip to content

Commit

Permalink
sad: introduce openssl mac library
Browse files Browse the repository at this point in the history
Four Message Authentication Code (MAC) libraries will be added:
 1. nettle
 2. gnutle
 3. gnupg
 4. openssl (this patch)

This patch introduces the openssl mac library along with all functions
required including initialization/deinitialization of mac context using
key data and generating the digest/mac/icv

Signed-off-by: Clay Kaiser <Clay.Kaiser@ibm.com>
Acked-by: Miroslav Lichvar <mlichvar@redhat.com>
Reviewed-by: Erez Geva <ErezGeva2@gmail.com>
  • Loading branch information
Clay Kaiser (via linuxptp-devel Mailing List) authored and richardcochran committed Jun 4, 2024
1 parent 5c56e39 commit 6e037df
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 2 deletions.
28 changes: 28 additions & 0 deletions incdefs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,34 @@ user_flags()
fi
done
done

# Look for openssl support.
for d in $dirs; do
sdirs=$(find $d -type d -name "openssl")
for s in $sdirs; do
have_crypto="0"
files=$(find $s -type f -name crypto.h)
for f in $files; do
if grep -q CRYPTO_memcmp $f; then
have_crypto="1"
break 1;
fi
done
have_evp="0"
files=$(find $s -type f -name evp.h)
for f in $files; do
if grep -q EVP_MAC_init $f; then
have_evp="1"
break 1;
fi
done
if [ $have_crypto = "1" ] &&
[ $have_evp = "1" ]; then
printf " -DHAVE_OPENSSL"
break 2
fi
done
done
}

#
Expand Down
7 changes: 7 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ incdefs := $(shell CC="$(CC)" $(srcdir)/incdefs.sh)
version := $(shell $(srcdir)/version.sh $(srcdir))
VPATH = $(srcdir)

ifeq (,$(findstring -DUSE_OPENSSL, $(EXTRA_CFLAGS)))
incdefs := $(filter-out -DHAVE_OPENSSL, $(incdefs))
endif

ifneq (,$(findstring -DHAVE_NETTLE, $(incdefs)))
LDLIBS += -lnettle
SECURITY += sad_nettle.o
Expand All @@ -53,6 +57,9 @@ SECURITY += sad_gnutls.o
else ifneq (,$(findstring -DHAVE_GNUPG, $(incdefs)))
LDLIBS += -lgcrypt
SECURITY += sad_gnupg.o
else ifneq (,$(findstring -DHAVE_OPENSSL, $(incdefs)))
LDLIBS += -lcrypto
SECURITY += sad_openssl.o
endif

prefix = /usr/local
Expand Down
2 changes: 1 addition & 1 deletion sad.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ int sad_create(struct config *cfg)
}

#if !defined (HAVE_NETTLE) && !defined (HAVE_GNUTLS) && \
!defined (HAVE_GNUPG)
!defined (HAVE_GNUPG) && !defined (HAVE_OPENSSL)
pr_err("sa_file set but security not supported");
return -1;
#endif
Expand Down
200 changes: 200 additions & 0 deletions sad_openssl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/**
* @file sad_openssl.c
* @brief Security Association Database openssl functions
* @note Copyright (C) 2024 IBM Corporation, Clay Kaiser <Clay.Kaiser@ibm.com>
* @note SPDX-License-Identifier: GPL-2.0+
*/
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>

#include "print.h"
#include "sad.h"
#include "sad_private.h"

struct mac_data {
EVP_MAC *algorithm;
EVP_MAC_CTX *context;
};

struct mac_data *sad_init_mac(integrity_alg_type algorithm,
const unsigned char *key, size_t key_len)
{
int err;
size_t length;

const char *name;
char *param, *algo;
EVP_MAC *mac_algorithm;
EVP_MAC_CTX *context;
OSSL_PARAM params[2];
EVP_CIPHER *cipher;
struct mac_data *mac_data;

/* verify key length */
if (key_len == 0) {
pr_err("BUG: key_len is zero");
return NULL;
}

/* retrieve mac algorithm */
switch (algorithm) {
case HMAC_SHA256_128:
case HMAC_SHA256:
name = "HMAC";
param = "digest";
algo = "SHA-256";
break;
case CMAC_AES128:
name = "CMAC";
param = "cipher";
algo = "AES-128-CBC";
break;
case CMAC_AES256:
name = "CMAC";
param = "cipher";
algo = "AES-256-CBC";
break;
default:
pr_err("BUG: unknown algorithm");
return NULL;
}
/* verify key length matches for cmac only */
switch (algorithm) {
case CMAC_AES128:
case CMAC_AES256:
cipher = EVP_CIPHER_fetch(NULL, algo, NULL);
length = EVP_CIPHER_get_key_length(cipher);
EVP_CIPHER_free(cipher);
if (key_len != length) {
pr_err("BUG: cipher key_len does not match");
return NULL;
}
break;
default:
break;
}
mac_algorithm = EVP_MAC_fetch(NULL, name, NULL);
if (!mac_algorithm) {
pr_err("EVP_MAC_fetch() failed");
return NULL;
}
context = EVP_MAC_CTX_new(mac_algorithm);
if (!context) {
pr_err("EVP_MAC_CTX_new() failed");
EVP_MAC_free(mac_algorithm);
return NULL;
}
params[0] = OSSL_PARAM_construct_utf8_string(param, algo, 0);
params[1] = OSSL_PARAM_construct_end();
err = EVP_MAC_CTX_set_params(context, params);
if (err == 0) {
pr_err("EVP_MAC_CTX_set_params() failed");
EVP_MAC_free(mac_algorithm);
EVP_MAC_CTX_free(context);
return NULL;
}

/* initialize context */
err = EVP_MAC_init(context, key, key_len, NULL);
if (err == 0) {
pr_err("EVP_MAC_init() failed");
EVP_MAC_free(mac_algorithm);
EVP_MAC_CTX_free(context);
return NULL;
}
/* initialize mac_data */
mac_data = calloc(1, sizeof(*mac_data));
if (!mac_data) {
EVP_MAC_free(mac_algorithm);
EVP_MAC_CTX_free(context);
return NULL;
}
mac_data->algorithm = mac_algorithm;
mac_data->context = context;

return mac_data;
}

void sad_deinit_mac(struct mac_data *data)
{
EVP_MAC_free(data->algorithm);
EVP_MAC_CTX_free(data->context);
free(data);
}

static inline int sad_update_mac(struct mac_data *mac_data,
const void *data, size_t data_len,
unsigned char *mac, size_t mac_len)
{
int err;
size_t digest_len;

/* confirm mac length is within buffer size */
if (mac_len > MAX_DIGEST_LENGTH) {
pr_err("BUG: mac_len larger than buffer");
return 0;
}

/* update data and retrieve mac */
err = EVP_MAC_init(mac_data->context, NULL, 0, NULL);
if (err == 0) {
pr_err("EVP_MAC_init() failed");
return 0;
}
err = EVP_MAC_update(mac_data->context, data, data_len);
if (err == 0) {
pr_err("EVP_MAC_update() failed");
return 0;
}
err = EVP_MAC_final(mac_data->context, mac,
&digest_len, MAX_DIGEST_LENGTH);
if (err == 0) {
pr_err("EVP_MAC_final() failed");
return 0;
}

/* confirm mac length is within library support */
if (mac_len > digest_len) {
pr_err("BUG: mac_len larger than library support");
return 0;
}

return 1;
}

int sad_hash(struct mac_data *mac_data,
const void *data, size_t data_len,
unsigned char *mac, size_t mac_len)
{
unsigned char digest_buffer[MAX_DIGEST_LENGTH];

/* update data and retrieve mac */
if (!sad_update_mac(mac_data, data, data_len,
digest_buffer, mac_len)) {
return 0;
}

/* move mac to desired location */
memcpy(mac, digest_buffer, mac_len);

return mac_len;
}

int sad_verify(struct mac_data *mac_data,
const void *data, size_t data_len,
unsigned char *mac, size_t mac_len)
{
unsigned char digest_buffer[MAX_DIGEST_LENGTH];

/* update data and retrieve mac */
if (!sad_update_mac(mac_data, data, data_len,
digest_buffer, mac_len)) {
return -1;
}

/* compare calculated with received */
return CRYPTO_memcmp(digest_buffer, mac, mac_len);
}
2 changes: 1 addition & 1 deletion sad_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct security_association_key {
};

#if defined (HAVE_NETTLE) || defined (HAVE_GNUTLS) || \
defined (HAVE_GNUPG)
defined (HAVE_GNUPG) || defined (HAVE_OPENSSL)
struct mac_data *sad_init_mac(integrity_alg_type algorithm,
const unsigned char *key, size_t key_len);

Expand Down

0 comments on commit 6e037df

Please sign in to comment.