git: 1219a3f40db3 - stable/13 - pfkey2: use correct value for a key length

From: Andrey V. Elsukov <ae_at_FreeBSD.org>
Date: Thu, 13 Mar 2025 10:23:48 UTC
The branch stable/13 has been updated by ae:

URL: https://cgit.FreeBSD.org/src/commit/?id=1219a3f40db386aaa10edfea27d9cc73fdea3935

commit 1219a3f40db386aaa10edfea27d9cc73fdea3935
Author:     Andrey V. Elsukov <ae@FreeBSD.org>
AuthorDate: 2025-03-06 12:18:59 +0000
Commit:     Andrey V. Elsukov <ae@FreeBSD.org>
CommitDate: 2025-03-13 10:23:29 +0000

    pfkey2: use correct value for a key length
    
    The length of key data is specified via sadb_key_bits field.
    Use specified size for buffer allocation and key copying.
    Also add a check that the value of sadb_key_bits is not zero,
    as explicitly required in RFC 2367.
    
    PR:             241010
    Submitted by:   jean-francois.hren at stormshield eu
    
    (cherry picked from commit 04207850a9b988d3c04e904cb5783f33da7fe184)
---
 sys/netipsec/key.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index 0dced6867f16..f21797009a60 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -668,7 +668,7 @@ static struct mbuf *key_setsadbxsa2(u_int8_t, u_int32_t, u_int32_t);
 static struct mbuf *key_setsadbxsareplay(u_int32_t);
 static struct mbuf *key_setsadbxpolicy(u_int16_t, u_int8_t,
 	u_int32_t, u_int32_t);
-static struct seckey *key_dup_keymsg(const struct sadb_key *, size_t,
+static struct seckey *key_dup_keymsg(const struct sadb_key *,
     struct malloc_type *);
 static struct seclifetime *key_dup_lifemsg(const struct sadb_lifetime *src,
     struct malloc_type *);
@@ -3395,6 +3395,9 @@ key_setsaval(struct secasvar *sav, const struct sadb_msghdr *mhp)
 			if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) &&
 			    sav->alg_auth != SADB_X_AALG_NULL)
 				error = EINVAL;
+			if (key0->sadb_key_bits == 0 || (sizeof(struct sadb_key) +
+			    (key0->sadb_key_bits >> 3)) > len)
+				error = EINVAL;
 			break;
 		case SADB_X_SATYPE_IPCOMP:
 		default:
@@ -3407,7 +3410,7 @@ key_setsaval(struct secasvar *sav, const struct sadb_msghdr *mhp)
 			goto fail;
 		}
 
-		sav->key_auth = key_dup_keymsg(key0, len, M_IPSEC_MISC);
+		sav->key_auth = key_dup_keymsg(key0, M_IPSEC_MISC);
 		if (sav->key_auth == NULL ) {
 			ipseclog((LOG_DEBUG, "%s: No more memory.\n",
 				  __func__));
@@ -3433,7 +3436,12 @@ key_setsaval(struct secasvar *sav, const struct sadb_msghdr *mhp)
 				error = EINVAL;
 				break;
 			}
-			sav->key_enc = key_dup_keymsg(key0, len, M_IPSEC_MISC);
+			if (key0->sadb_key_bits == 0 || (sizeof(struct sadb_key) +
+			    (key0->sadb_key_bits >> 3)) > len) {
+				error = EINVAL;
+				break;
+			}
+			sav->key_enc = key_dup_keymsg(key0, M_IPSEC_MISC);
 			if (sav->key_enc == NULL) {
 				ipseclog((LOG_DEBUG, "%s: No more memory.\n",
 					__func__));
@@ -4055,13 +4063,14 @@ key_setsadbxpolicy(u_int16_t type, u_int8_t dir, u_int32_t id, u_int32_t priorit
  * OUT: NULL no more memory
  */
 struct seckey *
-key_dup_keymsg(const struct sadb_key *src, size_t len,
-    struct malloc_type *type)
+key_dup_keymsg(const struct sadb_key *src, struct malloc_type *type)
 {
 	struct seckey *dst;
+	size_t len;
 
 	dst = malloc(sizeof(*dst), type, M_NOWAIT);
 	if (dst != NULL) {
+		len = src->sadb_key_bits >> 3;
 		dst->bits = src->sadb_key_bits;
 		dst->key_data = malloc(len, type, M_NOWAIT);
 		if (dst->key_data != NULL) {