summaryrefslogtreecommitdiffstats
path: root/crypto/hpke
diff options
context:
space:
mode:
authorStephen Farrell <stephen.farrell@cs.tcd.ie>2022-12-07 21:36:46 +0000
committerTomas Mraz <tomas@openssl.org>2022-12-08 10:59:03 +0100
commitcae72eefc3fbdd2f7a1a065f237bf3943619bca2 (patch)
treecba00a2de71c008076d5ed7f3afaecd370422444 /crypto/hpke
parentfc93335760686ad7cf3633d457caf18b0ac83ea2 (diff)
prevent HPKE sender setting seq unwisely
Reviewed-by: Shane Lontis <shane.lontis@oracle.com> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/19840)
Diffstat (limited to 'crypto/hpke')
-rw-r--r--crypto/hpke/hpke.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/crypto/hpke/hpke.c b/crypto/hpke/hpke.c
index a106366a75..12a12ad8fc 100644
--- a/crypto/hpke/hpke.c
+++ b/crypto/hpke/hpke.c
@@ -56,6 +56,7 @@ struct ossl_hpke_ctx_st
const OSSL_HPKE_KDF_INFO *kdf_info;
const OSSL_HPKE_AEAD_INFO *aead_info;
EVP_CIPHER *aead_ciph;
+ int role; /* sender(0) or receiver(1) */
uint64_t seq; /* aead sequence number */
unsigned char *shared_secret; /* KEM output, zz */
size_t shared_secretlen;
@@ -801,7 +802,7 @@ err:
* in doc/man3/OSSL_HPKE_CTX_new.pod to avoid duplication
*/
-OSSL_HPKE_CTX *OSSL_HPKE_CTX_new(int mode, OSSL_HPKE_SUITE suite,
+OSSL_HPKE_CTX *OSSL_HPKE_CTX_new(int mode, OSSL_HPKE_SUITE suite, int role,
OSSL_LIB_CTX *libctx, const char *propq)
{
OSSL_HPKE_CTX *ctx = NULL;
@@ -817,6 +818,10 @@ OSSL_HPKE_CTX *OSSL_HPKE_CTX_new(int mode, OSSL_HPKE_SUITE suite,
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
return NULL;
}
+ if (role != OSSL_HPKE_ROLE_SENDER && role != OSSL_HPKE_ROLE_RECEIVER) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL)
return NULL;
@@ -833,6 +838,7 @@ OSSL_HPKE_CTX *OSSL_HPKE_CTX_new(int mode, OSSL_HPKE_SUITE suite,
goto err;
}
}
+ ctx->role = role;
ctx->mode = mode;
ctx->suite = suite;
ctx->kem_info = kem_info;
@@ -915,6 +921,10 @@ int OSSL_HPKE_CTX_set1_ikme(OSSL_HPKE_CTX *ctx,
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
+ if (ctx->role != OSSL_HPKE_ROLE_SENDER) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
OPENSSL_clear_free(ctx->ikme, ctx->ikmelen);
ctx->ikme = OPENSSL_memdup(ikme, ikmelen);
if (ctx->ikme == NULL)
@@ -934,6 +944,10 @@ int OSSL_HPKE_CTX_set1_authpriv(OSSL_HPKE_CTX *ctx, EVP_PKEY *priv)
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
+ if (ctx->role != OSSL_HPKE_ROLE_SENDER) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
EVP_PKEY_free(ctx->authpriv);
ctx->authpriv = EVP_PKEY_dup(priv);
if (ctx->authpriv == NULL)
@@ -959,6 +973,10 @@ int OSSL_HPKE_CTX_set1_authpub(OSSL_HPKE_CTX *ctx,
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
+ if (ctx->role != OSSL_HPKE_ROLE_RECEIVER) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
/* check the value seems like a good public key for this kem */
kem_info = ossl_HPKE_KEM_INFO_find_id(ctx->suite.kem_id);
if (kem_info == NULL)
@@ -1020,6 +1038,15 @@ int OSSL_HPKE_CTX_set_seq(OSSL_HPKE_CTX *ctx, uint64_t seq)
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
+ /*
+ * We disallow senders from doing this as it's dangerous
+ * Receivers are ok to use this, as no harm should ensue
+ * if they go wrong.
+ */
+ if (ctx->role == OSSL_HPKE_ROLE_SENDER) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
ctx->seq = seq;
return 1;
}
@@ -1036,6 +1063,10 @@ int OSSL_HPKE_encap(OSSL_HPKE_CTX *ctx,
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
+ if (ctx->role != OSSL_HPKE_ROLE_SENDER) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
if (infolen > OSSL_HPKE_MAX_INFOLEN) {
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
@@ -1069,6 +1100,10 @@ int OSSL_HPKE_decap(OSSL_HPKE_CTX *ctx,
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
+ if (ctx->role != OSSL_HPKE_ROLE_RECEIVER) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
if (infolen > OSSL_HPKE_MAX_INFOLEN) {
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
@@ -1105,6 +1140,10 @@ int OSSL_HPKE_seal(OSSL_HPKE_CTX *ctx,
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
+ if (ctx->role != OSSL_HPKE_ROLE_SENDER) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
if ((ctx->seq + 1) == 0) { /* wrap around imminent !!! */
ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
@@ -1143,6 +1182,10 @@ int OSSL_HPKE_open(OSSL_HPKE_CTX *ctx,
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
+ if (ctx->role != OSSL_HPKE_ROLE_RECEIVER) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
if ((ctx->seq + 1) == 0) { /* wrap around imminent !!! */
ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;