crypt-offset (Crypt Offset) ---------------------------------- The crypt-offset attribute specifies the byte offset within a packet from which encryption begins. This is a per-device attribute that allows a portion of the packet header to remain in plaintext while the rest of the payload is encrypted. This is useful in scenarios where intermediate nodes need to inspect or process a fixed-size header before the encrypted payload. The default value is 0, meaning encryption starts from the beginning of the payload following the PSP header. spi-threshold (SPI Threshold) ------------------------------ The SPI (Security Parameter Index) is a 32-bit per-device identifier used to distinguish security associations. As SPI values are allocated monotonically, a threshold is needed to trigger timely SPI rotation before the space is exhausted. The spi-threshold attribute allows userspace to configure the value at which an SPI rotation should be initiated. The default is set to PSP_SPI_THRESHOLD_DEFAULT (~90% of 0x7FFFFFFF), providing a comfortable margin to perform rotation without racing to exhaustion. NOTE: A follow-up series will add notification support to alert subscribed users when the configured spi-threshold is reached, enabling timely SPI rotation. Signed-off-by: Akhilesh Samineni Reviewed-by: Kiran Kella Reviewed-by: Ajit Kumar Khaparde --- Documentation/netlink/specs/psp.yaml | 13 +++++++++++++ include/net/psp/types.h | 7 +++++++ include/uapi/linux/psp.h | 2 ++ net/psp/psp-nl-gen.c | 6 ++++-- net/psp/psp_main.c | 3 +++ net/psp/psp_nl.c | 27 +++++++++++++++++++++++---- 6 files changed, 52 insertions(+), 6 deletions(-) diff --git a/Documentation/netlink/specs/psp.yaml b/Documentation/netlink/specs/psp.yaml index f3a57782d2cf..b22869be91cf 100644 --- a/Documentation/netlink/specs/psp.yaml +++ b/Documentation/netlink/specs/psp.yaml @@ -38,6 +38,15 @@ attribute-sets: type: u32 enum: version enum-as-flags: true + - + name: crypt-offset + doc: The offset from the end of the PSP header to the start of the encrypted payload. + type: u8 + - + name: spi-threshold + doc: Threshold for the SPI to trigger notification to the user for appropriate rotate action. + type: u32 + - name: assoc attributes: @@ -170,6 +179,8 @@ operations: - ifindex - psp-versions-cap - psp-versions-ena + - crypt-offset + - spi-threshold pre: psp-device-get-locked post: psp-device-unlock dump: @@ -193,6 +204,8 @@ operations: attributes: - id - psp-versions-ena + - crypt-offset + - spi-threshold reply: attributes: [] pre: psp-device-get-locked diff --git a/include/net/psp/types.h b/include/net/psp/types.h index 25a9096d4e7d..875f7822557f 100644 --- a/include/net/psp/types.h +++ b/include/net/psp/types.h @@ -25,6 +25,9 @@ struct psphdr { #define PSP_SPI_KEY_ID GENMASK(30, 0) #define PSP_SPI_KEY_PHASE BIT(31) +/* Default SPI threshold: ~90% of max SPI (0x7FFFFFFF) to allow rotation before exhaustion */ +#define PSP_SPI_THRESHOLD_DEFAULT 0x73333333 + #define PSPHDR_CRYPT_OFFSET GENMASK(5, 0) #define PSPHDR_VERFL_SAMPLE BIT(7) @@ -38,9 +41,13 @@ struct psphdr { /** * struct psp_dev_config - PSP device configuration * @versions: PSP versions enabled on the device + * @crypt_offset: crypto offset configured on the device + * @spi_threshold: SPI threshold value on the device */ struct psp_dev_config { u32 versions; + u8 crypt_offset; + u32 spi_threshold; }; /** diff --git a/include/uapi/linux/psp.h b/include/uapi/linux/psp.h index a3a336488dc3..bb390159dc72 100644 --- a/include/uapi/linux/psp.h +++ b/include/uapi/linux/psp.h @@ -22,6 +22,8 @@ enum { PSP_A_DEV_IFINDEX, PSP_A_DEV_PSP_VERSIONS_CAP, PSP_A_DEV_PSP_VERSIONS_ENA, + PSP_A_DEV_CRYPT_OFFSET, + PSP_A_DEV_SPI_THRESHOLD, __PSP_A_DEV_MAX, PSP_A_DEV_MAX = (__PSP_A_DEV_MAX - 1) diff --git a/net/psp/psp-nl-gen.c b/net/psp/psp-nl-gen.c index 22a48d0fa378..e50b8b80955c 100644 --- a/net/psp/psp-nl-gen.c +++ b/net/psp/psp-nl-gen.c @@ -23,9 +23,11 @@ static const struct nla_policy psp_dev_get_nl_policy[PSP_A_DEV_ID + 1] = { }; /* PSP_CMD_DEV_SET - do */ -static const struct nla_policy psp_dev_set_nl_policy[PSP_A_DEV_PSP_VERSIONS_ENA + 1] = { +static const struct nla_policy psp_dev_set_nl_policy[PSP_A_DEV_SPI_THRESHOLD + 1] = { [PSP_A_DEV_ID] = NLA_POLICY_MIN(NLA_U32, 1), [PSP_A_DEV_PSP_VERSIONS_ENA] = NLA_POLICY_MASK(NLA_U32, 0xf), + [PSP_A_DEV_CRYPT_OFFSET] = { .type = NLA_U8, }, + [PSP_A_DEV_SPI_THRESHOLD] = { .type = NLA_U32, }, }; /* PSP_CMD_KEY_ROTATE - do */ @@ -75,7 +77,7 @@ static const struct genl_split_ops psp_nl_ops[] = { .doit = psp_nl_dev_set_doit, .post_doit = psp_device_unlock, .policy = psp_dev_set_nl_policy, - .maxattr = PSP_A_DEV_PSP_VERSIONS_ENA, + .maxattr = PSP_A_DEV_SPI_THRESHOLD, .flags = GENL_CMD_CAP_DO, }, { diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c index 9508b6c38003..536ee44db09d 100644 --- a/net/psp/psp_main.c +++ b/net/psp/psp_main.c @@ -79,6 +79,9 @@ psp_dev_create(struct net_device *netdev, INIT_LIST_HEAD(&psd->stale_assocs); refcount_set(&psd->refcnt, 1); + /* ~90% of 0x7FFFFFFF; allows SPI rotation well before space is exhausted */ + psd->config.spi_threshold = PSP_SPI_THRESHOLD_DEFAULT; + mutex_lock(&psp_devs_lock); err = xa_alloc_cyclic(&psp_devs, &psd->id, psd, xa_limit_16b, &last_id, GFP_KERNEL); diff --git a/net/psp/psp_nl.c b/net/psp/psp_nl.c index 6afd7707ec12..fbb77460a24b 100644 --- a/net/psp/psp_nl.c +++ b/net/psp/psp_nl.c @@ -101,7 +101,9 @@ psp_nl_dev_fill(struct psp_dev *psd, struct sk_buff *rsp, if (nla_put_u32(rsp, PSP_A_DEV_ID, psd->id) || nla_put_u32(rsp, PSP_A_DEV_IFINDEX, psd->main_netdev->ifindex) || nla_put_u32(rsp, PSP_A_DEV_PSP_VERSIONS_CAP, psd->caps->versions) || - nla_put_u32(rsp, PSP_A_DEV_PSP_VERSIONS_ENA, psd->config.versions)) + nla_put_u32(rsp, PSP_A_DEV_PSP_VERSIONS_ENA, psd->config.versions) || + nla_put_u8(rsp, PSP_A_DEV_CRYPT_OFFSET, psd->config.crypt_offset) || + nla_put_u32(rsp, PSP_A_DEV_SPI_THRESHOLD, psd->config.spi_threshold)) goto err_cancel_msg; genlmsg_end(rsp, hdr); @@ -193,6 +195,13 @@ int psp_nl_dev_set_doit(struct sk_buff *skb, struct genl_info *info) memcpy(&new_config, &psd->config, sizeof(new_config)); + if (!info->attrs[PSP_A_DEV_PSP_VERSIONS_ENA] && + !info->attrs[PSP_A_DEV_CRYPT_OFFSET] && + !info->attrs[PSP_A_DEV_SPI_THRESHOLD]) { + NL_SET_ERR_MSG(info->extack, "No settings present"); + return -EINVAL; + } + if (info->attrs[PSP_A_DEV_PSP_VERSIONS_ENA]) { new_config.versions = nla_get_u32(info->attrs[PSP_A_DEV_PSP_VERSIONS_ENA]); @@ -200,9 +209,19 @@ int psp_nl_dev_set_doit(struct sk_buff *skb, struct genl_info *info) NL_SET_ERR_MSG(info->extack, "Requested PSP versions not supported by the device"); return -EINVAL; } - } else { - NL_SET_ERR_MSG(info->extack, "No settings present"); - return -EINVAL; + } + + if (info->attrs[PSP_A_DEV_CRYPT_OFFSET]) + new_config.crypt_offset = + nla_get_u8(info->attrs[PSP_A_DEV_CRYPT_OFFSET]); + + if (info->attrs[PSP_A_DEV_SPI_THRESHOLD]) { + new_config.spi_threshold = + nla_get_u32(info->attrs[PSP_A_DEV_SPI_THRESHOLD]); + if (new_config.spi_threshold & PSP_SPI_KEY_PHASE) { + NL_SET_ERR_MSG(info->extack, "SPI threshold must not have bit 31 set"); + return -EINVAL; + } } rsp = psp_nl_reply_new(info); -- 2.45.4