Skip to content

Commit

Permalink
Expand support for EVP_PKEY_HMAC
Browse files Browse the repository at this point in the history
  • Loading branch information
justsmth committed Oct 18, 2024
1 parent 54fc7b7 commit 0a7bbfc
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 106 deletions.
19 changes: 14 additions & 5 deletions crypto/fipsmodule/evp/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ int EVP_RSA_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *
#define EVP_PKEY_CTRL_DH_PAD (EVP_PKEY_ALG_CTRL + 19)
#define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN (EVP_PKEY_ALG_CTRL + 20)
#define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR (EVP_PKEY_ALG_CTRL + 21)
#define EVP_PKEY_CTRL_SET_MAC_KEY (EVP_PKEY_ALG_CTRL + 22)

// EVP_PKEY_CTX_KEYGEN_INFO_COUNT is the maximum array length for
// |EVP_PKEY_CTX->keygen_info|. The array length corresponds to the number of
Expand Down Expand Up @@ -343,18 +344,26 @@ struct evp_pkey_method_st {
// operation.
int used_for_hmac(EVP_MD_CTX *ctx);

typedef struct {
const EVP_MD *md; // MD for HMAC use.
HMAC_CTX ctx;
} HMAC_PKEY_CTX;

typedef struct {
uint8_t *key;
size_t key_len;
} HMAC_KEY;

typedef struct {
const EVP_MD *md; // MD for HMAC use.
HMAC_CTX ctx;
HMAC_KEY ktmp;
} HMAC_PKEY_CTX;

// HMAC_KEY_set copies provided key into hmac_key. It frees any existing key
// on hmac_key. It returns 1 on success, and 0 otherwise.
int HMAC_KEY_set(HMAC_KEY* hmac_key, const uint8_t* key, const size_t key_len);
// HMAC_KEY_copy allocates and a new |HMAC_KEY| with identical contents (internal use).
int HMAC_KEY_copy(HMAC_KEY* dest, HMAC_KEY* src);
// HMAC_KEY_new allocates and zeroizes a |HMAC_KEY| for internal use.
HMAC_KEY *HMAC_KEY_new(void);
// HMAC_KEY_free frees resources of a |HMAC_KEY| (internal use).
void HMAC_KEY_free(HMAC_KEY* key);

typedef struct {
// key is the concatenation of the private seed and public key. It is stored
Expand Down
105 changes: 101 additions & 4 deletions crypto/fipsmodule/evp/p_hmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ static int hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
sctx = src->data;
dctx = dst->data;
dctx->md = sctx->md;
if(sctx->ktmp.key != NULL && !HMAC_KEY_copy(&sctx->ktmp, &dctx->ktmp)) {
OPENSSL_free(dctx);
return 0;
}
if (!HMAC_CTX_copy_ex(&dctx->ctx, &sctx->ctx)) {
OPENSSL_free(dctx);
return 0;
Expand All @@ -90,19 +94,78 @@ static int hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {

static void hmac_cleanup(EVP_PKEY_CTX *ctx) {
HMAC_PKEY_CTX *hctx = ctx->data;
OPENSSL_free(hctx->ktmp.key);
OPENSSL_free(hctx);
}

static int hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
static int hmac_ctrl(EVP_PKEY_CTX *ctx, int cmd, int p1, void *p2) {
int result = -2;

HMAC_PKEY_CTX *hctx = ctx->data;
switch (type) {
switch (cmd) {
case EVP_PKEY_CTRL_SET_MAC_KEY:
if (p1 < INT16_MAX && p1 > 0 && p2 != NULL) {
// p1 is the key length
// p2 is the key
if (HMAC_KEY_set(&hctx->ktmp, p2, p1)) {
result = 1;
} else {
result = 0;
}
}
break;
case EVP_PKEY_CTRL_MD:
hctx->md = p2;
result = 1;
break;
default:
OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
}
return result;
}

static int hmac_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value) {
if (!value) {
return 0;
}
if (strcmp(type, "key") == 0) {
// What if the key contains a 0-byte?
const size_t keylen = OPENSSL_strnlen(value, INT16_MAX);
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HMAC, EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_SET_MAC_KEY, keylen, (void*)value);
}
if (strcmp(type, "hexkey") == 0) {
size_t hex_keylen = 0;
uint8_t *key = OPENSSL_hexstr2buf(value, &hex_keylen);
if (key == NULL) {
return 0;
}
int result =
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HMAC, EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_SET_MAC_KEY, hex_keylen, key);
OPENSSL_free(key);
return result;
}
return -2;
}

static int hmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
GUARD_PTR(pkey);
HMAC_KEY *hmac = NULL;
HMAC_PKEY_CTX *hctx = ctx->data;
if(hctx == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PARAMETERS);
return 0;
}

if (!(hmac = HMAC_KEY_new()) ||
!HMAC_KEY_copy(hmac, &hctx->ktmp) ||
!EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, hmac)) {
HMAC_KEY_free(hmac);
return 0;
}

return 1;
}

Expand All @@ -111,7 +174,7 @@ DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_hmac_pkey_meth) {
out->init = hmac_init;
out->copy = hmac_copy;
out->cleanup = hmac_cleanup;
out->keygen = NULL;
out->keygen = hmac_keygen;
out->sign_init = NULL;
out->sign = NULL;
out->sign_message = NULL;
Expand All @@ -124,7 +187,7 @@ DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_hmac_pkey_meth) {
out->derive = NULL;
out->paramgen = NULL;
out->ctrl = hmac_ctrl;
out->ctrl_str = NULL;
out->ctrl_str = hmac_ctrl_str;
}

int used_for_hmac(EVP_MD_CTX *ctx) {
Expand All @@ -138,3 +201,37 @@ HMAC_KEY *HMAC_KEY_new(void) {
}
return key;
}

int HMAC_KEY_set(HMAC_KEY* hmac_key, const uint8_t* key, const size_t key_len) {
if(hmac_key == NULL ) {
return 0;
}
if (key == NULL || key_len == 0) {
hmac_key->key = NULL;
hmac_key->key_len = 0;
return 1;
}

uint8_t* new_key = OPENSSL_memdup(key, key_len);
if(new_key == NULL) {
return 0;
}
OPENSSL_free(hmac_key->key);
hmac_key->key = new_key;
hmac_key->key_len = key_len;
return 1;
}

void HMAC_KEY_free(HMAC_KEY* key) {
if (key != NULL) {
OPENSSL_free(key->key);
}
OPENSSL_free(key);
}

int HMAC_KEY_copy(HMAC_KEY* dest, HMAC_KEY* src) {
GUARD_PTR(dest);
GUARD_PTR(src);

return HMAC_KEY_set(dest, src->key, src->key_len);
}
Loading

0 comments on commit 0a7bbfc

Please sign in to comment.